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