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>
14 #include <netpgp/readerwriter.h>
18 #define PEP_NETPGP_DEBUG
20 PEP_STATUS pgp_init(PEP_SESSION session, bool in_first)
23 PEP_STATUS status = PEP_STATUS_OK;
24 const char *home = NULL;
27 if(!session) return PEP_UNKNOWN_ERROR;
29 netpgp = &session->ctx;
32 if (strcmp(setlocale(LC_ALL, NULL), "C") == 0)
33 setlocale(LC_ALL, "");
36 memset(netpgp, 0x0, sizeof(session->ctx));
38 // netpgp_setvar(netpgp, "max mem alloc", "4194304");
39 netpgp_setvar(netpgp, "need seckey", "1");
40 netpgp_setvar(netpgp, "need userid", "1");
42 // NetPGP shares home with GPG
45 netpgp_set_homedir(netpgp,(char*)home, NULL, 0);
47 status = PEP_INIT_NO_GPG_HOME;
51 // pair with gpg's cert-digest-algo
52 netpgp_setvar(netpgp, "hash", "SHA256");
54 // subset of gpg's personal-cipher-preferences
55 // here only one cipher can be selected
56 netpgp_setvar(netpgp, "cipher", "CAST5");
58 if (!netpgp_init(netpgp)) {
59 status = PEP_INIT_NETPGP_INIT_FAILED;
66 pgp_release(session, in_first);
70 void pgp_release(PEP_SESSION session, bool out_last)
77 netpgp = &session->ctx;
80 memset(netpgp, 0x0, sizeof(session->ctx));
82 // out_last unused here
85 // return 1 if the file contains ascii-armoured text
86 // buf MUST be \0 terminated to be checked for armour
88 _armoured(const char *buf, size_t size, const char *pattern)
90 unsigned armoured = 0;
93 regcomp(&r, pattern, REG_EXTENDED|REG_NEWLINE|REG_NOSUB);
94 if (regexec(&r, buf, 0, NULL, 0) == 0) {
102 /* return key ID's hexdump as a string */
103 static void id_to_str(const uint8_t *userid, char *fpr)
106 static const char *hexes = "0123456789abcdef";
107 for (i = 0; i < 8 ; i++) {
108 fpr[i * 2] = hexes[(unsigned)(userid[i] & 0xf0) >> 4];
109 fpr[(i * 2) + 1] = hexes[userid[i] & 0xf];
114 // Iterate through netpgp' reported valid signatures
115 // fill a list of valid figerprints
116 // returns PEP_STATUS_OK if all sig reported valid
117 // error status otherwise.
118 static PEP_STATUS _validation_results(netpgp_t *netpgp, pgp_validation_t *vresult,
119 stringlist_t **_keylist)
126 if (now < vresult->birthtime) {
127 // signature is not valid yet
128 #ifdef PEP_NETPGP_DEBUG
130 "signature not valid until %.24s\n",
131 ctime(&vresult->birthtime));
132 #endif //PEP_NETPGP_DEBUG
133 return PEP_UNENCRYPTED;
135 if (vresult->duration != 0 && now > vresult->birthtime + vresult->duration) {
136 // signature has expired
137 t = vresult->duration + vresult->birthtime;
138 #ifdef PEP_NETPGP_DEBUG
140 "signature not valid after %.24s\n",
142 #endif //PEP_NETPGP_DEBUG
143 return PEP_UNENCRYPTED;
145 if (vresult->validc && vresult->valid_sigs &&
146 !vresult->invalidc && !vresult->unknownc ) {
149 // caller responsible to free
150 *_keylist = new_stringlist(NULL);
152 if (*_keylist == NULL) {
153 return PEP_OUT_OF_MEMORY;
156 for (n = 0; n < vresult->validc; ++n) {
157 char id[MAX_ID_LENGTH + 1];
158 const uint8_t *userid = vresult->valid_sigs[n].signer_id;
160 #ifdef PEP_NETPGP_DEBUG
161 const pgp_key_t *key;
162 pgp_pubkey_t *sigkey;
164 key = pgp_getkeybyid(netpgp->io, netpgp->pubring,
165 (const uint8_t *) vresult->valid_sigs[n].signer_id,
167 pgp_print_keydata(netpgp->io, netpgp->pubring, key, "valid signature ", &key->key.pubkey, 0);
168 #endif //PEP_NETPGP_DEBUG
170 id_to_str(userid, id);
172 k = stringlist_add(k, id);
174 free_stringlist(*_keylist);
175 return PEP_OUT_OF_MEMORY;
178 return PEP_STATUS_OK;
180 if (vresult->validc + vresult->invalidc + vresult->unknownc == 0) {
181 // No signatures found - is this memory signed?
182 return PEP_VERIFY_NO_KEY;
185 if (vresult->invalidc) {
186 // some invalid signatures
188 #ifdef PEP_NETPGP_DEBUG
190 for (n = 0; n < vresult->invalidc; ++n) {
191 const pgp_key_t *key;
192 pgp_pubkey_t *sigkey;
194 key = pgp_getkeybyid(netpgp->io, netpgp->pubring,
195 (const uint8_t *) vresult->invalid_sigs[n].signer_id,
197 pgp_print_keydata(netpgp->io, netpgp->pubring, key, "invalid signature ", &key->key.pubkey, 0);
198 if (sigkey->duration != 0 && now > sigkey->birthtime + sigkey->duration) {
199 printf("EXPIRED !\n");
202 #endif //PEP_NETPGP_DEBUG
204 return PEP_DECRYPT_SIGNATURE_DOES_NOT_MATCH;
208 return PEP_DECRYPT_WRONG_FORMAT;
211 #define ARMOR_HEAD "^-----BEGIN PGP MESSAGE-----\\s*$"
212 PEP_STATUS pgp_decrypt_and_verify(
213 PEP_SESSION session, const char *ctext, size_t csize,
214 char **ptext, size_t *psize, stringlist_t **keylist
220 pgp_validation_t *vresult;
226 stringlist_t *_keylist = NULL;
236 if(!session || !ctext || !csize || !ptext || !psize || !keylist)
237 return PEP_UNKNOWN_ERROR;
239 netpgp = &session->ctx;
245 vresult = malloc(sizeof(pgp_validation_t));
246 memset(vresult, 0x0, sizeof(pgp_validation_t));
248 mem = pgp_decrypt_and_validate_buf(netpgp->io, vresult, ctext, csize,
249 netpgp->secring, netpgp->pubring,
250 _armoured(ctext, csize, ARMOR_HEAD),
252 NULL, -1, NULL /* pass fp,attempts,cb */);
254 return PEP_OUT_OF_MEMORY;
257 _psize = pgp_mem_len(mem);
259 if ((_ptext = calloc(1, _psize)) == NULL) {
260 result = PEP_OUT_OF_MEMORY;
263 memcpy(_ptext, pgp_mem_data(mem), _psize);
264 result = PEP_DECRYPTED;
266 result = PEP_DECRYPT_NO_KEY;
270 if (result == PEP_DECRYPTED) {
271 result = _validation_results(netpgp, vresult, &_keylist);
272 if (result != PEP_STATUS_OK) {
275 result = PEP_DECRYPTED_AND_VERIFIED;
278 if (result == PEP_DECRYPTED_AND_VERIFIED
279 || result == PEP_DECRYPTED) {
282 (*ptext)[*psize] = 0; // safeguard for naive users
283 if (result == PEP_DECRYPTED_AND_VERIFIED) {
287 /* _ptext and _keylist ownership transfer, don't free */
292 free_stringlist(_keylist);
298 pgp_memory_free(mem);
299 pgp_validate_result_free(vresult);
304 #define ARMOR_SIG_HEAD "^-----BEGIN PGP (SIGNATURE|SIGNED MESSAGE)-----\\s*$"
305 PEP_STATUS pgp_verify_text(
306 PEP_SESSION session, const char *text, size_t size,
307 const char *signature, size_t sig_size, stringlist_t **keylist
311 pgp_memory_t *signedmem;
313 pgp_validation_t *vresult;
316 stringlist_t *_keylist;
325 if(!session || !text || !size || !signature || !sig_size || !keylist)
326 return PEP_UNKNOWN_ERROR;
328 netpgp = &session->ctx;
332 vresult = malloc(sizeof(pgp_validation_t));
333 memset(vresult, 0x0, sizeof(pgp_validation_t));
335 signedmem = pgp_memory_new();
336 if (signedmem == NULL) {
337 return PEP_OUT_OF_MEMORY;
339 pgp_memory_add(signedmem, (const uint8_t*)text, size);
341 sig = pgp_memory_new();
343 pgp_memory_free(signedmem);
344 return PEP_OUT_OF_MEMORY;
346 pgp_memory_add(sig, (const uint8_t*)signature, sig_size);
348 pgp_validate_mem_detached(netpgp->io, vresult, sig,
350 _armoured(signature, sig_size, ARMOR_SIG_HEAD),
354 result = _validation_results(netpgp, vresult, &_keylist);
355 if (result != PEP_STATUS_OK) {
358 result = PEP_VERIFIED;
361 if (result == PEP_VERIFIED) {
362 /* TODO : check trust level */
363 result = PEP_VERIFIED_AND_TRUSTED;
366 if (result == PEP_VERIFIED || result == PEP_VERIFIED_AND_TRUSTED) {
369 /* _keylist ownership transfer, don't free */
374 free_stringlist(_keylist);
377 // free done by pgp_validate_mem_detached
378 // pgp_memory_free(sig);
379 // pgp_memory_free(signedmem);
380 pgp_validate_result_free(vresult);
385 PEP_STATUS pgp_encrypt_and_sign(
386 PEP_SESSION session, const stringlist_t *keylist, const char *ptext,
387 size_t psize, char **ctext, size_t *csize
391 const pgp_key_t *keypair;
392 pgp_seckey_t *seckey;
393 pgp_memory_t *signedmem;
397 pgp_keyring_t *rcpts;
400 const stringlist_t *_keylist;
409 if(!session || !ptext || !psize || !ctext || !csize || !keylist)
410 return PEP_UNKNOWN_ERROR;
412 netpgp = &session->ctx;
417 // Get signing details from netpgp
418 if ((userid = netpgp_getvar(netpgp, "userid")) == NULL ||
419 (keypair = pgp_getkeybyname(netpgp->io, netpgp->secring, userid)) == NULL ||
420 (seckey = pgp_decrypt_seckey(keypair, NULL /*passfp*/)) == NULL) {
421 return PEP_UNKNOWN_ERROR;
424 hashalg = netpgp_getvar(netpgp, "hash");
425 // netpgp (l)imitation - XXX why ?
426 if (seckey->pubkey.alg == PGP_PKA_DSA) {
431 signedmem = pgp_sign_buf(netpgp->io, ptext, psize, seckey,
432 time(NULL), /* birthtime */
438 pgp_forget(seckey, (unsigned)sizeof(*seckey));
441 return PEP_UNENCRYPTED;
444 // Encrypt signed data
445 if ((rcpts = calloc(1, sizeof(*rcpts))) == NULL) {
446 result = PEP_OUT_OF_MEMORY;
449 for (_keylist = keylist; _keylist != NULL; _keylist = _keylist->next) {
450 assert(_keylist->value);
451 // get key from netpgp's pubring
452 const pgp_key_t *key;
453 key = pgp_getkeybyname(netpgp->io,
458 result = PEP_KEY_NOT_FOUND;
461 #ifdef PEP_NETPGP_DEBUG
462 pgp_print_keydata(netpgp->io, netpgp->pubring, key,
463 "recipient pubkey ", &key->key.pubkey, 0);
464 #endif //PEP_NETPGP_DEBUG
466 // add key to recipients/signers
467 pgp_keyring_add(rcpts, key);
468 if(rcpts->keys == NULL){
469 result = PEP_OUT_OF_MEMORY;
474 cmem = pgp_encrypt_buf(netpgp->io, pgp_mem_data(signedmem),
475 pgp_mem_len(signedmem), rcpts, 1 /* armored */,
476 netpgp_getvar(netpgp, "cipher"),
477 1 /* takes raw OpenPGP message */);
480 result = PEP_OUT_OF_MEMORY;
484 char *_buffer = NULL;
485 size_t length = pgp_mem_len(cmem);
487 // Allocate transferable buffer
488 _buffer = malloc(length + 1);
490 if (_buffer == NULL) {
491 result = PEP_OUT_OF_MEMORY;
495 memcpy(_buffer, pgp_mem_data(cmem), length);
499 (*ctext)[*csize] = 0; // safeguard for naive users
500 result = PEP_STATUS_OK;
504 pgp_memory_free(cmem);
506 pgp_keyring_free(rcpts);
508 pgp_memory_free(signedmem);
513 /* return the hexdump as a string */
515 fpr_to_str (char **str, const uint8_t *fpr, size_t length)
520 /* 5 char per byte (hexes + space) tuple -1 space at the end + null */
521 *str = malloc((length / 2) * 5 - 1 + 1);
526 for (n = 0, i = 0 ; i < length - 1; i += 2) {
527 n += snprintf(&((*str)[n]), 6, "%02x%02x ", *fpr++, *fpr++);
529 snprintf(&((*str)[n]), 5, "%02x%02x", *fpr++, *fpr++);
535 str_to_fpr (const char *str, uint8_t *fpr, size_t *length)
541 while(*str && *length < PGP_FINGERPRINT_SIZE){
542 while (*str == ' ') str++;
543 for (j = 0; j < 2; j++) {
544 uint8_t *byte = &fpr[*length];
545 for (i = 0; i < 2; i++) {
548 if (*str >= 'a' && *str <= 'f')
549 *byte += 10 + *str - 'a';
550 else if (*str >= 'A' && *str <= 'F')
551 *byte += 10 + *str - 'A';
552 else if (*str >= '0' && *str <= '9')
564 static PEP_STATUS import_key_or_keypair(netpgp_t *netpgp, pgp_key_t *newkey){
569 if ((public = (newkey->type == PGP_PTAG_CT_PUBLIC_KEY))){
572 // Duplicate key as public only
573 if (!pgp_keydata_dup(&pubkey, newkey, 1 /* make_public */)){
574 return PEP_OUT_OF_MEMORY;
578 // Append generated key to netpgp's rings (key ownership transfered)
579 if (!public && !pgp_keyring_add(netpgp->secring, newkey)){
580 result = PEP_OUT_OF_MEMORY;
582 } else if (!pgp_keyring_add(netpgp->pubring, &pubkey)){
583 result = PEP_OUT_OF_MEMORY;
588 if (netpgp_save_pubring(netpgp) &&
589 (!public || netpgp_save_secring(netpgp)))
591 /* free nothing, everything transfered */
592 return PEP_STATUS_OK;
594 /* XXX in case only pubring save succeed
595 * pubring file is left as-is, but backup restore
596 * could be attempted if such corner case matters */
597 result = PEP_UNKNOWN_ERROR;
601 ((pgp_keyring_t *)netpgp->pubring)->keyc--;
603 ((pgp_keyring_t *)netpgp->secring)->keyc--;
605 pgp_key_free(&pubkey);
610 PEP_STATUS pgp_generate_keypair(
611 PEP_SESSION session, pEp_identity *identity
626 assert(identity->address);
627 assert(identity->fpr == NULL);
628 assert(identity->username);
630 if(!session || !identity ||
631 !identity->address || identity->fpr || !identity->username)
632 return PEP_UNKNOWN_ERROR;
634 netpgp = &session->ctx;
636 if(snprintf(newid, sizeof(newid),
637 "%s <%s>", identity->username, identity->address) >= sizeof(newid)){
638 return PEP_BUFFER_TOO_SMALL;
641 hashalg = netpgp_getvar(netpgp, "hash");
642 cipher = netpgp_getvar(netpgp, "cipher");
644 bzero(&newkey, sizeof(newkey));
645 bzero(&pubkey, sizeof(pubkey));
648 if (!pgp_rsa_generate_keypair(&newkey, 4096, 65537UL, hashalg, cipher,
649 (const uint8_t *) "", (const size_t) 0) ||
650 !pgp_add_selfsigned_userid(&newkey, (uint8_t *)newid)) {
651 result = PEP_CANNOT_CREATE_KEY;
655 // TODO "Expire-Date: 1y\n";
658 newkey.sigfingerprint.fingerprint,
659 newkey.sigfingerprint.length);
660 if (fprstr == NULL) {
661 result = PEP_OUT_OF_MEMORY;
665 result = import_key_or_keypair(netpgp, &newkey);
667 if (result == PEP_STATUS_OK) {
668 identity->fpr = fprstr;
669 /* free nothing, everything transfered */
670 return PEP_STATUS_OK;
676 pgp_key_free(&newkey);
681 PEP_STATUS pgp_delete_keypair(PEP_SESSION session, const char *fprstr)
684 uint8_t fpr[PGP_FINGERPRINT_SIZE];
693 if (!session || !fpr)
694 return PEP_UNKNOWN_ERROR;
696 netpgp = &session->ctx;
698 if (str_to_fpr(fprstr, fpr, &length)) {
699 if (!pgp_deletekeybyfpr(netpgp->io,
700 (pgp_keyring_t *)netpgp->secring,
701 (const uint8_t *)fpr, length)) {
702 return PEP_KEY_NOT_FOUND;
705 return PEP_OUT_OF_MEMORY;
708 /* pair was found in secring delete also corresponding pubkey
709 * in pubring if it exists */
711 pgp_deletekeybyfpr(netpgp->io,
712 (pgp_keyring_t *)netpgp->pubring,
713 (const uint8_t *)fpr, length);
716 // save rings (key ownership transfered)
717 if (netpgp_save_pubring(netpgp) &&
718 netpgp_save_secring(netpgp))
720 result = PEP_STATUS_OK;
722 result = PEP_UNKNOWN_ERROR;
728 #define ARMOR_KEY_HEAD "^-----BEGIN PGP (PUBLIC|PRIVATE) KEY BLOCK-----\\s*$"
729 PEP_STATUS pgp_import_keydata(PEP_SESSION session, const char *key_data, size_t size)
734 pgp_keyring_t tmpring;
741 if(!session || !key_data)
742 return PEP_UNKNOWN_ERROR;
744 netpgp = &session->ctx;
746 mem = pgp_memory_new();
748 return PEP_OUT_OF_MEMORY;
750 pgp_memory_add(mem, (const uint8_t*)key_data, size);
752 if (pgp_keyring_read_from_mem(netpgp->io, &tmpring,
753 _armoured(key_data, size, ARMOR_KEY_HEAD),
755 result = PEP_ILLEGAL_VALUE;
756 }else if (tmpring.keyc == 0){
757 result = PEP_UNKNOWN_ERROR;
758 }else if (tmpring.keyc > 1){
759 /* too many keys given */
760 result = PEP_ILLEGAL_VALUE;
762 result = import_key_or_keypair(netpgp, &tmpring.keys[0]);
765 pgp_memory_free(mem);
767 if (result != PEP_STATUS_OK){
768 pgp_keyring_purge(&tmpring);
774 PEP_STATUS pgp_export_keydata(
775 PEP_SESSION session, const char *fprstr, char **key_data, size_t *size
780 pgp_output_t *output;
782 uint8_t fpr[PGP_FINGERPRINT_SIZE];
794 netpgp = &session->ctx;
796 if (!session || !fpr || !key_data || !size)
797 return PEP_UNKNOWN_ERROR;
799 if (str_to_fpr(fprstr, fpr, &fprlen)) {
801 if ((key = (pgp_key_t *)pgp_getkeybyfpr(netpgp->io, netpgp->pubring,
803 &from, NULL)) == NULL) {
804 return PEP_KEY_NOT_FOUND;
807 return PEP_OUT_OF_MEMORY;
810 pgp_setup_memory_write(&output, &mem, 128);
812 if (mem == NULL || output == NULL) {
813 return PEP_OUT_OF_MEMORY;
816 if (!pgp_write_xfer_pubkey(output, key, 1)) {
817 result = PEP_UNKNOWN_ERROR;
822 buflen = pgp_mem_len(mem);
824 // Allocate transferable buffer
825 buffer = malloc(buflen + 1);
827 if (buffer == NULL) {
828 result = PEP_OUT_OF_MEMORY;
832 memcpy(buffer, pgp_mem_data(mem), buflen);
836 (*key_data)[*size] = 0; // safeguard for naive users
837 result = PEP_STATUS_OK;
840 pgp_teardown_memory_write(output, mem);
846 // "hkp://keys.gnupg.net"
847 PEP_STATUS pgp_recv_key(PEP_SESSION session, const char *pattern)
852 /* TODO ask for key */
853 return PEP_UNKNOWN_ERROR;
854 return PEP_GET_KEY_FAILED;
862 return PEP_STATUS_OK;
865 PEP_STATUS pgp_find_keys(
866 PEP_SESSION session, const char *pattern, stringlist_t **keylist
869 stringlist_t *_keylist;
879 return PEP_UNKNOWN_ERROR;
880 return PEP_GET_KEY_FAILED;
882 _keylist = new_stringlist(NULL);
883 stringlist_t *_k = _keylist;
886 fpr = "TODO key->subkeys->fpr";
888 _k = stringlist_add(_k, fpr);
891 free_stringlist(_keylist);
892 return PEP_OUT_OF_MEMORY;
897 return PEP_STATUS_OK;
900 PEP_STATUS pgp_send_key(PEP_SESSION session, const char *pattern)
907 return PEP_CANNOT_SEND_KEY;
908 return PEP_STATUS_OK;
912 PEP_STATUS pgp_get_key_rating(
915 PEP_comm_type *comm_type
918 PEP_STATUS status = PEP_STATUS_OK;
924 *comm_type = PEP_ct_unknown;
926 /* TODO get key from fpr */
927 return PEP_UNKNOWN_ERROR;
928 return PEP_GET_KEY_FAILED;
930 switch (/*TODO key->protocol*/ 4) {
931 case /* TODO OpenPGP */0:
932 case /* TODO DEFAULT */1:
933 *comm_type = PEP_ct_OpenPGP_unconfirmed;
935 case /* TODO CMS */2:
936 *comm_type = PEP_ct_CMS_unconfirmed;
939 *comm_type = PEP_ct_unknown;
940 return PEP_STATUS_OK;
943 for (; 1 == 0; /* Each subkeys */ ) {
944 if (/* TODO length */0 < 1024)
945 *comm_type = PEP_ct_key_too_short;
948 ( /* TODO pubkey_algo == RSA */ 0)
949 || (/* TODO pubkey_algo == RSA_E*/ 0)
950 || (/* TODO pubkey_algo == RSA_S*/ 0)
952 && /* sk->length */0 == 1024
954 *comm_type = PEP_ct_OpenPGP_weak_unconfirmed;
956 if (/* TODO invalid */ 1) {
957 *comm_type = PEP_ct_key_b0rken;
960 if (/* TODO expired */ 1) {
961 *comm_type = PEP_ct_key_expired;
964 if (/* TODO revoked*/ 1) {
965 *comm_type = PEP_ct_key_revoked;
969 *comm_type = PEP_ct_unknown;
970 return PEP_OUT_OF_MEMORY;
971 return PEP_UNKNOWN_ERROR;
977 PEP_STATUS pgp_renew_key(
983 PEP_STATUS status = PEP_STATUS_OK;
989 snprintf(date_text, 12, "%.4d-%.2d-%.2d\n", ts->tm_year + 1900,
990 ts->tm_mon + 1, ts->tm_mday);
993 return PEP_UNKNOWN_ERROR;
994 return PEP_STATUS_OK;
997 PEP_STATUS pgp_revoke_key(
1003 PEP_STATUS status = PEP_STATUS_OK;
1008 return PEP_UNKNOWN_ERROR;
1010 return PEP_STATUS_OK;
1013 PEP_STATUS pgp_key_expired(
1014 PEP_SESSION session,
1019 PEP_STATUS status = PEP_STATUS_OK;
1027 if (status != PEP_STATUS_OK)
1030 return PEP_STATUS_OK;