bc2a80a49e265f602786e14702f922dcfd7d398e
[fwknop.git] / lib / fko_encryption.c
1 /*
2  *****************************************************************************
3  *
4  * File:    fko_encryption.c
5  *
6  * Author:  Damien S. Stuart
7  *
8  * Purpose: Set/Get the spa encryption type.
9  *
10  * Copyright 2009-2010 Damien Stuart (dstuart@dstuart.org)
11  *
12  *  License (GNU Public License):
13  *
14  *  This program is free software; you can redistribute it and/or
15  *  modify it under the terms of the GNU General Public License
16  *  as published by the Free Software Foundation; either version 2
17  *  of the License, or (at your option) any later version.
18  *
19  *  This program is distributed in the hope that it will be useful,
20  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
21  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
22  *  GNU General Public License for more details.
23  *
24  *  You should have received a copy of the GNU General Public License
25  *  along with this program; if not, write to the Free Software
26  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307
27  *  USA
28  *
29  *****************************************************************************
30 */
31 #include "fko_common.h"
32 #include "fko.h"
33 #include "cipher_funcs.h"
34 #include "base64.h"
35
36 #if HAVE_LIBGPGME
37   #include "gpgme_funcs.h"
38   #if HAVE_SYS_STAT_H
39     #include <sys/stat.h>
40   #endif
41 #endif
42
43 /* Prep and encrypt using Rijndael
44 */
45 static int
46 _rijndael_encrypt(fko_ctx_t ctx, const char *enc_key)
47 {
48     char           *plain;
49     char           *b64cipher;
50     unsigned char  *cipher;
51     int             cipher_len;
52
53     /* Make a bucket big enough to hold the enc msg + digest (plaintext)
54      * and populate it appropriately.
55     */
56     plain = malloc(strlen(ctx->encoded_msg) + strlen(ctx->digest) + 2);
57     if(plain == NULL)
58         return(FKO_ERROR_MEMORY_ALLOCATION);
59
60     sprintf(plain, "%s:%s", ctx->encoded_msg, ctx->digest);
61
62     /* Make a bucket for the encrypted version and populate it.
63     */
64     cipher = malloc(strlen(plain) + 32); /* Plus padding for salt and Block */
65     if(cipher == NULL)
66         return(FKO_ERROR_MEMORY_ALLOCATION);
67
68     cipher_len = rij_encrypt(
69         (unsigned char*)plain, strlen(plain), (char*)enc_key, cipher
70     );
71
72     /* Now make a bucket for the base64-encoded version and populate it.
73     */
74     b64cipher = malloc(((cipher_len / 3) * 4) + 8);
75     if(b64cipher == NULL)
76         return(FKO_ERROR_MEMORY_ALLOCATION);
77
78     b64_encode(cipher, b64cipher, cipher_len);
79     strip_b64_eq(b64cipher);
80
81     ctx->encrypted_msg = strdup(b64cipher);
82
83     /* Clean-up
84     */
85     free(plain);
86     free(cipher);
87     free(b64cipher);
88
89     if(ctx->encrypted_msg == NULL)
90         return(FKO_ERROR_MEMORY_ALLOCATION);
91
92     return(FKO_SUCCESS);
93 }
94
95 /* Decode, decrypt, and parse SPA data into the context.
96 */
97 static int
98 _rijndael_decrypt(fko_ctx_t ctx, const char *dec_key)
99 {
100     char           *tbuf;
101     unsigned char  *ndx;
102     unsigned char  *cipher;
103     int             cipher_len, pt_len, i, err = 0;
104
105     int             b64_len = strlen(ctx->encrypted_msg);
106
107     /* Now see if we need to add the "Salted__" string to the front of the
108      * encrypted data.
109     */
110     if(strncmp(ctx->encrypted_msg, B64_RIJNDAEL_SALT, strlen(B64_RIJNDAEL_SALT)))
111     {
112         /* We need to realloc space for the salt.
113         */
114         tbuf = realloc(ctx->encrypted_msg, b64_len + 12);
115         if(tbuf == NULL)
116             return(FKO_ERROR_MEMORY_ALLOCATION);
117
118         memmove(tbuf+strlen(B64_RIJNDAEL_SALT), tbuf, b64_len);
119
120         ctx->encrypted_msg = memcpy(tbuf, B64_RIJNDAEL_SALT, strlen(B64_RIJNDAEL_SALT));
121
122         /* Adjust b64_len for added SALT value and Make sure we are still
123          * a properly NULL-terminated string (Ubuntu was one system for
124          * which this was an issue).
125         */
126         b64_len += strlen(B64_RIJNDAEL_SALT);
127         tbuf[b64_len] = '\0';
128     }
129
130     /* Create a bucket for the (base64) decoded encrypted data and get the
131      * raw cipher data.
132     */
133     cipher = malloc(strlen(ctx->encrypted_msg));
134     if(cipher == NULL)
135         return(FKO_ERROR_MEMORY_ALLOCATION);
136
137     cipher_len = b64_decode(ctx->encrypted_msg, cipher);
138
139     /* Create a bucket for the plaintext data and decrypt the message
140      * data into it.
141     */
142     ctx->encoded_msg = malloc(cipher_len);
143     if(ctx->encoded_msg == NULL)
144         return(FKO_ERROR_MEMORY_ALLOCATION);
145
146     pt_len = rij_decrypt(cipher, cipher_len, dec_key, (unsigned char*)ctx->encoded_msg);
147
148     /* Done with cipher...
149     */
150     free(cipher);
151
152     /* The length of the decrypted data should be within 32 bytes of the
153      * length of the encrypted version.
154     */
155     if(pt_len < (cipher_len - 32))
156         return(FKO_ERROR_DECRYPTION_SIZE);
157
158     /* At this point we can check the data to see if we have a good
159      * decryption by ensuring the first field (16-digit random decimal
160      * value) is valid and is followed by a colon.  Additional checks
161      * are made in fko_decode_spa_data().
162     */
163     ndx = (unsigned char *)ctx->encoded_msg;
164     for(i=0; i<FKO_RAND_VAL_SIZE; i++)
165         if(!isdigit(*(ndx++)))
166             err++;
167
168     if(err > 0 || *ndx != ':')
169         return(FKO_ERROR_DECRYPTION_FAILURE);
170
171     /* Call fko_decode and return the results.
172     */
173     return(fko_decode_spa_data(ctx));
174 }
175
176
177 #if HAVE_LIBGPGME
178
179 /* Prep and encrypt using gpgme
180 */
181 static int
182 gpg_encrypt(fko_ctx_t ctx, const char *enc_key)
183 {
184     int             res;
185     char           *plain;
186     char           *b64cipher;
187     unsigned char  *cipher = NULL;
188     size_t          cipher_len;
189
190     /* First make sure we have a recipient key set.
191     */
192     if(ctx->gpg_recipient == NULL)
193         return(FKO_ERROR_MISSING_GPG_KEY_DATA);
194
195     /* Make a bucket big enough to hold the enc msg + digest (plaintext)
196      * and populate it appropriately.
197     */
198     plain = malloc(strlen(ctx->encoded_msg) + strlen(ctx->digest) + 2);
199     if(plain == NULL)
200         return(FKO_ERROR_MEMORY_ALLOCATION);
201
202     sprintf(plain, "%s:%s", ctx->encoded_msg, ctx->digest);
203
204     res = gpgme_encrypt(ctx,
205         (unsigned char*)plain, strlen(plain),
206         enc_key, &cipher, &cipher_len
207     );
208
209     /* --DSS XXX: Better parsing of what went wrong would be nice :)
210     */
211     if(res != FKO_SUCCESS)
212     {
213         free(plain);
214
215         if(cipher)
216             free(cipher);
217
218         return(res);
219     }
220
221     /* Now make a bucket for the base64-encoded version and populate it.
222     */
223     b64cipher = malloc(((cipher_len / 3) * 4) + 8);
224     if(b64cipher == NULL)
225         return(FKO_ERROR_MEMORY_ALLOCATION);
226
227     b64_encode(cipher, b64cipher, cipher_len);
228     strip_b64_eq(b64cipher);
229
230     ctx->encrypted_msg = strdup(b64cipher);
231
232     /* Clean-up
233     */
234     free(plain);
235     free(cipher);
236     free(b64cipher);
237
238     if(ctx->encrypted_msg == NULL)
239         return(FKO_ERROR_MEMORY_ALLOCATION);
240
241     return(FKO_SUCCESS);
242 }
243
244 /* Prep and decrypt using gpgme
245 */
246 static int
247 gpg_decrypt(fko_ctx_t ctx, const char *dec_key)
248 {
249     char           *tbuf;
250     unsigned char  *cipher;
251     size_t          cipher_len;
252     int             res;
253
254     int             b64_len = strlen(ctx->encrypted_msg);
255
256     /* Now see if we need to add the "hQ" string to the front of the
257      * base64-encoded-GPG-encrypted data.
258     */
259     if(strncmp(ctx->encrypted_msg, B64_GPG_PREFIX, strlen(B64_GPG_PREFIX)))
260     {
261         /* We need to realloc space for the GPG prefix of hQ.
262         */
263         tbuf = realloc(ctx->encrypted_msg, b64_len + 12);
264         if(tbuf == NULL)
265             return(FKO_ERROR_MEMORY_ALLOCATION);
266
267         memmove(tbuf+strlen(B64_GPG_PREFIX), tbuf, b64_len);
268
269         ctx->encrypted_msg = memcpy(tbuf, B64_GPG_PREFIX, strlen(B64_GPG_PREFIX));
270
271         /* Adjust b64_len for added SALT value and Make sure we are still
272          * a properly NULL-terminated string (Ubuntu was one system for
273          * which this was an issue).
274         */
275         b64_len += strlen(B64_GPG_PREFIX);
276         tbuf[b64_len] = '\0';
277     }
278
279     /* Create a bucket for the (base64) decoded encrypted data and get the
280      * raw cipher data.
281     */
282     cipher = malloc(strlen(ctx->encrypted_msg));
283     if(cipher == NULL)
284         return(FKO_ERROR_MEMORY_ALLOCATION);
285
286     cipher_len = b64_decode(ctx->encrypted_msg, cipher);
287
288     /* Create a bucket for the plaintext data and decrypt the message
289      * data into it.
290     */
291     /* --DSS Actually, the needed memory will be malloced in the gpgme_decrypt
292     //       function. Just leaving this here for reference (for now).
293     //ctx->encoded_msg = malloc(cipher_len);
294     //if(ctx->encoded_msg == NULL)
295     //    return(FKO_ERROR_MEMORY_ALLOCATION);
296     */
297
298     res = gpgme_decrypt(ctx, cipher, cipher_len,
299         dec_key,  (unsigned char**)&ctx->encoded_msg, &cipher_len
300     );
301
302     /* Done with cipher...
303     */
304     free(cipher);
305
306     if(res != FKO_SUCCESS)
307         return(res);
308
309     /* XXX: We could put some kind of sanity check  of the decrypted
310      *      data here
311     */
312
313     /* Call fko_decode and return the results.
314     */
315     return(fko_decode_spa_data(ctx));
316 }
317
318 #endif /* HAVE_LIBGPGME */
319
320 /* Set the SPA encryption type.
321 */
322 int
323 fko_set_spa_encryption_type(fko_ctx_t ctx, const short encrypt_type)
324 {
325     /* Must be initialized
326     */
327     if(!CTX_INITIALIZED(ctx))
328         return(FKO_ERROR_CTX_NOT_INITIALIZED);
329
330     if(encrypt_type < 0 || encrypt_type >= FKO_LAST_ENCRYPTION_TYPE)
331         return(FKO_ERROR_INVALID_DATA);
332
333     ctx->encryption_type = encrypt_type;
334
335     ctx->state |= FKO_ENCRYPT_TYPE_MODIFIED;
336
337     return(FKO_SUCCESS);
338 }
339
340 /* Return the SPA encryption type.
341 */
342 int
343 fko_get_spa_encryption_type(fko_ctx_t ctx, short *enc_type)
344 {
345     /* Must be initialized
346     */
347     if(!CTX_INITIALIZED(ctx))
348         return(FKO_ERROR_CTX_NOT_INITIALIZED);
349
350     *enc_type = ctx->encryption_type;
351
352     return(FKO_SUCCESS);
353 }
354
355 /* Encrypt the encoded SPA data.
356 */
357 int
358 fko_encrypt_spa_data(fko_ctx_t ctx, const char *enc_key)
359 {
360     int             res = 0;
361
362     /* Must be initialized
363     */
364     if(!CTX_INITIALIZED(ctx))
365     {
366         return(FKO_ERROR_CTX_NOT_INITIALIZED);
367     }
368
369     /* If there is no encoded data or the SPA data has been modified,
370      * go ahead and re-encode here.
371     */
372     if(ctx->encoded_msg == NULL || FKO_IS_SPA_DATA_MODIFIED(ctx))
373         res = fko_encode_spa_data(ctx);
374
375     if(res)
376         return(res);
377
378     /* Croak on invalid encoded message as well. At present this is a
379      * check for a somewhat arbitrary minimum length for the encoded
380      * data.
381     */
382     if(strlen(ctx->encoded_msg) < MIN_SPA_ENCODED_MSG_SIZE)
383     {
384         return(FKO_ERROR_MISSING_ENCODED_DATA);
385     }
386
387     /* Encrypt according to type and return...
388     */
389     if(ctx->encryption_type == FKO_ENCRYPTION_RIJNDAEL)
390         res = _rijndael_encrypt(ctx, enc_key);
391     else if(ctx->encryption_type == FKO_ENCRYPTION_GPG)
392 #if HAVE_LIBGPGME
393         res = gpg_encrypt(ctx, enc_key);
394 #else
395         res = FKO_ERROR_UNSUPPORTED_FEATURE;
396 #endif
397     else
398         res = FKO_ERROR_INVALID_ENCRYPTION_TYPE;
399
400     return(res);
401 }
402
403 /* Decode, decrypt, and parse SPA data into the context.
404 */
405 int
406 fko_decrypt_spa_data(fko_ctx_t ctx, const char *dec_key)
407 {
408     int     enc_type, res;
409
410     /* Get the (assumed) type of encryption used. This will also provide
411      * some data validation.
412     */
413     enc_type = fko_encryption_type(ctx->encrypted_msg);
414
415     //strlen(ctx->encrypted_msg) <  MIN_SPA_ENCODED_MSG_SIZE)
416
417     if(enc_type == FKO_ENCRYPTION_GPG)
418     {
419         ctx->encryption_type = FKO_ENCRYPTION_GPG;
420 #if HAVE_LIBGPGME
421         res = gpg_decrypt(ctx, dec_key);
422 #else
423         res = FKO_ERROR_UNSUPPORTED_FEATURE;
424 #endif
425     }
426     else if(enc_type == FKO_ENCRYPTION_RIJNDAEL)
427     {
428         ctx->encryption_type = FKO_ENCRYPTION_RIJNDAEL;
429         res = _rijndael_decrypt(ctx, dec_key);
430     }
431     else
432         return(FKO_ERROR_INVALID_DATA);
433
434     return(res);
435 }
436
437 /* Return the assumed encryption type based on the raw encrypted data.
438 */
439 int
440 fko_encryption_type(const char *enc_data)
441 {
442     int enc_data_len;
443
444     /* Sanity check the data.
445     */
446     if(enc_data == NULL)
447         return(FKO_ENCRYPTION_INVALID_DATA);
448
449     /* Determine type of encryption used.  For now, we are using the
450      * size of the message.
451      *
452      * XXX: We will want to come up with a more reliable method of
453      *      identifying the encryption type.
454     */
455     enc_data_len = strlen(enc_data);
456
457     if(enc_data_len >= MIN_GNUPG_MSG_SIZE)
458         return(FKO_ENCRYPTION_GPG);
459
460     else if(enc_data_len < MIN_GNUPG_MSG_SIZE
461       && enc_data_len >= MIN_SPA_ENCODED_MSG_SIZE)
462         return(FKO_ENCRYPTION_RIJNDAEL);
463
464     else
465         return(FKO_ENCRYPTION_UNKNOWN);
466 }
467
468 /* Set the GPG recipient key name.
469 */
470 int
471 fko_set_gpg_recipient(fko_ctx_t ctx, const char *recip)
472 {
473 #if HAVE_LIBGPGME
474     int             res;
475     gpgme_key_t     key     = NULL;
476
477     /* Must be initialized
478     */
479     if(!CTX_INITIALIZED(ctx))
480         return(FKO_ERROR_CTX_NOT_INITIALIZED);
481
482     if(ctx->encryption_type != FKO_ENCRYPTION_GPG)
483         return(FKO_ERROR_WRONG_ENCRYPTION_TYPE);
484
485     ctx->gpg_recipient = strdup(recip);
486     if(ctx->gpg_recipient == NULL)
487         return(FKO_ERROR_MEMORY_ALLOCATION);
488
489     /* Get the key.
490     */
491     res = get_gpg_key(ctx, &key, 0);
492     if(res != FKO_SUCCESS)
493     {
494         free(ctx->gpg_recipient);
495         ctx->gpg_recipient = NULL;
496         return(res);
497     }
498
499     ctx->recipient_key = key;
500
501     ctx->state |= FKO_DATA_MODIFIED;
502
503     return(FKO_SUCCESS);
504 #else
505     return(FKO_ERROR_UNSUPPORTED_FEATURE);
506 #endif  /* HAVE_LIBGPGME */
507 }
508
509 /* Set the GPG home dir.
510 */
511 int
512 fko_set_gpg_exe(fko_ctx_t ctx, const char *gpg_exe)
513 {
514 #if HAVE_LIBGPGME
515     struct stat     st;
516
517     /* Must be initialized
518     */
519     if(!CTX_INITIALIZED(ctx))
520         return(FKO_ERROR_CTX_NOT_INITIALIZED);
521
522     /* If we are unable to stat the given path/file and determine if it
523      * is a regular file or symbolic link, then return with error.
524     */
525     if(stat(gpg_exe, &st) != 0)
526         return(FKO_ERROR_GPGME_BAD_GPG_EXE);
527
528     if(!S_ISREG(st.st_mode) && !S_ISLNK(st.st_mode))
529         return(FKO_ERROR_GPGME_BAD_GPG_EXE);
530
531     ctx->gpg_exe = strdup(gpg_exe);
532     if(ctx->gpg_exe == NULL)
533         return(FKO_ERROR_MEMORY_ALLOCATION);
534
535     return(FKO_SUCCESS);
536 #else
537     return(FKO_ERROR_UNSUPPORTED_FEATURE);
538 #endif  /* HAVE_LIBGPGME */
539 }
540
541 /* Get the GPG home dir.
542 */
543 int
544 fko_get_gpg_exe(fko_ctx_t ctx, char **gpg_exe)
545 {
546 #if HAVE_LIBGPGME
547     /* Must be initialized
548     */
549     if(!CTX_INITIALIZED(ctx))
550         return(FKO_ERROR_CTX_NOT_INITIALIZED);
551
552     *gpg_exe = ctx->gpg_exe;
553
554     return(FKO_SUCCESS);
555 #else
556     return(FKO_ERROR_UNSUPPORTED_FEATURE);
557 #endif  /* HAVE_LIBGPGME */
558 }
559
560 /* Get the GPG recipient key name.
561 */
562 int
563 fko_get_gpg_recipient(fko_ctx_t ctx, char **recipient)
564 {
565 #if HAVE_LIBGPGME
566     /* Must be initialized
567     */
568     if(!CTX_INITIALIZED(ctx))
569         return(FKO_ERROR_CTX_NOT_INITIALIZED);
570
571     *recipient = ctx->gpg_recipient;
572
573     return(FKO_SUCCESS);
574 #else
575     return(FKO_ERROR_UNSUPPORTED_FEATURE);
576 #endif  /* HAVE_LIBGPGME */
577 }
578
579 /* Set the GPG signer key name.
580 */
581 int
582 fko_set_gpg_signer(fko_ctx_t ctx, const char *signer)
583 {
584 #if HAVE_LIBGPGME
585     int             res;
586     gpgme_key_t     key     = NULL;
587
588     /* Must be initialized
589     */
590     if(!CTX_INITIALIZED(ctx))
591         return(FKO_ERROR_CTX_NOT_INITIALIZED);
592
593     if(ctx->encryption_type != FKO_ENCRYPTION_GPG)
594         return(FKO_ERROR_WRONG_ENCRYPTION_TYPE);
595
596     ctx->gpg_signer = strdup(signer);
597     if(ctx->gpg_signer == NULL)
598         return(FKO_ERROR_MEMORY_ALLOCATION);
599
600     /* Get the key.
601     */
602     res = get_gpg_key(ctx, &key, 1);
603     if(res != FKO_SUCCESS)
604     {
605         free(ctx->gpg_signer);
606         ctx->gpg_signer = NULL;
607         return(res);
608     }
609
610     ctx->signer_key = key;
611
612     ctx->state |= FKO_DATA_MODIFIED;
613
614     return(FKO_SUCCESS);
615 #else
616     return(FKO_ERROR_UNSUPPORTED_FEATURE);
617 #endif  /* HAVE_LIBGPGME */
618 }
619
620 /* Get the GPG signer key name.
621 */
622 int
623 fko_get_gpg_signer(fko_ctx_t ctx, char **signer)
624 {
625 #if HAVE_LIBGPGME
626     /* Must be initialized
627     */
628     if(!CTX_INITIALIZED(ctx))
629         return(FKO_ERROR_CTX_NOT_INITIALIZED);
630
631     *signer = ctx->gpg_signer;
632
633     return(FKO_SUCCESS);
634 #else
635     return(FKO_ERROR_UNSUPPORTED_FEATURE);
636 #endif  /* HAVE_LIBGPGME */
637 }
638
639 /* Set the GPG home dir.
640 */
641 int
642 fko_set_gpg_home_dir(fko_ctx_t ctx, const char *gpg_home_dir)
643 {
644 #if HAVE_LIBGPGME
645     struct stat     st;
646
647     /* Must be initialized
648     */
649     if(!CTX_INITIALIZED(ctx))
650         return(FKO_ERROR_CTX_NOT_INITIALIZED);
651
652     /* If we are unable to stat the given dir, then return with error.
653     */
654     if(stat(gpg_home_dir, &st) != 0)
655         return(FKO_ERROR_GPGME_BAD_HOME_DIR);
656
657     if(!S_ISDIR(st.st_mode))
658         return(FKO_ERROR_GPGME_BAD_HOME_DIR);
659
660     ctx->gpg_home_dir = strdup(gpg_home_dir);
661     if(ctx->gpg_home_dir == NULL)
662         return(FKO_ERROR_MEMORY_ALLOCATION);
663
664     return(FKO_SUCCESS);
665 #else
666     return(FKO_ERROR_UNSUPPORTED_FEATURE);
667 #endif  /* HAVE_LIBGPGME */
668 }
669
670 /* Get the GPG home dir.
671 */
672 int
673 fko_get_gpg_home_dir(fko_ctx_t ctx, char **home_dir)
674 {
675 #if HAVE_LIBGPGME
676     /* Must be initialized
677     */
678     if(!CTX_INITIALIZED(ctx))
679         return(FKO_ERROR_CTX_NOT_INITIALIZED);
680
681     *home_dir = ctx->gpg_home_dir;
682
683     return(FKO_SUCCESS);
684 #else
685     return(FKO_ERROR_UNSUPPORTED_FEATURE);
686 #endif  /* HAVE_LIBGPGME */
687 }
688
689 int
690 fko_set_gpg_signature_verify(fko_ctx_t ctx, const unsigned char val)
691 {
692 #if HAVE_LIBGPGME
693     /* Must be initialized
694     */
695     if(!CTX_INITIALIZED(ctx))
696         return(FKO_ERROR_CTX_NOT_INITIALIZED);
697
698     ctx->verify_gpg_sigs = (val != 0) ? 1 : 0;
699
700     return(FKO_SUCCESS);
701 #else
702     return(FKO_ERROR_UNSUPPORTED_FEATURE);
703 #endif  /* HAVE_LIBGPGME */
704 }
705
706 int
707 fko_get_gpg_signature_verify(fko_ctx_t ctx, unsigned char *val)
708 {
709 #if HAVE_LIBGPGME
710     /* Must be initialized
711     */
712     if(!CTX_INITIALIZED(ctx))
713         return(FKO_ERROR_CTX_NOT_INITIALIZED);
714
715     *val = ctx->verify_gpg_sigs;
716
717     return(FKO_SUCCESS);
718 #else
719     return(FKO_ERROR_UNSUPPORTED_FEATURE);
720 #endif  /* HAVE_LIBGPGME */
721 }
722
723 int
724 fko_set_gpg_ignore_verify_error(fko_ctx_t ctx, const unsigned char val)
725 {
726 #if HAVE_LIBGPGME
727     /* Must be initialized
728     */
729     if(!CTX_INITIALIZED(ctx))
730         return(FKO_ERROR_CTX_NOT_INITIALIZED);
731
732     ctx->ignore_gpg_sig_error = (val != 0) ? 1 : 0;
733
734     return(FKO_SUCCESS);
735 #else
736     return(FKO_ERROR_UNSUPPORTED_FEATURE);
737 #endif  /* HAVE_LIBGPGME */
738 }
739
740 int
741 fko_get_gpg_ignore_verify_error(fko_ctx_t ctx, unsigned char *val)
742 {
743 #if HAVE_LIBGPGME
744     /* Must be initialized
745     */
746     if(!CTX_INITIALIZED(ctx))
747         return(FKO_ERROR_CTX_NOT_INITIALIZED);
748
749     *val = ctx->ignore_gpg_sig_error;
750
751     return(FKO_SUCCESS);
752 #else
753     return(FKO_ERROR_UNSUPPORTED_FEATURE);
754 #endif  /* HAVE_LIBGPGME */
755 }
756
757
758 int
759 fko_get_gpg_signature_fpr(fko_ctx_t ctx, char **fpr)
760 {
761 #if HAVE_LIBGPGME
762     /* Must be initialized
763     */
764     if(!CTX_INITIALIZED(ctx))
765         return(FKO_ERROR_CTX_NOT_INITIALIZED);
766
767     /* Must be using GPG encryption.
768     */
769     if(ctx->encryption_type != FKO_ENCRYPTION_GPG)
770         return(FKO_ERROR_WRONG_ENCRYPTION_TYPE);
771
772     /* Make sure we are supposed to verify signatures.
773     */
774     if(ctx->verify_gpg_sigs == 0)
775         return(FKO_ERROR_GPGME_SIGNATURE_VERIFY_DISABLED);
776
777     /* Make sure we have a signature to work with.
778     */
779     if(ctx->gpg_sigs == NULL)
780         return(FKO_ERROR_GPGME_NO_SIGNATURE);
781
782     *fpr = ctx->gpg_sigs->fpr;
783
784     return(FKO_SUCCESS);
785 #else
786     return(FKO_ERROR_UNSUPPORTED_FEATURE);
787 #endif  /* HAVE_LIBGPGME */
788 }
789
790 int
791 fko_get_gpg_signature_id(fko_ctx_t ctx, char **id)
792 {
793 #if HAVE_LIBGPGME
794     /* Must be initialized
795     */
796     if(!CTX_INITIALIZED(ctx))
797         return(FKO_ERROR_CTX_NOT_INITIALIZED);
798
799     /* Must be using GPG encryption.
800     */
801     if(ctx->encryption_type != FKO_ENCRYPTION_GPG)
802         return(FKO_ERROR_WRONG_ENCRYPTION_TYPE);
803
804     /* Make sure we are supposed to verify signatures.
805     */
806     if(ctx->verify_gpg_sigs == 0)
807         return(FKO_ERROR_GPGME_SIGNATURE_VERIFY_DISABLED);
808
809     /* Make sure we have a signature to work with.
810     */
811     if(ctx->gpg_sigs == NULL)
812         return(FKO_ERROR_GPGME_NO_SIGNATURE);
813
814     *id = ctx->gpg_sigs->fpr + strlen(ctx->gpg_sigs->fpr) - 8;
815
816     return(FKO_SUCCESS);
817 #else
818     return(FKO_ERROR_UNSUPPORTED_FEATURE);
819 #endif  /* HAVE_LIBGPGME */
820 }
821
822 int
823 fko_get_gpg_signature_summary(fko_ctx_t ctx, int *sigsum)
824 {
825 #if HAVE_LIBGPGME
826     /* Must be initialized
827     */
828     if(!CTX_INITIALIZED(ctx))
829         return(FKO_ERROR_CTX_NOT_INITIALIZED);
830
831     /* Must be using GPG encryption.
832     */
833     if(ctx->encryption_type != FKO_ENCRYPTION_GPG)
834         return(FKO_ERROR_WRONG_ENCRYPTION_TYPE);
835
836     /* Make sure we are supposed to verify signatures.
837     */
838     if(ctx->verify_gpg_sigs == 0)
839         return(FKO_ERROR_GPGME_SIGNATURE_VERIFY_DISABLED);
840
841     /* Make sure we have a signature to work with.
842     */
843     if(ctx->gpg_sigs == NULL)
844         return(FKO_ERROR_GPGME_NO_SIGNATURE);
845
846     *sigsum = ctx->gpg_sigs->summary;
847
848     return(FKO_SUCCESS);
849 #else
850     return(FKO_ERROR_UNSUPPORTED_FEATURE);
851 #endif  /* HAVE_LIBGPGME */
852 }
853
854 int
855 fko_get_gpg_signature_status(fko_ctx_t ctx, int *sigstat)
856 {
857 #if HAVE_LIBGPGME
858     /* Must be initialized
859     */
860     if(!CTX_INITIALIZED(ctx))
861         return(FKO_ERROR_CTX_NOT_INITIALIZED);
862
863     /* Must be using GPG encryption.
864     */
865     if(ctx->encryption_type != FKO_ENCRYPTION_GPG)
866         return(FKO_ERROR_WRONG_ENCRYPTION_TYPE);
867
868     /* Make sure we are supposed to verify signatures.
869     */
870     if(ctx->verify_gpg_sigs == 0)
871         return(FKO_ERROR_GPGME_SIGNATURE_VERIFY_DISABLED);
872
873     /* Make sure we have a signature to work with.
874     */
875     if(ctx->gpg_sigs == NULL)
876         return(FKO_ERROR_GPGME_NO_SIGNATURE);
877
878     *sigstat = ctx->gpg_sigs->status;
879
880     return(FKO_SUCCESS);
881 #else
882     return(FKO_ERROR_UNSUPPORTED_FEATURE);
883 #endif  /* HAVE_LIBGPGME */
884 }
885
886 int
887 fko_gpg_signature_id_match(fko_ctx_t ctx, const char *id, unsigned char *result)
888 {
889 #if HAVE_LIBGPGME
890     char *curr_id;
891
892     /* Must be initialized
893     */
894     if(!CTX_INITIALIZED(ctx))
895         return(FKO_ERROR_CTX_NOT_INITIALIZED);
896
897     /* Must be using GPG encryption.
898     */
899     if(ctx->encryption_type != FKO_ENCRYPTION_GPG)
900         return(FKO_ERROR_WRONG_ENCRYPTION_TYPE);
901
902     /* Make sure we are supposed to verify signatures.
903     */
904     if(ctx->verify_gpg_sigs == 0)
905         return(FKO_ERROR_GPGME_SIGNATURE_VERIFY_DISABLED);
906
907     /* Make sure we have a signature to work with.
908     */
909     if(ctx->gpg_sigs == NULL)
910         return(FKO_ERROR_GPGME_NO_SIGNATURE);
911
912     fko_get_gpg_signature_id(ctx, &curr_id);
913
914     *result = strcmp(id, curr_id) == 0 ? 1 : 0;
915
916     return(FKO_SUCCESS);
917 #else
918     return(FKO_ERROR_UNSUPPORTED_FEATURE);
919 #endif  /* HAVE_LIBGPGME */
920 }
921
922 int
923 fko_gpg_signature_fpr_match(fko_ctx_t ctx, const char *id, unsigned char *result)
924 {
925 #if HAVE_LIBGPGME
926     /* Must be initialized
927     */
928     if(!CTX_INITIALIZED(ctx))
929         return(FKO_ERROR_CTX_NOT_INITIALIZED);
930
931     /* Must be using GPG encryption.
932     */
933     if(ctx->encryption_type != FKO_ENCRYPTION_GPG)
934         return(FKO_ERROR_WRONG_ENCRYPTION_TYPE);
935
936     /* Make sure we are supposed to verify signatures.
937     */
938     if(ctx->verify_gpg_sigs == 0)
939         return(FKO_ERROR_GPGME_SIGNATURE_VERIFY_DISABLED);
940
941     /* Make sure we have a signature to work with.
942     */
943     if(ctx->gpg_sigs == NULL)
944         return(FKO_ERROR_GPGME_NO_SIGNATURE);
945
946     *result = strcmp(id, ctx->gpg_sigs->fpr) == 0 ? 1 : 0;
947
948     return(FKO_SUCCESS);
949 #else
950     return(FKO_ERROR_UNSUPPORTED_FEATURE);
951 #endif  /* HAVE_LIBGPGME */
952 }
953
954 /***EOF***/