2 * Copyright (C) 2003, 2004, 2005, 2007, 2008, 2009, 2010 Free Software
5 * Author: Nikos Mavrogiannopoulos, Timo Schulz
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
26 /* Functions on keyring parsing
29 #include <gnutls_int.h>
30 #include <gnutls_datum.h>
31 #include <gnutls_global.h>
32 #include <gnutls_errors.h>
33 #include <openpgp_int.h>
34 #include <gnutls_openpgp.h>
35 #include <gnutls_num.h>
41 * gnutls_openpgp_keyring_init:
42 * @keyring: The structure to be initialized
44 * This function will initialize an keyring structure.
46 * Returns: %GNUTLS_E_SUCCESS on success, or an error code.
49 gnutls_openpgp_keyring_init (gnutls_openpgp_keyring_t * keyring)
51 *keyring = gnutls_calloc (1, sizeof (gnutls_openpgp_keyring_int));
54 return 0; /* success */
55 return GNUTLS_E_MEMORY_ERROR;
60 * gnutls_openpgp_keyring_deinit:
61 * @keyring: The structure to be initialized
63 * This function will deinitialize a keyring structure.
66 gnutls_openpgp_keyring_deinit (gnutls_openpgp_keyring_t keyring)
73 cdk_keydb_free (keyring->db);
77 gnutls_free (keyring);
81 * gnutls_openpgp_keyring_check_id:
82 * @ring: holds the keyring to check against
83 * @keyid: will hold the keyid to check for.
84 * @flags: unused (should be 0)
86 * Check if a given key ID exists in the keyring.
88 * Returns: %GNUTLS_E_SUCCESS on success (if keyid exists) and a
89 * negative error code on failure.
92 gnutls_openpgp_keyring_check_id (gnutls_openpgp_keyring_t ring,
93 const gnutls_openpgp_keyid_t keyid,
99 id[0] = _gnutls_read_uint32 (keyid);
100 id[1] = _gnutls_read_uint32 (&keyid[4]);
102 if (!cdk_keydb_get_pk (ring->db, id, &pk))
108 _gnutls_debug_log ("PGP: key not found %08lX\n", (unsigned long) id[1]);
109 return GNUTLS_E_NO_CERTIFICATE_FOUND;
113 * gnutls_openpgp_keyring_import:
114 * @keyring: The structure to store the parsed key.
115 * @data: The RAW or BASE64 encoded keyring.
116 * @format: One of #gnutls_openpgp_keyring_fmt elements.
118 * This function will convert the given RAW or Base64 encoded keyring
119 * to the native #gnutls_openpgp_keyring_t format. The output will be
120 * stored in 'keyring'.
122 * Returns: %GNUTLS_E_SUCCESS on success, or an error code.
125 gnutls_openpgp_keyring_import (gnutls_openpgp_keyring_t keyring,
126 const gnutls_datum_t * data,
127 gnutls_openpgp_crt_fmt_t format)
130 cdk_stream_t input = NULL;
132 opaque *raw_data = NULL;
134 if (data->data == NULL || data->size == 0)
137 return GNUTLS_E_OPENPGP_GETKEY_FAILED;
140 _gnutls_debug_log ("PGP: keyring import format '%s'\n",
141 format == GNUTLS_OPENPGP_FMT_RAW ? "raw" : "base64");
143 /* Create a new stream from the given data, decode it, and import
144 * the raw database. This to avoid using opencdk streams which are
147 if (format == GNUTLS_OPENPGP_FMT_BASE64)
151 err = cdk_stream_tmp_from_mem (data->data, data->size, &input);
153 err = cdk_stream_set_armor_flag (input, 0);
157 err = _gnutls_map_cdk_rc (err);
161 raw_len = cdk_stream_get_length (input);
165 err = GNUTLS_E_BASE64_DECODING_ERROR;
169 raw_data = gnutls_malloc (raw_len);
170 if (raw_data == NULL)
173 err = GNUTLS_E_MEMORY_ERROR;
180 cdk_stream_read (input, raw_data + written, raw_len - written);
185 while (written < raw_len && err != EOF && err > 0);
192 raw_len = data->size;
193 raw_data = data->data;
196 err = cdk_keydb_new (&keyring->db, CDK_DBTYPE_DATA, raw_data, raw_len);
200 return _gnutls_map_cdk_rc (err);
203 gnutls_free (raw_data);
204 cdk_stream_close (input);
209 #define knode_is_pkey(node) \
210 cdk_kbnode_find_packet (node, CDK_PKT_PUBLIC_KEY)!=NULL
213 * gnutls_openpgp_keyring_get_crt_count:
214 * @ring: is an OpenPGP key ring
216 * This function will return the number of OpenPGP certificates
217 * present in the given keyring.
219 * Returns: the number of subkeys, or a negative value on error.
222 gnutls_openpgp_keyring_get_crt_count (gnutls_openpgp_keyring_t ring)
226 cdk_keydb_search_t st;
229 err = cdk_keydb_search_start (&st, ring->db, CDK_DBSEARCH_NEXT, NULL);
230 if (err != CDK_Success)
233 return _gnutls_map_cdk_rc (err);
238 err = cdk_keydb_search (st, ring->db, &knode);
239 if (err != CDK_Error_No_Key && err != CDK_Success)
242 cdk_keydb_search_release (st);
243 return _gnutls_map_cdk_rc (err);
246 if (knode_is_pkey (knode))
249 cdk_kbnode_release (knode);
252 while (err != CDK_Error_No_Key);
254 cdk_keydb_search_release (st);
259 * gnutls_openpgp_keyring_get_crt:
260 * @ring: Holds the keyring.
261 * @idx: the index of the certificate to export
262 * @cert: An uninitialized #gnutls_openpgp_crt_t structure
264 * This function will extract an OpenPGP certificate from the given
265 * keyring. If the index given is out of range
266 * %GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE will be returned. The
267 * returned structure needs to be deinited.
269 * Returns: %GNUTLS_E_SUCCESS on success, or an error code.
272 gnutls_openpgp_keyring_get_crt (gnutls_openpgp_keyring_t ring,
273 unsigned int idx, gnutls_openpgp_crt_t * cert)
278 unsigned int count = 0;
279 cdk_keydb_search_t st;
281 err = cdk_keydb_search_start (&st, ring->db, CDK_DBSEARCH_NEXT, NULL);
282 if (err != CDK_Success)
285 return _gnutls_map_cdk_rc (err);
290 err = cdk_keydb_search (st, ring->db, &knode);
291 if (err != CDK_EOF && err != CDK_Success)
294 cdk_keydb_search_release (st);
295 return _gnutls_map_cdk_rc (err);
298 if (idx == count && err == CDK_Success)
300 ret = gnutls_openpgp_crt_init (cert);
302 (*cert)->knode = knode;
303 cdk_keydb_search_release (st);
307 if (knode_is_pkey (knode))
310 cdk_kbnode_release (knode);
313 while (err != CDK_EOF);
315 cdk_keydb_search_release (st);
316 return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;