static int import_pkcs12_privkey (gnutls_x509_privkey_t key, const gnutls_datum_t * data, gnutls_x509_crt_fmt_t format, const char* password, unsigned int flags) { int ret; gnutls_pkcs12_t p12; gnutls_x509_privkey_t newkey; ret = gnutls_pkcs12_init(&p12); if (ret < 0) return gnutls_assert_val(ret); ret = gnutls_pkcs12_import(p12, data, format, flags); if (ret < 0) { gnutls_assert(); goto fail; } ret = gnutls_pkcs12_simple_parse (p12, password, &newkey, NULL, NULL, NULL, NULL, NULL, 0); if (ret < 0) { gnutls_assert(); goto fail; } ret = gnutls_x509_privkey_cpy (key, newkey); gnutls_x509_privkey_deinit (newkey); if (ret < 0) { gnutls_assert(); goto fail; } ret = 0; fail: gnutls_pkcs12_deinit(p12); return ret; }
void doit(void) { #ifdef ENABLE_NON_SUITEB_CURVES const char *filename, *password = "******"; gnutls_pkcs12_t pkcs12; gnutls_datum_t data; gnutls_x509_crt_t *chain, *extras; unsigned int chain_size = 0, extras_size = 0, i; gnutls_x509_privkey_t pkey; int ret; ret = global_init(); if (ret < 0) fail("global_init failed %d\n", ret); gnutls_global_set_log_function(tls_log_func); if (debug) gnutls_global_set_log_level(2); ret = gnutls_pkcs12_init(&pkcs12); if (ret < 0) fail("initialization failed: %s\n", gnutls_strerror(ret)); filename = getenv("PKCS12_MANY_CERTS_FILE"); if (!filename) filename = "pkcs12-decode/pkcs12_5certs.p12"; if (debug) success ("Reading PKCS#12 blob from `%s' using password `%s'.\n", filename, password); ret = gnutls_load_file(filename, &data); if (ret < 0) fail("cannot open file"); ret = gnutls_pkcs12_import(pkcs12, &data, GNUTLS_X509_FMT_DER, 0); if (ret < 0) fail("pkcs12_import failed %d: %s\n", ret, gnutls_strerror(ret)); if (debug) success("Read file OK\n"); ret = gnutls_pkcs12_simple_parse(pkcs12, password, &pkey, &chain, &chain_size, &extras, &extras_size, NULL, 0); if (ret < 0) fail("pkcs12_simple_parse failed %d: %s\n", ret, gnutls_strerror(ret)); if (chain_size != 1) fail("chain size (%u) should have been 1\n", chain_size); if (extras_size != 4) fail("extras size (%u) should have been 4\n", extras_size); if (debug) { char dn[512]; size_t dn_size; dn_size = sizeof(dn); ret = gnutls_x509_crt_get_dn(chain[0], dn, &dn_size); if (ret < 0) fail("crt_get_dn failed %d: %s\n", ret, gnutls_strerror(ret)); success("dn: %s\n", dn); dn_size = sizeof(dn); ret = gnutls_x509_crt_get_issuer_dn(chain[0], dn, &dn_size); if (ret < 0) fail("crt_get_dn failed %d: %s\n", ret, gnutls_strerror(ret)); success("issuer dn: %s\n", dn); } gnutls_pkcs12_deinit(pkcs12); gnutls_x509_privkey_deinit(pkey); for (i = 0; i < chain_size; i++) gnutls_x509_crt_deinit(chain[i]); gnutls_free(chain); for (i = 0; i < extras_size; i++) gnutls_x509_crt_deinit(extras[i]); gnutls_free(extras); /* Try gnutls_x509_privkey_import2() */ ret = gnutls_x509_privkey_init(&pkey); if (ret < 0) fail("gnutls_x509_privkey_init failed %d: %s\n", ret, gnutls_strerror(ret)); ret = gnutls_x509_privkey_import2(pkey, &data, GNUTLS_X509_FMT_DER, password, 0); if (ret < 0) fail("gnutls_x509_privkey_import2 failed %d: %s\n", ret, gnutls_strerror(ret)); gnutls_x509_privkey_deinit(pkey); free(data.data); gnutls_global_deinit(); #else exit(77); #endif }
/** * gnutls_certificate_set_x509_simple_pkcs12_mem: * @res: is a #gnutls_certificate_credentials_t type. * @p12blob: the PKCS#12 blob. * @type: is PEM or DER of the @pkcs12file. * @password: optional password used to decrypt PKCS#12 file, bags and keys. * * This function sets a certificate/private key pair and/or a CRL in * the gnutls_certificate_credentials_t type. This function may * be called more than once (in case multiple keys/certificates exist * for the server). * * Encrypted PKCS#12 bags and PKCS#8 private keys are supported. However, * only password based security, and the same password for all * operations, are supported. * * PKCS#12 file may contain many keys and/or certificates, and this * function will try to auto-detect based on the key ID the certificate * and key pair to use. If the PKCS#12 file contain the issuer of * the selected certificate, it will be appended to the certificate * to form a chain. * * If more than one private keys are stored in the PKCS#12 file, * then only one key will be read (and it is undefined which one). * * It is believed that the limitations of this function is acceptable * for most usage, and that any more flexibility would introduce * complexity that would make it harder to use this functionality at * all. * * Note that, this function by default returns zero on success and a negative value on error. * Since 3.5.6, when the flag %GNUTLS_CERTIFICATE_API_V2 is set using gnutls_certificate_set_flags() * it returns an index (greater or equal to zero). That index can be used to other functions to refer to the added key-pair. * * Returns: On success this functions returns zero, and otherwise a negative value on error (see above for modifying that behavior). * * Since: 2.8.0 **/ int gnutls_certificate_set_x509_simple_pkcs12_mem (gnutls_certificate_credentials_t res, const gnutls_datum_t * p12blob, gnutls_x509_crt_fmt_t type, const char *password) { gnutls_pkcs12_t p12; gnutls_x509_privkey_t key = NULL; gnutls_x509_crt_t *chain = NULL; gnutls_x509_crl_t crl = NULL; unsigned int chain_size = 0, i; int ret, idx; ret = gnutls_pkcs12_init(&p12); if (ret < 0) { gnutls_assert(); return ret; } ret = gnutls_pkcs12_import(p12, p12blob, type, 0); if (ret < 0) { gnutls_assert(); gnutls_pkcs12_deinit(p12); return ret; } if (password) { ret = gnutls_pkcs12_verify_mac(p12, password); if (ret < 0) { gnutls_assert(); gnutls_pkcs12_deinit(p12); return ret; } } ret = gnutls_pkcs12_simple_parse(p12, password, &key, &chain, &chain_size, NULL, NULL, &crl, 0); gnutls_pkcs12_deinit(p12); if (ret < 0) { gnutls_assert(); return ret; } if (key && chain) { ret = gnutls_certificate_set_x509_key(res, chain, chain_size, key); if (ret < 0) { gnutls_assert(); goto done; } idx = ret; } else { gnutls_assert(); ret = GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE; goto done; } if (crl) { ret = gnutls_certificate_set_x509_crl(res, &crl, 1); if (ret < 0) { gnutls_assert(); goto done; } } if (res->flags & GNUTLS_CERTIFICATE_API_V2) ret = idx; else ret = 0; done: if (chain) { for (i = 0; i < chain_size; i++) gnutls_x509_crt_deinit(chain[i]); gnutls_free(chain); } if (key) gnutls_x509_privkey_deinit(key); if (crl) gnutls_x509_crl_deinit(crl); return ret; }