Merge branch 'master' of git://repo.or.cz/gnutls
[gnutls.git] / libextra / gnutls_openpgp.c
blobddbbfc9a79a09aaacaac77266f242552fdaf0db7
1 /*
2 * Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007 Free Software Foundation
4 * Author: Timo Schulz
6 * This file is part of GNUTLS-EXTRA.
8 * GNUTLS-EXTRA is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License as
10 * published by the Free Software Foundation; either version 2 of the
11 * License, or (at your option) any later version.
13 * GNUTLS-EXTRA is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with GNUTLS-EXTRA; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
21 * 02110-1301, USA.
25 #include "gnutls_int.h"
26 #include "gnutls_errors.h"
27 #include "gnutls_mpi.h"
28 #include "gnutls_cert.h"
29 #include "gnutls_datum.h"
30 #include "gnutls_global.h"
31 #include <openpgp/gnutls_openpgp.h>
32 #include "read-file.h"
33 #include <gnutls_str.h>
34 #include <stdio.h>
35 #include <gcrypt.h>
36 #include <time.h>
37 #include <sys/stat.h>
39 #define OPENPGP_NAME_SIZE 256
41 #define datum_append(x, y, z) _gnutls_datum_append_m (x, y, z, gnutls_realloc)
45 static void
46 release_mpi_array (mpi_t * arr, size_t n)
48 mpi_t x;
50 while (arr && n--)
52 x = *arr;
53 _gnutls_mpi_release (&x);
54 *arr = NULL;
55 arr++;
60 /* Map an OpenCDK error type to a GnuTLS error type. */
61 int
62 _gnutls_map_cdk_rc (int rc)
64 switch (rc)
66 case CDK_Success:
67 return 0;
68 case CDK_Too_Short:
69 return GNUTLS_E_SHORT_MEMORY_BUFFER;
70 case CDK_General_Error:
71 return GNUTLS_E_INTERNAL_ERROR;
72 case CDK_File_Error:
73 return GNUTLS_E_FILE_ERROR;
74 case CDK_MPI_Error:
75 return GNUTLS_E_MPI_SCAN_FAILED;
76 case CDK_Error_No_Key:
77 return GNUTLS_E_OPENPGP_GETKEY_FAILED;
78 case CDK_Wrong_Format:
79 return GNUTLS_E_OPENPGP_TRUSTDB_VERSION_UNSUPPORTED;
80 case CDK_Armor_Error:
81 return GNUTLS_E_BASE64_DECODING_ERROR;
82 case CDK_Inv_Value:
83 return GNUTLS_E_INVALID_REQUEST;
84 default:
85 return GNUTLS_E_INTERNAL_ERROR;
90 static unsigned long
91 buftou32 (const uint8_t * buf)
93 unsigned a;
94 a = buf[0] << 24;
95 a |= buf[1] << 16;
96 a |= buf[2] << 8;
97 a |= buf[3];
98 return a;
102 static int
103 kbx_blob_new (keybox_blob ** r_ctx)
105 keybox_blob *c;
107 if (!r_ctx)
109 gnutls_assert ();
110 return GNUTLS_E_INVALID_REQUEST;
113 c = cdk_calloc (1, sizeof *c);
114 if (!c)
116 gnutls_assert ();
117 return GNUTLS_E_MEMORY_ERROR;
119 *r_ctx = c;
121 return 0;
125 void
126 kbx_blob_release (keybox_blob * ctx)
128 if (!ctx)
129 return;
130 cdk_free (ctx->data);
131 cdk_free (ctx);
135 cdk_keydb_hd_t
136 kbx_to_keydb (keybox_blob * blob)
138 cdk_keydb_hd_t db;
139 cdk_error_t rc;
141 if (!blob)
143 gnutls_assert ();
144 return NULL;
147 switch (blob->type)
149 case KBX_BLOB_FILE:
150 rc = cdk_keydb_new_from_file (&db, 0, (const char*)blob->data);
151 break;
153 case KBX_BLOB_DATA:
154 rc = cdk_keydb_new_from_mem (&db, 0, blob->data, blob->size);
155 break;
157 default:
158 gnutls_assert ();
159 db = NULL;
160 break;
163 return db;
167 /* Extract a keybox blob from the given position. */
168 keybox_blob *
169 kbx_read_blob (const gnutls_datum_t * keyring, size_t pos)
171 keybox_blob *blob = NULL;
172 int rc;
174 if (!keyring || !keyring->data || pos > keyring->size)
176 gnutls_assert ();
177 return NULL;
180 rc = kbx_blob_new (&blob);
181 if (rc)
182 return NULL;
184 blob->type = keyring->data[pos];
185 if (blob->type != KBX_BLOB_FILE && blob->type != KBX_BLOB_DATA)
187 kbx_blob_release (blob);
188 return NULL;
190 blob->size = buftou32 (keyring->data + pos + 2);
191 if (!blob->size)
193 kbx_blob_release (blob);
194 return NULL;
196 blob->data = cdk_calloc (1, blob->size + 1);
197 if (!blob->data)
198 return NULL;
199 memcpy (blob->data, keyring->data + (pos + 6), blob->size);
200 blob->data[blob->size] = '\0';
202 return blob;
206 /* Creates a keyring blob from raw data
208 * Format:
209 * 1 octet type
210 * 1 octet armored
211 * 4 octet size of blob
212 * n octets data
214 static uint8_t *
215 kbx_data_to_keyring (int type, int enc, const char *data,
216 size_t size, size_t * r_size)
218 uint8_t *p = NULL;
220 if (!data)
221 return NULL;
223 p = gnutls_malloc (1 + 1 + 4 + size);
224 if (!p)
225 return NULL;
226 p[0] = type; /* type: {keyring,name} */
227 p[1] = enc; /* encoded: {plain, armored} */
228 p[2] = size >> 24;
229 p[3] = size >> 16;
230 p[4] = size >> 8;
231 p[5] = size;
232 memcpy (p + 6, data, size);
233 if (r_size)
234 *r_size = 6 + size;
235 return p;
239 static int
240 openpgp_pk_to_gnutls_cert (gnutls_cert * cert, cdk_pkt_pubkey_t pk)
242 uint8_t buf[512+2];
243 size_t nbytes;
244 int algo, i;
245 int rc = 0;
247 if (!cert || !pk)
249 gnutls_assert ();
250 return GNUTLS_E_INVALID_REQUEST;
253 /* GnuTLS OpenPGP does not support ELG keys */
254 if (is_ELG (pk->pubkey_algo))
255 return GNUTLS_E_UNWANTED_ALGORITHM;
257 algo = is_DSA (pk->pubkey_algo) ? GNUTLS_PK_DSA : GNUTLS_PK_RSA;
258 cert->subject_pk_algorithm = algo;
259 cert->version = pk->version;
260 cert->cert_type = GNUTLS_CRT_OPENPGP;
262 cert->key_usage = 0;
263 if (pk->pubkey_usage & CDK_KEY_USG_SIGN)
264 cert->key_usage = KEY_DIGITAL_SIGNATURE;
265 if (pk->pubkey_usage & CDK_KEY_USG_ENCR)
266 cert->key_usage = KEY_KEY_ENCIPHERMENT;
267 if (!cert->key_usage) /* Fallback code. */
269 if (pk->pubkey_algo == GCRY_PK_DSA || pk->pubkey_algo == GCRY_PK_RSA_S)
270 cert->key_usage = KEY_DIGITAL_SIGNATURE;
271 else if (pk->pubkey_algo == GCRY_PK_RSA_E)
272 cert->key_usage = KEY_KEY_ENCIPHERMENT;
273 else if (pk->pubkey_algo == GCRY_PK_RSA)
274 cert->key_usage = KEY_DIGITAL_SIGNATURE | KEY_KEY_ENCIPHERMENT;
277 cert->params_size = cdk_pk_get_npkey (pk->pubkey_algo);
278 for (i = 0; i < cert->params_size; i++)
280 nbytes = sizeof (buf) / sizeof (buf[0]);
281 cdk_pk_get_mpi (pk, i, buf, nbytes, &nbytes, NULL);
282 rc = _gnutls_mpi_scan_pgp (&cert->params[i], buf, &nbytes);
283 if (rc)
285 rc = GNUTLS_E_MPI_SCAN_FAILED;
286 break;
290 if (rc)
291 release_mpi_array (cert->params, i - 1);
292 return rc;
296 * _gnutls_openpgp_raw_privkey_to_gkey - Converts an OpenPGP secret key to GnuTLS
297 * @pkey: the GnuTLS private key context to store the key.
298 * @raw_key: the raw data which contains the whole key packets.
299 * @format: the format of the key packets.
301 * The RFC2440 (OpenPGP Message Format) data is converted into the
302 * GnuTLS specific data which is need to perform secret key operations.
304 * This function can read both BASE64 and RAW keys.
307 _gnutls_openpgp_raw_privkey_to_gkey (gnutls_privkey * pkey,
308 const gnutls_datum_t * raw_key,
309 gnutls_openpgp_key_fmt_t format)
311 cdk_kbnode_t snode = NULL;
312 cdk_packet_t pkt;
313 cdk_stream_t out;
314 cdk_pkt_seckey_t sk = NULL;
315 int pke_algo, i, j;
316 size_t nbytes = 0;
317 uint8_t buf[512];
318 int rc = 0;
320 if (!pkey || raw_key->size <= 0)
322 gnutls_assert ();
323 return GNUTLS_E_CERTIFICATE_ERROR;
326 rc = cdk_stream_tmp_new (&out);
327 if (rc)
328 return GNUTLS_E_CERTIFICATE_ERROR;
330 if (format == GNUTLS_OPENPGP_FMT_BASE64)
332 rc = cdk_stream_set_armor_flag (out, 0);
333 if (rc)
335 cdk_stream_close (out);
336 rc = _gnutls_map_cdk_rc (rc);
337 gnutls_assert ();
338 goto leave;
342 cdk_stream_write (out, raw_key->data, raw_key->size);
343 cdk_stream_seek (out, 0);
345 rc = cdk_keydb_get_keyblock (out, &snode);
346 cdk_stream_close (out);
347 if (rc)
349 rc = GNUTLS_E_OPENPGP_GETKEY_FAILED;
350 goto leave;
353 pkt = cdk_kbnode_find_packet (snode, CDK_PKT_SECRET_KEY);
354 if (!pkt)
356 rc = GNUTLS_E_OPENPGP_GETKEY_FAILED;
357 goto leave;
359 sk = pkt->pkt.secret_key;
360 pke_algo = sk->pk->pubkey_algo;
361 pkey->params_size = cdk_pk_get_npkey (pke_algo);
362 for (i = 0; i < pkey->params_size; i++)
364 nbytes = sizeof (buf) / sizeof (buf[0]);
365 cdk_pk_get_mpi (sk->pk, i, buf, nbytes, &nbytes, NULL);
366 rc = _gnutls_mpi_scan_pgp (&pkey->params[i], buf, &nbytes);
367 if (rc)
369 rc = GNUTLS_E_MPI_SCAN_FAILED;
370 release_mpi_array (pkey->params, i - 1);
371 goto leave;
375 pkey->params_size += cdk_pk_get_nskey (pke_algo);
376 for (j = 0; j < cdk_pk_get_nskey (pke_algo); j++, i++)
378 nbytes = sizeof (buf) / sizeof (buf[0]);
379 cdk_sk_get_mpi (sk, j, buf, nbytes, &nbytes, NULL);
380 rc = _gnutls_mpi_scan_pgp (&pkey->params[i], buf, &nbytes);
381 if (rc)
383 rc = GNUTLS_E_MPI_SCAN_FAILED;
384 release_mpi_array (pkey->params, i - 1);
385 goto leave;
389 if (is_ELG (pke_algo))
390 return GNUTLS_E_UNWANTED_ALGORITHM;
391 else if (is_DSA (pke_algo))
392 pkey->pk_algorithm = GNUTLS_PK_DSA;
393 else if (is_RSA (pke_algo))
394 pkey->pk_algorithm = GNUTLS_PK_RSA;
396 leave:
397 cdk_kbnode_release (snode);
398 return rc;
403 * _gnutls_openpgp_raw_key_to_gcert - Converts raw OpenPGP data to GnuTLS certs
404 * @cert: the certificate to store the data.
405 * @raw: the buffer which contains the whole OpenPGP key packets.
407 * The RFC2440 (OpenPGP Message Format) data is converted to a GnuTLS
408 * specific certificate.
411 _gnutls_openpgp_raw_key_to_gcert (gnutls_cert * cert,
412 const gnutls_datum_t * raw)
414 cdk_kbnode_t knode = NULL;
415 cdk_packet_t pkt = NULL;
416 int rc;
418 if (!cert)
420 gnutls_assert ();
421 return GNUTLS_E_INVALID_REQUEST;
424 memset (cert, 0, sizeof *cert);
426 rc = cdk_kbnode_read_from_mem (&knode, raw->data, raw->size);
427 if (!(rc = _gnutls_map_cdk_rc (rc)))
428 pkt = cdk_kbnode_find_packet (knode, CDK_PKT_PUBLIC_KEY);
429 if (!pkt)
431 gnutls_assert ();
432 rc = _gnutls_map_cdk_rc (rc);
434 if (!rc)
435 rc = _gnutls_set_datum (&cert->raw, raw->data, raw->size);
436 if (!rc)
437 rc = openpgp_pk_to_gnutls_cert (cert, pkt->pkt.public_key);
439 cdk_kbnode_release (knode);
440 return rc;
445 * gnutls_openpgp_get_key - Retrieve a key from the keyring.
446 * @key: the destination context to save the key.
447 * @keyring: the datum struct that contains all keyring information.
448 * @attr: The attribute (keyid, fingerprint, ...).
449 * @by: What attribute is used.
451 * This function can be used to retrieve keys by different pattern
452 * from a binary or a file keyring.
455 gnutls_openpgp_get_key (gnutls_datum_t * key,
456 const gnutls_datum_t * keyring, key_attr_t by,
457 opaque * pattern)
459 keybox_blob *blob = NULL;
460 cdk_keydb_hd_t db = NULL;
461 cdk_kbnode_t knode = NULL;
462 unsigned long keyid[2];
463 unsigned char *buf;
464 void *desc;
465 size_t len;
466 int rc = 0;
468 if (!key || !keyring || by == KEY_ATTR_NONE)
470 gnutls_assert ();
471 return GNUTLS_E_INVALID_REQUEST;
474 memset (key, 0, sizeof *key);
475 blob = kbx_read_blob (keyring, 0);
476 if (!blob)
477 return GNUTLS_E_MEMORY_ERROR;
478 db = kbx_to_keydb (blob);
480 if (by == KEY_ATTR_SHORT_KEYID)
482 keyid[0] = buftou32 (pattern);
483 desc = keyid;
485 else if (by == KEY_ATTR_KEYID)
487 keyid[0] = buftou32 (pattern);
488 keyid[1] = buftou32 (pattern + 4);
489 desc = keyid;
491 else
492 desc = pattern;
493 rc = cdk_keydb_search_start (db, by, desc);
494 if (!rc)
495 rc = cdk_keydb_search (db, &knode);
496 if (rc)
498 rc = _gnutls_map_cdk_rc (rc);
499 goto leave;
502 if (!cdk_kbnode_find (knode, CDK_PKT_PUBLIC_KEY))
504 rc = GNUTLS_E_OPENPGP_GETKEY_FAILED;
505 goto leave;
508 /* We let the function allocate the buffer to avoid
509 to call the function twice. */
510 rc = cdk_kbnode_write_to_mem_alloc (knode, &buf, &len);
511 if (!rc)
512 datum_append (key, buf, len);
513 cdk_free (buf);
515 leave:
516 cdk_keydb_free (db);
517 cdk_kbnode_release (knode);
518 kbx_blob_release (blob);
519 return rc;
523 /* Convert the stream to a datum. In this case we use the mmap
524 function to map the entire stream to a buffer. */
525 static int
526 stream_to_datum (cdk_stream_t inp, gnutls_datum_t * raw)
528 uint8_t *buf;
529 size_t buflen;
531 if (!buf || !raw)
533 gnutls_assert ();
534 return GNUTLS_E_INVALID_REQUEST;
537 cdk_stream_mmap (inp, &buf, &buflen);
538 datum_append (raw, buf, buflen);
539 cdk_free (buf);
541 if (!buflen)
542 return GNUTLS_E_INTERNAL_ERROR;
543 return 0;
549 * gnutls_certificate_set_openpgp_key_mem - Used to set OpenPGP keys
550 * @res: the destination context to save the data.
551 * @cert: the datum that contains the public key.
552 * @key: the datum that contains the secret key.
554 * This funtion is used to load OpenPGP keys into the GnuTLS credential
555 * structure.
556 * It doesn't matter whether the keys are armored or not, but the files
557 * should only contain one key which should not be encrypted.
560 gnutls_certificate_set_openpgp_key_mem (gnutls_certificate_credentials_t
561 res, const gnutls_datum_t * cert,
562 const gnutls_datum_t * key)
564 gnutls_datum_t raw;
565 cdk_kbnode_t knode = NULL, ctx = NULL, p;
566 cdk_packet_t pkt;
567 int i = 0;
568 int rc = 0;
569 cdk_stream_t inp = NULL;
571 if (!res || !key || !cert)
573 gnutls_assert ();
574 return GNUTLS_E_INVALID_REQUEST;
577 rc = cdk_stream_tmp_from_mem (cert->data, cert->size, &inp);
578 if (rc)
580 rc = _gnutls_map_cdk_rc (rc);
581 gnutls_assert ();
582 return rc;
585 if (cdk_armor_filter_use (inp))
586 cdk_stream_set_armor_flag (inp, 0);
588 res->cert_list = gnutls_realloc_fast (res->cert_list,
589 (1 + res->ncerts) *
590 sizeof (gnutls_cert *));
591 if (res->cert_list == NULL)
593 gnutls_assert ();
594 return GNUTLS_E_MEMORY_ERROR;
597 res->cert_list_length = gnutls_realloc_fast (res->cert_list_length,
598 (1 +
599 res->ncerts) * sizeof (int));
600 if (res->cert_list_length == NULL)
602 gnutls_assert ();
603 return GNUTLS_E_MEMORY_ERROR;
606 res->cert_list[res->ncerts] = gnutls_calloc (1, sizeof (gnutls_cert));
607 if (res->cert_list[res->ncerts] == NULL)
609 gnutls_assert ();
610 return GNUTLS_E_MEMORY_ERROR;
613 i = 1;
614 rc = cdk_keydb_get_keyblock (inp, &knode);
616 while (knode && (p = cdk_kbnode_walk (knode, &ctx, 0)))
618 pkt = cdk_kbnode_get_packet (p);
619 if (i > MAX_PUBLIC_PARAMS_SIZE)
621 gnutls_assert ();
622 break;
624 if (pkt->pkttype == CDK_PKT_PUBLIC_KEY)
626 int n = res->ncerts;
628 cdk_pkt_pubkey_t pk = pkt->pkt.public_key;
629 res->cert_list_length[n] = 1;
631 if (stream_to_datum (inp, &res->cert_list[n][0].raw))
633 gnutls_assert ();
634 return GNUTLS_E_MEMORY_ERROR;
636 rc = openpgp_pk_to_gnutls_cert (&res->cert_list[n][0], pk);
637 if (rc < 0)
639 gnutls_assert ();
640 return rc;
642 i++;
646 if (rc == CDK_EOF && i > 1)
647 rc = 0;
649 cdk_stream_close (inp);
651 if (rc)
653 cdk_kbnode_release (knode);
654 gnutls_assert ();
655 rc = _gnutls_map_cdk_rc (rc);
656 goto leave;
659 res->ncerts++;
660 res->pkey = gnutls_realloc_fast (res->pkey,
661 (res->ncerts) * sizeof (gnutls_privkey));
662 if (!res->pkey)
664 gnutls_assert ();
665 return GNUTLS_E_MEMORY_ERROR;
668 /* ncerts has been incremented before */
670 rc = cdk_stream_tmp_from_mem (key->data, key->size, &inp);
671 if (rc)
673 gnutls_assert ();
674 return GNUTLS_E_INTERNAL_ERROR;
677 if (cdk_armor_filter_use (inp))
678 cdk_stream_set_armor_flag (inp, 0);
680 memset (&raw, 0, sizeof raw);
682 if (stream_to_datum (inp, &raw))
684 gnutls_assert ();
685 return GNUTLS_E_INTERNAL_ERROR;
687 cdk_stream_close (inp);
689 rc = _gnutls_openpgp_raw_privkey_to_gkey (&res->pkey[res->ncerts - 1],
690 &raw,
691 GNUTLS_OPENPGP_FMT_RAW);
692 if (rc)
694 gnutls_assert ();
697 _gnutls_free_datum (&raw);
699 leave:
700 cdk_kbnode_release (knode);
702 return rc;
707 * gnutls_certificate_set_openpgp_key_file - Used to set OpenPGP keys
708 * @res: the destination context to save the data.
709 * @certfile: the file that contains the public key.
710 * @keyfile: the file that contains the secret key.
712 * This funtion is used to load OpenPGP keys into the GnuTLS credentials structure.
713 * It doesn't matter whether the keys are armored or not, but the files
714 * should only contain one key which should not be encrypted.
717 gnutls_certificate_set_openpgp_key_file (gnutls_certificate_credentials_t
718 res, const char *certfile,
719 const char *keyfile)
721 struct stat statbuf;
722 gnutls_datum_t key, cert;
723 int rc;
725 if (!res || !keyfile || !certfile)
727 gnutls_assert ();
728 return GNUTLS_E_INVALID_REQUEST;
731 if (stat (certfile, &statbuf) || stat (keyfile, &statbuf))
733 gnutls_assert ();
734 return GNUTLS_E_FILE_ERROR;
737 cert.data = read_binary_file (certfile, &cert.size);
738 if (cert.data == NULL)
740 gnutls_assert ();
741 return GNUTLS_E_FILE_ERROR;
744 key.data = read_binary_file (keyfile, &key.size);
745 if (key.data == NULL)
747 gnutls_assert ();
748 free (cert.data);
749 return GNUTLS_E_FILE_ERROR;
752 rc = gnutls_certificate_set_openpgp_key_mem (res, &cert, &key);
754 free (cert.data);
755 free (key.data);
757 if (rc < 0)
759 gnutls_assert ();
760 return rc;
763 return 0;
768 gnutls_openpgp_count_key_names (const gnutls_datum_t * cert)
770 cdk_kbnode_t knode, p, ctx;
771 cdk_packet_t pkt;
772 int nuids;
774 if (cert == NULL)
776 gnutls_assert ();
777 return 0;
780 if (cdk_kbnode_read_from_mem (&knode, cert->data, cert->size))
782 gnutls_assert ();
783 return 0;
786 ctx = NULL;
787 for (nuids = 0;;)
789 p = cdk_kbnode_walk (knode, &ctx, 0);
790 if (!p)
791 break;
792 pkt = cdk_kbnode_get_packet (p);
793 if (pkt->pkttype == CDK_PKT_USER_ID)
794 nuids++;
797 cdk_kbnode_release (knode);
798 return nuids;
806 * gnutls_openpgp_add_keyring_file - Adds a keyring file for OpenPGP
807 * @keyring: data buffer to store the file.
808 * @name: filename of the keyring.
810 * The function is used to set keyrings that will be used internally
811 * by various OpenCDK functions. For example to find a key when it
812 * is needed for an operations.
815 gnutls_openpgp_add_keyring_file (gnutls_datum_t * keyring, const char *name)
817 cdk_stream_t inp = NULL;
818 uint8_t *blob;
819 size_t nbytes;
820 int enc = 0;
821 int rc = 0;
823 if (!keyring || !name)
825 gnutls_assert ();
826 return GNUTLS_E_INVALID_REQUEST;
829 rc = cdk_stream_open (name, &inp);
830 if (rc)
831 return _gnutls_map_cdk_rc (rc);
832 enc = cdk_armor_filter_use (inp);
833 cdk_stream_close (inp);
835 blob = kbx_data_to_keyring (KBX_BLOB_FILE, enc, name,
836 strlen (name), &nbytes);
837 if (blob && nbytes)
839 if (datum_append (keyring, blob, nbytes) < 0)
841 gnutls_assert ();
842 return GNUTLS_E_MEMORY_ERROR;
844 gnutls_free (blob);
846 return 0;
851 * gnutls_openpgp_add_keyring_mem - Adds keyring data for OpenPGP
852 * @keyring: data buffer to store the file.
853 * @data: the binary data of the keyring.
854 * @len: the size of the binary buffer.
856 * Same as gnutls_openpgp_add_keyring_mem but now we store the
857 * data instead of the filename.
860 gnutls_openpgp_add_keyring_mem (gnutls_datum_t * keyring,
861 const void *data, size_t len)
863 uint8_t *blob;
864 size_t nbytes = 0;
866 if (!keyring || !data || !len)
868 gnutls_assert ();
869 return GNUTLS_E_INVALID_REQUEST;
872 blob = kbx_data_to_keyring (KBX_BLOB_DATA, 0, data, len, &nbytes);
873 if (blob && nbytes)
875 if (datum_append (keyring, blob, nbytes) < 0)
877 gnutls_assert ();
878 return GNUTLS_E_MEMORY_ERROR;
880 gnutls_free (blob);
883 return 0;
888 * gnutls_certificate_set_openpgp_keyring_file - Adds a keyring file for OpenPGP
889 * @c: A certificate credentials structure
890 * @file: filename of the keyring.
892 * The function is used to set keyrings that will be used internally
893 * by various OpenPGP functions. For example to find a key when it
894 * is needed for an operations. The keyring will also be used at the
895 * verification functions.
899 gnutls_certificate_set_openpgp_keyring_file
900 (gnutls_certificate_credentials_t c, const char *file)
902 struct stat statbuf;
904 if (!c || !file)
906 gnutls_assert ();
907 return GNUTLS_E_INVALID_REQUEST;
910 if (stat (file, &statbuf))
911 return GNUTLS_E_FILE_ERROR;
913 return gnutls_openpgp_add_keyring_file (&c->keyring, file);
917 * gnutls_certificate_set_openpgp_keyring_mem - Add keyring data for OpenPGP
918 * @c: A certificate credentials structure
919 * @data: buffer with keyring data.
920 * @dlen: length of data buffer.
922 * The function is used to set keyrings that will be used internally
923 * by various OpenPGP functions. For example to find a key when it
924 * is needed for an operations. The keyring will also be used at the
925 * verification functions.
929 gnutls_certificate_set_openpgp_keyring_mem (gnutls_certificate_credentials_t
930 c, const opaque * data,
931 size_t dlen)
933 cdk_stream_t inp;
934 size_t count;
935 uint8_t *buf;
936 int rc;
938 if (!c || !data || !dlen)
940 gnutls_assert ();
941 return GNUTLS_E_INVALID_REQUEST;
944 rc = cdk_stream_tmp_from_mem (data, dlen, &inp);
945 if (rc)
946 return GNUTLS_E_FILE_ERROR;
948 /* Maybe it's a little confusing that we check the output..
949 but it's possible, that the data we want to add, is armored
950 and we only want to store plaintext keyring data. */
951 if (cdk_armor_filter_use (inp))
952 cdk_stream_set_armor_flag (inp, 0);
954 /* fixme: this is possible the armored length. */
955 count = cdk_stream_get_length (inp);
956 buf = gnutls_malloc (count + 1);
957 if (!buf)
959 gnutls_assert ();
960 cdk_stream_close (inp);
961 return GNUTLS_E_MEMORY_ERROR;
964 count = cdk_stream_read (inp, buf, count);
965 buf[count] = '\0';
966 rc = gnutls_openpgp_add_keyring_mem (&c->keyring, buf, count);
967 cdk_stream_close (inp);
969 return rc;
973 * _gnutls_openpgp_request_key - Receives a key from a database, key server etc
974 * @ret - a pointer to gnutls_datum_t structure.
975 * @cred - a gnutls_certificate_credentials_t structure.
976 * @key_fingerprint - The keyFingerprint
977 * @key_fingerprint_size - the size of the fingerprint
979 * Retrieves a key from a local database, keyring, or a key server. The
980 * return value is locally allocated.
984 _gnutls_openpgp_request_key (gnutls_session_t session, gnutls_datum_t * ret,
985 const gnutls_certificate_credentials_t cred,
986 opaque * key_fpr, int key_fpr_size)
988 int rc = 0;
990 if (!ret || !cred || !key_fpr)
992 gnutls_assert ();
993 return GNUTLS_E_INVALID_REQUEST;
996 if (key_fpr_size != 16 && key_fpr_size != 20)
997 return GNUTLS_E_HASH_FAILED; /* only MD5 and SHA1 are supported */
999 rc = gnutls_openpgp_get_key (ret, &cred->keyring, KEY_ATTR_FPR, key_fpr);
1000 if (rc >= 0) /* key was found */
1001 return rc;
1002 else
1003 rc = GNUTLS_E_OPENPGP_GETKEY_FAILED;
1005 /* If the callback function was set, then try this one. */
1006 if (session->internals.openpgp_recv_key_func != NULL)
1008 rc = session->internals.openpgp_recv_key_func (session,
1009 key_fpr,
1010 key_fpr_size, ret);
1011 if (rc < 0)
1013 gnutls_assert ();
1014 return GNUTLS_E_OPENPGP_GETKEY_FAILED;
1018 return rc;
1023 * gnutls_certificate_set_openpgp_keyserver - Used to set an OpenPGP key server
1024 * @res: the destination context to save the data.
1025 * @keyserver: is the key server address
1026 * @port: is the key server port to connect to
1028 * This funtion will set a key server for use with openpgp keys. This
1029 * key server will only be used if the peer sends a key fingerprint instead
1030 * of a key in the handshake. Using a key server may delay the handshake
1031 * process.
1035 gnutls_certificate_set_openpgp_keyserver (gnutls_certificate_credentials_t
1036 res, const char *keyserver,
1037 int port)
1039 if (!res || !keyserver)
1041 gnutls_assert ();
1042 return GNUTLS_E_INVALID_REQUEST;
1045 if (!port)
1046 port = 11371;
1048 gnutls_free (res->pgp_key_server);
1049 res->pgp_key_server = gnutls_strdup (keyserver);
1050 if (!res->pgp_key_server)
1051 return GNUTLS_E_MEMORY_ERROR;
1052 res->pgp_key_server_port = port;
1054 return 0;
1059 * gnutls_certificate_set_openpgp_trustdb - Used to set an GnuPG trustdb
1060 * @res: the destination context to save the data.
1061 * @trustdb: is the trustdb filename
1063 * This funtion will set a GnuPG trustdb which will be used in key
1064 * verification functions. Only version 3 trustdb files are supported.
1068 gnutls_certificate_set_openpgp_trustdb (gnutls_certificate_credentials_t
1069 res, const char *trustdb)
1071 if (!res || !trustdb)
1073 gnutls_assert ();
1074 return GNUTLS_E_INVALID_REQUEST;
1077 /* FIXME: We do not support the trustdb yet. */
1078 gnutls_free (res->pgp_trustdb);
1079 res->pgp_trustdb = gnutls_strdup (trustdb);
1080 if (res->pgp_trustdb == NULL)
1081 return GNUTLS_E_MEMORY_ERROR;
1083 return 0;
1087 * gnutls_openpgp_set_recv_key_function - Used to set a key retrieval callback for PGP keys
1088 * @session: a TLS session
1089 * @func: the callback
1091 * This funtion will set a key retrieval function for OpenPGP keys. This
1092 * callback is only useful in server side, and will be used if the peer
1093 * sent a key fingerprint instead of a full key.
1096 void
1097 gnutls_openpgp_set_recv_key_function (gnutls_session_t session,
1098 gnutls_openpgp_recv_key_func func)
1100 session->internals.openpgp_recv_key_func = func;
1104 /* Copies a gnutls_openpgp_privkey_t to a gnutls_privkey structure. */
1106 _gnutls_openpgp_privkey_to_gkey (gnutls_privkey * dest,
1107 gnutls_openpgp_privkey_t src)
1109 int i, ret;
1111 memset (dest, 0, sizeof (gnutls_privkey));
1113 for (i = 0; i < src->pkey.params_size; i++)
1115 dest->params[i] = _gnutls_mpi_copy (src->pkey.params[i]);
1116 if (dest->params[i] == NULL)
1118 gnutls_assert ();
1119 ret = GNUTLS_E_MEMORY_ERROR;
1120 goto cleanup;
1124 dest->pk_algorithm = src->pkey.pk_algorithm;
1125 dest->params_size = src->pkey.params_size;
1127 return 0;
1129 cleanup:
1130 for (i = 0; i < src->pkey.params_size; i++)
1131 _gnutls_mpi_release (&dest->params[i]);
1132 return ret;
1135 /* Converts a parsed gnutls_openpgp_key_t to a gnutls_cert structure.
1138 _gnutls_openpgp_key_to_gcert (gnutls_cert * gcert, gnutls_openpgp_key_t cert)
1140 opaque *der;
1141 size_t der_size = 0;
1142 gnutls_datum_t raw;
1143 int ret;
1145 memset (gcert, 0, sizeof (gnutls_cert));
1146 gcert->cert_type = GNUTLS_CRT_OPENPGP;
1149 ret = gnutls_openpgp_key_export (cert, GNUTLS_OPENPGP_FMT_RAW,
1150 NULL, &der_size);
1151 if (ret != GNUTLS_E_SHORT_MEMORY_BUFFER)
1153 gnutls_assert ();
1154 return ret;
1157 der = gnutls_malloc (der_size);
1158 if (der == NULL)
1160 gnutls_assert ();
1161 return GNUTLS_E_MEMORY_ERROR;
1164 ret = gnutls_openpgp_key_export (cert, GNUTLS_OPENPGP_FMT_RAW,
1165 der, &der_size);
1166 if (ret < 0)
1168 gnutls_assert ();
1169 gnutls_free (der);
1170 return ret;
1173 raw.data = der;
1174 raw.size = der_size;
1176 ret = _gnutls_openpgp_raw_key_to_gcert (gcert, &raw);
1177 if (ret < 0)
1179 gnutls_assert ();
1180 gnutls_free (der);
1181 return ret;
1184 gnutls_free (der);
1186 return 0;
1191 * gnutls_certificate_set_openpgp_key - Used to set keys in a gnutls_certificate_credentials_t structure
1192 * @res: is an #gnutls_certificate_credentials_t structure.
1193 * @key: contains an openpgp public key
1194 * @pkey: is an openpgp private key
1196 * This function sets a certificate/private key pair in the
1197 * gnutls_certificate_credentials_t structure. This function may be called
1198 * more than once (in case multiple keys/certificates exist for the
1199 * server).
1203 gnutls_certificate_set_openpgp_key (gnutls_certificate_credentials_t
1204 res, gnutls_openpgp_key_t key,
1205 gnutls_openpgp_privkey_t pkey)
1207 int ret;
1209 /* this should be first */
1211 res->pkey = gnutls_realloc_fast (res->pkey,
1212 (res->ncerts + 1) *
1213 sizeof (gnutls_privkey));
1214 if (res->pkey == NULL)
1216 gnutls_assert ();
1217 return GNUTLS_E_MEMORY_ERROR;
1220 ret = _gnutls_openpgp_privkey_to_gkey (&res->pkey[res->ncerts], pkey);
1221 if (ret < 0)
1223 gnutls_assert ();
1224 return ret;
1227 res->cert_list = gnutls_realloc_fast (res->cert_list,
1228 (1 +
1229 res->ncerts) *
1230 sizeof (gnutls_cert *));
1231 if (res->cert_list == NULL)
1233 gnutls_assert ();
1234 return GNUTLS_E_MEMORY_ERROR;
1237 res->cert_list_length = gnutls_realloc_fast (res->cert_list_length,
1238 (1 +
1239 res->ncerts) * sizeof (int));
1240 if (res->cert_list_length == NULL)
1242 gnutls_assert ();
1243 return GNUTLS_E_MEMORY_ERROR;
1246 res->cert_list[res->ncerts] = gnutls_calloc (1, sizeof (gnutls_cert));
1247 if (res->cert_list[res->ncerts] == NULL)
1249 gnutls_assert ();
1250 return GNUTLS_E_MEMORY_ERROR;
1253 res->cert_list_length[res->ncerts] = 1;
1255 ret = _gnutls_openpgp_key_to_gcert (res->cert_list[res->ncerts], key);
1256 if (ret < 0)
1258 gnutls_assert ();
1259 return ret;
1262 res->ncerts++;
1264 /* FIXME: Check if the keys match. */
1266 return 0;