...
1 #include "pEp_internal.h"
8 #define _GPGERR(X) ((X) & 0xffffL)
11 static struct gpg_s gpg;
13 static bool ensure_config_values(stringlist_t *keys, stringlist_t *values)
15 static char buf[MAX_LINELENGTH];
21 unsigned int found = 0;
23 f = Fopen(gpg_conf(), "r");
25 if (f == NULL && errno == ENOMEM)
29 int length = stringlist_length(keys);
30 unsigned int n = (1 << length) - 1;
32 assert(length <= sizeof(unsigned int) * CHAR_BIT);
33 assert(length == stringlist_length(values));
38 s = Fgets(buf, MAX_LINELENGTH, f);
46 char * t = strtok_r(s, " ", &rest);
47 for (i = 1, _k = keys, _v = values; _k != NULL;
48 _k = _k->next, _v = _v->next, i <<= 1) {
49 if (t && strncmp(t, _k->value, strlen(_k->value)) == 0)
60 f = Freopen(gpg_conf(), "a", f);
63 f = Fopen(gpg_conf(), "w");
70 for (i = 1, _k = keys, _v = values; _k != NULL; _k = _k->next,
71 _v = _v->next, i <<= 1) {
72 if ((found & i) == 0) {
73 r = Fprintf(f, "%s %s\n", _k->value, _v->value);
84 PEP_STATUS pgp_init(PEP_SESSION session, bool in_first)
86 PEP_STATUS status = PEP_STATUS_OK;
87 gpgme_error_t gpgme_error;
91 stringlist_t *conf_keys = new_stringlist("keyserver");
92 stringlist_t *conf_values = new_stringlist("hkp://keys.gnupg.net");
94 stringlist_add(conf_keys, "cert-digest-algo");
95 stringlist_add(conf_values, "SHA256");
97 stringlist_add(conf_keys, "no-emit-version");
98 stringlist_add(conf_values, "");
100 stringlist_add(conf_keys, "no-comments");
101 stringlist_add(conf_values, "");
103 stringlist_add(conf_keys, "personal-cipher-preferences");
104 stringlist_add(conf_values, "AES AES256 AES192 CAST5");
106 stringlist_add(conf_keys, "personal-digest-preferences");
107 stringlist_add(conf_values, "SHA512 SHA384 SHA256 SHA224");
109 bResult = ensure_config_values(conf_keys, conf_values);
111 free_stringlist(conf_keys);
112 free_stringlist(conf_values);
116 status = PEP_INIT_NO_GPG_HOME;
121 gpgme = dlopen(LIBGPGME, RTLD_LAZY);
123 status = PEP_INIT_CANNOT_LOAD_GPGME;
127 memset(&gpg, 0, sizeof(struct gpg_s));
130 = (gpgme_set_locale_t) (intptr_t) dlsym(gpgme,
132 assert(gpg.gpgme_set_locale);
135 = (gpgme_check_version_t) (intptr_t) dlsym(gpgme,
136 "gpgme_check_version");
137 assert(gpg.gpgme_check);
140 = (gpgme_new_t) (intptr_t) dlsym(gpgme, "gpgme_new");
141 assert(gpg.gpgme_new);
144 = (gpgme_release_t) (intptr_t) dlsym(gpgme, "gpgme_release");
145 assert(gpg.gpgme_release);
147 gpg.gpgme_set_protocol
148 = (gpgme_set_protocol_t) (intptr_t) dlsym(gpgme,
149 "gpgme_set_protocol");
150 assert(gpg.gpgme_set_protocol);
153 = (gpgme_set_armor_t) (intptr_t) dlsym(gpgme,
155 assert(gpg.gpgme_set_armor);
158 = (gpgme_data_new_t) (intptr_t) dlsym(gpgme,
160 assert(gpg.gpgme_data_new);
162 gpg.gpgme_data_new_from_mem
163 = (gpgme_data_new_from_mem_t) (intptr_t) dlsym(gpgme,
164 "gpgme_data_new_from_mem");
165 assert(gpg.gpgme_data_new_from_mem);
167 gpg.gpgme_data_release
168 = (gpgme_data_release_t) (intptr_t) dlsym(gpgme,
169 "gpgme_data_release");
170 assert(gpg.gpgme_data_release);
172 gpg.gpgme_data_identify
173 = (gpgme_data_identify_t) (intptr_t) dlsym(gpgme,
174 "gpgme_data_identify");
175 assert(gpg.gpgme_data_identify);
178 = (gpgme_data_seek_t) (intptr_t) dlsym(gpgme,
180 assert(gpg.gpgme_data_seek);
183 = (gpgme_data_read_t) (intptr_t) dlsym(gpgme,
185 assert(gpg.gpgme_data_read);
188 = (gpgme_op_decrypt_t) (intptr_t) dlsym(gpgme,
190 assert(gpg.gpgme_op_decrypt);
193 = (gpgme_op_verify_t) (intptr_t) dlsym(gpgme,
195 assert(gpg.gpgme_op_verify);
197 gpg.gpgme_op_decrypt_verify
198 = (gpgme_op_decrypt_verify_t) (intptr_t) dlsym(gpgme,
199 "gpgme_op_decrypt_verify");
200 assert(gpg.gpgme_op_decrypt_verify);
202 gpg.gpgme_op_decrypt_result
203 = (gpgme_op_decrypt_result_t) (intptr_t) dlsym(gpgme,
204 "gpgme_op_decrypt_result");
205 assert(gpg.gpgme_op_decrypt_result);
207 gpg.gpgme_op_encrypt_sign
208 = (gpgme_op_encrypt_sign_t) (intptr_t) dlsym(gpgme,
209 "gpgme_op_encrypt_sign");
210 assert(gpg.gpgme_op_encrypt_sign);
212 gpg.gpgme_op_verify_result
213 = (gpgme_op_verify_result_t) (intptr_t) dlsym(gpgme,
214 "gpgme_op_verify_result");
215 assert(gpg.gpgme_op_verify_result);
217 gpg.gpgme_signers_clear
218 = (gpgme_signers_clear_t) (intptr_t) dlsym(gpgme,
219 "gpgme_signers_clear");
220 assert(gpg.gpgme_signers_clear);
222 gpg.gpgme_signers_add
223 = (gpgme_signers_add_t) (intptr_t) dlsym(gpgme,
224 "gpgme_signers_add");
225 assert(gpg.gpgme_signers_add);
228 = (gpgme_get_key_t) (intptr_t) dlsym(gpgme, "gpgme_get_key");
229 assert(gpg.gpgme_get_key);
232 = (gpgme_op_genkey_t) (intptr_t) dlsym(gpgme,
234 assert(gpg.gpgme_op_genkey);
236 gpg.gpgme_op_genkey_result
237 = (gpgme_op_genkey_result_t) (intptr_t) dlsym(gpgme,
238 "gpgme_op_genkey_result");
239 assert(gpg.gpgme_op_genkey_result);
241 gpg.gpgme_op_delete = (gpgme_op_delete_t) (intptr_t)
242 dlsym(gpgme, "gpgme_op_delete");
243 assert(gpg.gpgme_op_delete);
245 gpg.gpgme_op_import = (gpgme_op_import_t) (intptr_t)
246 dlsym(gpgme, "gpgme_op_import");
247 assert(gpg.gpgme_op_import);
249 gpg.gpgme_op_export = (gpgme_op_export_t) (intptr_t)
250 dlsym(gpgme, "gpgme_op_export");
251 assert(gpg.gpgme_op_export);
253 gpg.gpgme_set_keylist_mode = (gpgme_set_keylist_mode_t) (intptr_t)
254 dlsym(gpgme, "gpgme_set_keylist_mode");
255 assert(gpg.gpgme_set_keylist_mode);
257 gpg.gpgme_get_keylist_mode = (gpgme_get_keylist_mode_t) (intptr_t)
258 dlsym(gpgme, "gpgme_get_keylist_mode");
259 assert(gpg.gpgme_get_keylist_mode);
261 gpg.gpgme_op_keylist_start = (gpgme_op_keylist_start_t) (intptr_t)
262 dlsym(gpgme, "gpgme_op_keylist_start");
263 assert(gpg.gpgme_op_keylist_start);
265 gpg.gpgme_op_keylist_next = (gpgme_op_keylist_next_t) (intptr_t)
266 dlsym(gpgme, "gpgme_op_keylist_next");
267 assert(gpg.gpgme_op_keylist_next);
269 gpg.gpgme_op_keylist_end = (gpgme_op_keylist_end_t) (intptr_t)
270 dlsym(gpgme, "gpgme_op_keylist_end");
271 assert(gpg.gpgme_op_keylist_end);
273 gpg.gpgme_op_import_keys = (gpgme_op_import_keys_t) (intptr_t)
274 dlsym(gpgme, "gpgme_op_import_keys");
275 assert(gpg.gpgme_op_import_keys);
277 gpg.gpgme_key_ref = (gpgme_key_ref_t) (intptr_t)
278 dlsym(gpgme, "gpgme_key_ref");
279 assert(gpg.gpgme_key_ref);
281 gpg.gpgme_key_unref = (gpgme_key_unref_t) (intptr_t)
282 dlsym(gpgme, "gpgme_key_unref");
283 assert(gpg.gpgme_key_unref);
285 gpg.version = gpg.gpgme_check(NULL);
287 if (strcmp(setlocale(LC_ALL, NULL), "C") == 0)
288 setlocale(LC_ALL, "");
290 gpg.gpgme_set_locale(NULL, LC_CTYPE, setlocale(LC_CTYPE, NULL));
291 #ifdef LC_MESSAGES // Windoze
292 gpg.gpgme_set_locale (NULL, LC_MESSAGES, setlocale(LC_MESSAGES, NULL));
296 gpgme_error = gpg.gpgme_new(&session->ctx);
297 gpgme_error = _GPGERR(gpgme_error);
298 if (gpgme_error != GPG_ERR_NO_ERROR) {
299 status = PEP_INIT_GPGME_INIT_FAILED;
302 assert(session->ctx);
304 gpgme_error = gpg.gpgme_set_protocol(session->ctx, GPGME_PROTOCOL_OpenPGP);
305 gpgme_error = _GPGERR(gpgme_error);
306 assert(gpgme_error == GPG_ERR_NO_ERROR);
308 gpg.gpgme_set_armor(session->ctx, 1);
310 return PEP_STATUS_OK;
313 pgp_release(session, in_first);
317 void pgp_release(PEP_SESSION session, bool out_last)
320 gpg.gpgme_release(session->ctx);
329 PEP_STATUS pgp_decrypt_and_verify(
330 PEP_SESSION session, const char *ctext, size_t csize,
331 char **ptext, size_t *psize, stringlist_t **keylist
335 gpgme_error_t gpgme_error;
336 gpgme_data_t cipher, plain;
337 gpgme_data_type_t dt;
339 stringlist_t *_keylist = NULL;
353 gpgme_error = gpg.gpgme_data_new_from_mem(&cipher, ctext, csize, 0);
354 gpgme_error = _GPGERR(gpgme_error);
355 assert(gpgme_error == GPG_ERR_NO_ERROR);
356 if (gpgme_error != GPG_ERR_NO_ERROR) {
357 if (gpgme_error == GPG_ERR_ENOMEM)
358 return PEP_OUT_OF_MEMORY;
360 return PEP_UNKNOWN_ERROR;
363 gpgme_error = gpg.gpgme_data_new(&plain);
364 gpgme_error = _GPGERR(gpgme_error);
365 assert(gpgme_error == GPG_ERR_NO_ERROR);
366 if (gpgme_error != GPG_ERR_NO_ERROR) {
367 gpg.gpgme_data_release(cipher);
368 if (gpgme_error == GPG_ERR_ENOMEM)
369 return PEP_OUT_OF_MEMORY;
371 return PEP_UNKNOWN_ERROR;
374 dt = gpg.gpgme_data_identify(cipher);
376 case GPGME_DATA_TYPE_PGP_SIGNED:
377 case GPGME_DATA_TYPE_PGP_OTHER:
378 gpgme_error = gpg.gpgme_op_decrypt_verify(session->ctx, cipher,
380 gpgme_error = _GPGERR(gpgme_error);
381 assert(gpgme_error != GPG_ERR_INV_VALUE);
382 assert(gpgme_error != GPG_ERR_NO_DATA);
384 switch (gpgme_error) {
385 case GPG_ERR_NO_ERROR:
387 gpgme_verify_result_t gpgme_verify_result;
388 char *_buffer = NULL;
390 size_t length = gpg.gpgme_data_seek(plain, 0, SEEK_END);
391 gpgme_signature_t gpgme_signature;
393 assert(length != -1);
394 gpg.gpgme_data_seek(plain, 0, SEEK_SET);
396 // TODO: make things less memory consuming
397 // the following algorithm allocates memory for the complete
400 _buffer = malloc(length + 1);
402 if (_buffer == NULL) {
403 gpg.gpgme_data_release(plain);
404 gpg.gpgme_data_release(cipher);
405 return PEP_OUT_OF_MEMORY;
408 reading = gpg.gpgme_data_read(plain, _buffer, length);
409 assert(length == reading);
411 gpgme_verify_result =
412 gpg.gpgme_op_verify_result(session->ctx);
413 assert(gpgme_verify_result);
414 gpgme_signature = gpgme_verify_result->signatures;
416 if (gpgme_signature) {
418 _keylist = new_stringlist(NULL);
420 if (_keylist == NULL) {
421 gpg.gpgme_data_release(plain);
422 gpg.gpgme_data_release(cipher);
424 return PEP_OUT_OF_MEMORY;
428 result = PEP_DECRYPTED_AND_VERIFIED;
430 switch (_GPGERR(gpgme_signature->status)) {
431 case GPG_ERR_NO_ERROR:
432 k = stringlist_add(k, gpgme_signature->fpr);
434 case GPG_ERR_CERT_REVOKED:
435 case GPG_ERR_BAD_SIGNATURE:
436 result = PEP_DECRYPT_SIGNATURE_DOES_NOT_MATCH;
438 case GPG_ERR_SIG_EXPIRED:
439 case GPG_ERR_KEY_EXPIRED:
440 case GPG_ERR_NO_PUBKEY:
441 k = stringlist_add(k, gpgme_signature->fpr);
442 if (result == PEP_DECRYPTED_AND_VERIFIED)
443 result = PEP_DECRYPTED;
445 case GPG_ERR_GENERAL:
448 if (result == PEP_DECRYPTED_AND_VERIFIED)
449 result = PEP_DECRYPTED;
452 } while ((gpgme_signature = gpgme_signature->next));
455 result = PEP_DECRYPTED;
458 if (result == PEP_DECRYPTED_AND_VERIFIED
459 || result == PEP_DECRYPTED) {
462 (*ptext)[*psize] = 0; // safeguard for naive users
466 free_stringlist(_keylist);
471 case GPG_ERR_DECRYPT_FAILED:
472 result = PEP_DECRYPT_WRONG_FORMAT;
474 case GPG_ERR_BAD_PASSPHRASE:
478 gpgme_decrypt_result_t gpgme_decrypt_result = gpg.gpgme_op_decrypt_result(session->ctx);
479 result = PEP_DECRYPT_NO_KEY;
481 if (gpgme_decrypt_result != NULL) {
482 if (gpgme_decrypt_result->unsupported_algorithm)
483 *keylist = new_stringlist(gpgme_decrypt_result->unsupported_algorithm);
485 *keylist = new_stringlist("");
487 if (*keylist == NULL) {
488 result = PEP_OUT_OF_MEMORY;
491 stringlist_t *_keylist = *keylist;
492 for (gpgme_recipient_t r = gpgme_decrypt_result->recipients; r != NULL; r = r->next) {
493 _keylist = stringlist_add(_keylist, r->keyid);
495 if (_keylist == NULL) {
496 free_stringlist(*keylist);
498 result = PEP_OUT_OF_MEMORY;
502 if (result == PEP_OUT_OF_MEMORY)
510 result = PEP_DECRYPT_WRONG_FORMAT;
513 gpg.gpgme_data_release(plain);
514 gpg.gpgme_data_release(cipher);
518 PEP_STATUS pgp_verify_text(
519 PEP_SESSION session, const char *text, size_t size,
520 const char *signature, size_t sig_size, stringlist_t **keylist
524 gpgme_error_t gpgme_error;
525 gpgme_data_t d_text, d_sig;
526 stringlist_t *_keylist;
537 gpgme_error = gpg.gpgme_data_new_from_mem(&d_text, text, size, 0);
538 gpgme_error = _GPGERR(gpgme_error);
539 assert(gpgme_error == GPG_ERR_NO_ERROR);
540 if (gpgme_error != GPG_ERR_NO_ERROR) {
541 if (gpgme_error == GPG_ERR_ENOMEM)
542 return PEP_OUT_OF_MEMORY;
544 return PEP_UNKNOWN_ERROR;
547 gpgme_error = gpg.gpgme_data_new_from_mem(&d_sig, signature, sig_size, 0);
548 gpgme_error = _GPGERR(gpgme_error);
549 assert(gpgme_error == GPG_ERR_NO_ERROR);
550 if (gpgme_error != GPG_ERR_NO_ERROR) {
551 gpg.gpgme_data_release(d_text);
552 if (gpgme_error == GPG_ERR_ENOMEM)
553 return PEP_OUT_OF_MEMORY;
555 return PEP_UNKNOWN_ERROR;
558 gpgme_error = gpg.gpgme_op_verify(session->ctx, d_sig, d_text, NULL);
559 gpgme_error = _GPGERR(gpgme_error);
560 assert(gpgme_error != GPG_ERR_INV_VALUE);
562 switch (gpgme_error) {
563 case GPG_ERR_NO_ERROR:
565 gpgme_verify_result_t gpgme_verify_result;
566 gpgme_signature_t gpgme_signature;
568 gpgme_verify_result =
569 gpg.gpgme_op_verify_result(session->ctx);
570 assert(gpgme_verify_result);
571 gpgme_signature = gpgme_verify_result->signatures;
573 if (gpgme_signature) {
575 _keylist = new_stringlist(NULL);
577 if (_keylist == NULL) {
578 gpg.gpgme_data_release(d_text);
579 gpg.gpgme_data_release(d_sig);
580 return PEP_OUT_OF_MEMORY;
584 result = PEP_VERIFIED;
586 k = stringlist_add(k, gpgme_signature->fpr);
588 free_stringlist(_keylist);
589 gpg.gpgme_data_release(d_text);
590 gpg.gpgme_data_release(d_sig);
591 return PEP_OUT_OF_MEMORY;
593 if (gpgme_signature->summary & GPGME_SIGSUM_RED) {
594 if (gpgme_signature->summary & GPGME_SIGSUM_KEY_EXPIRED
595 || gpgme_signature->summary & GPGME_SIGSUM_SIG_EXPIRED) {
596 if (result == PEP_VERIFIED
597 || result == PEP_VERIFIED_AND_TRUSTED)
598 result = PEP_UNENCRYPTED;
601 result = PEP_DECRYPT_SIGNATURE_DOES_NOT_MATCH;
606 if (gpgme_signature->summary & GPGME_SIGSUM_VALID) {
607 if (result == PEP_VERIFIED)
608 result = PEP_VERIFIED_AND_TRUSTED;
610 if (gpgme_signature->summary & GPGME_SIGSUM_GREEN) {
613 else if (gpgme_signature->summary & GPGME_SIGSUM_KEY_MISSING) {
614 result = PEP_VERIFY_NO_KEY;
616 else if (gpgme_signature->summary & GPGME_SIGSUM_SYS_ERROR) {
617 if (result == PEP_VERIFIED
618 || result == PEP_VERIFIED_AND_TRUSTED)
619 result = PEP_UNENCRYPTED;
625 } while ((gpgme_signature = gpgme_signature->next));
629 result = PEP_UNENCRYPTED;
634 case GPG_ERR_NO_DATA:
635 result = PEP_DECRYPT_WRONG_FORMAT;
637 case GPG_ERR_INV_VALUE:
639 result = PEP_UNKNOWN_ERROR;
643 gpg.gpgme_data_release(d_text);
644 gpg.gpgme_data_release(d_sig);
649 PEP_STATUS pgp_encrypt_and_sign(
650 PEP_SESSION session, const stringlist_t *keylist, const char *ptext,
651 size_t psize, char **ctext, size_t *csize
655 gpgme_error_t gpgme_error;
656 gpgme_data_t plain, cipher;
658 gpgme_encrypt_flags_t flags;
659 const stringlist_t *_keylist;
672 gpgme_error = gpg.gpgme_data_new_from_mem(&plain, ptext, psize, 0);
673 gpgme_error = _GPGERR(gpgme_error);
674 assert(gpgme_error == GPG_ERR_NO_ERROR);
675 if (gpgme_error != GPG_ERR_NO_ERROR) {
676 if (gpgme_error == GPG_ERR_ENOMEM)
677 return PEP_OUT_OF_MEMORY;
679 return PEP_UNKNOWN_ERROR;
682 gpgme_error = gpg.gpgme_data_new(&cipher);
683 gpgme_error = _GPGERR(gpgme_error);
684 assert(gpgme_error == GPG_ERR_NO_ERROR);
685 if (gpgme_error != GPG_ERR_NO_ERROR) {
686 gpg.gpgme_data_release(plain);
687 if (gpgme_error == GPG_ERR_ENOMEM)
688 return PEP_OUT_OF_MEMORY;
690 return PEP_UNKNOWN_ERROR;
693 rcpt = calloc(stringlist_length(keylist) + 1, sizeof(gpgme_key_t));
696 gpg.gpgme_data_release(plain);
697 gpg.gpgme_data_release(cipher);
698 return PEP_OUT_OF_MEMORY;
701 gpg.gpgme_signers_clear(session->ctx);
703 for (_keylist = keylist, i = 0; _keylist != NULL; _keylist = _keylist->next, i++) {
704 assert(_keylist->value);
705 gpgme_error = gpg.gpgme_get_key(session->ctx, _keylist->value,
707 gpgme_error = _GPGERR(gpgme_error);
708 assert(gpgme_error != GPG_ERR_ENOMEM);
710 switch (gpgme_error) {
712 for (j = 0; j<i; j++)
713 gpg.gpgme_key_unref(rcpt[j]);
715 gpg.gpgme_data_release(plain);
716 gpg.gpgme_data_release(cipher);
717 return PEP_OUT_OF_MEMORY;
718 case GPG_ERR_NO_ERROR:
720 gpgme_error_t _gpgme_error = gpg.gpgme_signers_add(session->ctx, rcpt[0]);
721 _gpgme_error = _GPGERR(_gpgme_error);
722 assert(_gpgme_error == GPG_ERR_NO_ERROR);
726 for (j = 0; j<i; j++)
727 gpg.gpgme_key_unref(rcpt[j]);
729 gpg.gpgme_data_release(plain);
730 gpg.gpgme_data_release(cipher);
731 return PEP_KEY_NOT_FOUND;
732 case GPG_ERR_AMBIGUOUS_NAME:
733 for (j = 0; j<i; j++)
734 gpg.gpgme_key_unref(rcpt[j]);
736 gpg.gpgme_data_release(plain);
737 gpg.gpgme_data_release(cipher);
738 return PEP_KEY_HAS_AMBIG_NAME;
739 default: // GPG_ERR_INV_VALUE if CTX or R_KEY is not a valid pointer or
740 // FPR is not a fingerprint or key ID
741 for (j = 0; j<i; j++)
742 gpg.gpgme_key_unref(rcpt[j]);
744 gpg.gpgme_data_release(plain);
745 gpg.gpgme_data_release(cipher);
746 return PEP_GET_KEY_FAILED;
750 // TODO: remove that and replace with proper key management
751 flags = GPGME_ENCRYPT_ALWAYS_TRUST;
753 gpgme_error = gpg.gpgme_op_encrypt_sign(session->ctx, rcpt, flags,
755 gpgme_error = _GPGERR(gpgme_error);
756 switch (gpgme_error) {
757 case GPG_ERR_NO_ERROR:
759 char *_buffer = NULL;
761 size_t length = gpg.gpgme_data_seek(cipher, 0, SEEK_END);
762 assert(length != -1);
763 gpg.gpgme_data_seek(cipher, 0, SEEK_SET);
765 // TODO: make things less memory consuming
766 // the following algorithm allocates a buffer for the complete text
768 _buffer = malloc(length + 1);
770 if (_buffer == NULL) {
771 for (j = 0; j<stringlist_length(keylist); j++)
772 gpg.gpgme_key_unref(rcpt[j]);
774 gpg.gpgme_data_release(plain);
775 gpg.gpgme_data_release(cipher);
776 return PEP_OUT_OF_MEMORY;
779 reading = gpg.gpgme_data_read(cipher, _buffer, length);
780 assert(length == reading);
784 (*ctext)[*csize] = 0; // safeguard for naive users
785 result = PEP_STATUS_OK;
789 result = PEP_UNKNOWN_ERROR;
792 for (j = 0; j<stringlist_length(keylist); j++)
793 gpg.gpgme_key_unref(rcpt[j]);
795 gpg.gpgme_data_release(plain);
796 gpg.gpgme_data_release(cipher);
800 PEP_STATUS pgp_generate_keypair(
801 PEP_SESSION session, pEp_identity *identity
804 gpgme_error_t gpgme_error;
806 const char *template =
807 "<GnupgKeyParms format=\"internal\">\n"
812 /* "Passphrase: %s\n" */
814 "</GnupgKeyParms>\n";
816 gpgme_genkey_result_t gpgme_genkey_result;
820 assert(identity->address);
821 assert(identity->fpr == NULL);
822 assert(identity->username);
824 parms = calloc(1, PARMS_MAX);
827 return PEP_OUT_OF_MEMORY;
829 result = snprintf(parms, PARMS_MAX, template, identity->username,
830 identity->address); // , session->passphrase);
831 assert(result < PARMS_MAX);
832 if (result >= PARMS_MAX) {
834 return PEP_BUFFER_TOO_SMALL;
837 gpgme_error = gpg.gpgme_op_genkey(session->ctx, parms, NULL, NULL);
838 gpgme_error = _GPGERR(gpgme_error);
841 switch (gpgme_error) {
842 case GPG_ERR_NO_ERROR:
844 case GPG_ERR_INV_VALUE:
845 return PEP_ILLEGAL_VALUE;
846 case GPG_ERR_GENERAL:
847 return PEP_CANNOT_CREATE_KEY;
850 return PEP_UNKNOWN_ERROR;
853 gpgme_genkey_result = gpg.gpgme_op_genkey_result(session->ctx);
854 assert(gpgme_genkey_result);
855 assert(gpgme_genkey_result->fpr);
857 identity->fpr = strdup(gpgme_genkey_result->fpr);
859 return PEP_STATUS_OK;
862 PEP_STATUS pgp_delete_keypair(PEP_SESSION session, const char *fpr)
864 gpgme_error_t gpgme_error;
870 gpgme_error = gpg.gpgme_get_key(session->ctx, fpr, &key, 0);
871 gpgme_error = _GPGERR(gpgme_error);
872 assert(gpgme_error != GPG_ERR_ENOMEM);
873 switch (gpgme_error) {
874 case GPG_ERR_NO_ERROR:
877 return PEP_KEY_NOT_FOUND;
878 case GPG_ERR_INV_VALUE:
879 return PEP_ILLEGAL_VALUE;
880 case GPG_ERR_AMBIGUOUS_NAME:
881 return PEP_KEY_HAS_AMBIG_NAME;
883 return PEP_OUT_OF_MEMORY;
886 return PEP_UNKNOWN_ERROR;
889 gpgme_error = gpg.gpgme_op_delete(session->ctx, key, 1);
890 gpgme_error = _GPGERR(gpgme_error);
891 gpg.gpgme_key_unref(key);
892 switch (gpgme_error) {
893 case GPG_ERR_NO_ERROR:
895 case GPG_ERR_INV_VALUE:
897 return PEP_UNKNOWN_ERROR;
898 case GPG_ERR_NO_PUBKEY:
900 return PEP_KEY_NOT_FOUND;
901 case GPG_ERR_AMBIGUOUS_NAME:
903 return PEP_KEY_HAS_AMBIG_NAME;
906 return PEP_UNKNOWN_ERROR;
909 return PEP_STATUS_OK;
912 PEP_STATUS pgp_import_keydata(PEP_SESSION session, const char *key_data, size_t size)
914 gpgme_error_t gpgme_error;
920 gpgme_error = gpg.gpgme_data_new_from_mem(&dh, key_data, size, 0);
921 gpgme_error = _GPGERR(gpgme_error);
922 assert(gpgme_error != GPG_ERR_ENOMEM);
923 switch (gpgme_error) {
924 case GPG_ERR_NO_ERROR:
927 return PEP_OUT_OF_MEMORY;
928 case GPG_ERR_INV_VALUE:
930 return PEP_UNKNOWN_ERROR;
933 return PEP_UNKNOWN_ERROR;
936 gpgme_error = gpg.gpgme_op_import(session->ctx, dh);
937 gpgme_error = _GPGERR(gpgme_error);
938 switch (gpgme_error) {
939 case GPG_ERR_NO_ERROR:
941 case GPG_ERR_INV_VALUE:
943 gpg.gpgme_data_release(dh);
944 return PEP_UNKNOWN_ERROR;
945 case GPG_ERR_NO_DATA:
946 gpg.gpgme_data_release(dh);
947 return PEP_ILLEGAL_VALUE;
950 gpg.gpgme_data_release(dh);
951 return PEP_UNKNOWN_ERROR;
954 gpg.gpgme_data_release(dh);
955 return PEP_STATUS_OK;
958 PEP_STATUS pgp_export_keydata(
959 PEP_SESSION session, const char *fpr, char **key_data, size_t *size
962 gpgme_error_t gpgme_error;
973 gpgme_error = gpg.gpgme_data_new(&dh);
974 gpgme_error = _GPGERR(gpgme_error);
975 assert(gpgme_error != GPG_ERR_ENOMEM);
976 switch (gpgme_error) {
977 case GPG_ERR_NO_ERROR:
980 return PEP_OUT_OF_MEMORY;
981 case GPG_ERR_INV_VALUE:
983 return PEP_UNKNOWN_ERROR;
986 return PEP_UNKNOWN_ERROR;
989 gpgme_error = gpg.gpgme_op_export(session->ctx, fpr,
990 GPGME_EXPORT_MODE_MINIMAL, dh);
991 gpgme_error = _GPGERR(gpgme_error);
992 switch (gpgme_error) {
993 case GPG_ERR_NO_ERROR:
996 gpg.gpgme_data_release(dh);
997 return PEP_KEY_NOT_FOUND;
998 case GPG_ERR_INV_VALUE:
1000 gpg.gpgme_data_release(dh);
1001 return PEP_UNKNOWN_ERROR;
1004 gpg.gpgme_data_release(dh);
1005 return PEP_UNKNOWN_ERROR;
1008 _size = gpg.gpgme_data_seek(dh, 0, SEEK_END);
1009 assert(_size != -1);
1010 gpg.gpgme_data_seek(dh, 0, SEEK_SET);
1012 buffer = malloc(_size + 1);
1014 if (buffer == NULL) {
1015 gpg.gpgme_data_release(dh);
1016 return PEP_OUT_OF_MEMORY;
1019 reading = gpg.gpgme_data_read(dh, buffer, _size);
1020 assert(_size == reading);
1022 // safeguard for the naive user
1028 gpg.gpgme_data_release(dh);
1029 return PEP_STATUS_OK;
1032 static void _switch_mode(pEpSession *session, gpgme_keylist_mode_t remove_mode,
1033 gpgme_keylist_mode_t add_mode)
1035 gpgme_error_t gpgme_error;
1036 gpgme_keylist_mode_t mode;
1038 mode = gpg.gpgme_get_keylist_mode(session->ctx);
1040 mode &= ~remove_mode;
1043 gpgme_error = gpg.gpgme_set_keylist_mode(session->ctx, mode);
1044 gpgme_error = _GPGERR(gpgme_error);
1045 assert(gpgme_error == GPG_ERR_NO_ERROR);
1048 PEP_STATUS pgp_recv_key(PEP_SESSION session, const char *pattern)
1050 gpgme_error_t gpgme_error;
1056 _switch_mode(session, GPGME_KEYLIST_MODE_LOCAL, GPGME_KEYLIST_MODE_EXTERN);
1058 gpgme_error = gpg.gpgme_op_keylist_start(session->ctx, pattern, 0);
1059 gpgme_error = _GPGERR(gpgme_error);
1060 switch (gpgme_error) {
1061 case GPG_ERR_NO_ERROR:
1063 case GPG_ERR_INV_VALUE:
1065 _switch_mode(session, GPGME_KEYLIST_MODE_EXTERN, GPGME_KEYLIST_MODE_LOCAL);
1066 return PEP_UNKNOWN_ERROR;
1068 _switch_mode(session, GPGME_KEYLIST_MODE_EXTERN, GPGME_KEYLIST_MODE_LOCAL);
1069 return PEP_GET_KEY_FAILED;
1072 gpgme_ctx_t import_ctx;
1073 gpgme_error = gpg.gpgme_new(&import_ctx);
1074 assert(gpgme_error == GPG_ERR_NO_ERROR);
1077 gpgme_error = gpg.gpgme_op_keylist_next(session->ctx, &key);
1078 gpgme_error = _GPGERR(gpgme_error);
1079 assert(gpgme_error != GPG_ERR_INV_VALUE);
1080 switch (gpgme_error) {
1083 case GPG_ERR_NO_ERROR:
1085 gpgme_error_t gpgme_error;
1086 gpgme_key_t keys[2];
1091 gpgme_error = gpg.gpgme_op_import_keys(import_ctx, keys);
1092 gpgme_error = _GPGERR(gpgme_error);
1093 gpg.gpgme_key_unref(key);
1094 assert(gpgme_error != GPG_ERR_INV_VALUE);
1095 assert(gpgme_error != GPG_ERR_CONFLICT);
1098 case GPG_ERR_ENOMEM:
1099 gpg.gpgme_op_keylist_end(session->ctx);
1100 gpg.gpgme_release(import_ctx);
1101 _switch_mode(session, GPGME_KEYLIST_MODE_EXTERN, GPGME_KEYLIST_MODE_LOCAL);
1102 return PEP_OUT_OF_MEMORY;
1104 gpg.gpgme_op_keylist_end(session->ctx);
1105 gpg.gpgme_release(import_ctx);
1106 _switch_mode(session, GPGME_KEYLIST_MODE_EXTERN, GPGME_KEYLIST_MODE_LOCAL);
1107 return PEP_UNKNOWN_ERROR;
1109 } while (gpgme_error != GPG_ERR_EOF);
1111 gpg.gpgme_op_keylist_end(session->ctx);
1112 gpg.gpgme_release(import_ctx);
1113 _switch_mode(session, GPGME_KEYLIST_MODE_EXTERN, GPGME_KEYLIST_MODE_LOCAL);
1114 return PEP_STATUS_OK;
1117 PEP_STATUS pgp_find_keys(
1118 PEP_SESSION session, const char *pattern, stringlist_t **keylist
1121 gpgme_error_t gpgme_error;
1123 stringlist_t *_keylist;
1132 gpgme_error = gpg.gpgme_op_keylist_start(session->ctx, pattern, 0);
1133 gpgme_error = _GPGERR(gpgme_error);
1134 switch (gpgme_error) {
1135 case GPG_ERR_NO_ERROR:
1137 case GPG_ERR_INV_VALUE:
1139 return PEP_UNKNOWN_ERROR;
1141 gpg.gpgme_op_keylist_end(session->ctx);
1142 return PEP_GET_KEY_FAILED;
1145 _keylist = new_stringlist(NULL);
1146 stringlist_t *_k = _keylist;
1149 gpgme_error = gpg.gpgme_op_keylist_next(session->ctx, &key);
1150 gpgme_error = _GPGERR(gpgme_error);
1151 assert(gpgme_error != GPG_ERR_INV_VALUE);
1152 switch (gpgme_error) {
1155 case GPG_ERR_NO_ERROR:
1157 assert(key->subkeys);
1158 fpr = key->subkeys->fpr;
1160 _k = stringlist_add(_k, fpr);
1164 case GPG_ERR_ENOMEM:
1165 free_stringlist(_keylist);
1166 gpg.gpgme_op_keylist_end(session->ctx);
1167 return PEP_OUT_OF_MEMORY;
1169 gpg.gpgme_op_keylist_end(session->ctx);
1170 return PEP_UNKNOWN_ERROR;
1172 } while (gpgme_error != GPG_ERR_EOF);
1174 gpg.gpgme_op_keylist_end(session->ctx);
1175 *keylist = _keylist;
1176 return PEP_STATUS_OK;
1179 PEP_STATUS pgp_send_key(PEP_SESSION session, const char *pattern)
1181 gpgme_error_t gpgme_error;
1186 gpgme_error = gpg.gpgme_op_export(session->ctx, pattern,
1187 GPGME_EXPORT_MODE_EXTERN, NULL);
1188 gpgme_error = _GPGERR(gpgme_error);
1189 assert(gpgme_error != GPG_ERR_INV_VALUE);
1190 if (gpgme_error == GPG_ERR_NO_ERROR)
1191 return PEP_STATUS_OK;
1193 return PEP_CANNOT_SEND_KEY;
1196 PEP_STATUS pgp_get_key_rating(
1197 PEP_SESSION session,
1199 PEP_comm_type *comm_type
1202 PEP_STATUS status = PEP_STATUS_OK;
1203 gpgme_error_t gpgme_error;
1210 *comm_type = PEP_ct_unknown;
1212 gpgme_error = gpg.gpgme_op_keylist_start(session->ctx, fpr, 0);
1213 gpgme_error = _GPGERR(gpgme_error);
1214 switch (gpgme_error) {
1215 case GPG_ERR_NO_ERROR:
1217 case GPG_ERR_INV_VALUE:
1219 return PEP_UNKNOWN_ERROR;
1221 return PEP_GET_KEY_FAILED;
1224 gpgme_error = gpg.gpgme_op_keylist_next(session->ctx, &key);
1225 gpgme_error = _GPGERR(gpgme_error);
1226 assert(gpgme_error != GPG_ERR_INV_VALUE);
1229 gpg.gpgme_op_keylist_end(session->ctx);
1230 return PEP_KEY_NOT_FOUND;
1233 switch (key->protocol) {
1234 case GPGME_PROTOCOL_OpenPGP:
1235 case GPGME_PROTOCOL_DEFAULT:
1236 *comm_type = PEP_ct_OpenPGP_unconfirmed;
1238 case GPGME_PROTOCOL_CMS:
1239 *comm_type = PEP_ct_CMS_unconfirmed;
1242 *comm_type = PEP_ct_unknown;
1243 gpg.gpgme_op_keylist_end(session->ctx);
1244 return PEP_STATUS_OK;
1247 switch (gpgme_error) {
1250 case GPG_ERR_NO_ERROR:
1252 assert(key->subkeys);
1253 for (gpgme_subkey_t sk = key->subkeys; sk != NULL; sk = sk->next) {
1254 if (sk->length < 1024)
1255 *comm_type = PEP_ct_key_too_short;
1258 (sk->pubkey_algo == GPGME_PK_RSA)
1259 || (sk->pubkey_algo == GPGME_PK_RSA_E)
1260 || (sk->pubkey_algo == GPGME_PK_RSA_S)
1262 && sk->length == 1024
1264 *comm_type = PEP_ct_OpenPGP_weak_unconfirmed;
1267 *comm_type = PEP_ct_key_b0rken;
1271 *comm_type = PEP_ct_key_expired;
1275 *comm_type = PEP_ct_key_revoked;
1280 case GPG_ERR_ENOMEM:
1281 gpg.gpgme_op_keylist_end(session->ctx);
1282 *comm_type = PEP_ct_unknown;
1283 return PEP_OUT_OF_MEMORY;
1285 gpg.gpgme_op_keylist_end(session->ctx);
1286 return PEP_UNKNOWN_ERROR;
1289 gpg.gpgme_op_keylist_end(session->ctx);
1294 static PEP_STATUS find_single_key(
1295 PEP_SESSION session,
1300 gpgme_error_t gpgme_error;
1304 gpgme_error = gpg.gpgme_op_keylist_start(session->ctx, fpr, 0);
1305 gpgme_error = _GPGERR(gpgme_error);
1306 switch (gpgme_error) {
1307 case GPG_ERR_NO_ERROR:
1309 case GPG_ERR_INV_VALUE:
1311 return PEP_UNKNOWN_ERROR;
1313 return PEP_GET_KEY_FAILED;
1316 gpgme_error = gpg.gpgme_op_keylist_next(session->ctx, key);
1317 gpgme_error = _GPGERR(gpgme_error);
1318 assert(gpgme_error != GPG_ERR_INV_VALUE);
1320 gpg.gpgme_op_keylist_end(session->ctx);
1322 return PEP_STATUS_OK;
1325 typedef struct _renew_state {
1337 const char *fpr_ref;
1338 const char *date_ref;
1341 static gpgme_error_t renew_fsm(
1343 gpgme_status_code_t statuscode,
1348 renew_state *handle = _handle;
1350 switch (handle->state) {
1352 if (statuscode == GPGME_STATUS_GET_LINE) {
1353 assert(strcmp(args, "keyedit.prompt") == 0);
1354 if (strcmp(args, "keyedit.prompt")) {
1355 handle->state = renew_error;
1356 return GPG_ERR_GENERAL;
1358 write(fd, "expire\n", 7);
1359 handle->state = renew_date;
1364 if (statuscode == GPGME_STATUS_GET_LINE) {
1365 assert(strcmp(args, "keygen.valid") == 0);
1366 if (strcmp(args, "keygen.valid")) {
1367 handle->state = renew_error;
1368 return GPG_ERR_GENERAL;
1370 write(fd, "2015-12-31\n", 11);
1371 handle->state = renew_secret_key;
1375 case renew_secret_key:
1376 if (statuscode == GPGME_STATUS_GET_LINE) {
1377 assert(strcmp(args, "keyedit.prompt") == 0);
1378 if (strcmp(args, "keyedit.prompt")) {
1379 handle->state = renew_error;
1380 return GPG_ERR_GENERAL;
1382 write(fd, "key 1\n", 6);
1383 handle->state = renew_command2;
1387 case renew_command2:
1388 if (statuscode == GPGME_STATUS_GET_LINE) {
1389 assert(strcmp(args, "keyedit.prompt") == 0);
1390 if (strcmp(args, "keyedit.prompt")) {
1391 handle->state = renew_error;
1392 return GPG_ERR_GENERAL;
1394 write(fd, "expire\n", 7);
1395 handle->state = renew_date2;
1400 if (statuscode == GPGME_STATUS_GET_LINE) {
1401 assert(strcmp(args, "keygen.valid") == 0);
1402 if (strcmp(args, "keygen.valid")) {
1403 handle->state = renew_error;
1404 return GPG_ERR_GENERAL;
1406 write(fd, "2015-12-31\n", 11);
1407 handle->state = renew_quit;
1412 if (statuscode == GPGME_STATUS_GET_LINE) {
1413 assert(strcmp(args, "keyedit.prompt") == 0);
1414 if (strcmp(args, "keyedit.prompt")) {
1415 handle->state = renew_error;
1416 return GPG_ERR_GENERAL;
1418 write(fd, "quit\n", 5);
1419 handle->state = renew_save;
1424 if (statuscode == GPGME_STATUS_GET_BOOL) {
1425 assert(strcmp(args, "keyedit.save.okay") == 0);
1426 if (strcmp(args, "keyedit.save.okay")) {
1427 handle->state = renew_error;
1428 return GPG_ERR_GENERAL;
1430 write(fd, "Y\n", 2);
1431 handle->state = renew_exit;
1439 return GPG_ERR_GENERAL;
1442 return GPG_ERR_NO_ERROR;
1445 static ssize_t _nullwriter(
1454 PEP_STATUS pgp_renew_key(
1455 PEP_SESSION session,
1460 PEP_STATUS status = PEP_STATUS_OK;
1461 gpgme_error_t gpgme_error;
1463 gpgme_data_t output;
1470 memset(&handle, 0, sizeof(renew_state));
1471 handle.fpr_ref = fpr;
1472 snprintf(date_text, 11, "%.4d-%.2d-%.2d", ts->tm_year + 1900,
1473 ts->tm_mon + 1, ts->tm_mday);
1474 handle.date_ref = date_text;
1476 status = find_single_key(session, fpr, &key);
1477 if (status != PEP_STATUS_OK)
1480 struct gpgme_data_cbs data_cbs;
1481 memset(&data_cbs, 0, sizeof(struct gpgme_data_cbs));
1482 data_cbs.write = _nullwriter;
1483 gpgme_data_new_from_cbs(&output, &data_cbs, &handle);
1485 gpgme_error = gpgme_op_edit(session->ctx, key, renew_fsm, &handle,
1487 assert(gpgme_error == GPG_ERR_NO_ERROR);
1489 gpg.gpgme_data_release(output);
1490 gpg.gpgme_key_unref(key);
1492 return PEP_STATUS_OK;
1495 PEP_STATUS pgp_revoke_key(PEP_SESSION session, const char *fpr)
1497 PEP_STATUS status = PEP_STATUS_OK;
1503 status = find_single_key(session, fpr, &key);
1504 if (status != PEP_STATUS_OK)
1507 return PEP_STATUS_OK;