1 #include "pEp_internal.h"
2 #include "pgp_netpgp.h"
9 #include <netpgp/config.h>
10 #include <netpgp/memory.h>
11 #include <netpgp/crypto.h>
12 #include <netpgp/netpgpsdk.h>
13 #include <netpgp/validate.h>
17 #define PEP_NETPGP_DEBUG
19 PEP_STATUS pgp_init(PEP_SESSION session, bool in_first)
22 PEP_STATUS status = PEP_STATUS_OK;
23 const char *home = NULL;
26 if(!session) return PEP_UNKNOWN_ERROR;
28 netpgp = &session->ctx;
31 if (strcmp(setlocale(LC_ALL, NULL), "C") == 0)
32 setlocale(LC_ALL, "");
35 memset(netpgp, 0x0, sizeof(session->ctx));
37 // netpgp_setvar(netpgp, "max mem alloc", "4194304");
38 netpgp_setvar(netpgp, "need seckey", "1");
39 netpgp_setvar(netpgp, "need userid", "1");
41 // NetPGP shares home with GPG
44 netpgp_set_homedir(netpgp,(char*)home, NULL, 0);
46 status = PEP_INIT_NO_GPG_HOME;
50 // pair with gpg's cert-digest-algo
51 netpgp_setvar(netpgp, "hash", "SHA256");
53 // subset of gpg's personal-cipher-preferences
54 // here only one cipher can be selected
55 netpgp_setvar(netpgp, "cipher", "AES256");
57 if (!netpgp_init(netpgp)) {
58 status = PEP_INIT_NETPGP_INIT_FAILED;
65 pgp_release(session, in_first);
69 void pgp_release(PEP_SESSION session, bool out_last)
76 netpgp = &session->ctx;
79 memset(netpgp, 0x0, sizeof(session->ctx));
81 // out_last unused here
84 // return 1 if the file contains ascii-armoured text
85 // buf MUST be \0 terminated to be checked for armour
87 _armoured(const char *buf, size_t size, const char *pattern)
89 unsigned armoured = 0;
92 regcomp(&r, pattern, REG_EXTENDED|REG_NEWLINE|REG_NOSUB);
93 if (regexec(&r, buf, 0, NULL, 0) == 0) {
101 // Iterate through netpgp' reported valid signatures
102 // fill a list of valid figerprints
103 // returns PEP_STATUS_OK if all sig reported valid
104 // error status otherwise.
105 static PEP_STATUS _validation_results(netpgp_t *netpgp, pgp_validation_t *vresult,
106 stringlist_t **_keylist)
113 if (now < vresult->birthtime) {
114 // signature is not valid yet
115 #ifdef PEP_NETPGP_DEBUG
117 "signature not valid until %.24s\n",
118 ctime(&vresult->birthtime));
119 #endif //PEP_NETPGP_DEBUG
120 return PEP_UNENCRYPTED;
122 if (vresult->duration != 0 && now > vresult->birthtime + vresult->duration) {
123 // signature has expired
124 t = vresult->duration + vresult->birthtime;
125 #ifdef PEP_NETPGP_DEBUG
127 "signature not valid after %.24s\n",
129 #endif //PEP_NETPGP_DEBUG
130 return PEP_UNENCRYPTED;
132 if (vresult->validc && vresult->valid_sigs &&
133 !vresult->invalidc && !vresult->unknownc ) {
136 // caller responsible to free
137 *_keylist = new_stringlist(NULL);
139 if (*_keylist == NULL) {
140 return PEP_OUT_OF_MEMORY;
143 for (n = 0; n < vresult->validc; ++n) {
145 char id[MAX_ID_LENGTH + 1];
146 static const char *hexes = "0123456789abcdef";
147 const uint8_t *userid = vresult->valid_sigs[n].signer_id;
149 #ifdef PEP_NETPGP_DEBUG
150 const pgp_key_t *key;
151 pgp_pubkey_t *sigkey;
153 key = pgp_getkeybyid(netpgp->io, netpgp->pubring,
154 (const uint8_t *) vresult->valid_sigs[n].signer_id,
156 pgp_print_keydata(netpgp->io, netpgp->pubring, key, "valid signature ", &key->key.pubkey, 0);
157 #endif //PEP_NETPGP_DEBUG
159 for (i = 0; i < 8 ; i++) {
160 id[i * 2] = hexes[(unsigned)(userid[i] & 0xf0) >> 4];
161 id[(i * 2) + 1] = hexes[userid[i] & 0xf];
165 k = stringlist_add(k, id);
167 free_stringlist(*_keylist);
168 return PEP_OUT_OF_MEMORY;
171 return PEP_STATUS_OK;
173 if (vresult->validc + vresult->invalidc + vresult->unknownc == 0) {
174 // No signatures found - is this memory signed?
175 return PEP_VERIFY_NO_KEY;
178 if (vresult->invalidc) {
179 // some invalid signatures
181 #ifdef PEP_NETPGP_DEBUG
183 for (n = 0; n < vresult->invalidc; ++n) {
184 const pgp_key_t *key;
185 pgp_pubkey_t *sigkey;
187 key = pgp_getkeybyid(netpgp->io, netpgp->pubring,
188 (const uint8_t *) vresult->invalid_sigs[n].signer_id,
190 pgp_print_keydata(netpgp->io, netpgp->pubring, key, "invalid signature ", &key->key.pubkey, 0);
191 if (sigkey->duration != 0 && now > sigkey->birthtime + sigkey->duration) {
192 printf("EXPIRED !\n");
195 #endif //PEP_NETPGP_DEBUG
197 return PEP_DECRYPT_SIGNATURE_DOES_NOT_MATCH;
201 return PEP_DECRYPT_WRONG_FORMAT;
204 #define ARMOR_HEAD "^-----BEGIN PGP MESSAGE-----\\s*$"
205 PEP_STATUS pgp_decrypt_and_verify(
206 PEP_SESSION session, const char *ctext, size_t csize,
207 char **ptext, size_t *psize, stringlist_t **keylist
213 pgp_validation_t *vresult;
219 stringlist_t *_keylist = NULL;
229 if(!session || !ctext || !csize || !ptext || !psize || !keylist)
230 return PEP_UNKNOWN_ERROR;
232 netpgp = &session->ctx;
238 vresult = malloc(sizeof(pgp_validation_t));
239 memset(vresult, 0x0, sizeof(pgp_validation_t));
241 mem = pgp_decrypt_and_validate_buf(netpgp->io, vresult, ctext, csize,
242 netpgp->secring, netpgp->pubring,
243 _armoured(ctext, csize, ARMOR_HEAD),
245 NULL, -1, NULL /* pass fp,attempts,cb */);
247 return PEP_OUT_OF_MEMORY;
250 _psize = pgp_mem_len(mem);
252 if ((_ptext = calloc(1, _psize)) == NULL) {
253 result = PEP_OUT_OF_MEMORY;
256 memcpy(_ptext, pgp_mem_data(mem), _psize);
257 result = PEP_DECRYPTED;
259 result = PEP_DECRYPT_NO_KEY;
263 if (result == PEP_DECRYPTED) {
264 result = _validation_results(netpgp, vresult, &_keylist);
265 if (result != PEP_STATUS_OK) {
268 result = PEP_DECRYPTED_AND_VERIFIED;
271 if (result == PEP_DECRYPTED_AND_VERIFIED
272 || result == PEP_DECRYPTED) {
275 (*ptext)[*psize] = 0; // safeguard for naive users
276 if (result == PEP_DECRYPTED_AND_VERIFIED) {
280 /* _ptext and _keylist ownership transfer, don't free */
285 free_stringlist(_keylist);
291 pgp_memory_free(mem);
292 pgp_validate_result_free(vresult);
297 #define ARMOR_SIG_HEAD "^-----BEGIN PGP (SIGNATURE|SIGNED MESSAGE)-----\\s*$"
298 PEP_STATUS pgp_verify_text(
299 PEP_SESSION session, const char *text, size_t size,
300 const char *signature, size_t sig_size, stringlist_t **keylist
304 pgp_memory_t *signedmem;
306 pgp_validation_t *vresult;
309 stringlist_t *_keylist;
318 if(!session || !text || !size || !signature || !sig_size || !keylist)
319 return PEP_UNKNOWN_ERROR;
321 netpgp = &session->ctx;
325 vresult = malloc(sizeof(pgp_validation_t));
326 memset(vresult, 0x0, sizeof(pgp_validation_t));
328 signedmem = pgp_memory_new();
329 if (signedmem == NULL) {
330 return PEP_OUT_OF_MEMORY;
332 pgp_memory_add(signedmem, (const uint8_t*)text, size);
334 sig = pgp_memory_new();
336 pgp_memory_free(signedmem);
337 return PEP_OUT_OF_MEMORY;
339 pgp_memory_add(sig, (const uint8_t*)signature, sig_size);
341 pgp_validate_mem_detached(netpgp->io, vresult, sig,
343 _armoured(signature, sig_size, ARMOR_SIG_HEAD),
347 result = _validation_results(netpgp, vresult, &_keylist);
348 if (result != PEP_STATUS_OK) {
351 result = PEP_VERIFIED;
354 if (result == PEP_VERIFIED) {
355 /* TODO : check trust level */
356 result = PEP_VERIFIED_AND_TRUSTED;
359 if (result == PEP_VERIFIED || result == PEP_VERIFIED_AND_TRUSTED) {
362 /* _keylist ownership transfer, don't free */
367 free_stringlist(_keylist);
370 // free done by pgp_validate_mem_detached
371 // pgp_memory_free(sig);
372 // pgp_memory_free(signedmem);
373 pgp_validate_result_free(vresult);
378 PEP_STATUS pgp_encrypt_and_sign(
379 PEP_SESSION session, const stringlist_t *keylist, const char *ptext,
380 size_t psize, char **ctext, size_t *csize
384 const pgp_key_t *keypair;
385 pgp_seckey_t *seckey;
386 pgp_memory_t *signedmem;
390 pgp_keyring_t *rcpts;
393 const stringlist_t *_keylist;
403 if(!session || !ptext || !psize || !ctext || !csize || !keylist)
404 return PEP_UNKNOWN_ERROR;
406 netpgp = &session->ctx;
411 // Get signing details from netpgp
412 if ((userid = netpgp_getvar(netpgp, "userid")) == NULL ||
413 (keypair = pgp_getkeybyname(netpgp->io, netpgp->secring, userid)) == NULL ||
414 (seckey = pgp_decrypt_seckey(keypair, NULL /*passfp*/)) == NULL) {
415 return PEP_UNKNOWN_ERROR;
418 hashalg = netpgp_getvar(netpgp, "hash");
419 // netpgp (l)imitation - XXX why ?
420 if (seckey->pubkey.alg == PGP_PKA_DSA) {
425 signedmem = pgp_sign_buf(netpgp->io, ptext, psize, seckey,
426 time(NULL), /* birthtime */
432 pgp_forget(seckey, (unsigned)sizeof(*seckey));
435 return PEP_UNENCRYPTED;
438 // Encrypt signed data
439 if ((rcpts = calloc(1, sizeof(*rcpts))) == NULL) {
440 result = PEP_OUT_OF_MEMORY;
443 for (_keylist = keylist; _keylist != NULL; _keylist = _keylist->next) {
444 assert(_keylist->value);
445 // get key from netpgp's pubring
446 const pgp_key_t *key;
447 key = pgp_getkeybyname(netpgp->io,
452 result = PEP_KEY_NOT_FOUND;
455 #ifdef PEP_NETPGP_DEBUG
456 pgp_print_keydata(netpgp->io, netpgp->pubring, key,
457 "recipient pubkey ", &key->key.pubkey, 0);
458 #endif //PEP_NETPGP_DEBUG
460 // add key to recipients/signers
461 pgp_keyring_add(rcpts, key);
462 if(rcpts->keys == NULL){
463 result = PEP_OUT_OF_MEMORY;
468 cmem = pgp_encrypt_buf(netpgp->io, pgp_mem_data(signedmem),
469 pgp_mem_len(signedmem), rcpts, 1 /* armored */,
470 netpgp_getvar(netpgp, "cipher"),
471 1 /* takes raw OpenPGP message */);
474 result = PEP_OUT_OF_MEMORY;
478 char *_buffer = NULL;
479 size_t length = pgp_mem_len(cmem);
480 assert(length != -1);
482 // Allocate transferable buffer
483 _buffer = malloc(length + 1);
485 if (_buffer == NULL) {
486 result = PEP_OUT_OF_MEMORY;
490 memcpy(_buffer, pgp_mem_data(cmem), length);
494 (*ctext)[*csize] = 0; // safeguard for naive users
495 result = PEP_STATUS_OK;
499 pgp_memory_free(cmem);
501 pgp_keyring_free(rcpts);
503 pgp_memory_free(signedmem);
508 PEP_STATUS pgp_generate_keypair(
509 PEP_SESSION session, pEp_identity *identity
513 const char *template =
518 /* "Passphrase: %s\n" */
524 assert(identity->address);
525 assert(identity->fpr == NULL);
526 assert(identity->username);
528 parms = calloc(1, PARMS_MAX);
531 return PEP_OUT_OF_MEMORY;
533 result = snprintf(parms, PARMS_MAX, template, identity->username,
535 assert(result < PARMS_MAX);
536 if (result >= PARMS_MAX) {
538 return PEP_BUFFER_TOO_SMALL;
541 /* TODO generate key */
545 return PEP_UNKNOWN_ERROR;
546 return PEP_ILLEGAL_VALUE;
547 return PEP_CANNOT_CREATE_KEY;
549 identity->fpr = strdup("TODO generated key fpr");
551 return PEP_STATUS_OK;
554 PEP_STATUS pgp_delete_keypair(PEP_SESSION session, const char *fpr)
559 /* TODO get key with given fpr */
560 return PEP_KEY_NOT_FOUND;
561 return PEP_ILLEGAL_VALUE;
562 return PEP_KEY_HAS_AMBIG_NAME;
563 return PEP_OUT_OF_MEMORY;
564 return PEP_UNKNOWN_ERROR;
566 /* TODO delete that key */
567 return PEP_UNKNOWN_ERROR;
568 return PEP_KEY_NOT_FOUND;
569 return PEP_KEY_HAS_AMBIG_NAME;
570 return PEP_UNKNOWN_ERROR;
572 return PEP_STATUS_OK;
575 PEP_STATUS pgp_import_keydata(PEP_SESSION session, const char *key_data, size_t size)
581 return PEP_UNKNOWN_ERROR;
582 return PEP_ILLEGAL_VALUE;
583 return PEP_UNKNOWN_ERROR;
584 return PEP_STATUS_OK;
587 PEP_STATUS pgp_export_keydata(
588 PEP_SESSION session, const char *fpr, char **key_data, size_t *size
602 return PEP_KEY_NOT_FOUND;
603 return PEP_UNKNOWN_ERROR;
604 return PEP_UNKNOWN_ERROR;
606 _size = /* TODO */ 0;
609 buffer = malloc(_size + 1);
611 if (buffer == NULL) {
613 return PEP_OUT_OF_MEMORY;
616 // safeguard for the naive user
622 return PEP_STATUS_OK;
626 // "hkp://keys.gnupg.net"
627 PEP_STATUS pgp_recv_key(PEP_SESSION session, const char *pattern)
632 /* TODO ask for key */
633 return PEP_UNKNOWN_ERROR;
634 return PEP_GET_KEY_FAILED;
642 return PEP_STATUS_OK;
645 PEP_STATUS pgp_find_keys(
646 PEP_SESSION session, const char *pattern, stringlist_t **keylist
649 stringlist_t *_keylist;
659 return PEP_UNKNOWN_ERROR;
660 return PEP_GET_KEY_FAILED;
662 _keylist = new_stringlist(NULL);
663 stringlist_t *_k = _keylist;
666 fpr = "TODO key->subkeys->fpr";
668 _k = stringlist_add(_k, fpr);
671 free_stringlist(_keylist);
672 return PEP_OUT_OF_MEMORY;
677 return PEP_STATUS_OK;
680 PEP_STATUS pgp_send_key(PEP_SESSION session, const char *pattern)
687 return PEP_CANNOT_SEND_KEY;
688 return PEP_STATUS_OK;
692 PEP_STATUS pgp_get_key_rating(
695 PEP_comm_type *comm_type
698 PEP_STATUS status = PEP_STATUS_OK;
704 *comm_type = PEP_ct_unknown;
706 /* TODO get key from fpr */
707 return PEP_UNKNOWN_ERROR;
708 return PEP_GET_KEY_FAILED;
710 switch (/*TODO key->protocol*/ 4) {
711 case /* TODO OpenPGP */0:
712 case /* TODO DEFAULT */1:
713 *comm_type = PEP_ct_OpenPGP_unconfirmed;
715 case /* TODO CMS */2:
716 *comm_type = PEP_ct_CMS_unconfirmed;
719 *comm_type = PEP_ct_unknown;
720 return PEP_STATUS_OK;
723 for (; 1 == 0; /* Each subkeys */ ) {
724 if (/* TODO length */0 < 1024)
725 *comm_type = PEP_ct_key_too_short;
728 ( /* TODO pubkey_algo == RSA */ 0)
729 || (/* TODO pubkey_algo == RSA_E*/ 0)
730 || (/* TODO pubkey_algo == RSA_S*/ 0)
732 && /* sk->length */0 == 1024
734 *comm_type = PEP_ct_OpenPGP_weak_unconfirmed;
736 if (/* TODO invalid */ 1) {
737 *comm_type = PEP_ct_key_b0rken;
740 if (/* TODO expired */ 1) {
741 *comm_type = PEP_ct_key_expired;
744 if (/* TODO revoked*/ 1) {
745 *comm_type = PEP_ct_key_revoked;
749 *comm_type = PEP_ct_unknown;
750 return PEP_OUT_OF_MEMORY;
751 return PEP_UNKNOWN_ERROR;