2 * Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
3 * Free Software Foundation, Inc.
5 * Author: Timo Schulz, Nikos Mavrogiannopoulos
7 * This file is part of GnuTLS.
9 * The GnuTLS is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public License
11 * as published by the Free Software Foundation; either version 2.1 of
12 * the License, or (at your option) any later version.
14 * This library is distributed in the hope that it will be useful, but
15 * WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this library; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
26 #include "gnutls_int.h"
27 #include "gnutls_errors.h"
28 #include "gnutls_mpi.h"
29 #include "gnutls_num.h"
30 #include "gnutls_cert.h"
31 #include "gnutls_datum.h"
32 #include "gnutls_global.h"
33 #include "gnutls_openpgp.h"
34 #include "read-file.h"
35 #include <gnutls_str.h>
36 #include <gnutls_sig.h>
40 #define datum_append(x, y, z) _gnutls_datum_append_m (x, y, z, gnutls_realloc)
42 /* Map an OpenCDK error type to a GnuTLS error type. */
44 _gnutls_map_cdk_rc (int rc)
51 return GNUTLS_E_SHORT_MEMORY_BUFFER;
52 case CDK_General_Error:
53 return GNUTLS_E_INTERNAL_ERROR;
55 return GNUTLS_E_FILE_ERROR;
57 return GNUTLS_E_MPI_SCAN_FAILED;
58 case CDK_Error_No_Key:
59 return GNUTLS_E_OPENPGP_GETKEY_FAILED;
61 return GNUTLS_E_BASE64_DECODING_ERROR;
63 return GNUTLS_E_INVALID_REQUEST;
65 return GNUTLS_E_INTERNAL_ERROR;
70 * _gnutls_openpgp_raw_crt_to_gcert - Converts raw OpenPGP data to GnuTLS certs
71 * @cert: the certificate to store the data.
72 * @raw: the buffer which contains the whole OpenPGP key packets.
74 * The RFC2440 (OpenPGP Message Format) data is converted to a GnuTLS
75 * specific certificate.
78 _gnutls_openpgp_raw_crt_to_gcert (gnutls_cert * gcert,
79 const gnutls_datum_t * raw,
80 const gnutls_openpgp_keyid_t keyid)
82 gnutls_openpgp_crt_t pcrt;
85 ret = gnutls_openpgp_crt_init (&pcrt);
92 ret = gnutls_openpgp_crt_import (pcrt, raw, GNUTLS_OPENPGP_FMT_RAW);
96 gnutls_openpgp_crt_deinit (pcrt);
102 ret = gnutls_openpgp_crt_set_preferred_key_id (pcrt, keyid);
106 gnutls_openpgp_crt_deinit (pcrt);
111 ret = _gnutls_openpgp_crt_to_gcert (gcert, pcrt);
112 gnutls_openpgp_crt_deinit (pcrt);
118 * gnutls_certificate_set_openpgp_key:
119 * @res: is a #gnutls_certificate_credentials_t structure.
120 * @key: contains an openpgp public key
121 * @pkey: is an openpgp private key
123 * This function sets a certificate/private key pair in the
124 * gnutls_certificate_credentials_t structure. This function may be
125 * called more than once (in case multiple keys/certificates exist
128 * Note that this function requires that the preferred key ids have
129 * been set and be used. See gnutls_openpgp_crt_set_preferred_key_id().
130 * Otherwise the master key will be used.
132 * Returns: On success, %GNUTLS_E_SUCCESS (zero) is returned,
133 * otherwise an error code is returned.
136 gnutls_certificate_set_openpgp_key (gnutls_certificate_credentials_t res,
137 gnutls_openpgp_crt_t crt,
138 gnutls_openpgp_privkey_t pkey)
141 gnutls_privkey_t privkey;
144 /* this should be first */
146 ret = gnutls_privkey_init (&privkey);
154 gnutls_privkey_import_openpgp (privkey, pkey,
155 GNUTLS_PRIVKEY_IMPORT_COPY);
158 gnutls_privkey_deinit (privkey);
164 ccert = gnutls_calloc (1, sizeof (gnutls_cert));
168 gnutls_privkey_deinit (privkey);
169 return GNUTLS_E_MEMORY_ERROR;
172 ret = _gnutls_openpgp_crt_to_gcert (ccert, crt);
177 gnutls_privkey_deinit (privkey);
181 ret = certificate_credentials_append_pkey (res, privkey);
183 ret = certificate_credential_append_crt_list (res, ccert, 1);
189 gnutls_privkey_deinit (privkey);
195 /* FIXME: Check if the keys match. */
201 * gnutls_openpgp_get_key:
202 * @key: the destination context to save the key.
203 * @keyring: the datum struct that contains all keyring information.
204 * @attr: The attribute (keyid, fingerprint, ...).
205 * @by: What attribute is used.
207 * This function can be used to retrieve keys by different pattern
208 * from a binary or a file keyring.
211 gnutls_openpgp_get_key (gnutls_datum_t * key,
212 gnutls_openpgp_keyring_t keyring, key_attr_t by,
215 cdk_kbnode_t knode = NULL;
216 unsigned long keyid[2];
221 cdk_keydb_search_t st;
223 if (!key || !keyring || by == KEY_ATTR_NONE)
226 return GNUTLS_E_INVALID_REQUEST;
229 memset (key, 0, sizeof *key);
231 if (by == KEY_ATTR_SHORT_KEYID)
233 keyid[0] = _gnutls_read_uint32 (pattern);
236 else if (by == KEY_ATTR_KEYID)
238 keyid[0] = _gnutls_read_uint32 (pattern);
239 keyid[1] = _gnutls_read_uint32 (pattern + 4);
244 rc = cdk_keydb_search_start (&st, keyring->db, by, desc);
246 rc = cdk_keydb_search (st, keyring->db, &knode);
248 cdk_keydb_search_release (st);
252 rc = _gnutls_map_cdk_rc (rc);
256 if (!cdk_kbnode_find (knode, CDK_PKT_PUBLIC_KEY))
258 rc = GNUTLS_E_OPENPGP_GETKEY_FAILED;
262 /* We let the function allocate the buffer to avoid
263 to call the function twice. */
264 rc = cdk_kbnode_write_to_mem_alloc (knode, &buf, &len);
266 datum_append (key, buf, len);
270 cdk_kbnode_release (knode);
275 * gnutls_certificate_set_openpgp_key_mem:
276 * @res: the destination context to save the data.
277 * @cert: the datum that contains the public key.
278 * @key: the datum that contains the secret key.
279 * @format: the format of the keys
281 * This funtion is used to load OpenPGP keys into the GnuTLS credential
282 * structure. The datum should contain at least one valid non encrypted subkey.
284 * Returns: On success, %GNUTLS_E_SUCCESS is returned, otherwise a
285 * negative error value.
288 gnutls_certificate_set_openpgp_key_mem (gnutls_certificate_credentials_t res,
289 const gnutls_datum_t * cert,
290 const gnutls_datum_t * key,
291 gnutls_openpgp_crt_fmt_t format)
293 return gnutls_certificate_set_openpgp_key_mem2 (res, cert, key,
298 * gnutls_certificate_set_openpgp_key_file:
299 * @res: the destination context to save the data.
300 * @certfile: the file that contains the public key.
301 * @keyfile: the file that contains the secret key.
302 * @format: the format of the keys
304 * This funtion is used to load OpenPGP keys into the GnuTLS
305 * credentials structure. The file should contain at least one valid non encrypted subkey.
307 * Returns: On success, %GNUTLS_E_SUCCESS is returned, otherwise a
308 * negative error value.
311 gnutls_certificate_set_openpgp_key_file (gnutls_certificate_credentials_t res,
312 const char *certfile,
314 gnutls_openpgp_crt_fmt_t format)
316 return gnutls_certificate_set_openpgp_key_file2 (res, certfile,
317 keyfile, NULL, format);
321 get_keyid (gnutls_openpgp_keyid_t keyid, const char *str)
323 size_t keyid_size = GNUTLS_OPENPGP_KEYID_SIZE;
325 if (strlen (str) != 16)
328 ("The OpenPGP subkey ID has to be 16 hexadecimal characters.\n");
329 return GNUTLS_E_INVALID_REQUEST;
332 if (_gnutls_hex2bin (str, strlen (str), keyid, &keyid_size) < 0)
334 _gnutls_debug_log ("Error converting hex string: %s.\n", str);
335 return GNUTLS_E_INVALID_REQUEST;
342 * gnutls_certificate_set_openpgp_key_mem2:
343 * @res: the destination context to save the data.
344 * @cert: the datum that contains the public key.
345 * @key: the datum that contains the secret key.
346 * @subkey_id: a hex encoded subkey id
347 * @format: the format of the keys
349 * This funtion is used to load OpenPGP keys into the GnuTLS
350 * credentials structure. The datum should contain at least one valid non encrypted subkey.
352 * The special keyword "auto" is also accepted as @subkey_id. In that
353 * case the gnutls_openpgp_crt_get_auth_subkey() will be used to
354 * retrieve the subkey.
356 * Returns: On success, %GNUTLS_E_SUCCESS is returned, otherwise a
357 * negative error value.
362 gnutls_certificate_set_openpgp_key_mem2 (gnutls_certificate_credentials_t res,
363 const gnutls_datum_t * cert,
364 const gnutls_datum_t * key,
365 const char *subkey_id,
366 gnutls_openpgp_crt_fmt_t format)
368 gnutls_openpgp_privkey_t pkey;
369 gnutls_openpgp_crt_t crt;
371 uint8_t keyid[GNUTLS_OPENPGP_KEYID_SIZE];
373 ret = gnutls_openpgp_privkey_init (&pkey);
380 ret = gnutls_openpgp_privkey_import (pkey, key, format, NULL, 0);
384 gnutls_openpgp_privkey_deinit (pkey);
388 ret = gnutls_openpgp_crt_init (&crt);
392 gnutls_openpgp_privkey_deinit (pkey);
396 ret = gnutls_openpgp_crt_import (crt, cert, format);
400 gnutls_openpgp_privkey_deinit (pkey);
401 gnutls_openpgp_crt_deinit (crt);
405 if (subkey_id != NULL)
407 if (strcasecmp (subkey_id, "auto") == 0)
408 ret = gnutls_openpgp_crt_get_auth_subkey (crt, keyid, 1);
410 ret = get_keyid (keyid, subkey_id);
417 ret = gnutls_openpgp_crt_set_preferred_key_id (crt, keyid);
419 ret = gnutls_openpgp_privkey_set_preferred_key_id (pkey, keyid);
425 gnutls_openpgp_privkey_deinit (pkey);
426 gnutls_openpgp_crt_deinit (crt);
431 ret = gnutls_certificate_set_openpgp_key (res, crt, pkey);
433 gnutls_openpgp_crt_deinit (crt);
434 gnutls_openpgp_privkey_deinit (pkey);
440 * gnutls_certificate_set_openpgp_key_file2:
441 * @res: the destination context to save the data.
442 * @certfile: the file that contains the public key.
443 * @keyfile: the file that contains the secret key.
444 * @subkey_id: a hex encoded subkey id
445 * @format: the format of the keys
447 * This funtion is used to load OpenPGP keys into the GnuTLS credential
448 * structure. The file should contain at least one valid non encrypted subkey.
450 * The special keyword "auto" is also accepted as @subkey_id. In that
451 * case the gnutls_openpgp_crt_get_auth_subkey() will be used to
452 * retrieve the subkey.
454 * Returns: On success, %GNUTLS_E_SUCCESS is returned, otherwise a
455 * negative error value.
460 gnutls_certificate_set_openpgp_key_file2 (gnutls_certificate_credentials_t
461 res, const char *certfile,
463 const char *subkey_id,
464 gnutls_openpgp_crt_fmt_t format)
467 gnutls_datum_t key, cert;
471 if (!res || !keyfile || !certfile)
474 return GNUTLS_E_INVALID_REQUEST;
477 if (stat (certfile, &statbuf) || stat (keyfile, &statbuf))
480 return GNUTLS_E_FILE_ERROR;
483 cert.data = read_binary_file (certfile, &size);
484 cert.size = (unsigned int) size;
485 if (cert.data == NULL)
488 return GNUTLS_E_FILE_ERROR;
491 key.data = read_binary_file (keyfile, &size);
492 key.size = (unsigned int) size;
493 if (key.data == NULL)
497 return GNUTLS_E_FILE_ERROR;
501 gnutls_certificate_set_openpgp_key_mem2 (res, &cert, &key, subkey_id,
518 gnutls_openpgp_count_key_names (const gnutls_datum_t * cert)
520 cdk_kbnode_t knode, p, ctx;
530 if (cdk_kbnode_read_from_mem (&knode, cert->data, cert->size))
539 p = cdk_kbnode_walk (knode, &ctx, 0);
542 pkt = cdk_kbnode_get_packet (p);
543 if (pkt->pkttype == CDK_PKT_USER_ID)
547 cdk_kbnode_release (knode);
552 * gnutls_certificate_set_openpgp_keyring_file:
553 * @c: A certificate credentials structure
554 * @file: filename of the keyring.
555 * @format: format of keyring.
557 * The function is used to set keyrings that will be used internally
558 * by various OpenPGP functions. For example to find a key when it
559 * is needed for an operations. The keyring will also be used at the
560 * verification functions.
562 * Returns: On success, %GNUTLS_E_SUCCESS is returned, otherwise a
563 * negative error value.
566 gnutls_certificate_set_openpgp_keyring_file (gnutls_certificate_credentials_t
568 gnutls_openpgp_crt_fmt_t format)
577 return GNUTLS_E_INVALID_REQUEST;
580 ring.data = read_binary_file (file, &size);
581 ring.size = (unsigned int) size;
582 if (ring.data == NULL)
585 return GNUTLS_E_FILE_ERROR;
589 gnutls_certificate_set_openpgp_keyring_mem (c, ring.data, ring.size,
598 * gnutls_certificate_set_openpgp_keyring_mem:
599 * @c: A certificate credentials structure
600 * @data: buffer with keyring data.
601 * @dlen: length of data buffer.
602 * @format: the format of the keyring
604 * The function is used to set keyrings that will be used internally
605 * by various OpenPGP functions. For example to find a key when it
606 * is needed for an operations. The keyring will also be used at the
607 * verification functions.
609 * Returns: On success, %GNUTLS_E_SUCCESS is returned, otherwise a
610 * negative error value.
613 gnutls_certificate_set_openpgp_keyring_mem (gnutls_certificate_credentials_t
614 c, const opaque * data,
616 gnutls_openpgp_crt_fmt_t format)
618 gnutls_datum_t ddata;
621 ddata.data = (void *) data;
624 if (!c || !data || !dlen)
627 return GNUTLS_E_INVALID_REQUEST;
630 rc = gnutls_openpgp_keyring_init (&c->keyring);
637 rc = gnutls_openpgp_keyring_import (c->keyring, &ddata, format);
641 gnutls_openpgp_keyring_deinit (c->keyring);
649 * _gnutls_openpgp_request_key - Receives a key from a database, key server etc
650 * @ret - a pointer to gnutls_datum_t structure.
651 * @cred - a gnutls_certificate_credentials_t structure.
652 * @key_fingerprint - The keyFingerprint
653 * @key_fingerprint_size - the size of the fingerprint
655 * Retrieves a key from a local database, keyring, or a key server. The
656 * return value is locally allocated.
660 _gnutls_openpgp_request_key (gnutls_session_t session, gnutls_datum_t * ret,
661 const gnutls_certificate_credentials_t cred,
662 opaque * key_fpr, int key_fpr_size)
666 if (!ret || !cred || !key_fpr)
669 return GNUTLS_E_INVALID_REQUEST;
672 if (key_fpr_size != 16 && key_fpr_size != 20)
673 return GNUTLS_E_HASH_FAILED; /* only MD5 and SHA1 are supported */
675 rc = gnutls_openpgp_get_key (ret, cred->keyring, KEY_ATTR_FPR, key_fpr);
677 if (rc >= 0) /* key was found */
683 rc = GNUTLS_E_OPENPGP_GETKEY_FAILED;
685 /* If the callback function was set, then try this one. */
686 if (session->internals.openpgp_recv_key_func != NULL)
688 rc = session->internals.openpgp_recv_key_func (session,
694 rc = GNUTLS_E_OPENPGP_GETKEY_FAILED;
705 * gnutls_openpgp_set_recv_key_function:
706 * @session: a TLS session
707 * @func: the callback
709 * This funtion will set a key retrieval function for OpenPGP keys. This
710 * callback is only useful in server side, and will be used if the peer
711 * sent a key fingerprint instead of a full key.
715 gnutls_openpgp_set_recv_key_function (gnutls_session_t session,
716 gnutls_openpgp_recv_key_func func)
718 session->internals.openpgp_recv_key_func = func;
722 /* Converts a parsed gnutls_openpgp_crt_t to a gnutls_cert structure.
725 _gnutls_openpgp_crt_to_gcert (gnutls_cert * gcert, gnutls_openpgp_crt_t cert)
728 uint8_t keyid[GNUTLS_OPENPGP_KEYID_SIZE];
731 memset (gcert, 0, sizeof (gnutls_cert));
732 gcert->cert_type = GNUTLS_CRT_OPENPGP;
733 gcert->sign_algo = GNUTLS_SIGN_UNKNOWN; /* N/A here */
735 gcert->version = gnutls_openpgp_crt_get_version (cert);
736 gcert->params_size = MAX_PUBLIC_PARAMS_SIZE;
738 ret = gnutls_openpgp_crt_get_preferred_key_id (cert, keyid);
746 ("Importing Openpgp cert and using openpgp sub key: %s\n",
747 _gnutls_bin2hex (keyid, GNUTLS_OPENPGP_KEYID_SIZE, err_buf, sizeof (err_buf),
750 KEYID_IMPORT (kid32, keyid);
752 idx = gnutls_openpgp_crt_get_subkey_idx (cert, keyid);
759 gcert->subject_pk_algorithm =
760 gnutls_openpgp_crt_get_subkey_pk_algorithm (cert, idx, NULL);
762 gnutls_openpgp_crt_get_subkey_usage (cert, idx, &gcert->key_usage);
763 gcert->use_subkey = 1;
765 memcpy (gcert->subkey_id, keyid, GNUTLS_OPENPGP_KEYID_SIZE);
768 _gnutls_openpgp_crt_get_mpis (cert, kid32, gcert->params,
769 &gcert->params_size);
774 ("Importing Openpgp cert and using main openpgp key\n");
775 gcert->subject_pk_algorithm =
776 gnutls_openpgp_crt_get_pk_algorithm (cert, NULL);
778 gnutls_openpgp_crt_get_key_usage (cert, &gcert->key_usage);
780 _gnutls_openpgp_crt_get_mpis (cert, NULL, gcert->params,
781 &gcert->params_size);
782 gcert->use_subkey = 0;
791 { /* copy the raw certificate */
792 #define SMALL_RAW 512
794 size_t raw_size = SMALL_RAW;
796 /* initially allocate a bogus size, just in case the certificate
797 * fits in it. That way we minimize the DER encodings performed.
799 raw = gnutls_malloc (raw_size);
803 return GNUTLS_E_MEMORY_ERROR;
807 gnutls_openpgp_crt_export (cert, GNUTLS_OPENPGP_FMT_RAW, raw,
809 if (ret < 0 && ret != GNUTLS_E_SHORT_MEMORY_BUFFER)
816 if (ret == GNUTLS_E_SHORT_MEMORY_BUFFER)
818 raw = gnutls_realloc (raw, raw_size);
822 return GNUTLS_E_MEMORY_ERROR;
826 gnutls_openpgp_crt_export (cert, GNUTLS_OPENPGP_FMT_RAW, raw,
836 gcert->raw.data = raw;
837 gcert->raw.size = raw_size;