...
1 // This file is under GNU General Public License 3.0
4 #include "pEp_internal.h"
5 #include "pgp_netpgp.h"
12 #include <netpgp/config.h>
13 #include <netpgp/memory.h>
14 #include <netpgp/crypto.h>
15 #include <netpgp/netpgpsdk.h>
16 #include <netpgp/validate.h>
17 #include <netpgp/readerwriter.h>
19 #include <curl/curl.h>
23 static netpgp_t netpgp;
24 static pthread_mutex_t netpgp_mutex;
26 static PEP_STATUS init_netpgp()
28 PEP_STATUS status = PEP_STATUS_OK;
29 const char *home = NULL;
31 if(pthread_mutex_init(&netpgp_mutex, NULL)){
32 return PEP_OUT_OF_MEMORY;
35 if(pthread_mutex_lock(&netpgp_mutex)){
36 return PEP_UNKNOWN_ERROR;
39 if (strcmp(setlocale(LC_ALL, NULL), "C") == 0)
40 setlocale(LC_ALL, "");
42 memset(&netpgp, 0x0, sizeof(netpgp_t));
44 // netpgp_setvar(&netpgp, "max mem alloc", "4194304");
45 netpgp_setvar(&netpgp, "need seckey", "1");
46 // netpgp_setvar(&netpgp, "need userid", "1");
48 // NetPGP shares home with GPG
49 #if defined(WIN32) || defined(NDEBUG)
52 home = gpg_home(false);
56 netpgp_set_homedir(&netpgp,(char*)home, NULL, 0);
58 status = PEP_INIT_NO_GPG_HOME;
62 // pair with gpg's cert-digest-algo
63 netpgp_setvar(&netpgp, "hash", "SHA256");
65 // subset of gpg's personal-cipher-preferences
66 // here only one cipher can be selected
67 netpgp_setvar(&netpgp, "cipher", "CAST5");
69 if (!netpgp_init(&netpgp)) {
70 status = PEP_INIT_NETPGP_INIT_FAILED;
74 // netpgp_set_debug("packet-parse.c");
77 pthread_mutex_unlock(&netpgp_mutex);
82 static void release_netpgp()
84 if(pthread_mutex_lock(&netpgp_mutex)){
88 memset(&netpgp, 0x0, sizeof(netpgp_t));
90 pthread_mutex_destroy(&netpgp_mutex);
95 static PEP_STATUS init_curl(
96 pthread_mutex_t *curl_mutex,
99 PEP_STATUS status = PEP_STATUS_OK;
101 if(pthread_mutex_init(curl_mutex, NULL)){
102 return PEP_OUT_OF_MEMORY;
105 if(pthread_mutex_lock(curl_mutex)){
106 return PEP_UNKNOWN_ERROR;
110 curl_global_init(CURL_GLOBAL_DEFAULT);
113 pthread_mutex_unlock(curl_mutex);
117 static void release_curl(
118 pthread_mutex_t *curl_mutex,
121 if(pthread_mutex_lock(curl_mutex)){
126 curl_global_cleanup();
129 pthread_mutex_destroy(curl_mutex);
134 static PEP_STATUS curl_get_ctx(
137 PEP_STATUS status = PEP_STATUS_OK;
138 struct curl_slist *headers=NULL;
140 if ((*curl = curl_easy_init()) == NULL) {
141 return PEP_OUT_OF_MEMORY;
144 curl_easy_setopt(*curl, CURLOPT_FOLLOWLOCATION, 1L);
145 curl_easy_setopt(*curl, CURLOPT_MAXREDIRS, 3L);
147 headers=curl_slist_append(headers,"Pragma: no-cache");
149 headers=curl_slist_append(headers,"Cache-Control: no-cache");
153 return PEP_OUT_OF_MEMORY;
156 curl_easy_setopt(curl,CURLOPT_HTTPHEADER,headers);
157 curl_slist_free_all(headers);
159 // TODO curl_easy_setopt(curl,CURLOPT_PROXY,proxy);
163 static void curl_release_ctx(
167 curl_easy_cleanup(*curl);
174 PEP_STATUS pgp_init(PEP_SESSION session, bool in_first)
176 PEP_STATUS status = PEP_STATUS_OK;
179 if(!session) return PEP_ILLEGAL_VALUE;
182 if((status = init_netpgp()) != PEP_STATUS_OK)
186 if((status = init_curl(
187 &session->ctx.curl_mutex,
188 in_first) != PEP_STATUS_OK)){
189 if(in_first) release_netpgp();
193 return PEP_STATUS_OK;
196 void pgp_release(PEP_SESSION session, bool out_last)
204 release_curl(&session->ctx.curl_mutex, out_last);
207 // return 1 if the file contains ascii-armoured text
209 _armoured(const char *buf, size_t size, const char *pattern)
211 unsigned armoured = 0;
213 regcomp(&r, pattern, REG_EXTENDED|REG_NOSUB);
214 if (regnexec(&r, buf, size, 0, NULL, 0) == 0) {
221 /* write key fingerprint hexdump as a string */
223 fpr_to_str (char **str, const uint8_t *fpr, size_t length)
228 /* 4 hexes per short + null */
229 *str = malloc((length / 2) * 4 + 1);
234 for (n = 0, i = 0 ; i < length; i += 2) {
235 n += snprintf(&((*str)[n]), 5, "%02X%02X", fpr[i], fpr[i+1]);
241 /* write key fingerprint bytes read from hex string
242 * accept spaces and hexes */
244 str_to_fpr (const char *str, uint8_t *fpr, size_t *length)
253 while(*str && *length < PGP_FINGERPRINT_SIZE){
254 while (*str == ' ') str++;
255 for (j = 0; j < 2; j++) {
256 uint8_t *byte = &fpr[*length];
258 for (i = 0; i < 2; i++) {
261 if (*str >= 'a' && *str <= 'f')
262 *byte += 10 + *str - 'a';
263 else if (*str >= 'A' && *str <= 'F')
264 *byte += 10 + *str - 'A';
265 else if (*str >= '0' && *str <= '9')
277 // Iterate through netpgp' reported valid signatures
278 // fill a list of valid figerprints
279 // returns PEP_STATUS_OK if all sig reported valid
280 // error status otherwise.
281 static PEP_STATUS _validation_results(
283 pgp_validation_t *vresult,
284 stringlist_t **keylist
293 if (now < vresult->birthtime) {
294 // signature is not valid yet
295 return PEP_DECRYPT_SIGNATURE_DOES_NOT_MATCH;
297 if (vresult->duration != 0 && now > vresult->birthtime + vresult->duration) {
298 // signature has expired
299 t = vresult->duration + vresult->birthtime;
300 return PEP_DECRYPT_SIGNATURE_DOES_NOT_MATCH;
302 if (vresult->validc && vresult->valid_sigs &&
303 !vresult->invalidc && !vresult->unknownc ) {
305 stringlist_t *_keylist;
307 // caller responsible to free
308 _keylist = new_stringlist(NULL);
310 if (_keylist == NULL) {
311 return PEP_OUT_OF_MEMORY;
314 stringlist_t *k = _keylist;
316 for (unsigned n = 0; n < vresult->validc; ++n) {
318 const pgp_key_t *signer;
320 const uint8_t *keyid = vresult->valid_sigs[n].signer_id;
322 signer = pgp_getkeybyid(netpgp->io, netpgp->pubring,
323 keyid, &from, NULL, NULL,
324 0, 0); /* check neither revocation nor expiry
325 as is should be checked already */
328 signer->pubkeyfpr.fingerprint,
329 signer->pubkeyfpr.length);
334 free_stringlist(_keylist);
335 return PEP_OUT_OF_MEMORY;
338 k = stringlist_add(k, fprstr);
343 free_stringlist(_keylist);
344 return PEP_OUT_OF_MEMORY;
351 return PEP_STATUS_OK;
354 free_stringlist(_keylist);
355 return PEP_VERIFY_NO_KEY;
357 if (vresult->validc + vresult->invalidc + vresult->unknownc == 0) {
358 // No signatures found - is this memory signed?
359 return PEP_VERIFY_NO_KEY;
362 if (vresult->invalidc) {
363 // some invalid signatures
364 return PEP_DECRYPT_SIGNATURE_DOES_NOT_MATCH;
368 return PEP_DECRYPTED;
371 #define _ENDL "\\s*(\r\n|\r|\n)"
372 #define ARMOR_HEAD "^-----BEGIN PGP MESSAGE-----"_ENDL
373 PEP_STATUS pgp_decrypt_and_verify(
374 PEP_SESSION session, const char *ctext, size_t csize,
375 const char *dsigtext, size_t dsigsize,
376 char **ptext, size_t *psize, stringlist_t **keylist,
377 char** filename_ptr // will be ignored
383 stringlist_t *_keylist = NULL;
392 if(!session || !ctext || !csize || !ptext || !psize || !keylist)
393 return PEP_ILLEGAL_VALUE;
395 if(pthread_mutex_lock(&netpgp_mutex)){
396 return PEP_UNKNOWN_ERROR;
403 pgp_validation_t *vresult = malloc(sizeof(pgp_validation_t));
404 memset(vresult, 0x0, sizeof(pgp_validation_t));
406 key_id_t *recipients_key_ids = NULL;
407 unsigned recipients_count = 0;
409 pgp_memory_t *mem = pgp_decrypt_and_validate_buf(netpgp.io, vresult, ctext, csize,
410 netpgp.secring, netpgp.pubring,
411 _armoured(ctext, csize, ARMOR_HEAD),
412 &recipients_key_ids, &recipients_count);
415 result = PEP_OUT_OF_MEMORY;
419 const size_t _psize = pgp_mem_len(mem);
421 if ((_ptext = malloc(_psize + 1)) == NULL) {
422 result = PEP_OUT_OF_MEMORY;
425 memcpy(_ptext, pgp_mem_data(mem), _psize);
426 _ptext[_psize] = '\0'; // safeguard for naive users
427 result = PEP_DECRYPTED;
429 result = PEP_DECRYPT_NO_KEY;
433 if (result == PEP_DECRYPTED) {
434 result = _validation_results(&netpgp, vresult, &_keylist);
435 if (result == PEP_DECRYPTED ||
436 result == PEP_VERIFY_NO_KEY) {
437 if((_keylist = new_stringlist("")) == NULL) {
438 result = PEP_OUT_OF_MEMORY;
441 result = PEP_DECRYPTED;
442 }else if (result != PEP_STATUS_OK) {
445 result = PEP_DECRYPTED_AND_VERIFIED;
449 stringlist_t *k = _keylist;
450 for (unsigned n = 0; n < recipients_count; ++n) {
452 const pgp_key_t *rcpt;
454 key_id_t *keyid = &recipients_key_ids[n];
456 rcpt = pgp_getkeybyid(netpgp.io, netpgp.pubring,
457 *keyid, &from, NULL, NULL,
458 0, 0); /* check neither revocation nor expiry*/
461 rcpt->pubkeyfpr.fingerprint,
462 rcpt->pubkeyfpr.length);
464 // if no key found put ID instead of fpr
470 result = PEP_OUT_OF_MEMORY;
474 k = stringlist_add_unique(k, fprstr);
479 result = PEP_OUT_OF_MEMORY;
484 if (result == PEP_DECRYPTED_AND_VERIFIED
485 || result == PEP_DECRYPTED) {
488 (*ptext)[*psize] = 0; // safeguard for naive users
491 /* _ptext and _keylist ownership transfer, don't free */
496 free_stringlist(_keylist);
502 pgp_memory_free(mem);
503 pgp_validate_result_free(vresult);
506 free(recipients_key_ids);
507 pthread_mutex_unlock(&netpgp_mutex);
512 #define ARMOR_SIG_HEAD "^-----BEGIN PGP (SIGNATURE|SIGNED MESSAGE)-----"_ENDL
513 PEP_STATUS pgp_verify_text(
514 PEP_SESSION session, const char *text, size_t size,
515 const char *signature, size_t sig_size, stringlist_t **keylist
518 pgp_memory_t *signedmem;
520 pgp_validation_t *vresult;
523 stringlist_t *_keylist;
532 if(!session || !text || !size || !signature || !sig_size || !keylist)
533 return PEP_ILLEGAL_VALUE;
535 if(pthread_mutex_lock(&netpgp_mutex)){
536 return PEP_UNKNOWN_ERROR;
541 vresult = malloc(sizeof(pgp_validation_t));
542 if (vresult == NULL) {
543 result = PEP_OUT_OF_MEMORY;
546 memset(vresult, 0x0, sizeof(pgp_validation_t));
548 signedmem = pgp_memory_new();
549 if (signedmem == NULL) {
550 result = PEP_OUT_OF_MEMORY;
553 pgp_memory_add(signedmem, (const uint8_t*)text, size);
555 sig = pgp_memory_new();
557 pgp_memory_free(signedmem);
558 result = PEP_OUT_OF_MEMORY;
561 pgp_memory_add(sig, (const uint8_t*)signature, sig_size);
563 pgp_validate_mem_detached(netpgp.io, vresult, sig,
565 _armoured(signature, sig_size, ARMOR_SIG_HEAD),
569 result = _validation_results(&netpgp, vresult, &_keylist);
570 if (result != PEP_STATUS_OK) {
573 result = PEP_VERIFIED;
576 if (result == PEP_VERIFIED) {
577 /* TODO : check trust level */
578 result = PEP_VERIFIED_AND_TRUSTED;
581 if (result == PEP_VERIFIED || result == PEP_VERIFIED_AND_TRUSTED) {
584 /* _keylist ownership transfer, don't free */
588 free_stringlist(_keylist);
591 // free done by pgp_validate_mem_detached
592 // pgp_memory_free(sig);
593 // pgp_memory_free(signedmem);
594 pgp_validate_result_free(vresult);
597 pthread_mutex_unlock(&netpgp_mutex);
602 static PEP_STATUS _encrypt_and_sign(
603 PEP_SESSION session, const stringlist_t *keylist, const char *ptext,
604 size_t psize, char **ctext, size_t *csize, bool do_sign
607 pgp_key_t *signer = NULL;
608 pgp_seckey_t *seckey = NULL;
609 pgp_memory_t *signedmem = NULL;
612 pgp_keyring_t *rcpts;
615 const stringlist_t *_keylist;
624 if(!session || !ptext || !psize || !ctext || !csize || !keylist)
625 return PEP_ILLEGAL_VALUE;
627 if(pthread_mutex_lock(&netpgp_mutex)){
628 return PEP_UNKNOWN_ERROR;
634 if ((rcpts = calloc(1, sizeof(*rcpts))) == NULL) {
635 result = PEP_OUT_OF_MEMORY;
638 for (_keylist = keylist; _keylist != NULL; _keylist = _keylist->next) {
639 assert(_keylist->value);
641 const pgp_key_t *key;
642 uint8_t fpr[PGP_FINGERPRINT_SIZE];
646 if (str_to_fpr(_keylist->value, fpr, &fprlen)) {
647 if ((key = (pgp_key_t *)pgp_getkeybyfpr(netpgp.io, netpgp.pubring,
648 fpr, fprlen, &from, NULL,
649 /* reject revoked, accept expired */
651 result = PEP_KEY_NOT_FOUND;
655 result = PEP_ILLEGAL_VALUE;
659 /* Signer is the first key in the list */
662 signer = (pgp_key_t *)pgp_getkeybyfpr(netpgp.io, netpgp.secring,
666 0,0); /* accept any */
668 result = PEP_KEY_NOT_FOUND;
673 // add key to recipients/signers
674 pgp_keyring_add(rcpts, key);
675 if(rcpts->keys == NULL){
676 result = PEP_OUT_OF_MEMORY;
682 if(rcpts->keyc == 0){
683 result = PEP_ILLEGAL_VALUE;
687 seckey = pgp_key_get_certkey(signer);
689 /* No signig key. Revoked ? */
691 result = PEP_GET_KEY_FAILED;
695 hashalg = netpgp_getvar(&netpgp, "hash");
699 unsigned encrypt_raw_packet;
703 signedmem = pgp_sign_buf(netpgp.io, ptext, psize, seckey,
704 time(NULL), /* birthtime */
711 result = PEP_UNENCRYPTED;
714 stext = (char*) pgp_mem_data(signedmem);
715 ssize = pgp_mem_len(signedmem);
716 encrypt_raw_packet = 1 /* takes raw OpenPGP message */;
720 encrypt_raw_packet = 0 /* not a raw OpenPGP message */;
723 // Encrypt (maybe) signed data
725 cmem = pgp_encrypt_buf(netpgp.io, stext,
726 ssize, rcpts, 1 /* armored */,
727 netpgp_getvar(&netpgp, "cipher"),
731 result = PEP_OUT_OF_MEMORY;
735 char *_buffer = NULL;
736 size_t length = pgp_mem_len(cmem);
738 // Allocate transferable buffer
739 _buffer = malloc(length + 1);
741 if (_buffer == NULL) {
742 result = PEP_OUT_OF_MEMORY;
746 memcpy(_buffer, pgp_mem_data(cmem), length);
750 (*ctext)[*csize] = 0; // safeguard for naive users
751 result = PEP_STATUS_OK;
755 pgp_memory_free(cmem);
758 pgp_memory_free(signedmem);
761 pgp_keyring_free(rcpts);
763 pthread_mutex_unlock(&netpgp_mutex);
769 PEP_STATUS pgp_sign_only(
770 PEP_SESSION session, const char* fpr, const char *ptext,
771 size_t psize, char **stext, size_t *ssize
774 pgp_key_t *signer = NULL;
775 pgp_seckey_t *seckey = NULL;
776 pgp_memory_t *signedmem = NULL;
777 pgp_memory_t *text = NULL;
778 pgp_output_t *output;
783 pgp_create_sig_t *sig;
784 uint8_t keyid[PGP_KEY_ID_SIZE];
795 if(!session || !ptext || !psize || !stext || !ssize || !fpr || !fpr[0])
796 return PEP_ILLEGAL_VALUE;
798 if(pthread_mutex_lock(&netpgp_mutex)){
799 return PEP_UNKNOWN_ERROR;
805 if ((snrs = calloc(1, sizeof(*snrs))) == NULL) {
806 result = PEP_OUT_OF_MEMORY;
810 assert(fpr && fpr[0]);
812 uint8_t uint_fpr[PGP_FINGERPRINT_SIZE];
816 if (str_to_fpr(fpr, uint_fpr, &fprlen)) {
817 if ((signer = (pgp_key_t *)pgp_getkeybyfpr(netpgp.io, netpgp.secring,
818 uint_fpr, fprlen, &from, NULL,
819 /* reject revoked and expired */
821 result = PEP_KEY_NOT_FOUND;
825 result = PEP_ILLEGAL_VALUE;
829 // add key to signers
830 pgp_keyring_add(snrs, signer);
831 if(snrs->keys == NULL){
832 result = PEP_OUT_OF_MEMORY;
838 result = PEP_ILLEGAL_VALUE;
842 seckey = pgp_key_get_certkey(signer);
844 /* No signing key. Revoked ? */
846 result = PEP_GET_KEY_FAILED;
850 hashalg = netpgp_getvar(&netpgp, "hash");
855 text = pgp_memory_new();
856 pgp_memory_add(text, (const uint8_t*)ptext, psize);
858 pgp_setup_memory_write(&output, &signedmem, psize);
859 pgp_writer_push_armor_msg(output);
861 pgp_hash_alg_t hash_alg = pgp_str_to_hash_alg(hashalg);
863 sig = pgp_create_sig_new();
864 pgp_start_sig(sig, seckey, hash_alg, PGP_SIG_BINARY);
866 pgp_sig_add_data(sig, pgp_mem_data(text), pgp_mem_len(text));
867 pgp_memory_free(text);
869 pgp_add_creation_time(sig, time(NULL));
870 pgp_add_sig_expiration_time(sig, 0);
871 pgp_keyid(keyid, sizeof(keyid), &seckey->pubkey, hash_alg);
872 pgp_add_issuer_keyid(sig, keyid);
873 pgp_end_hashed_subpkts(sig);
875 pgp_write_sig(output, sig, &seckey->pubkey, seckey);
876 pgp_writer_close(output);
877 pgp_create_sig_delete(sig);
880 result = PEP_UNENCRYPTED;
883 _stext = (char*) pgp_mem_data(signedmem);
884 _ssize = pgp_mem_len(signedmem);
886 // Allocate transferable buffer
887 char *_buffer = malloc(_ssize + 1);
890 if (_buffer == NULL) {
891 result = PEP_OUT_OF_MEMORY;
895 memcpy(_buffer, _stext, _ssize);
898 (*stext)[*ssize] = 0; // safeguard for naive users
900 result = PEP_STATUS_OK;
903 pgp_memory_free(signedmem);
905 pgp_keyring_free(snrs);
907 pthread_mutex_unlock(&netpgp_mutex);
913 PEP_STATUS pgp_encrypt_and_sign(
914 PEP_SESSION session, const stringlist_t *keylist, const char *ptext,
915 size_t psize, char **ctext, size_t *csize
919 result = _encrypt_and_sign(session, keylist, ptext, psize, ctext, csize,
924 PEP_STATUS pgp_encrypt_only(
925 PEP_SESSION session, const stringlist_t *keylist, const char *ptext,
926 size_t psize, char **ctext, size_t *csize
930 result = _encrypt_and_sign(session, keylist, ptext, psize, ctext, csize,
936 PEP_STATUS pgp_generate_keypair(
937 PEP_SESSION session, pEp_identity *identity
941 pgp_key_t *newpubkey;
950 assert(identity->address);
951 assert(identity->fpr == NULL);
952 assert(identity->username);
954 if(!session || !identity ||
955 !identity->address || identity->fpr || !identity->username)
956 return PEP_ILLEGAL_VALUE;
958 if(pthread_mutex_lock(&netpgp_mutex)){
959 return PEP_UNKNOWN_ERROR;
962 if(snprintf(newid, sizeof(newid),
963 "%s <%s>", identity->username, identity->address) >= sizeof(newid)){
964 result = PEP_BUFFER_TOO_SMALL;
968 hashalg = netpgp_getvar(&netpgp, "hash");
969 cipher = netpgp_getvar(&netpgp, "cipher");
971 bzero(&newseckey, sizeof(newseckey));
974 if (!pgp_rsa_generate_keypair(&newseckey, 4096, 65537UL, hashalg, cipher,
975 (const uint8_t *) "", (const size_t) 0))
977 result = PEP_CANNOT_CREATE_KEY;
981 /* make a public key out of generated secret key */
982 if((newpubkey = pgp_ensure_pubkey(
984 &newseckey.key.seckey.pubkey,
985 newseckey.pubkeyid))==NULL)
987 result = PEP_OUT_OF_MEMORY;
991 // "Expire-Date: 1y\n";
992 if (!pgp_add_selfsigned_userid(&newseckey, newpubkey,
993 (uint8_t *)newid, 365*24*3600))
995 result = PEP_CANNOT_CREATE_KEY;
999 if (newpubkey == NULL)
1001 result = PEP_OUT_OF_MEMORY;
1005 // Append key to netpgp's rings (key ownership transfered)
1006 if (!pgp_keyring_add(netpgp.secring, &newseckey)){
1007 result = PEP_OUT_OF_MEMORY;
1012 if (netpgp_save_pubring(&netpgp) && netpgp_save_secring(&netpgp))
1014 char *fprstr = NULL;
1016 newseckey.pubkeyfpr.fingerprint,
1017 newseckey.pubkeyfpr.length);
1019 if (fprstr == NULL) {
1020 result = PEP_OUT_OF_MEMORY;
1024 /* keys saved, pass fingerprint back */
1025 identity->fpr = fprstr;
1026 result = PEP_STATUS_OK;
1028 /* free nothing, everything transfered */
1031 /* XXX in case only pubring save succeed
1032 * pubring file is left as-is, but backup restore
1033 * could be attempted if such corner case matters */
1034 result = PEP_UNKNOWN_ERROR;
1038 ((pgp_keyring_t *)netpgp.secring)->keyc--;
1040 pgp_deletekeybyfpr(netpgp.io,
1041 (pgp_keyring_t *)netpgp.pubring,
1042 newseckey.pubkeyfpr.fingerprint,
1043 newseckey.pubkeyfpr.length);
1045 pgp_key_free(&newseckey);
1047 pthread_mutex_unlock(&netpgp_mutex);
1052 PEP_STATUS pgp_delete_keypair(PEP_SESSION session, const char *fprstr)
1054 uint8_t fpr[PGP_FINGERPRINT_SIZE];
1062 if (!session || !fprstr)
1063 return PEP_ILLEGAL_VALUE;
1065 if(pthread_mutex_lock(&netpgp_mutex)){
1066 return PEP_UNKNOWN_ERROR;
1069 if (str_to_fpr(fprstr, fpr, &length)) {
1070 unsigned insec = pgp_deletekeybyfpr(netpgp.io,
1071 (pgp_keyring_t *)netpgp.secring,
1072 (const uint8_t *)fpr, length);
1073 unsigned inpub = pgp_deletekeybyfpr(netpgp.io,
1074 (pgp_keyring_t *)netpgp.pubring,
1075 (const uint8_t *)fpr, length);
1076 if(!insec && !inpub){
1077 result = PEP_KEY_NOT_FOUND;
1080 result = PEP_STATUS_OK;
1083 result = PEP_OUT_OF_MEMORY;
1088 if (netpgp_save_pubring(&netpgp) &&
1089 netpgp_save_secring(&netpgp))
1091 result = PEP_STATUS_OK;
1093 result = PEP_UNKNOWN_ERROR;
1097 pthread_mutex_unlock(&netpgp_mutex);
1102 #define ARMOR_KEY_HEAD "^-----BEGIN PGP (PUBLIC|PRIVATE) KEY BLOCK-----"_ENDL
1103 PEP_STATUS pgp_import_keydata(
1104 PEP_SESSION session,
1105 const char *key_data,
1107 identity_list **private_idents
1112 PEP_STATUS result = PEP_STATUS_OK;
1117 // reporting imported private keys not supported
1118 // stub code to be reomoved
1120 *private_idents = NULL;
1122 if(!session || !key_data)
1123 return PEP_ILLEGAL_VALUE;
1125 if(pthread_mutex_lock(&netpgp_mutex)){
1126 return PEP_UNKNOWN_ERROR;
1129 mem = pgp_memory_new();
1131 result = PEP_OUT_OF_MEMORY;
1134 pgp_memory_add(mem, (const uint8_t*)key_data, size);
1136 if (pgp_keyring_read_from_mem(netpgp.io, netpgp.pubring, netpgp.secring,
1137 _armoured(key_data, size, ARMOR_KEY_HEAD),
1139 result = PEP_ILLEGAL_VALUE;
1142 pgp_memory_free(mem);
1145 if (netpgp_save_pubring(&netpgp) &&
1146 netpgp_save_secring(&netpgp))
1148 // we never really know if a key was imported. MEH.
1149 result = PEP_KEY_IMPORT_STATUS_UNKNOWN;
1151 result = PEP_UNKNOWN_ERROR;
1155 pthread_mutex_unlock(&netpgp_mutex);
1160 static PEP_STATUS _export_keydata(
1167 pgp_output_t *output;
1169 pgp_setup_memory_write(&output, &mem, 128);
1171 if (mem == NULL || output == NULL) {
1172 return PEP_ILLEGAL_VALUE;
1175 if (!pgp_write_xfer_key(output, key, 1)) {
1176 result = PEP_UNKNOWN_ERROR;
1181 *buflen = pgp_mem_len(mem);
1183 // Allocate transferable buffer
1184 *buffer = malloc(*buflen + 1);
1186 if (*buffer == NULL) {
1187 result = PEP_OUT_OF_MEMORY;
1191 memcpy(*buffer, pgp_mem_data(mem), *buflen);
1192 (*buffer)[*buflen] = 0; // safeguard for naive users
1194 return PEP_STATUS_OK;
1197 pgp_teardown_memory_write(output, mem);
1202 PEP_STATUS pgp_export_keydata(
1203 PEP_SESSION session, const char *fprstr, char **key_data, size_t *size,
1208 uint8_t fpr[PGP_FINGERPRINT_SIZE];
1214 const pgp_keyring_t *srcring;
1222 srcring = netpgp.secring;
1224 srcring = netpgp.pubring;
1226 if (!session || !fprstr || !key_data || !size)
1227 return PEP_ILLEGAL_VALUE;
1229 if(pthread_mutex_lock(&netpgp_mutex)){
1230 return PEP_UNKNOWN_ERROR;
1233 if (str_to_fpr(fprstr, fpr, &fprlen)) {
1236 if ((key = (pgp_key_t *)pgp_getkeybyfpr(netpgp.io, srcring,
1238 NULL,0,0)) == NULL) {
1239 result = PEP_KEY_NOT_FOUND;
1243 result = PEP_OUT_OF_MEMORY;
1247 result = _export_keydata(key, &buffer, &buflen);
1249 if(result == PEP_STATUS_OK)
1253 result = PEP_STATUS_OK;
1257 pthread_mutex_unlock(&netpgp_mutex);
1268 HKPAnswerWriter(void *contents, size_t size, size_t nmemb, void *userp)
1270 size_t realsize = size * nmemb;
1271 struct HKP_answer *mem = (struct HKP_answer *)userp;
1273 mem->memory = realloc(mem->memory, mem->size + realsize + 1);
1274 if(mem->memory == NULL) {
1279 memcpy(&(mem->memory[mem->size]), contents, realsize);
1280 mem->size += realsize;
1281 mem->memory[mem->size] = 0;
1286 #define HKP_SERVER "http://keys.gnupg.net:11371"
1287 // #define HKP_SERVER "http://127.0.0.1:11371"
1289 PEP_STATUS pgp_recv_key(PEP_SESSION session, const char *pattern)
1291 static const char *ks_cmd = HKP_SERVER
1293 "op=get&options=mr&exact=on&"
1295 char *encoded_pattern;
1296 char *request = NULL;
1297 struct HKP_answer answer;
1307 if (!session || !pattern )
1308 return PEP_ILLEGAL_VALUE;
1310 if(pthread_mutex_lock(&session->ctx.curl_mutex)){
1311 return PEP_UNKNOWN_ERROR;
1314 result = curl_get_ctx(&curl);
1315 if(result != PEP_STATUS_OK){
1319 encoded_pattern = curl_easy_escape(curl, (char*)pattern, 0);
1320 if(!encoded_pattern){
1321 result = PEP_OUT_OF_MEMORY;
1322 goto release_curl_ctx;
1325 if((request = malloc(strlen(ks_cmd) + strlen(encoded_pattern) + 1))==NULL){
1326 result = PEP_OUT_OF_MEMORY;
1327 goto free_encoded_pattern;
1330 //(*stpcpy(stpcpy(request, ks_cmd), encoded_pattern)) = '\0';
1331 stpcpy(stpcpy(request, ks_cmd), encoded_pattern);
1333 curl_easy_setopt(curl, CURLOPT_URL,request);
1335 curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, HKPAnswerWriter);
1337 answer.memory = NULL;
1339 curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&answer);
1341 curlres = curl_easy_perform(curl);
1342 if(curlres != CURLE_OK) {
1343 result = PEP_GET_KEY_FAILED;
1347 if(!answer.memory || !answer.size) {
1348 result = PEP_OUT_OF_MEMORY;
1352 result = pgp_import_keydata(session,
1357 free(answer.memory);
1360 free_encoded_pattern:
1361 curl_free(encoded_pattern);
1363 curl_release_ctx(&curl);
1365 pthread_mutex_unlock(&session->ctx.curl_mutex);
1370 typedef PEP_STATUS (*find_key_cb_t)(void*, pgp_key_t *);
1372 static PEP_STATUS find_keys_do(pgp_keyring_t* keyring,
1373 const char *pattern, find_key_cb_t cb, void* cb_arg)
1375 uint8_t fpr[PGP_FINGERPRINT_SIZE];
1381 // Try find a fingerprint in pattern
1382 if (str_to_fpr(pattern, fpr, &length)) {
1386 // Only one fingerprint can match
1387 if ((key = (pgp_key_t *)pgp_getkeybyfpr(
1390 (const uint8_t *)fpr, length,
1392 NULL, 0, 0)) == NULL) {
1394 return PEP_KEY_NOT_FOUND;
1397 result = cb(cb_arg, key);
1400 // Search by name for pattern. Can match many.
1402 result = PEP_KEY_NOT_FOUND;
1403 while((key = (pgp_key_t *)pgp_getnextkeybyname(
1406 (const char *)pattern,
1409 result = cb(cb_arg, key);
1410 if (result != PEP_STATUS_OK)
1420 static PEP_STATUS add_key_fpr_to_stringlist(void *arg, pgp_key_t *key)
1422 stringlist_t **keylist = arg;
1423 char *newfprstr = NULL;
1425 fpr_to_str(&newfprstr,
1426 key->pubkeyfpr.fingerprint,
1427 key->pubkeyfpr.length);
1429 if (newfprstr == NULL) {
1430 return PEP_OUT_OF_MEMORY;
1433 stringlist_add(*keylist, newfprstr);
1435 if (*keylist == NULL) {
1436 return PEP_OUT_OF_MEMORY;
1439 return PEP_STATUS_OK;
1442 static PEP_STATUS add_secret_key_fpr_to_stringlist(void *arg, pgp_key_t *key)
1444 if (pgp_is_key_secret(key)) {
1445 stringlist_t **keylist = arg;
1446 char *newfprstr = NULL;
1448 fpr_to_str(&newfprstr,
1449 key->pubkeyfpr.fingerprint,
1450 key->pubkeyfpr.length);
1452 if (newfprstr == NULL) {
1453 return PEP_OUT_OF_MEMORY;
1455 stringlist_add(*keylist, newfprstr);
1457 if (*keylist == NULL) {
1458 return PEP_OUT_OF_MEMORY;
1462 return PEP_STATUS_OK;
1465 static PEP_STATUS add_keyinfo_to_stringpair_list(void* arg, pgp_key_t *key) {
1466 stringpair_list_t** keyinfo_list = (stringpair_list_t**)arg;
1467 stringpair_t* pair = NULL;
1468 char* id_fpr = NULL;
1469 char* primary_userid = (char*)pgp_key_get_primary_userid(key);
1472 // bool key_revoked = false;
1474 // PEP_STATUS key_status = pgp_key_revoked(session, id_fpr, &key_revoked);
1476 // if (key_revoked || key_status == PEP_GET_KEY_FAILED)
1477 // return PEP_STATUS_OK; // we just move on
1479 fpr_to_str(&id_fpr, key->pubkeyfpr.fingerprint,
1480 key->pubkeyfpr.length);
1482 pair = new_stringpair(id_fpr, primary_userid);
1485 return PEP_OUT_OF_MEMORY;
1487 *keyinfo_list = stringpair_list_add(*keyinfo_list, pair);
1489 if (*keyinfo_list == NULL)
1490 return PEP_OUT_OF_MEMORY;
1491 return PEP_STATUS_OK;
1494 PEP_STATUS pgp_find_keys(
1495 PEP_SESSION session, const char *pattern, stringlist_t **keylist
1498 stringlist_t *_keylist, *_k;
1506 if (!session || !pattern || !keylist )
1508 return PEP_ILLEGAL_VALUE;
1511 if (pthread_mutex_lock(&netpgp_mutex))
1513 return PEP_UNKNOWN_ERROR;
1517 _keylist = new_stringlist(NULL);
1518 if (_keylist == NULL) {
1519 result = PEP_OUT_OF_MEMORY;
1524 result = find_keys_do((pgp_keyring_t *)netpgp.pubring,
1525 pattern, &add_key_fpr_to_stringlist, &_k);
1527 if (result == PEP_STATUS_OK) {
1528 *keylist = _keylist;
1529 // Transfer ownership, no free
1533 free_stringlist(_keylist);
1536 pthread_mutex_unlock(&netpgp_mutex);
1541 #define HKP_REQ_PREFIX "keytext="
1542 #define HKP_REQ_PREFIX_LEN 8
1544 static PEP_STATUS send_key_cb(void *arg, pgp_key_t *key)
1546 char *buffer = NULL;
1549 stringlist_t *encoded_keys;
1550 encoded_keys = (stringlist_t*)arg;
1552 result = _export_keydata(key, &buffer, &buflen);
1554 if(result == PEP_STATUS_OK){
1555 char *encoded_key = curl_escape(buffer, (int)buflen);
1557 result = PEP_OUT_OF_MEMORY;
1560 size_t encoded_key_len = strlen(encoded_key);
1562 char *request = calloc(1, HKP_REQ_PREFIX_LEN + encoded_key_len + 1);
1564 result = PEP_OUT_OF_MEMORY;
1565 goto free_encoded_key;
1568 memcpy(request, HKP_REQ_PREFIX, HKP_REQ_PREFIX_LEN);
1569 memcpy(request + HKP_REQ_PREFIX_LEN, encoded_key, encoded_key_len);
1570 request[HKP_REQ_PREFIX_LEN + encoded_key_len] = '\0';
1572 if(!stringlist_add(encoded_keys, request)){
1573 result = PEP_OUT_OF_MEMORY;
1578 curl_free(encoded_key);
1587 PEP_STATUS pgp_send_key(PEP_SESSION session, const char *pattern)
1589 static const char *ks_cmd = HKP_SERVER "/pks/add";
1597 if (!session || !pattern )
1598 return PEP_ILLEGAL_VALUE;
1600 stringlist_t *encoded_keys = new_stringlist(NULL);
1601 assert(encoded_keys);
1602 if (encoded_keys == NULL) {
1603 return PEP_OUT_OF_MEMORY;
1606 if(pthread_mutex_lock(&netpgp_mutex)){
1607 result = PEP_UNKNOWN_ERROR;
1608 goto free_encoded_keys;
1611 result = find_keys_do((pgp_keyring_t *)netpgp.pubring,
1612 pattern, &send_key_cb, (void*)encoded_keys);
1614 pthread_mutex_unlock(&netpgp_mutex);
1616 if(result != PEP_STATUS_OK){
1617 goto free_encoded_keys;
1620 if(pthread_mutex_lock(&session->ctx.curl_mutex)){
1621 result = PEP_UNKNOWN_ERROR;
1622 goto free_encoded_keys;
1625 result = curl_get_ctx(&curl);
1626 if(result != PEP_STATUS_OK){
1630 if(result == PEP_STATUS_OK){
1633 for (const stringlist_t *post = encoded_keys; post != NULL; post = post->next) {
1634 assert(post->value);
1636 curl_easy_setopt(curl, CURLOPT_URL, ks_cmd);
1637 curl_easy_setopt(curl, CURLOPT_POST, 1L);
1638 curl_easy_setopt(curl, CURLOPT_POSTFIELDS, post->value);
1639 curl_easy_setopt(curl, CURLOPT_FAILONERROR, 1L);
1641 // Uncomment if debugging
1642 // curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L);
1644 curlres = curl_easy_perform(curl);
1646 if(curlres != CURLE_OK) {
1648 result = PEP_CANNOT_SEND_KEY;
1649 goto release_curl_ctx;
1655 curl_release_ctx(&curl);
1657 pthread_mutex_unlock(&session->ctx.curl_mutex);
1659 free_stringlist(encoded_keys);
1665 PEP_STATUS pgp_get_key_rating(
1666 PEP_SESSION session,
1668 PEP_comm_type *comm_type
1672 uint8_t fpr[PGP_FINGERPRINT_SIZE];
1677 PEP_STATUS status = PEP_STATUS_OK;
1683 if (!session || !fprstr || !comm_type )
1684 return PEP_ILLEGAL_VALUE;
1686 *comm_type = PEP_ct_unknown;
1688 if(pthread_mutex_lock(&netpgp_mutex)){
1689 return PEP_UNKNOWN_ERROR;
1692 if (!str_to_fpr(fprstr, fpr, &length)) {
1693 status = PEP_ILLEGAL_VALUE;
1697 key = pgp_getkeybyfpr(
1700 fpr, length, &from, NULL,0,0);
1704 status = PEP_KEY_NOT_FOUND;
1708 switch(pgp_key_get_rating(key)){
1710 *comm_type = PEP_ct_OpenPGP_unconfirmed;
1713 *comm_type = PEP_ct_OpenPGP_weak_unconfirmed;
1716 *comm_type = PEP_ct_key_too_short;
1719 *comm_type = PEP_ct_key_b0rken;
1722 *comm_type = PEP_ct_key_expired;
1725 *comm_type = PEP_ct_key_revoked;
1732 pthread_mutex_unlock(&netpgp_mutex);
1737 PEP_STATUS pgp_renew_key(
1738 PEP_SESSION session,
1745 uint8_t fpr[PGP_FINGERPRINT_SIZE];
1749 const uint8_t *primid;
1751 PEP_STATUS status = PEP_STATUS_OK;
1756 if (!session || !fprstr )
1757 return PEP_ILLEGAL_VALUE;
1763 when = mktime((struct tm*)ts);
1764 if(now && when && when > now){
1765 duration = when - now;
1767 return PEP_ILLEGAL_VALUE;
1770 /* Default 1 year from now */
1771 duration = 365*24*3600;
1774 if(pthread_mutex_lock(&netpgp_mutex)){
1775 return PEP_UNKNOWN_ERROR;
1779 if (!str_to_fpr(fprstr, fpr, &length)) {
1780 status = PEP_ILLEGAL_VALUE;
1784 pkey = pgp_getkeybyfpr(
1787 fpr, length, &from, NULL,
1788 1, 0); /* reject revoked, accept expired */
1792 status = PEP_KEY_NOT_FOUND;
1797 skey = pgp_getkeybyfpr(
1800 fpr, length, &from, NULL,
1801 1, 0); /* reject revoked, accept expired */
1805 status = PEP_KEY_NOT_FOUND;
1809 if((primid = pgp_key_get_primary_userid(skey)) == NULL)
1811 status = PEP_KEY_HAS_AMBIG_NAME;
1815 // FIXME : renew in a more gentle way
1816 if (!pgp_add_selfsigned_userid(skey, pkey, primid, duration))
1818 status = PEP_CANNOT_CREATE_KEY;
1823 if (netpgp_save_pubring(&netpgp) &&
1824 netpgp_save_secring(&netpgp))
1826 status = PEP_STATUS_OK;
1828 status = PEP_UNKNOWN_ERROR;
1832 pthread_mutex_unlock(&netpgp_mutex);
1837 PEP_STATUS pgp_revoke_key(
1838 PEP_SESSION session,
1843 uint8_t fpr[PGP_FINGERPRINT_SIZE];
1847 PEP_STATUS status = PEP_STATUS_OK;
1852 if (!session || !fprstr)
1853 return PEP_UNKNOWN_ERROR;
1855 if(pthread_mutex_lock(&netpgp_mutex)){
1856 return PEP_UNKNOWN_ERROR;
1859 // FIXME : deduplicate that code w/ renew
1860 if (!str_to_fpr(fprstr, fpr, &length)) {
1861 status = PEP_ILLEGAL_VALUE;
1865 pgp_key_t *pkey = pgp_getkeybyfpr(
1868 fpr, length, &from, NULL,
1869 1, 0); /* reject revoked, accept expired */
1873 status = PEP_KEY_NOT_FOUND;
1878 pgp_key_t *skey = pgp_getkeybyfpr(
1881 fpr, length, &from, NULL,
1882 1, 0); /* reject revoked, accept expired */
1886 status = PEP_KEY_NOT_FOUND;
1890 pgp_key_revoke(skey, pkey,
1891 0, /* no reason code specified */
1895 pthread_mutex_unlock(&netpgp_mutex);
1900 PEP_STATUS pgp_key_expired(
1901 PEP_SESSION session,
1907 PEP_STATUS status = PEP_STATUS_OK;
1908 PEP_comm_type comm_type;
1914 if (!session || !fprstr || !expired)
1915 return PEP_UNKNOWN_ERROR;
1917 // TODO : take "when" in account
1921 status = pgp_get_key_rating(session, fprstr, &comm_type);
1923 if (status != PEP_STATUS_OK)
1926 if (comm_type == PEP_ct_key_expired){
1930 return PEP_STATUS_OK;
1933 PEP_STATUS pgp_key_revoked(
1934 PEP_SESSION session,
1939 PEP_STATUS status = PEP_STATUS_OK;
1940 PEP_comm_type comm_type;
1948 status = pgp_get_key_rating(session, fprstr, &comm_type);
1950 if (status != PEP_STATUS_OK)
1953 if (comm_type == PEP_ct_key_revoked){
1957 return PEP_STATUS_OK;
1960 PEP_STATUS pgp_key_created(
1961 PEP_SESSION session,
1966 uint8_t fpr[PGP_FINGERPRINT_SIZE];
1971 PEP_STATUS status = PEP_STATUS_OK;
1977 if (!session || !fprstr || !created)
1978 return PEP_UNKNOWN_ERROR;
1982 if(pthread_mutex_lock(&netpgp_mutex)){
1983 return PEP_UNKNOWN_ERROR;
1986 if (!str_to_fpr(fprstr, fpr, &length)) {
1987 status = PEP_ILLEGAL_VALUE;
1991 key = pgp_getkeybyfpr(
1994 fpr, length, &from, NULL,0,0);
1998 *created = (time_t) key->key.pubkey.birthtime;
2002 status = PEP_KEY_NOT_FOUND;
2009 pthread_mutex_unlock(&netpgp_mutex);
2015 PEP_STATUS pgp_list_keyinfo(
2016 PEP_SESSION session, const char* pattern, stringpair_list_t** keyinfo_list)
2019 if (!session || !keyinfo_list)
2020 return PEP_UNKNOWN_ERROR;
2022 if (pthread_mutex_lock(&netpgp_mutex))
2024 return PEP_UNKNOWN_ERROR;
2032 result = find_keys_do((pgp_keyring_t *)netpgp.pubring,
2033 pattern, &add_keyinfo_to_stringpair_list, (void*)keyinfo_list);
2036 result = PEP_KEY_NOT_FOUND;
2038 pthread_mutex_unlock(&netpgp_mutex);
2043 /* copied from find_keys, but we need to use a callback that filters. */
2044 PEP_STATUS pgp_find_private_keys(
2045 PEP_SESSION session, const char *pattern, stringlist_t **keylist)
2047 stringlist_t *_keylist, *_k;
2054 if (!session || !keylist )
2056 return PEP_ILLEGAL_VALUE;
2059 if (pthread_mutex_lock(&netpgp_mutex))
2061 return PEP_UNKNOWN_ERROR;
2065 _keylist = new_stringlist(NULL);
2066 if (_keylist == NULL) {
2067 result = PEP_OUT_OF_MEMORY;
2072 result = find_keys_do((pgp_keyring_t *)netpgp.secring,
2073 pattern, &add_secret_key_fpr_to_stringlist, &_k);
2075 if (result == PEP_STATUS_OK) {
2076 *keylist = _keylist;
2077 // Transfer ownership, no free
2081 free_stringlist(_keylist);
2084 pthread_mutex_unlock(&netpgp_mutex);
2089 PEP_STATUS pgp_contains_priv_key(
2090 PEP_SESSION session,
2092 bool *has_private) {
2093 stringlist_t* keylist = NULL;
2094 PEP_STATUS status = pgp_find_private_keys(session, fpr, &keylist);
2095 if (status == PEP_STATUS_OK && keylist) {
2096 free_stringlist(keylist);
2097 *has_private = true;
2100 *has_private = false;
2105 PEP_STATUS pgp_import_ultimately_trusted_keypairs(PEP_SESSION session) {
2106 // Not implemented - netpgp doesn't appear to keep track of trust status in
2107 // a meaningful way, though there is space for it in the structs.
2108 return PEP_STATUS_OK;