2
* Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation
4
* Author: Timo Schulz, Nikos Mavrogiannopoulos
6
* This file is part of GNUTLS.
8
* The GNUTLS library 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 2.1 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
19
* License along with this library; if not, write to the Free Software
20
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
25
#include "gnutls_int.h"
26
#include "gnutls_errors.h"
27
#include "gnutls_mpi.h"
28
#include "gnutls_num.h"
29
#include "gnutls_cert.h"
30
#include "gnutls_datum.h"
31
#include "gnutls_global.h"
32
#include "openpgp/gnutls_openpgp.h"
33
#include "read-file.h"
34
#include <gnutls_str.h>
35
#include <gnutls_sig.h>
41
#define datum_append(x, y, z) _gnutls_datum_append_m (x, y, z, gnutls_realloc)
43
/* Map an OpenCDK error type to a GnuTLS error type. */
45
_gnutls_map_cdk_rc (int rc)
52
return GNUTLS_E_SHORT_MEMORY_BUFFER;
53
case CDK_General_Error:
54
return GNUTLS_E_INTERNAL_ERROR;
56
return GNUTLS_E_FILE_ERROR;
58
return GNUTLS_E_MPI_SCAN_FAILED;
59
case CDK_Error_No_Key:
60
return GNUTLS_E_OPENPGP_GETKEY_FAILED;
62
return GNUTLS_E_BASE64_DECODING_ERROR;
64
return GNUTLS_E_INVALID_REQUEST;
66
return GNUTLS_E_INTERNAL_ERROR;
71
* _gnutls_openpgp_raw_crt_to_gcert - Converts raw OpenPGP data to GnuTLS certs
72
* @cert: the certificate to store the data.
73
* @raw: the buffer which contains the whole OpenPGP key packets.
75
* The RFC2440 (OpenPGP Message Format) data is converted to a GnuTLS
76
* specific certificate.
79
_gnutls_openpgp_raw_crt_to_gcert (gnutls_cert * gcert,
80
const gnutls_datum_t * raw, 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 - Used to set keys in a gnutls_certificate_credentials_t structure
119
* @res: is an #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 called
125
* more than once (in case multiple keys/certificates exist for the
128
* With this function the subkeys of the certificate are not used.
132
gnutls_certificate_set_openpgp_key (gnutls_certificate_credentials_t
133
res, gnutls_openpgp_crt_t crt,
134
gnutls_openpgp_privkey_t pkey)
138
/* this should be first */
140
res->pkey = gnutls_realloc_fast (res->pkey,
142
sizeof (gnutls_privkey));
143
if (res->pkey == NULL)
146
return GNUTLS_E_MEMORY_ERROR;
149
ret = _gnutls_openpgp_privkey_to_gkey (&res->pkey[res->ncerts], pkey);
156
res->cert_list = gnutls_realloc_fast (res->cert_list,
159
sizeof (gnutls_cert *));
160
if (res->cert_list == NULL)
163
return GNUTLS_E_MEMORY_ERROR;
166
res->cert_list_length = gnutls_realloc_fast (res->cert_list_length,
168
res->ncerts) * sizeof (int));
169
if (res->cert_list_length == NULL)
172
return GNUTLS_E_MEMORY_ERROR;
175
res->cert_list[res->ncerts] = gnutls_calloc (1, sizeof (gnutls_cert));
176
if (res->cert_list[res->ncerts] == NULL)
179
return GNUTLS_E_MEMORY_ERROR;
182
res->cert_list_length[res->ncerts] = 1;
184
ret = _gnutls_openpgp_crt_to_gcert (res->cert_list[res->ncerts], crt);
193
/* FIXME: Check if the keys match. */
199
* gnutls_openpgp_get_key - Retrieve a key from the keyring.
200
* @key: the destination context to save the key.
201
* @keyring: the datum struct that contains all keyring information.
202
* @attr: The attribute (keyid, fingerprint, ...).
203
* @by: What attribute is used.
205
* This function can be used to retrieve keys by different pattern
206
* from a binary or a file keyring.
209
gnutls_openpgp_get_key (gnutls_datum_t * key,
210
gnutls_openpgp_keyring_t keyring, key_attr_t by,
213
cdk_kbnode_t knode = NULL;
214
unsigned long keyid[2];
219
cdk_keydb_search_t st;
221
if (!key || !keyring || by == KEY_ATTR_NONE)
224
return GNUTLS_E_INVALID_REQUEST;
227
memset (key, 0, sizeof *key);
229
if (by == KEY_ATTR_SHORT_KEYID)
231
keyid[0] = _gnutls_read_uint32(pattern);
234
else if (by == KEY_ATTR_KEYID)
236
keyid[0] = _gnutls_read_uint32(pattern);
237
keyid[1] = _gnutls_read_uint32(pattern + 4);
242
rc = cdk_keydb_search_start (&st, keyring->db, by, desc);
244
rc = cdk_keydb_search (st, keyring->db, &knode);
246
cdk_keydb_search_release( st);
250
rc = _gnutls_map_cdk_rc (rc);
254
if (!cdk_kbnode_find (knode, CDK_PKT_PUBLIC_KEY))
256
rc = GNUTLS_E_OPENPGP_GETKEY_FAILED;
260
/* We let the function allocate the buffer to avoid
261
to call the function twice. */
262
rc = cdk_kbnode_write_to_mem_alloc (knode, &buf, &len);
264
datum_append (key, buf, len);
268
cdk_kbnode_release (knode);
273
* gnutls_certificate_set_openpgp_key_mem - Used to set OpenPGP keys
274
* @res: the destination context to save the data.
275
* @cert: the datum that contains the public key.
276
* @key: the datum that contains the secret key.
277
* @format: the format of the keys
279
* This funtion is used to load OpenPGP keys into the GnuTLS credential
280
* structure. The files should contain non encrypted keys.
282
* Returns: On success, %GNUTLS_E_SUCCESS is returned, otherwise a
283
* negative error value.
286
gnutls_certificate_set_openpgp_key_mem (gnutls_certificate_credentials_t
287
res, const gnutls_datum_t * icert,
288
const gnutls_datum_t * ikey,
289
gnutls_openpgp_crt_fmt_t format)
291
return gnutls_certificate_set_openpgp_key_mem2 (res, icert, ikey,
297
* gnutls_certificate_set_openpgp_key_file - Used to set OpenPGP keys
298
* @res: the destination context to save the data.
299
* @certfile: the file that contains the public key.
300
* @keyfile: the file that contains the secret key.
301
* @format: the format of the keys
303
* This funtion is used to load OpenPGP keys into the GnuTLS
304
* credentials structure. The files should only contain one key which
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
312
res, const char *certfile,
314
gnutls_openpgp_crt_fmt_t format)
316
return gnutls_certificate_set_openpgp_key_file2 (res, certfile,
317
keyfile, NULL, format);
320
static int get_keyid( gnutls_openpgp_keyid_t keyid, const char* str)
322
size_t keyid_size = sizeof(keyid);
324
if (strlen(str) != 16)
326
_gnutls_debug_log("The OpenPGP subkey ID has to be 16 hexadecimal characters.\n");
327
return GNUTLS_E_INVALID_REQUEST;
330
if (_gnutls_hex2bin (str, strlen(str), keyid, &keyid_size) < 0)
332
_gnutls_debug_log("Error converting hex string: %s.\n", str);
333
return GNUTLS_E_INVALID_REQUEST;
340
* gnutls_certificate_set_openpgp_key_mem2 - Used to set OpenPGP keys
341
* @res: the destination context to save the data.
342
* @cert: the datum that contains the public key.
343
* @key: the datum that contains the secret key.
344
* @subkey_id: a hex encoded subkey id
345
* @format: the format of the keys
347
* This funtion is used to load OpenPGP keys into the GnuTLS
348
* credentials structure. The files should only contain one key which
351
* The special keyword "auto" is also accepted as &subkey_id. In that
352
* case the gnutls_openpgp_crt_get_auth_subkey() will be used to
353
* retrieve the subkey.
355
* Returns: On success, %GNUTLS_E_SUCCESS is returned, otherwise a
356
* negative error value.
361
gnutls_certificate_set_openpgp_key_mem2 (gnutls_certificate_credentials_t
362
res, const gnutls_datum_t * icert,
363
const gnutls_datum_t * ikey,
364
const char* subkey_id,
365
gnutls_openpgp_crt_fmt_t format)
367
gnutls_openpgp_privkey_t key;
368
gnutls_openpgp_crt_t cert;
371
ret = gnutls_openpgp_privkey_init( &key);
377
ret = gnutls_openpgp_privkey_import( key, ikey, format, NULL, 0);
380
gnutls_openpgp_privkey_deinit( key);
384
ret = gnutls_openpgp_crt_init( &cert);
387
gnutls_openpgp_privkey_deinit( key);
391
ret = gnutls_openpgp_crt_import( cert, icert, format);
394
gnutls_openpgp_privkey_deinit( key);
395
gnutls_openpgp_crt_deinit( cert);
399
if (subkey_id != NULL)
401
gnutls_openpgp_keyid_t keyid;
403
if (strcasecmp( subkey_id, "auto")==0)
404
ret = gnutls_openpgp_crt_get_auth_subkey( cert, keyid, 1);
406
ret = get_keyid( keyid, subkey_id);
410
ret = gnutls_openpgp_crt_set_preferred_key_id( cert, keyid);
412
ret = gnutls_openpgp_privkey_set_preferred_key_id( key, keyid);
418
gnutls_openpgp_privkey_deinit( key);
419
gnutls_openpgp_crt_deinit( cert);
424
ret = gnutls_certificate_set_openpgp_key( res, cert, key);
426
gnutls_openpgp_privkey_deinit( key);
427
gnutls_openpgp_crt_deinit( cert);
434
* gnutls_certificate_set_openpgp_key_file2 - Used to set OpenPGP keys
435
* @res: the destination context to save the data.
436
* @certfile: the file that contains the public key.
437
* @keyfile: the file that contains the secret key.
438
* @subkey_id: a hex encoded subkey id
439
* @format: the format of the keys
441
* This funtion is used to load OpenPGP keys into the GnuTLS credential
442
* structure. The files should contain non encrypted keys.
444
* The special keyword "auto" is also accepted as &subkey_id. In that case
445
* the gnutls_openpgp_crt_get_auth_subkey() will be used to retrieve the subkey.
447
* Returns: On success, %GNUTLS_E_SUCCESS is returned, otherwise a
448
* negative error value.
453
gnutls_certificate_set_openpgp_key_file2 (gnutls_certificate_credentials_t
454
res, const char *certfile,
456
const char* subkey_id,
457
gnutls_openpgp_crt_fmt_t format)
460
gnutls_datum_t key, cert;
464
if (!res || !keyfile || !certfile)
467
return GNUTLS_E_INVALID_REQUEST;
470
if (stat (certfile, &statbuf) || stat (keyfile, &statbuf))
473
return GNUTLS_E_FILE_ERROR;
476
cert.data = read_binary_file (certfile, &size);
477
cert.size = (unsigned int)size;
478
if (cert.data == NULL)
481
return GNUTLS_E_FILE_ERROR;
484
key.data = read_binary_file (keyfile, &size);
485
key.size = (unsigned int)size;
486
if (key.data == NULL)
490
return GNUTLS_E_FILE_ERROR;
493
rc = gnutls_certificate_set_openpgp_key_mem2 (res, &cert, &key, subkey_id, format);
509
gnutls_openpgp_count_key_names (const gnutls_datum_t * cert)
511
cdk_kbnode_t knode, p, ctx;
521
if (cdk_kbnode_read_from_mem (&knode, cert->data, cert->size))
530
p = cdk_kbnode_walk (knode, &ctx, 0);
533
pkt = cdk_kbnode_get_packet (p);
534
if (pkt->pkttype == CDK_PKT_USER_ID)
538
cdk_kbnode_release (knode);
544
* gnutls_certificate_set_openpgp_keyring_file - Sets a keyring file for OpenPGP
545
* @c: A certificate credentials structure
546
* @file: filename of the keyring.
548
* The function is used to set keyrings that will be used internally
549
* by various OpenPGP functions. For example to find a key when it
550
* is needed for an operations. The keyring will also be used at the
551
* verification functions.
553
* Returns: On success, %GNUTLS_E_SUCCESS is returned, otherwise a
554
* negative error value.
557
gnutls_certificate_set_openpgp_keyring_file (gnutls_certificate_credentials_t c,
559
gnutls_openpgp_crt_fmt_t format)
568
return GNUTLS_E_INVALID_REQUEST;
571
ring.data = read_binary_file (file, &size);
572
ring.size = (unsigned int)size;
573
if (ring.data == NULL)
576
return GNUTLS_E_FILE_ERROR;
579
rc = gnutls_certificate_set_openpgp_keyring_mem (c, ring.data, ring.size, format);
587
* gnutls_certificate_set_openpgp_keyring_mem - Add keyring data for OpenPGP
588
* @c: A certificate credentials structure
589
* @data: buffer with keyring data.
590
* @dlen: length of data buffer.
592
* The function is used to set keyrings that will be used internally
593
* by various OpenPGP functions. For example to find a key when it
594
* is needed for an operations. The keyring will also be used at the
595
* verification functions.
597
* Returns: On success, %GNUTLS_E_SUCCESS is returned, otherwise a
598
* negative error value.
601
gnutls_certificate_set_openpgp_keyring_mem (gnutls_certificate_credentials_t
602
c, const opaque * data,
603
size_t dlen, gnutls_openpgp_crt_fmt_t format)
608
ddata.data = (void*)data;
611
if (!c || !data || !dlen)
614
return GNUTLS_E_INVALID_REQUEST;
617
rc = gnutls_openpgp_keyring_init( &c->keyring);
623
rc = gnutls_openpgp_keyring_import( c->keyring, &ddata, format);
626
gnutls_openpgp_keyring_deinit( c->keyring);
634
* _gnutls_openpgp_request_key - Receives a key from a database, key server etc
635
* @ret - a pointer to gnutls_datum_t structure.
636
* @cred - a gnutls_certificate_credentials_t structure.
637
* @key_fingerprint - The keyFingerprint
638
* @key_fingerprint_size - the size of the fingerprint
640
* Retrieves a key from a local database, keyring, or a key server. The
641
* return value is locally allocated.
645
_gnutls_openpgp_request_key (gnutls_session_t session, gnutls_datum_t * ret,
646
const gnutls_certificate_credentials_t cred,
647
opaque * key_fpr, int key_fpr_size)
651
if (!ret || !cred || !key_fpr)
654
return GNUTLS_E_INVALID_REQUEST;
657
if (key_fpr_size != 16 && key_fpr_size != 20)
658
return GNUTLS_E_HASH_FAILED; /* only MD5 and SHA1 are supported */
660
rc = gnutls_openpgp_get_key (ret, cred->keyring, KEY_ATTR_FPR, key_fpr);
662
if (rc >= 0) /* key was found */
668
rc = GNUTLS_E_OPENPGP_GETKEY_FAILED;
670
/* If the callback function was set, then try this one. */
671
if (session->internals.openpgp_recv_key_func != NULL)
673
rc = session->internals.openpgp_recv_key_func (session,
679
rc = GNUTLS_E_OPENPGP_GETKEY_FAILED;
690
* gnutls_openpgp_set_recv_key_function - Used to set a key retrieval callback for PGP keys
691
* @session: a TLS session
692
* @func: the callback
694
* This funtion will set a key retrieval function for OpenPGP keys. This
695
* callback is only useful in server side, and will be used if the peer
696
* sent a key fingerprint instead of a full key.
700
gnutls_openpgp_set_recv_key_function (gnutls_session_t session,
701
gnutls_openpgp_recv_key_func func)
703
session->internals.openpgp_recv_key_func = func;
707
/* Copies a gnutls_openpgp_privkey_t to a gnutls_privkey structure. */
709
_gnutls_openpgp_privkey_to_gkey (gnutls_privkey * dest,
710
gnutls_openpgp_privkey_t src)
713
gnutls_openpgp_keyid_t keyid;
716
if (dest==NULL || src == NULL)
719
return GNUTLS_E_CERTIFICATE_ERROR;
722
dest->params_size = MAX_PRIV_PARAMS_SIZE;
724
ret = gnutls_openpgp_privkey_get_preferred_key_id( src, keyid);
731
_gnutls_debug_log("Importing Openpgp key and using openpgp sub key: %s\n",
732
_gnutls_bin2hex( keyid, sizeof(keyid), err_buf, sizeof(err_buf)));
734
KEYID_IMPORT(kid32, keyid);
736
idx = gnutls_openpgp_privkey_get_subkey_idx( src, keyid);
743
dest->pk_algorithm = gnutls_openpgp_privkey_get_subkey_pk_algorithm( src, idx, NULL);
745
ret = _gnutls_openpgp_privkey_get_mpis( src, kid32, dest->params, &dest->params_size);
749
_gnutls_debug_log("Importing Openpgp key and using main openpgp key.\n");
751
dest->pk_algorithm = gnutls_openpgp_privkey_get_pk_algorithm( src, NULL);
752
ret = _gnutls_openpgp_privkey_get_mpis( src, NULL, dest->params, &dest->params_size);
766
/* Converts a parsed gnutls_openpgp_crt_t to a gnutls_cert structure.
769
_gnutls_openpgp_crt_to_gcert (gnutls_cert * gcert, gnutls_openpgp_crt_t cert)
772
gnutls_openpgp_keyid_t keyid;
775
memset (gcert, 0, sizeof (gnutls_cert));
776
gcert->cert_type = GNUTLS_CRT_OPENPGP;
777
gcert->version = gnutls_openpgp_crt_get_version( cert);
778
gcert->params_size = MAX_PUBLIC_PARAMS_SIZE;
780
ret = gnutls_openpgp_crt_get_preferred_key_id( cert, keyid);
787
_gnutls_debug_log("Importing Openpgp cert and using openpgp sub key: %s\n",
788
_gnutls_bin2hex( keyid, sizeof(keyid), err_buf, sizeof(err_buf)));
790
KEYID_IMPORT(kid32, keyid);
792
idx = gnutls_openpgp_crt_get_subkey_idx( cert, keyid);
799
gcert->subject_pk_algorithm = gnutls_openpgp_crt_get_subkey_pk_algorithm( cert, idx, NULL);
801
gnutls_openpgp_crt_get_subkey_usage( cert, idx, &gcert->key_usage);
802
gcert->use_subkey = 1;
804
memcpy(gcert->subkey_id, keyid, sizeof(keyid));
806
ret = _gnutls_openpgp_crt_get_mpis( cert, kid32, gcert->params, &gcert->params_size);
810
_gnutls_debug_log("Importing Openpgp cert and using main openpgp key\n");
811
gcert->subject_pk_algorithm = gnutls_openpgp_crt_get_pk_algorithm( cert, NULL);
813
gnutls_openpgp_crt_get_key_usage( cert, &gcert->key_usage);
814
ret = _gnutls_openpgp_crt_get_mpis( cert, NULL, gcert->params, &gcert->params_size);
815
gcert->use_subkey = 0;
824
{ /* copy the raw certificate */
825
#define SMALL_RAW 512
827
size_t raw_size = SMALL_RAW;
829
/* initially allocate a bogus size, just in case the certificate
830
* fits in it. That way we minimize the DER encodings performed.
832
raw = gnutls_malloc (raw_size);
836
return GNUTLS_E_MEMORY_ERROR;
840
gnutls_openpgp_crt_export (cert, GNUTLS_OPENPGP_FMT_RAW, raw, &raw_size);
841
if (ret < 0 && ret != GNUTLS_E_SHORT_MEMORY_BUFFER)
848
if (ret == GNUTLS_E_SHORT_MEMORY_BUFFER)
850
raw = gnutls_realloc (raw, raw_size);
854
return GNUTLS_E_MEMORY_ERROR;
858
gnutls_openpgp_crt_export (cert, GNUTLS_OPENPGP_FMT_RAW, raw,
868
gcert->raw.data = raw;
869
gcert->raw.size = raw_size;
878
* gnutls_openpgp_privkey_sign_hash - sign the given data using the private key params
879
* @key: Holds the key
880
* @hash: holds the data to be signed
881
* @signature: will contain newly allocated signature
883
* This function will sign the given hash using the private key. You
884
* should use gnutls_openpgp_privkey_set_subkey() before calling this
885
* function to set the subkey to use.
887
* Returns: On success, %GNUTLS_E_SUCCESS is returned, otherwise a
888
* negative error value.
891
gnutls_openpgp_privkey_sign_hash (gnutls_openpgp_privkey_t key,
892
const gnutls_datum_t * hash,
893
gnutls_datum_t * signature)
896
mpi_t params[MAX_PUBLIC_PARAMS_SIZE];
897
int params_size = MAX_PUBLIC_PARAMS_SIZE;
899
gnutls_openpgp_keyid_t keyid;
904
return GNUTLS_E_INVALID_REQUEST;
907
result = gnutls_openpgp_privkey_get_preferred_key_id( key, keyid);
912
KEYID_IMPORT( kid, keyid);
913
result = _gnutls_openpgp_privkey_get_mpis (key, kid,
914
params, ¶ms_size);
918
result = _gnutls_openpgp_privkey_get_mpis (key, NULL,
919
params, ¶ms_size);
928
pk_algorithm = gnutls_openpgp_privkey_get_pk_algorithm (key, NULL);
930
result = _gnutls_sign (pk_algorithm, params,
931
params_size, hash, signature);
933
for (i=0;i<params_size;i++)
934
_gnutls_mpi_release( ¶ms[i]);