/** * gnutls_x509_privkey_deinit: * @key: The structure to be deinitialized * * This function will deinitialize a private key structure. **/ void gnutls_x509_privkey_deinit(gnutls_x509_privkey_t key) { if (!key) return; _gnutls_x509_privkey_reinit(key); gnutls_free(key); }
/** * gnutls_x509_privkey_import_pkcs8: * @key: The data to store the parsed key * @data: The DER or PEM encoded key. * @format: One of DER or PEM * @password: the password to decrypt the key (if it is encrypted). * @flags: 0 if encrypted or GNUTLS_PKCS_PLAIN if not encrypted. * * This function will convert the given DER or PEM encoded PKCS8 2.0 * encrypted key to the native gnutls_x509_privkey_t format. The * output will be stored in @key. Both RSA and DSA keys can be * imported, and flags can only be used to indicate an unencrypted * key. * * The @password can be either ASCII or UTF-8 in the default PBES2 * encryption schemas, or ASCII for the PKCS12 schemas. * * If the Certificate is PEM encoded it should have a header of * "ENCRYPTED PRIVATE KEY", or "PRIVATE KEY". You only need to * specify the flags if the key is DER encoded, since in that case * the encryption status cannot be auto-detected. * * If the %GNUTLS_PKCS_PLAIN flag is specified and the supplied data * are encrypted then %GNUTLS_E_DECRYPTION_FAILED is returned. * * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a * negative error value. **/ int gnutls_x509_privkey_import_pkcs8(gnutls_x509_privkey_t key, const gnutls_datum_t * data, gnutls_x509_crt_fmt_t format, const char *password, unsigned int flags) { int result = 0, need_free = 0; gnutls_datum_t _data; if (key == NULL) { gnutls_assert(); return GNUTLS_E_INVALID_REQUEST; } _data.data = data->data; _data.size = data->size; key->params.algo = GNUTLS_PK_UNKNOWN; /* If the Certificate is in PEM format then decode it */ if (format == GNUTLS_X509_FMT_PEM) { /* Try the first header */ result = _gnutls_fbase64_decode(PEM_UNENCRYPTED_PKCS8, data->data, data->size, &_data); if (result < 0) { /* Try the encrypted header */ result = _gnutls_fbase64_decode(PEM_PKCS8, data->data, data->size, &_data); if (result < 0) { gnutls_assert(); return result; } } else if (flags == 0) flags |= GNUTLS_PKCS_PLAIN; need_free = 1; } if (key->expanded) { _gnutls_x509_privkey_reinit(key); } key->expanded = 1; /* Here we don't check for password == NULL to maintain a backwards * compatibility behavior, with old versions that were encrypting using * a NULL password. */ if (flags & GNUTLS_PKCS_PLAIN) { result = decode_private_key_info(&_data, key); if (result < 0) { /* check if it is encrypted */ if (pkcs8_key_decode(&_data, "", key, 0) == 0) result = GNUTLS_E_DECRYPTION_FAILED; } } else { /* encrypted. */ result = pkcs8_key_decode(&_data, password, key, 1); } if (result < 0) { gnutls_assert(); goto cleanup; } /* This part is necessary to get the public key on certain algorithms. * In the import above we only get the private key. */ result = _gnutls_pk_fixup(key->params.algo, GNUTLS_IMPORT, &key->params); if (result < 0) { gnutls_assert(); goto cleanup; } if (need_free) _gnutls_free_datum(&_data); /* The key has now been decoded. */ return 0; cleanup: asn1_delete_structure2(&key->key, ASN1_DELETE_FLAG_ZEROIZE); key->params.algo = GNUTLS_PK_UNKNOWN; if (need_free) _gnutls_free_datum(&_data); return result; }
/** * gnutls_x509_privkey_import: * @key: The structure to store the parsed key * @data: The DER or PEM encoded certificate. * @format: One of DER or PEM * * This function will convert the given DER or PEM encoded key to the * native #gnutls_x509_privkey_t format. The output will be stored in * @key . * * If the key is PEM encoded it should have a header that contains "PRIVATE * KEY". Note that this function falls back to PKCS #8 decoding without * password, if the default format fails to import. * * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a * negative error value. **/ int gnutls_x509_privkey_import(gnutls_x509_privkey_t key, const gnutls_datum_t * data, gnutls_x509_crt_fmt_t format) { int result = 0, need_free = 0; gnutls_datum_t _data; if (key == NULL) { gnutls_assert(); return GNUTLS_E_INVALID_REQUEST; } _data.data = data->data; _data.size = data->size; key->pk_algorithm = GNUTLS_PK_UNKNOWN; /* If the Certificate is in PEM format then decode it */ if (format == GNUTLS_X509_FMT_PEM) { /* Try the first header */ result = _gnutls_fbase64_decode(PEM_KEY_RSA, data->data, data->size, &_data); if (result >= 0) key->pk_algorithm = GNUTLS_PK_RSA; if (result == GNUTLS_E_BASE64_UNEXPECTED_HEADER_ERROR) { /* try for the second header */ result = _gnutls_fbase64_decode(PEM_KEY_DSA, data->data, data->size, &_data); if (result >= 0) key->pk_algorithm = GNUTLS_PK_DSA; if (result == GNUTLS_E_BASE64_UNEXPECTED_HEADER_ERROR) { /* try for the second header */ result = _gnutls_fbase64_decode(PEM_KEY_ECC, data->data, data->size, &_data); if (result >= 0) key->pk_algorithm = GNUTLS_PK_EC; } } if (result < 0) { gnutls_assert(); goto failover; } need_free = 1; } if (key->expanded) { _gnutls_x509_privkey_reinit(key); } key->expanded = 1; if (key->pk_algorithm == GNUTLS_PK_RSA) { key->key = _gnutls_privkey_decode_pkcs1_rsa_key(&_data, key); if (key->key == NULL) gnutls_assert(); } else if (key->pk_algorithm == GNUTLS_PK_DSA) { key->key = decode_dsa_key(&_data, key); if (key->key == NULL) gnutls_assert(); } else if (key->pk_algorithm == GNUTLS_PK_EC) { result = _gnutls_privkey_decode_ecc_key(&key->key, &_data, key, 0); if (result < 0) { gnutls_assert(); goto failover; } } else { /* Try decoding with both, and accept the one that * succeeds. */ key->pk_algorithm = GNUTLS_PK_RSA; key->key = _gnutls_privkey_decode_pkcs1_rsa_key(&_data, key); if (key->key == NULL) { key->pk_algorithm = GNUTLS_PK_DSA; key->key = decode_dsa_key(&_data, key); if (key->key == NULL) { key->pk_algorithm = GNUTLS_PK_EC; result = _gnutls_privkey_decode_ecc_key(&key->key, &_data, key, 0); if (result < 0) { gnutls_assert(); goto failover; } } } } if (key->key == NULL) { gnutls_assert(); result = GNUTLS_E_ASN1_DER_ERROR; goto failover; } if (need_free) _gnutls_free_datum(&_data); /* The key has now been decoded. */ return 0; failover: /* Try PKCS #8 */ if (result == GNUTLS_E_BASE64_UNEXPECTED_HEADER_ERROR) { _gnutls_debug_log ("Falling back to PKCS #8 key decoding\n"); result = gnutls_x509_privkey_import_pkcs8(key, data, format, NULL, GNUTLS_PKCS_PLAIN); } if (need_free) _gnutls_free_datum(&_data); return result; }