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>
37 /* Map an OpenCDK error type to a GnuTLS error type. */
39 _gnutls_map_cdk_rc (int rc
)
46 return GNUTLS_E_PARSING_ERROR
;
48 return GNUTLS_E_SHORT_MEMORY_BUFFER
;
49 case CDK_General_Error
:
50 return GNUTLS_E_INTERNAL_ERROR
;
52 return GNUTLS_E_FILE_ERROR
;
54 return GNUTLS_E_MPI_SCAN_FAILED
;
55 case CDK_Error_No_Key
:
56 return GNUTLS_E_OPENPGP_GETKEY_FAILED
;
58 return GNUTLS_E_BASE64_DECODING_ERROR
;
60 return GNUTLS_E_INVALID_REQUEST
;
62 return GNUTLS_E_INTERNAL_ERROR
;
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
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.
85 gnutls_certificate_set_openpgp_key (gnutls_certificate_credentials_t res
,
86 gnutls_openpgp_crt_t crt
,
87 gnutls_openpgp_privkey_t pkey
)
90 gnutls_privkey_t privkey
;
91 gnutls_pcert_st
*ccert
= NULL
;
94 gnutls_str_array_t names
;
96 _gnutls_str_array_init(&names
);
98 /* this should be first */
100 ret
= gnutls_privkey_init (&privkey
);
108 gnutls_privkey_import_openpgp (privkey
, pkey
,
109 GNUTLS_PRIVKEY_IMPORT_COPY
);
116 ccert
= gnutls_calloc (1, sizeof (gnutls_pcert_st
));
120 ret
= GNUTLS_E_MEMORY_ERROR
;
124 max_size
= sizeof(name
);
126 for (i
= 0; !(ret
< 0); i
++)
128 ret
= gnutls_openpgp_crt_get_name(crt
, i
, name
, &max_size
);
131 ret2
= _gnutls_str_array_append(&names
, name
, max_size
);
141 ret
= gnutls_pcert_import_openpgp (ccert
, crt
, 0);
148 ret
= certificate_credentials_append_pkey (res
, privkey
);
150 ret
= certificate_credential_append_crt_list (res
, names
, ccert
, 1);
160 ret
= _gnutls_check_key_cert_match (res
);
170 gnutls_privkey_deinit (privkey
);
172 _gnutls_str_array_clear(&names
);
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
,
191 cdk_kbnode_t knode
= NULL
;
192 unsigned long keyid
[2];
197 cdk_keydb_search_t st
;
199 if (!key
|| !keyring
|| by
== KEY_ATTR_NONE
)
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
);
212 else if (by
== KEY_ATTR_KEYID
)
214 keyid
[0] = _gnutls_read_uint32 (pattern
);
215 keyid
[1] = _gnutls_read_uint32 (pattern
+ 4);
220 rc
= cdk_keydb_search_start (&st
, keyring
->db
, by
, desc
);
222 rc
= cdk_keydb_search (st
, keyring
->db
, &knode
);
224 cdk_keydb_search_release (st
);
228 rc
= _gnutls_map_cdk_rc (rc
);
232 if (!cdk_kbnode_find (knode
, CDK_PKT_PUBLIC_KEY
))
234 rc
= GNUTLS_E_OPENPGP_GETKEY_FAILED
;
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
);
242 _gnutls_datum_append (key
, buf
, len
);
246 cdk_kbnode_release (knode
);
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
,
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
,
290 gnutls_openpgp_crt_fmt_t format
)
292 return gnutls_certificate_set_openpgp_key_file2 (res
, certfile
,
293 keyfile
, NULL
, format
);
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)
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
;
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.
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
;
347 uint8_t keyid
[GNUTLS_OPENPGP_KEYID_SIZE
];
349 ret
= gnutls_openpgp_privkey_init (&pkey
);
356 ret
= gnutls_openpgp_privkey_import (pkey
, key
, format
, NULL
, 0);
360 gnutls_openpgp_privkey_deinit (pkey
);
364 ret
= gnutls_openpgp_crt_init (&crt
);
368 gnutls_openpgp_privkey_deinit (pkey
);
372 ret
= gnutls_openpgp_crt_import (crt
, cert
, format
);
376 gnutls_openpgp_privkey_deinit (pkey
);
377 gnutls_openpgp_crt_deinit (crt
);
381 if (subkey_id
!= NULL
)
383 if (strcasecmp (subkey_id
, "auto") == 0)
384 ret
= gnutls_openpgp_crt_get_auth_subkey (crt
, keyid
, 1);
386 ret
= get_keyid (keyid
, subkey_id
);
393 ret
= gnutls_openpgp_crt_set_preferred_key_id (crt
, keyid
);
395 ret
= gnutls_openpgp_privkey_set_preferred_key_id (pkey
, keyid
);
401 gnutls_openpgp_privkey_deinit (pkey
);
402 gnutls_openpgp_crt_deinit (crt
);
407 ret
= gnutls_certificate_set_openpgp_key (res
, crt
, pkey
);
409 gnutls_openpgp_crt_deinit (crt
);
410 gnutls_openpgp_privkey_deinit (pkey
);
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.
436 gnutls_certificate_set_openpgp_key_file2 (gnutls_certificate_credentials_t
437 res
, const char *certfile
,
439 const char *subkey_id
,
440 gnutls_openpgp_crt_fmt_t format
)
443 gnutls_datum_t key
, cert
;
447 if (!res
|| !keyfile
|| !certfile
)
450 return GNUTLS_E_INVALID_REQUEST
;
453 if (stat (certfile
, &statbuf
) || stat (keyfile
, &statbuf
))
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
)
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
)
473 return GNUTLS_E_FILE_ERROR
;
477 gnutls_certificate_set_openpgp_key_mem2 (res
, &cert
, &key
, subkey_id
,
494 gnutls_openpgp_count_key_names (const gnutls_datum_t
* cert
)
496 cdk_kbnode_t knode
, p
, ctx
;
506 if (cdk_kbnode_read_from_mem (&knode
, 0, cert
->data
, cert
->size
))
515 p
= cdk_kbnode_walk (knode
, &ctx
, 0);
518 pkt
= cdk_kbnode_get_packet (p
);
519 if (pkt
->pkttype
== CDK_PKT_USER_ID
)
523 cdk_kbnode_release (knode
);
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
,
544 gnutls_openpgp_crt_fmt_t format
)
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
)
561 return GNUTLS_E_FILE_ERROR
;
565 gnutls_certificate_set_openpgp_keyring_mem (c
, ring
.data
, ring
.size
,
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
,
592 gnutls_openpgp_crt_fmt_t format
)
594 gnutls_datum_t ddata
;
597 ddata
.data
= (void *) data
;
600 if (!c
|| !data
|| !dlen
)
603 return GNUTLS_E_INVALID_REQUEST
;
606 rc
= gnutls_openpgp_keyring_init (&c
->keyring
);
613 rc
= gnutls_openpgp_keyring_import (c
->keyring
, &ddata
, format
);
617 gnutls_openpgp_keyring_deinit (c
->keyring
);
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
)
642 if (!ret
|| !cred
|| !key_fpr
)
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 */
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
,
670 rc
= GNUTLS_E_OPENPGP_GETKEY_FAILED
;
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.
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
;