int ne_ssl_clicert_decrypt(ne_ssl_client_cert *cc, const char *password) { int ret; gnutls_x509_crt cert = NULL; gnutls_x509_privkey pkey = NULL; if (gnutls_pkcs12_verify_mac(cc->p12, password) != 0) { return -1; } ret = pkcs12_parse(cc->p12, &pkey, &cert, NULL, password); if (ret < 0) return ret; if (!cert || (!pkey && !cc->keyless)) { if (cert) gnutls_x509_crt_deinit(cert); if (pkey) gnutls_x509_privkey_deinit(pkey); return -1; } gnutls_pkcs12_deinit(cc->p12); populate_cert(&cc->cert, cert); cc->pkey = pkey; cc->decrypted = 1; cc->p12 = NULL; return 0; }
/** * Adds all subjects in a PKCS12 files and notifies the frontend of them. */ static TokenError _backend_addFile(Backend *backend, const char *data, size_t length, void *tag) { SharedPKCS12 *p12 = pkcs12_parse(data, length); if (!p12) return TokenError_BadFile; STACK_OF(X509) *certList = pkcs12_listCerts(p12->data); if (!certList) return TokenError_Unknown; int certCount = sk_X509_num(certList); for (int i = 0; i < certCount; i++) { X509 *x = sk_X509_value(certList, i); if (!certutil_hasKeyUsage(x, backend->notifier->keyUsage)) goto dontAddCert; X509_NAME *id = X509_get_subject_name(x); if (!certutil_matchSubjectFilter(backend->notifier->subjectFilter, id)) goto dontAddCert; PKCS12Token *token = createToken(backend, p12, id, tag); if (token) { backend->notifier->notifyFunction((Token*)token, TokenChange_Added); continue; } dontAddCert: X509_free(x); } pkcs12_release(p12); return TokenError_Success; }
ne_ssl_client_cert *ne_ssl_clicert_read(const char *filename) { int ret; gnutls_datum data; gnutls_pkcs12 p12; ne_ssl_client_cert *cc; char *friendly_name = NULL; gnutls_x509_crt cert = NULL; gnutls_x509_privkey pkey = NULL; if (read_to_datum(filename, &data)) return NULL; if (gnutls_pkcs12_init(&p12) != 0) { return NULL; } ret = gnutls_pkcs12_import(p12, &data, GNUTLS_X509_FMT_DER, 0); ne_free(data.data); if (ret < 0) { gnutls_pkcs12_deinit(p12); return NULL; } if (gnutls_pkcs12_verify_mac(p12, "") == 0) { if (pkcs12_parse(p12, &pkey, &cert, &friendly_name, "") != 0 || !cert || !pkey) { gnutls_pkcs12_deinit(p12); return NULL; } cc = ne_calloc(sizeof *cc); cc->pkey = pkey; cc->decrypted = 1; cc->friendly_name = friendly_name; populate_cert(&cc->cert, cert); gnutls_pkcs12_deinit(p12); cc->p12 = NULL; return cc; } else { /* TODO: calling pkcs12_parse() here to find the friendly_name * seems to break horribly. */ cc = ne_calloc(sizeof *cc); cc->p12 = p12; return cc; } }