2 * This is (now) gnutls_pkcs12_simple_parse() from GnuTLS 3.1, although
3 * it was actually taken from parse_pkcs12() in GnuTLS 2.12.x (where it
4 * was under LGPLv2.1) and modified locally. The modifications were
5 * accepted back into GnuTLS in commit 9a43e8fa.
7 #define opaque unsigned char
8 #define gnutls_assert() do {} while(0)
11 * Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
12 * Free Software Foundation, Inc.
14 * Author: Nikos Mavrogiannopoulos
16 * This file WAS part of GnuTLS.
18 * The GnuTLS is free software; you can redistribute it and/or
19 * modify it under the terms of the GNU Lesser General Public License
20 * as published by the Free Software Foundation; either version 2.1 of
21 * the License, or (at your option) any later version.
23 * This library is distributed in the hope that it will be useful, but
24 * WITHOUT ANY WARRANTY; without even the implied warranty of
25 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
26 * Lesser General Public License for more details.
28 * You should have received a copy of the GNU Lesser General Public
29 * License along with this library; if not, write to the Free Software
30 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
37 gnutls_pkcs12_simple_parse (gnutls_certificate_credentials_t res,
40 gnutls_x509_privkey_t * key,
41 gnutls_x509_crt_t * cert,
42 gnutls_x509_crt_t ** extra_certs_ret,
43 unsigned int * extra_certs_ret_len,
44 gnutls_x509_crl_t * crl)
46 gnutls_pkcs12_bag_t bag = NULL;
47 gnutls_x509_crt_t *extra_certs = NULL;
48 int extra_certs_len = 0;
51 size_t cert_id_size = 0;
52 size_t key_id_size = 0;
61 /* find the first private key */
67 ret = gnutls_pkcs12_bag_init (&bag);
75 ret = gnutls_pkcs12_get_bag (p12, idx, bag);
76 if (ret == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE)
84 ret = gnutls_pkcs12_bag_get_type (bag, 0);
91 if (ret == GNUTLS_BAG_ENCRYPTED)
93 ret = gnutls_pkcs12_bag_decrypt (bag, password);
101 elements_in_bag = gnutls_pkcs12_bag_get_count (bag);
102 if (elements_in_bag < 0)
108 for (i = 0; i < elements_in_bag; i++)
113 type = gnutls_pkcs12_bag_get_type (bag, i);
120 ret = gnutls_pkcs12_bag_get_data (bag, i, &data);
129 case GNUTLS_BAG_PKCS8_ENCRYPTED_KEY:
130 case GNUTLS_BAG_PKCS8_KEY:
131 if (*key != NULL) /* too simple to continue */
137 ret = gnutls_x509_privkey_init (key);
144 ret = gnutls_x509_privkey_import_pkcs8
145 (*key, &data, GNUTLS_X509_FMT_DER, password,
146 type == GNUTLS_BAG_PKCS8_KEY ? GNUTLS_PKCS_PLAIN : 0);
150 gnutls_x509_privkey_deinit (*key);
154 key_id_size = sizeof (key_id);
156 gnutls_x509_privkey_get_key_id (*key, 0, key_id,
161 gnutls_x509_privkey_deinit (*key);
165 privkey_ok = 1; /* break */
173 gnutls_pkcs12_bag_deinit (bag);
175 if (privkey_ok != 0) /* private key was found */
179 if (privkey_ok == 0) /* no private key */
182 return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
185 /* now find the corresponding certificate
194 ret = gnutls_pkcs12_bag_init (&bag);
202 ret = gnutls_pkcs12_get_bag (p12, idx, bag);
203 if (ret == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE)
211 ret = gnutls_pkcs12_bag_get_type (bag, 0);
218 if (ret == GNUTLS_BAG_ENCRYPTED)
220 ret = gnutls_pkcs12_bag_decrypt (bag, password);
228 elements_in_bag = gnutls_pkcs12_bag_get_count (bag);
229 if (elements_in_bag < 0)
235 for (i = 0; i < elements_in_bag; i++)
239 gnutls_x509_crt_t this_cert;
241 type = gnutls_pkcs12_bag_get_type (bag, i);
248 ret = gnutls_pkcs12_bag_get_data (bag, i, &data);
257 case GNUTLS_BAG_CERTIFICATE:
258 ret = gnutls_x509_crt_init (&this_cert);
266 gnutls_x509_crt_import (this_cert, &data, GNUTLS_X509_FMT_DER);
270 gnutls_x509_crt_deinit (this_cert);
274 /* check if the key id match */
275 cert_id_size = sizeof (cert_id);
277 gnutls_x509_crt_get_key_id (this_cert, 0, cert_id, &cert_id_size);
281 gnutls_x509_crt_deinit (this_cert);
285 if (memcmp (cert_id, key_id, cert_id_size) != 0)
286 { /* they don't match - skip the certificate */
289 extra_certs = gnutls_realloc (extra_certs,
290 sizeof(extra_certs[0]) *
295 ret = GNUTLS_E_MEMORY_ERROR;
298 extra_certs[extra_certs_len - 1] = this_cert;
303 gnutls_x509_crt_deinit (this_cert);
309 if (*cert != NULL) /* no need to set it again */
326 ret = gnutls_x509_crl_init (crl);
333 ret = gnutls_x509_crl_import (*crl, &data, GNUTLS_X509_FMT_DER);
337 gnutls_x509_crl_deinit (*crl);
342 case GNUTLS_BAG_ENCRYPTED:
343 /* XXX Bother to recurse one level down? Unlikely to
344 use the same password anyway. */
345 case GNUTLS_BAG_EMPTY:
352 gnutls_pkcs12_bag_deinit (bag);
359 gnutls_pkcs12_bag_deinit (bag);
364 gnutls_x509_privkey_deinit(*key);
366 gnutls_x509_crt_deinit(*cert);
370 for (i = 0; i < extra_certs_len; i++)
371 gnutls_x509_crt_deinit(extra_certs[i]);
372 gnutls_free(extra_certs);
375 else if (extra_certs_ret)
377 *extra_certs_ret = extra_certs;
378 *extra_certs_ret_len = extra_certs_len;