corrected copyright notices
[gnutls.git] / lib / openpgp / gnutls_openpgp.c
blobceb53c4a6c20e28da59b0ca9ed911bf39fb94c19
1 /*
2 * Copyright (C) 2002-2012 Free Software Foundation, Inc.
4 * Author: Timo Schulz, Nikos Mavrogiannopoulos
6 * This file is part of GnuTLS.
8 * The GnuTLS is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public License
10 * as published by the Free Software Foundation; either version 3 of
11 * the License, or (at your option) any later version.
13 * This library 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 * Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public License
19 * along with this program. If not, see <http://www.gnu.org/licenses/>
23 #include "gnutls_int.h"
24 #include "gnutls_errors.h"
25 #include "gnutls_mpi.h"
26 #include "gnutls_num.h"
27 #include "gnutls_datum.h"
28 #include "gnutls_global.h"
29 #include "gnutls_openpgp.h"
30 #include "read-file.h"
31 #include <gnutls/abstract.h>
32 #include <gnutls_str.h>
33 #include <gnutls_sig.h>
34 #include <stdio.h>
35 #include <sys/stat.h>
37 /* Map an OpenCDK error type to a GnuTLS error type. */
38 int
39 _gnutls_map_cdk_rc (int rc)
41 switch (rc)
43 case CDK_Success:
44 return 0;
45 case CDK_EOF:
46 return GNUTLS_E_PARSING_ERROR;
47 case CDK_Too_Short:
48 return GNUTLS_E_SHORT_MEMORY_BUFFER;
49 case CDK_General_Error:
50 return GNUTLS_E_INTERNAL_ERROR;
51 case CDK_File_Error:
52 return GNUTLS_E_FILE_ERROR;
53 case CDK_MPI_Error:
54 return GNUTLS_E_MPI_SCAN_FAILED;
55 case CDK_Error_No_Key:
56 return GNUTLS_E_OPENPGP_GETKEY_FAILED;
57 case CDK_Armor_Error:
58 return GNUTLS_E_BASE64_DECODING_ERROR;
59 case CDK_Inv_Value:
60 return GNUTLS_E_INVALID_REQUEST;
61 default:
62 return GNUTLS_E_INTERNAL_ERROR;
66 /**
67 * gnutls_certificate_set_openpgp_key:
68 * @res: is a #gnutls_certificate_credentials_t structure.
69 * @crt: contains an openpgp public key
70 * @pkey: is an openpgp private key
72 * This function sets a certificate/private key pair in the
73 * gnutls_certificate_credentials_t structure. This function may be
74 * called more than once (in case multiple keys/certificates exist
75 * for the server).
77 * Note that this function requires that the preferred key ids have
78 * been set and be used. See gnutls_openpgp_crt_set_preferred_key_id().
79 * Otherwise the master key will be used.
81 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned,
82 * otherwise a negative error code is returned.
83 **/
84 int
85 gnutls_certificate_set_openpgp_key (gnutls_certificate_credentials_t res,
86 gnutls_openpgp_crt_t crt,
87 gnutls_openpgp_privkey_t pkey)
89 int ret, ret2, i;
90 gnutls_privkey_t privkey;
91 gnutls_pcert_st *ccert = NULL;
92 char name[MAX_CN];
93 size_t max_size;
94 gnutls_str_array_t names;
96 _gnutls_str_array_init(&names);
98 /* this should be first */
100 ret = gnutls_privkey_init (&privkey);
101 if (ret < 0)
103 gnutls_assert ();
104 return ret;
107 ret =
108 gnutls_privkey_import_openpgp (privkey, pkey,
109 GNUTLS_PRIVKEY_IMPORT_COPY);
110 if (ret < 0)
112 gnutls_assert ();
113 goto cleanup;
116 ccert = gnutls_calloc (1, sizeof (gnutls_pcert_st));
117 if (ccert == NULL)
119 gnutls_assert ();
120 ret = GNUTLS_E_MEMORY_ERROR;
121 goto cleanup;
124 max_size = sizeof(name);
125 ret = 0;
126 for (i = 0; !(ret < 0); i++)
128 ret = gnutls_openpgp_crt_get_name(crt, i, name, &max_size);
129 if (ret >= 0)
131 ret2 = _gnutls_str_array_append(&names, name, max_size);
132 if (ret2 < 0)
134 gnutls_assert();
135 ret = ret2;
136 goto cleanup;
141 ret = gnutls_pcert_import_openpgp (ccert, crt, 0);
142 if (ret < 0)
144 gnutls_assert ();
145 goto cleanup;
148 ret = certificate_credentials_append_pkey (res, privkey);
149 if (ret >= 0)
150 ret = certificate_credential_append_crt_list (res, names, ccert, 1);
152 if (ret < 0)
154 gnutls_assert ();
155 goto cleanup;
158 res->ncerts++;
160 ret = _gnutls_check_key_cert_match (res);
161 if (ret < 0)
163 gnutls_assert ();
164 return ret;
167 return 0;
169 cleanup:
170 gnutls_privkey_deinit (privkey);
171 gnutls_free (ccert);
172 _gnutls_str_array_clear(&names);
173 return ret;
177 * gnutls_openpgp_get_key:
178 * @key: the destination context to save the key.
179 * @keyring: the datum struct that contains all keyring information.
180 * @attr: The attribute (keyid, fingerprint, ...).
181 * @by: What attribute is used.
183 * This function can be used to retrieve keys by different pattern
184 * from a binary or a file keyring.
187 gnutls_openpgp_get_key (gnutls_datum_t * key,
188 gnutls_openpgp_keyring_t keyring, key_attr_t by,
189 uint8_t * pattern)
191 cdk_kbnode_t knode = NULL;
192 unsigned long keyid[2];
193 unsigned char *buf;
194 void *desc;
195 size_t len;
196 int rc = 0;
197 cdk_keydb_search_t st;
199 if (!key || !keyring || by == KEY_ATTR_NONE)
201 gnutls_assert ();
202 return GNUTLS_E_INVALID_REQUEST;
205 memset (key, 0, sizeof *key);
207 if (by == KEY_ATTR_SHORT_KEYID)
209 keyid[0] = _gnutls_read_uint32 (pattern);
210 desc = keyid;
212 else if (by == KEY_ATTR_KEYID)
214 keyid[0] = _gnutls_read_uint32 (pattern);
215 keyid[1] = _gnutls_read_uint32 (pattern + 4);
216 desc = keyid;
218 else
219 desc = pattern;
220 rc = cdk_keydb_search_start (&st, keyring->db, by, desc);
221 if (!rc)
222 rc = cdk_keydb_search (st, keyring->db, &knode);
224 cdk_keydb_search_release (st);
226 if (rc)
228 rc = _gnutls_map_cdk_rc (rc);
229 goto leave;
232 if (!cdk_kbnode_find (knode, CDK_PKT_PUBLIC_KEY))
234 rc = GNUTLS_E_OPENPGP_GETKEY_FAILED;
235 goto leave;
238 /* We let the function allocate the buffer to avoid
239 to call the function twice. */
240 rc = cdk_kbnode_write_to_mem_alloc (knode, &buf, &len);
241 if (!rc)
242 _gnutls_datum_append (key, buf, len);
243 gnutls_free (buf);
245 leave:
246 cdk_kbnode_release (knode);
247 return rc;
251 * gnutls_certificate_set_openpgp_key_mem:
252 * @res: the destination context to save the data.
253 * @cert: the datum that contains the public key.
254 * @key: the datum that contains the secret key.
255 * @format: the format of the keys
257 * This funtion is used to load OpenPGP keys into the GnuTLS credential
258 * structure. The datum should contain at least one valid non encrypted subkey.
260 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
261 * negative error value.
264 gnutls_certificate_set_openpgp_key_mem (gnutls_certificate_credentials_t res,
265 const gnutls_datum_t * cert,
266 const gnutls_datum_t * key,
267 gnutls_openpgp_crt_fmt_t format)
269 return gnutls_certificate_set_openpgp_key_mem2 (res, cert, key,
270 NULL, format);
274 * gnutls_certificate_set_openpgp_key_file:
275 * @res: the destination context to save the data.
276 * @certfile: the file that contains the public key.
277 * @keyfile: the file that contains the secret key.
278 * @format: the format of the keys
280 * This funtion is used to load OpenPGP keys into the GnuTLS
281 * credentials structure. The file should contain at least one valid non encrypted subkey.
283 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
284 * negative error value.
287 gnutls_certificate_set_openpgp_key_file (gnutls_certificate_credentials_t res,
288 const char *certfile,
289 const char *keyfile,
290 gnutls_openpgp_crt_fmt_t format)
292 return gnutls_certificate_set_openpgp_key_file2 (res, certfile,
293 keyfile, NULL, format);
296 static int
297 get_keyid (gnutls_openpgp_keyid_t keyid, const char *str)
299 size_t keyid_size = GNUTLS_OPENPGP_KEYID_SIZE;
301 if (strlen (str) != 16)
303 _gnutls_debug_log
304 ("The OpenPGP subkey ID has to be 16 hexadecimal characters.\n");
305 return GNUTLS_E_INVALID_REQUEST;
308 if (_gnutls_hex2bin (str, strlen (str), keyid, &keyid_size) < 0)
310 _gnutls_debug_log ("Error converting hex string: %s.\n", str);
311 return GNUTLS_E_INVALID_REQUEST;
314 return 0;
318 * gnutls_certificate_set_openpgp_key_mem2:
319 * @res: the destination context to save the data.
320 * @cert: the datum that contains the public key.
321 * @key: the datum that contains the secret key.
322 * @subkey_id: a hex encoded subkey id
323 * @format: the format of the keys
325 * This funtion is used to load OpenPGP keys into the GnuTLS
326 * credentials structure. The datum should contain at least one valid non encrypted subkey.
328 * The special keyword "auto" is also accepted as @subkey_id. In that
329 * case the gnutls_openpgp_crt_get_auth_subkey() will be used to
330 * retrieve the subkey.
332 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
333 * negative error value.
335 * Since: 2.4.0
338 gnutls_certificate_set_openpgp_key_mem2 (gnutls_certificate_credentials_t res,
339 const gnutls_datum_t * cert,
340 const gnutls_datum_t * key,
341 const char *subkey_id,
342 gnutls_openpgp_crt_fmt_t format)
344 gnutls_openpgp_privkey_t pkey;
345 gnutls_openpgp_crt_t crt;
346 int ret;
347 uint8_t keyid[GNUTLS_OPENPGP_KEYID_SIZE];
349 ret = gnutls_openpgp_privkey_init (&pkey);
350 if (ret < 0)
352 gnutls_assert ();
353 return ret;
356 ret = gnutls_openpgp_privkey_import (pkey, key, format, NULL, 0);
357 if (ret < 0)
359 gnutls_assert ();
360 gnutls_openpgp_privkey_deinit (pkey);
361 return ret;
364 ret = gnutls_openpgp_crt_init (&crt);
365 if (ret < 0)
367 gnutls_assert ();
368 gnutls_openpgp_privkey_deinit (pkey);
369 return ret;
372 ret = gnutls_openpgp_crt_import (crt, cert, format);
373 if (ret < 0)
375 gnutls_assert ();
376 gnutls_openpgp_privkey_deinit (pkey);
377 gnutls_openpgp_crt_deinit (crt);
378 return ret;
381 if (subkey_id != NULL)
383 if (strcasecmp (subkey_id, "auto") == 0)
384 ret = gnutls_openpgp_crt_get_auth_subkey (crt, keyid, 1);
385 else
386 ret = get_keyid (keyid, subkey_id);
388 if (ret < 0)
389 gnutls_assert ();
391 if (ret >= 0)
393 ret = gnutls_openpgp_crt_set_preferred_key_id (crt, keyid);
394 if (ret >= 0)
395 ret = gnutls_openpgp_privkey_set_preferred_key_id (pkey, keyid);
398 if (ret < 0)
400 gnutls_assert ();
401 gnutls_openpgp_privkey_deinit (pkey);
402 gnutls_openpgp_crt_deinit (crt);
403 return ret;
407 ret = gnutls_certificate_set_openpgp_key (res, crt, pkey);
409 gnutls_openpgp_crt_deinit (crt);
410 gnutls_openpgp_privkey_deinit (pkey);
412 return ret;
416 * gnutls_certificate_set_openpgp_key_file2:
417 * @res: the destination context to save the data.
418 * @certfile: the file that contains the public key.
419 * @keyfile: the file that contains the secret key.
420 * @subkey_id: a hex encoded subkey id
421 * @format: the format of the keys
423 * This funtion is used to load OpenPGP keys into the GnuTLS credential
424 * structure. The file should contain at least one valid non encrypted subkey.
426 * The special keyword "auto" is also accepted as @subkey_id. In that
427 * case the gnutls_openpgp_crt_get_auth_subkey() will be used to
428 * retrieve the subkey.
430 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
431 * negative error value.
433 * Since: 2.4.0
436 gnutls_certificate_set_openpgp_key_file2 (gnutls_certificate_credentials_t
437 res, const char *certfile,
438 const char *keyfile,
439 const char *subkey_id,
440 gnutls_openpgp_crt_fmt_t format)
442 struct stat statbuf;
443 gnutls_datum_t key, cert;
444 int rc;
445 size_t size;
447 if (!res || !keyfile || !certfile)
449 gnutls_assert ();
450 return GNUTLS_E_INVALID_REQUEST;
453 if (stat (certfile, &statbuf) || stat (keyfile, &statbuf))
455 gnutls_assert ();
456 return GNUTLS_E_FILE_ERROR;
459 cert.data = (void*)read_binary_file (certfile, &size);
460 cert.size = (unsigned int) size;
461 if (cert.data == NULL)
463 gnutls_assert ();
464 return GNUTLS_E_FILE_ERROR;
467 key.data = (void*)read_binary_file (keyfile, &size);
468 key.size = (unsigned int) size;
469 if (key.data == NULL)
471 gnutls_assert ();
472 free (cert.data);
473 return GNUTLS_E_FILE_ERROR;
476 rc =
477 gnutls_certificate_set_openpgp_key_mem2 (res, &cert, &key, subkey_id,
478 format);
480 free (cert.data);
481 free (key.data);
483 if (rc < 0)
485 gnutls_assert ();
486 return rc;
489 return 0;
494 gnutls_openpgp_count_key_names (const gnutls_datum_t * cert)
496 cdk_kbnode_t knode, p, ctx;
497 cdk_packet_t pkt;
498 int nuids;
500 if (cert == NULL)
502 gnutls_assert ();
503 return 0;
506 if (cdk_kbnode_read_from_mem (&knode, 0, cert->data, cert->size))
508 gnutls_assert ();
509 return 0;
512 ctx = NULL;
513 for (nuids = 0;;)
515 p = cdk_kbnode_walk (knode, &ctx, 0);
516 if (!p)
517 break;
518 pkt = cdk_kbnode_get_packet (p);
519 if (pkt->pkttype == CDK_PKT_USER_ID)
520 nuids++;
523 cdk_kbnode_release (knode);
524 return nuids;
528 * gnutls_certificate_set_openpgp_keyring_file:
529 * @c: A certificate credentials structure
530 * @file: filename of the keyring.
531 * @format: format of keyring.
533 * The function is used to set keyrings that will be used internally
534 * by various OpenPGP functions. For example to find a key when it
535 * is needed for an operations. The keyring will also be used at the
536 * verification functions.
538 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
539 * negative error value.
542 gnutls_certificate_set_openpgp_keyring_file (gnutls_certificate_credentials_t c,
543 const char *file,
544 gnutls_openpgp_crt_fmt_t format)
546 gnutls_datum_t ring;
547 size_t size;
548 int rc;
550 if (!c || !file)
552 gnutls_assert ();
553 return GNUTLS_E_INVALID_REQUEST;
556 ring.data = (void*)read_binary_file (file, &size);
557 ring.size = (unsigned int) size;
558 if (ring.data == NULL)
560 gnutls_assert ();
561 return GNUTLS_E_FILE_ERROR;
564 rc =
565 gnutls_certificate_set_openpgp_keyring_mem (c, ring.data, ring.size,
566 format);
568 free (ring.data);
570 return rc;
574 * gnutls_certificate_set_openpgp_keyring_mem:
575 * @c: A certificate credentials structure
576 * @data: buffer with keyring data.
577 * @dlen: length of data buffer.
578 * @format: the format of the keyring
580 * The function is used to set keyrings that will be used internally
581 * by various OpenPGP functions. For example to find a key when it
582 * is needed for an operations. The keyring will also be used at the
583 * verification functions.
585 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
586 * negative error value.
589 gnutls_certificate_set_openpgp_keyring_mem (gnutls_certificate_credentials_t
590 c, const uint8_t * data,
591 size_t dlen,
592 gnutls_openpgp_crt_fmt_t format)
594 gnutls_datum_t ddata;
595 int rc;
597 ddata.data = (void *) data;
598 ddata.size = dlen;
600 if (!c || !data || !dlen)
602 gnutls_assert ();
603 return GNUTLS_E_INVALID_REQUEST;
606 rc = gnutls_openpgp_keyring_init (&c->keyring);
607 if (rc < 0)
609 gnutls_assert ();
610 return rc;
613 rc = gnutls_openpgp_keyring_import (c->keyring, &ddata, format);
614 if (rc < 0)
616 gnutls_assert ();
617 gnutls_openpgp_keyring_deinit (c->keyring);
618 return rc;
621 return 0;
625 * _gnutls_openpgp_request_key - Receives a key from a database, key server etc
626 * @ret - a pointer to gnutls_datum_t structure.
627 * @cred - a gnutls_certificate_credentials_t structure.
628 * @key_fingerprint - The keyFingerprint
629 * @key_fingerprint_size - the size of the fingerprint
631 * Retrieves a key from a local database, keyring, or a key server. The
632 * return value is locally allocated.
636 _gnutls_openpgp_request_key (gnutls_session_t session, gnutls_datum_t * ret,
637 const gnutls_certificate_credentials_t cred,
638 uint8_t * key_fpr, int key_fpr_size)
640 int rc = 0;
642 if (!ret || !cred || !key_fpr)
644 gnutls_assert ();
645 return GNUTLS_E_INVALID_REQUEST;
648 if (key_fpr_size != 16 && key_fpr_size != 20)
649 return GNUTLS_E_HASH_FAILED; /* only MD5 and SHA1 are supported */
651 rc = gnutls_openpgp_get_key (ret, cred->keyring, KEY_ATTR_FPR, key_fpr);
653 if (rc >= 0) /* key was found */
655 rc = 0;
656 goto error;
658 else
659 rc = GNUTLS_E_OPENPGP_GETKEY_FAILED;
661 /* If the callback function was set, then try this one. */
662 if (session->internals.openpgp_recv_key_func != NULL)
664 rc = session->internals.openpgp_recv_key_func (session,
665 key_fpr,
666 key_fpr_size, ret);
667 if (rc < 0)
669 gnutls_assert ();
670 rc = GNUTLS_E_OPENPGP_GETKEY_FAILED;
671 goto error;
675 error:
677 return rc;
681 * gnutls_openpgp_set_recv_key_function:
682 * @session: a TLS session
683 * @func: the callback
685 * This funtion will set a key retrieval function for OpenPGP keys. This
686 * callback is only useful in server side, and will be used if the peer
687 * sent a key fingerprint instead of a full key.
690 void
691 gnutls_openpgp_set_recv_key_function (gnutls_session_t session,
692 gnutls_openpgp_recv_key_func func)
694 session->internals.openpgp_recv_key_func = func;