/* Load the private key. * @mand should be non zero if it is required to read a private key. */ gnutls_x509_privkey_t load_x509_private_key (int mand, common_info_st * info) { gnutls_x509_privkey_t key; int ret; gnutls_datum_t dat; size_t size; unsigned int flags = 0; const char* pass; if (!info->privkey && !mand) return NULL; if (info->privkey == NULL) error (EXIT_FAILURE, 0, "missing --load-privkey"); ret = gnutls_x509_privkey_init (&key); if (ret < 0) error (EXIT_FAILURE, 0, "privkey_init: %s", gnutls_strerror (ret)); dat.data = (void*)read_binary_file (info->privkey, &size); dat.size = size; if (!dat.data) error (EXIT_FAILURE, errno, "reading --load-privkey: %s", info->privkey); if (info->pkcs8) { pass = get_password (info, &flags, 0); ret = gnutls_x509_privkey_import_pkcs8 (key, &dat, info->incert_format, pass, flags); } else { ret = gnutls_x509_privkey_import2 (key, &dat, info->incert_format, NULL, 0); if (ret == GNUTLS_E_DECRYPTION_FAILED) { pass = get_password (info, &flags, 0); ret = gnutls_x509_privkey_import2 (key, &dat, info->incert_format, pass, flags); } } free (dat.data); if (ret == GNUTLS_E_BASE64_UNEXPECTED_HEADER_ERROR) { error (EXIT_FAILURE, 0, "import error: could not find a valid PEM header; " "check if your key is PKCS #12 encoded"); } if (ret < 0) error (EXIT_FAILURE, 0, "importing --load-privkey: %s: %s", info->privkey, gnutls_strerror (ret)); return key; }
static int import_Key(QWidget * w, gnutls_x509_privkey_t * privkey, gnutls_datum_t * raw) { int ret; if (raw->size == 0) return -1; gnutls_x509_privkey_init(privkey); ret = gnutls_x509_privkey_import2(*privkey, raw, GNUTLS_X509_FMT_PEM, NULL, 0); if (ret == GNUTLS_E_DECRYPTION_FAILED && w != NULL) { bool ok; QString text; text = QInputDialog::getText(w, QLatin1String ("This file requires a password"), QLatin1String("Please enter your password"), QLineEdit::Password, QString(), &ok); if (!ok) { ret = -1; goto fail; } ret = gnutls_x509_privkey_import2(*privkey, raw, GNUTLS_X509_FMT_PEM, text.toAscii().data(), 0); } if (ret == GNUTLS_E_BASE64_DECODING_ERROR || ret == GNUTLS_E_BASE64_UNEXPECTED_HEADER_ERROR) ret = gnutls_x509_privkey_import(*privkey, raw, GNUTLS_X509_FMT_DER); if (ret < 0) { goto fail; } return 0; fail: gnutls_x509_privkey_deinit(*privkey); *privkey = NULL; return ret; }
PrivateKey::PrivateKey(const Blob& import) { if (gnutls_global_init() != GNUTLS_E_SUCCESS) throw CryptoException("Can't initialize GnuTLS."); int err = gnutls_x509_privkey_init(&x509_key); if (err != GNUTLS_E_SUCCESS) throw CryptoException("Can't initialize private key !"); const gnutls_datum_t dt {(uint8_t*)import.data(), static_cast<unsigned>(import.size())}; err = gnutls_x509_privkey_import2(x509_key, &dt, GNUTLS_X509_FMT_PEM, nullptr, GNUTLS_PKCS_PLAIN); if (err != GNUTLS_E_SUCCESS) err = gnutls_x509_privkey_import2(x509_key, &dt, GNUTLS_X509_FMT_DER, nullptr, GNUTLS_PKCS_PLAIN); if (err != GNUTLS_E_SUCCESS) { gnutls_x509_privkey_deinit(x509_key); throw CryptoException("Can't load private key !"); } gnutls_privkey_init(&key); if (gnutls_privkey_import_x509(key, x509_key, GNUTLS_PRIVKEY_IMPORT_COPY) != GNUTLS_E_SUCCESS) { throw CryptoException("Can't load generic private key !"); } }
/** * gnutls_privkey_import_x509_raw: * @pkey: The private key * @data: The private key data to be imported * @format: The format of the private key * @password: A password (optional) * @flags: an ORed sequence of gnutls_pkcs_encrypt_flags_t * * This function will import the given private key to the abstract * #gnutls_privkey_t type. * * The supported formats are basic unencrypted key, PKCS8, PKCS12, * and the openssl format. * * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a * negative error value. * * Since: 3.1.0 **/ int gnutls_privkey_import_x509_raw(gnutls_privkey_t pkey, const gnutls_datum_t * data, gnutls_x509_crt_fmt_t format, const char *password, unsigned int flags) { gnutls_x509_privkey_t xpriv; int ret; ret = gnutls_x509_privkey_init(&xpriv); if (ret < 0) return gnutls_assert_val(ret); if (pkey->pin.cb) { gnutls_x509_privkey_set_pin_function(xpriv, pkey->pin.cb, pkey->pin.data); } ret = gnutls_x509_privkey_import2(xpriv, data, format, password, flags); if (ret < 0) { gnutls_assert(); goto cleanup; } ret = gnutls_privkey_import_x509(pkey, xpriv, GNUTLS_PRIVKEY_IMPORT_AUTO_RELEASE); if (ret < 0) { gnutls_assert(); goto cleanup; } return 0; cleanup: gnutls_x509_privkey_deinit(xpriv); 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 }
int main(int argc, char *argv[]) { int ret = 1; int i; gnutls_pubkey_t pubkey = NULL; gnutls_x509_privkey_t sigkey = NULL; gnutls_x509_crt_t sigcert = NULL; gnutls_x509_crt_t crt = NULL; const char *pubkey_filename = NULL; const char *sigkey_filename = NULL; const char *cert_filename = NULL; const char *modulus_str = NULL; const char *issuercert_filename = NULL; unsigned char *modulus_bin = NULL; int modulus_len = 0; gnutls_datum_t datum = { NULL, 0}, out = { NULL, 0}; int serial = 1; time_t now; int err; FILE *cert_file; char *subject = NULL; const char *error = NULL; int days = 365; char *sigkeypass = NULL; uint32_t ser_number; long int exponent = 0x10001; bool write_pem = false; uint8_t id[512]; size_t id_size = sizeof(id); enum cert_type_t certtype = CERT_TYPE_EK; const char *oid; unsigned int key_usage; char *tpm_manufacturer = NULL; char *tpm_version = NULL; char *tpm_model = NULL; char *platf_manufacturer = NULL; char *platf_version = NULL; char *platf_model = NULL; i = 1; while (i < argc) { if (!strcmp(argv[i], "--pubkey")) { i++; if (i == argc) { fprintf(stderr, "Missing argument for --pubkey.\n"); goto cleanup; } pubkey_filename = argv[i]; } else if (!strcmp(argv[i], "--modulus")) { i++; if (i == argc) { fprintf(stderr, "Missing argument for --modulus.\n"); goto cleanup; } modulus_str = argv[i]; if (!(modulus_bin = hex_str_to_bin(modulus_str, &modulus_len))) { goto cleanup; } } else if (!strcmp(argv[i], "--exponent")) { i++; if (i == argc) { fprintf(stderr, "Missing argument for --exponent.\n"); goto cleanup; } exponent = strtol(argv[i], NULL, 0); if (exponent == 0) { fprintf(stderr, "Exponent is wrong and cannot be 0.\n"); goto cleanup; } if (exponent > UINT_MAX) { fprintf(stderr, "Exponent must fit into 32bits.\n"); goto cleanup; } } else if (!strcmp(argv[i], "--signkey")) { i++; if (i == argc) { fprintf(stderr, "Missing argument for --signkey.\n"); goto cleanup; } sigkey_filename = argv[i]; } else if (!strcmp(argv[i], "--signkey-password")) { i++; if (i == argc) { fprintf(stderr, "Missing argument for --signkey-password.\n"); goto cleanup; } sigkeypass = argv[i]; } else if (!strcmp(argv[i], "--issuercert")) { i++; if (i == argc) { fprintf(stderr, "Missing argument for --issuercert.\n"); goto cleanup; } issuercert_filename = argv[i]; } else if (!strcmp(argv[i], "--out-cert")) { i++; if (i == argc) { fprintf(stderr, "Missing argument for --out-cert.\n"); goto cleanup; } cert_filename = argv[i]; } else if (!strcmp(argv[i], "--subject")) { i++; if (i == argc) { fprintf(stderr, "Missing argument for --subject.\n"); goto cleanup; } subject = argv[i]; } else if (!strcmp(argv[i], "--days")) { i++; if (i == argc) { fprintf(stderr, "Missing argument for --days.\n"); goto cleanup; } days = atoi(argv[i]); } else if (!strcmp(argv[i], "--serial")) { i++; if (i == argc) { fprintf(stderr, "Missing argument for --serial.\n"); goto cleanup; } serial = atoi(argv[i]); } else if (!strcmp(argv[i], "--type")) { i++; if (i == argc) { fprintf(stderr, "Missing argument for --type.\n"); goto cleanup; } if (!strcasecmp(argv[i], "ek")) { certtype = CERT_TYPE_EK; } else if (!strcasecmp(argv[i], "platform")) { certtype = CERT_TYPE_PLATFORM; // } else if (!strcasecmp(argv[i], "aik")) { // /* AIK cert needs EK cert as input */ // certtype = CERT_TYPE_AIK; } else { fprintf(stderr, "Unknown certificate type '%s'.\n", argv[i]); goto cleanup; } } else if (!strcmp(argv[i], "--tpm-manufacturer")) { i++; if (i == argc) { fprintf(stderr, "Missing argument for --tpm-manufacturer.\n"); goto cleanup; } tpm_manufacturer = argv[i]; } else if (!strcmp(argv[i], "--tpm-model")) { i++; if (i == argc) { fprintf(stderr, "Missing argument for --tpm-model.\n"); goto cleanup; } tpm_model = argv[i]; } else if (!strcmp(argv[i], "--tpm-version")) { i++; if (i == argc) { fprintf(stderr, "Missing argument for --tpm-version.\n"); goto cleanup; } tpm_version = argv[i]; } else if (!strcmp(argv[i], "--platform-manufacturer")) { i++; if (i == argc) { fprintf(stderr, "Missing argument for --platform-manufacturer.\n"); goto cleanup; } platf_manufacturer = argv[i]; } else if (!strcmp(argv[i], "--platform-model")) { i++; if (i == argc) { fprintf(stderr, "Missing argument for --platform-model.\n"); goto cleanup; } platf_model = argv[i]; } else if (!strcmp(argv[i], "--platform-version")) { i++; if (i == argc) { fprintf(stderr, "Missing argument for --platform-version.\n"); goto cleanup; } platf_version = argv[i]; } else if (!strcmp(argv[i], "--pem")) { write_pem = true; } else if (!strcmp(argv[i], "--help")) { usage(argv[0]); exit(0); } else { fprintf(stderr, "Unknown command line parameter '%s'.\n", argv[i]); usage(argv[0]); exit(1); } i++; } ser_number = htonl(serial); if (pubkey_filename == NULL && modulus_bin == NULL) { fprintf(stderr, "Missing public EK file and modulus.\n"); usage(argv[0]); goto cleanup; } if (issuercert_filename == NULL) { fprintf(stderr, "The issuer certificate name is required.\n"); goto cleanup; } switch (certtype) { case CERT_TYPE_EK: case CERT_TYPE_PLATFORM: if (tpm_manufacturer == NULL || tpm_model == NULL || tpm_version == NULL) { fprintf(stderr, "--tpm-manufacturer and --tpm-model and " "--tpm version " "must all be provided\n"); goto cleanup; } break; case CERT_TYPE_AIK: break; } switch (certtype) { case CERT_TYPE_PLATFORM: if (platf_manufacturer == NULL || platf_model == NULL || platf_version == NULL) { fprintf(stderr, "--platform-manufacturer and --platform-model and " "--platform version " "must all be provided\n"); goto cleanup; } break; case CERT_TYPE_EK: case CERT_TYPE_AIK: break; } err = gnutls_global_init(); if (err < 0) { fprintf(stderr, "gnutls_global_init failed.\n"); goto cleanup; } gnutls_x509_privkey_init(&sigkey); if (pubkey_filename) { gnutls_pubkey_init(&pubkey); err = gnutls_load_file(pubkey_filename, &datum); if (err != GNUTLS_E_SUCCESS) { fprintf(stderr, "Could not open file for EK public key: %s\n", strerror(errno)); goto cleanup; } err = gnutls_pubkey_import(pubkey, &datum, GNUTLS_X509_FMT_PEM); gnutls_free(datum.data); datum.data = NULL; if (err != GNUTLS_E_SUCCESS) { fprintf(stderr, "Could not import EK.\n"); goto cleanup; } } else { pubkey = create_rsa_from_modulus(modulus_bin, modulus_len, exponent); free(modulus_bin); modulus_bin = NULL; if (pubkey == NULL) goto cleanup; } /* all types of keys must have pubkey set now otherwise the signing will not work */ if (sigkey_filename == NULL) { fprintf(stderr, "Missing signature key.\n"); usage(argv[0]); exit(1); } #define CHECK_GNUTLS_ERROR(_err, _msg, ...) \ if (_err != GNUTLS_E_SUCCESS) { \ fprintf(stderr, _msg, __VA_ARGS__); \ goto cleanup; \ } err = gnutls_load_file(sigkey_filename, &datum); CHECK_GNUTLS_ERROR(err, "Could not read signing key from file %s: %s\n", sigkey_filename, gnutls_strerror(err)); if (sigkeypass) { err = gnutls_x509_privkey_import2(sigkey, &datum, GNUTLS_X509_FMT_PEM, sigkeypass, 0); } else { err = gnutls_x509_privkey_import(sigkey, &datum, GNUTLS_X509_FMT_PEM); } gnutls_free(datum.data); datum.data = NULL; CHECK_GNUTLS_ERROR(err, "Could not import signing key : %s\n", gnutls_strerror(err)); err = gnutls_load_file(issuercert_filename, &datum); CHECK_GNUTLS_ERROR(err, "Could not read certificate from file %s : %s\n", issuercert_filename, gnutls_strerror(err)); gnutls_x509_crt_init(&sigcert); err = gnutls_x509_crt_import(sigcert, &datum, GNUTLS_X509_FMT_PEM); gnutls_free(datum.data); datum.data = NULL; CHECK_GNUTLS_ERROR(err, "Could not import issuer certificate: %s\n", gnutls_strerror(err)); err = gnutls_x509_crt_init(&crt); CHECK_GNUTLS_ERROR(err, "CRT init failed: %s\n", gnutls_strerror(err)) /* 3.5.1 Version */ err = gnutls_x509_crt_set_version(crt, 3); CHECK_GNUTLS_ERROR(err, "Could not set version on CRT: %s\n", gnutls_strerror(err)) /* 3.5.2 Serial Number */ err = gnutls_x509_crt_set_serial(crt, &ser_number, sizeof(ser_number)); CHECK_GNUTLS_ERROR(err, "Could not set serial on CRT: %s\n", gnutls_strerror(err)) /* 3.5.5 Validity */ now = time(NULL); err = gnutls_x509_crt_set_activation_time(crt, now); CHECK_GNUTLS_ERROR(err, "Could not set activation time on CRT: %s\n", gnutls_strerror(err)) err = gnutls_x509_crt_set_expiration_time(crt, now + (time_t)days * 24 * 60 * 60); CHECK_GNUTLS_ERROR(err, "Could not set expiration time on CRT: %s\n", gnutls_strerror(err)) /* 3.5.6 Subject -- should be empty, but we allow it anyway */ if (subject) { err = gnutls_x509_crt_set_dn(crt, subject, &error); CHECK_GNUTLS_ERROR(err, "Could not set DN on CRT: %s\n" "DN '%s must be fault after %s\n.'", gnutls_strerror(err), subject, error) } /* 3.5.7 Public Key Info */ switch (certtype) { case CERT_TYPE_EK: oid = "1.2.840.113549.1.1.7"; break; case CERT_TYPE_PLATFORM: oid = NULL; break; case CERT_TYPE_AIK: oid = "1.2.840.113549.1.1.1"; break; default: fprintf(stderr, "Internal error: unhandle case in line %d\n", __LINE__); goto cleanup; } if (oid) { err = gnutls_x509_crt_set_key_purpose_oid(crt, oid, 0); CHECK_GNUTLS_ERROR(err, "Could not set key purpose on CRT: %s\n", gnutls_strerror(err)) } /* 3.5.8 Certificate Policies -- skip since not mandated */ /* 3.5.9 Subject Alternative Names -- missing code */ err = create_tpm_manufacturer_info(tpm_manufacturer, tpm_model, tpm_version, &datum); if (!err && datum.size > 0) { /* * GNUTLS's write_new_general_name can only handle a few GNUTLS_SAN_* * -> we have to use GNUTLS_SAN_URI */ err = gnutls_x509_crt_set_subject_alt_name(crt, GNUTLS_SAN_URI, datum.data, datum.size, GNUTLS_FSAN_SET); CHECK_GNUTLS_ERROR(err, "Could not set subject alt name: %s\n", gnutls_strerror(err)) }
/* Loads a x509 private key list */ gnutls_x509_privkey_t *load_privkey_list(int mand, size_t * privkey_size, common_info_st * info) { static gnutls_x509_privkey_t key[MAX_KEYS]; char *ptr; int ret, i; gnutls_datum_t dat, file_data; int ptr_size; unsigned int flags = 0; const char *pass; *privkey_size = 0; fprintf(stderr, "Loading private key list...\n"); if (info->privkey == NULL) { if (mand) { fprintf(stderr, "missing --load-privkey"); exit(1); } else return NULL; } ret = gnutls_load_file(info->privkey, &file_data); if (ret < 0) { fprintf(stderr, "%s", info->privkey); exit(1); } ptr = (void *) file_data.data; ptr_size = file_data.size; for (i = 0; i < MAX_KEYS; i++) { ret = gnutls_x509_privkey_init(&key[i]); if (ret < 0) { fprintf(stderr, "privkey_init: %s", gnutls_strerror(ret)); exit(1); } dat.data = (void *) ptr; dat.size = ptr_size; ret = gnutls_x509_privkey_import2(key[i], &dat, info->incert_format, NULL, 0); if (ret == GNUTLS_E_DECRYPTION_FAILED) { pass = get_password(info, &flags, 0); ret = gnutls_x509_privkey_import2(key[i], &dat, info-> incert_format, pass, flags); } if (ret < 0 && *privkey_size > 0) break; if (ret < 0) { fprintf(stderr, "privkey_import: %s", gnutls_strerror(ret)); exit(1); } (*privkey_size)++; if (info->incert_format != GNUTLS_X509_FMT_PEM) break; ptr = strstr(ptr, "---END"); if (ptr == NULL) break; ptr++; ptr_size = file_data.size; ptr_size -= (unsigned int) ((unsigned char *) ptr - (unsigned char *) buffer); if (ptr_size < 0) break; } gnutls_free(file_data.data); fprintf(stderr, "Loaded %d private keys.\n", (int) *privkey_size); return key; }