static int dcrypt_gnutls_store_private_key(struct dcrypt_private_key *key, const char *cipher, buffer_t *destination, dcrypt_password_cb *cb, void *ctx, const char **error_r) { gnutls_privkey_t priv = (gnutls_privkey_t)key; gnutls_x509_privkey_t xkey; gnutls_privkey_export_x509(priv, &xkey); /* then export PEM */ size_t outl = 0; gnutls_x509_privkey_export_pkcs8(xkey, GNUTLS_X509_FMT_PEM, NULL, 0, NULL, &outl); char buffer[outl]; gnutls_x509_privkey_export_pkcs8(xkey, GNUTLS_X509_FMT_PEM, NULL, 0, buffer, &outl); buffer_append(destination, buffer, outl); memset(buffer, 0, sizeof(buffer)); return 0; }
void print_private_key(FILE *outfile, common_info_st * cinfo, gnutls_x509_privkey_t key) { int ret; size_t size; if (!key) return; if (!cinfo->pkcs8) { /* Only print private key parameters when an unencrypted * format is used */ if (cinfo->outcert_format == GNUTLS_X509_FMT_PEM) privkey_info_int(outfile, cinfo, key); size = lbuffer_size; ret = gnutls_x509_privkey_export(key, cinfo->outcert_format, lbuffer, &size); if (ret < 0) { fprintf(stderr, "privkey_export: %s\n", gnutls_strerror(ret)); exit(1); } if (cinfo->no_compat == 0 && gnutls_x509_privkey_get_seed(key, NULL, NULL, 0) != GNUTLS_E_INVALID_REQUEST) { gnutls_x509_privkey_set_flags(key, GNUTLS_PRIVKEY_FLAG_EXPORT_COMPAT); fwrite(lbuffer, 1, size, outfile); size = lbuffer_size; ret = gnutls_x509_privkey_export(key, cinfo->outcert_format, lbuffer, &size); if (ret < 0) { fprintf(stderr, "privkey_export: %s\n", gnutls_strerror(ret)); exit(1); } } } else { unsigned int flags = 0; const char *pass; pass = get_password(cinfo, &flags, 0); flags |= cipher_to_flags(cinfo->pkcs_cipher); size = lbuffer_size; ret = gnutls_x509_privkey_export_pkcs8(key, cinfo->outcert_format, pass, flags, lbuffer, &size); if (ret < 0) { fprintf(stderr, "privkey_export_pkcs8: %s\n", gnutls_strerror(ret)); exit(1); } } fwrite(lbuffer, 1, size, outfile); }
static int try_export_pem(gnutls_x509_privkey_t key, dnssec_binary_t *pem) { assert(key); gnutls_x509_crt_fmt_t format = GNUTLS_X509_FMT_PEM; char *password = NULL; int flags = 0; return gnutls_x509_privkey_export_pkcs8(key, format, password, flags, pem->data, &pem->size); }
Blob PrivateKey::serialize() const { if (!x509_key) return {}; size_t buf_sz = 8192; Blob buffer; buffer.resize(buf_sz); int err = gnutls_x509_privkey_export_pkcs8(x509_key, GNUTLS_X509_FMT_PEM, nullptr, GNUTLS_PKCS_PLAIN, buffer.data(), &buf_sz); if (err != GNUTLS_E_SUCCESS) { std::cerr << "Could not export private key - " << gnutls_strerror(err) << std::endl; return {}; } buffer.resize(buf_sz); return buffer; }
void Plugin::_loadPrivateKey() { QFile file(this->keyFile); int bits; size_t size; QByteArray data; gnutls_datum_t datum; int error; if (!file.open(QIODevice::ReadWrite)) throw Properties("error", "Unable to open the private key file").add("file", this->keyFile); ASSERT_INIT(gnutls_x509_privkey_init(&this->key), "privkey"); // Checks that the private key is valid if (file.size() > 0) { data = file.readAll(); datum.size = data.size(); datum.data = (unsigned char *)data.data(); if ((error = gnutls_x509_privkey_import_pkcs8(this->key, &datum, GNUTLS_X509_FMT_PEM, this->keyPassword.data(), 0)) != GNUTLS_E_SUCCESS) { LOG_ERROR("Invalid private key", Properties("error", gnutls_strerror(error)).toMap(), "Plugin", "_generatePrivateKey"); file.resize(0); } else if (gnutls_x509_privkey_sec_param(this->key) != this->secParam) file.resize(0); } // Generates the private key if (file.size() == 0) { bits = gnutls_sec_param_to_pk_bits(GNUTLS_PK_RSA, this->secParam); LOG_INFO("Generating a new private key", Properties("secParam", gnutls_sec_param_get_name(this->secParam)).add("bits", bits).toMap(), "Plugin", "_generatePrivateKey"); ASSERT(gnutls_x509_privkey_generate(this->key, GNUTLS_PK_RSA, bits, 0)); ASSERT(gnutls_x509_privkey_verify_params(this->key)); size = bits; data.resize((int)size); ASSERT(gnutls_x509_privkey_export_pkcs8(this->key, GNUTLS_X509_FMT_PEM, this->keyPassword.data(), GNUTLS_PKCS_USE_PBES2_AES_256, data.data(), &size)); data.resize((int)size); file.write(data); } }
/** * ntfs_pkcs12_extract_rsa_key */ static ntfs_rsa_private_key ntfs_pkcs12_extract_rsa_key(u8 *pfx, int pfx_size, char *password, char *thumbprint, int thumbprint_size, NTFS_DF_TYPES *df_type) { int err, bag_index, flags; gnutls_datum_t dpfx, dkey; gnutls_pkcs12_t pkcs12 = NULL; gnutls_pkcs12_bag_t bag = NULL; gnutls_x509_privkey_t pkey = NULL; gnutls_x509_crt_t crt = NULL; ntfs_rsa_private_key rsa_key = NULL; char purpose_oid[100]; size_t purpose_oid_size = sizeof(purpose_oid); size_t tp_size = thumbprint_size; BOOL have_thumbprint = FALSE; *df_type = DF_TYPE_UNKNOWN; /* Create a pkcs12 structure. */ err = gnutls_pkcs12_init(&pkcs12); if (err) { ntfs_log_error("Failed to initialize PKCS#12 structure: %s\n", gnutls_strerror(err)); return NULL; } /* Convert the PFX file (DER format) to native pkcs12 format. */ dpfx.data = pfx; dpfx.size = pfx_size; err = gnutls_pkcs12_import(pkcs12, &dpfx, GNUTLS_X509_FMT_DER, 0); if (err) { ntfs_log_error("Failed to convert the PFX file from DER to " "native PKCS#12 format: %s\n", gnutls_strerror(err)); goto err; } /* * Verify that the password is correct and that the key file has not * been tampered with. Note if the password has zero length and the * verification fails, retry with password set to NULL. This is needed * to get passwordless .pfx files generated with Windows XP SP1 (and * probably earlier versions of Windows) to work. */ retry_verify: err = gnutls_pkcs12_verify_mac(pkcs12, password); if (err) { if (err == GNUTLS_E_MAC_VERIFY_FAILED && password && !strlen(password)) { password = NULL; goto retry_verify; } ntfs_log_error("Failed to verify the MAC: %s Is the " "password correct?\n", gnutls_strerror(err)); goto err; } for (bag_index = 0; ; bag_index++) { err = gnutls_pkcs12_bag_init(&bag); if (err) { ntfs_log_error("Failed to initialize PKCS#12 Bag " "structure: %s\n", gnutls_strerror(err)); goto err; } err = gnutls_pkcs12_get_bag(pkcs12, bag_index, bag); if (err) { if (err == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE) { err = 0; break; } ntfs_log_error("Failed to obtain Bag from PKCS#12 " "structure: %s\n", gnutls_strerror(err)); goto err; } check_again: err = gnutls_pkcs12_bag_get_count(bag); if (err < 0) { ntfs_log_error("Failed to obtain Bag count: %s\n", gnutls_strerror(err)); goto err; } err = gnutls_pkcs12_bag_get_type(bag, 0); if (err < 0) { ntfs_log_error("Failed to determine Bag type: %s\n", gnutls_strerror(err)); goto err; } flags = 0; switch (err) { case GNUTLS_BAG_PKCS8_KEY: flags = GNUTLS_PKCS_PLAIN; case GNUTLS_BAG_PKCS8_ENCRYPTED_KEY: err = gnutls_pkcs12_bag_get_data(bag, 0, &dkey); if (err < 0) { ntfs_log_error("Failed to obtain Bag data: " "%s\n", gnutls_strerror(err)); goto err; } err = gnutls_x509_privkey_init(&pkey); if (err) { ntfs_log_error("Failed to initialized " "private key structure: %s\n", gnutls_strerror(err)); goto err; } /* Decrypt the private key into GNU TLS format. */ err = gnutls_x509_privkey_import_pkcs8(pkey, &dkey, GNUTLS_X509_FMT_DER, password, flags); if (err) { ntfs_log_error("Failed to convert private " "key from DER to GNU TLS " "format: %s\n", gnutls_strerror(err)); goto err; } #if 0 /* * Export the key again, but unencrypted, and output it * to stderr. Note the output has an RSA header so to * compare to openssl pkcs12 -nodes -in myfile.pfx * output need to ignore the part of the key between * the first "MII..." up to the second "MII...". The * actual RSA private key begins at the second "MII..." * and in my testing at least was identical to openssl * output and was also identical both on big and little * endian so gnutls should be endianness safe. */ char *buf = malloc(8192); size_t bufsize = 8192; err = gnutls_x509_privkey_export_pkcs8(pkey, GNUTLS_X509_FMT_PEM, "", GNUTLS_PKCS_PLAIN, buf, &bufsize); if (err) { ntfs_log_error("eek1\n"); exit(1); } ntfs_log_error("%s\n", buf); free(buf); #endif /* Convert the private key to our internal format. */ rsa_key = ntfs_rsa_private_key_import_from_gnutls(pkey); if (!rsa_key) goto err; break; case GNUTLS_BAG_ENCRYPTED: err = gnutls_pkcs12_bag_decrypt(bag, password); if (err) { ntfs_log_error("Failed to decrypt Bag: %s\n", gnutls_strerror(err)); goto err; } goto check_again; case GNUTLS_BAG_CERTIFICATE: err = gnutls_pkcs12_bag_get_data(bag, 0, &dkey); if (err < 0) { ntfs_log_error("Failed to obtain Bag data: " "%s\n", gnutls_strerror(err)); goto err; } err = gnutls_x509_crt_init(&crt); if (err) { ntfs_log_error("Failed to initialize " "certificate structure: %s\n", gnutls_strerror(err)); goto err; } err = gnutls_x509_crt_import(crt, &dkey, GNUTLS_X509_FMT_DER); if (err) { ntfs_log_error("Failed to convert certificate " "from DER to GNU TLS format: " "%s\n", gnutls_strerror(err)); goto err; } err = gnutls_x509_crt_get_key_purpose_oid(crt, 0, purpose_oid, &purpose_oid_size, NULL); if (err) { ntfs_log_error("Failed to get key purpose " "OID: %s\n", gnutls_strerror(err)); goto err; } purpose_oid[purpose_oid_size - 1] = '\0'; if (!strcmp(purpose_oid, NTFS_EFS_CERT_PURPOSE_OID_DRF)) *df_type = DF_TYPE_DRF; else if (!strcmp(purpose_oid, NTFS_EFS_CERT_PURPOSE_OID_DDF)) *df_type = DF_TYPE_DDF; else { ntfs_log_error("Certificate has unknown " "purpose OID %s.\n", purpose_oid); err = EINVAL; goto err; } /* Return the thumbprint to the caller. */ err = gnutls_x509_crt_get_fingerprint(crt, GNUTLS_DIG_SHA1, thumbprint, &tp_size); if (err) { ntfs_log_error("Failed to get thumbprint: " "%s\n", gnutls_strerror(err)); goto err; } if (tp_size != NTFS_SHA1_THUMBPRINT_SIZE) { ntfs_log_error("Invalid thumbprint size %zd. " "Should be %d.\n", tp_size, thumbprint_size); err = EINVAL; goto err; } have_thumbprint = TRUE; gnutls_x509_crt_deinit(crt); crt = NULL; break; default: /* We do not care about other types. */ break; } gnutls_pkcs12_bag_deinit(bag); } err: if (rsa_key && (err || *df_type == DF_TYPE_UNKNOWN || !have_thumbprint)) { if (!err) ntfs_log_error("Key type or thumbprint not found, " "aborting.\n"); ntfs_rsa_private_key_release(rsa_key); rsa_key = NULL; } if (crt) gnutls_x509_crt_deinit(crt); if (pkey) gnutls_x509_privkey_deinit(pkey); if (bag) gnutls_pkcs12_bag_deinit(bag); if (pkcs12) gnutls_pkcs12_deinit(pkcs12); return rsa_key; }