/** * 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) { uint8_t *out; /* Try the first header */ result = _gnutls_fbase64_decode (PEM_KEY_RSA, data->data, data->size, &out); 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, &out); 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, &out); if (result >= 0) key->pk_algorithm = GNUTLS_PK_EC; } } if (result < 0) { gnutls_assert (); goto failover; } _data.data = out; _data.size = result; need_free = 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) { key->key = _gnutls_privkey_decode_ecc_key (&_data, key); if (key->key == NULL) gnutls_assert (); } 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; key->key = _gnutls_privkey_decode_ecc_key (&_data, key); if (key->key == NULL) gnutls_assert (); } } } 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; }
/** * gnutls_x509_privkey_import - This function will import a DER or PEM encoded key * @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 of "RSA PRIVATE KEY", or * "DSA PRIVATE KEY". * * Returns 0 on success. * **/ 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) { opaque *out; /* Try the first header */ result = _gnutls_fbase64_decode (PEM_KEY_RSA, data->data, data->size, &out); key->pk_algorithm = GNUTLS_PK_RSA; if (result <= 0) { /* try for the second header */ result = _gnutls_fbase64_decode (PEM_KEY_DSA, data->data, data->size, &out); key->pk_algorithm = GNUTLS_PK_DSA; if (result <= 0) { if (result == 0) result = GNUTLS_E_INTERNAL_ERROR; gnutls_assert (); return result; } } _data.data = out; _data.size = result; need_free = 1; } if (key->pk_algorithm == GNUTLS_PK_RSA) { key->key = _gnutls_privkey_decode_pkcs1_rsa_key (&_data, key); if (key->key == NULL) { gnutls_assert (); result = GNUTLS_E_ASN1_DER_ERROR; goto cleanup; } } else if (key->pk_algorithm == GNUTLS_PK_DSA) { key->key = decode_dsa_key (&_data, key); if (key->key == NULL) { gnutls_assert (); result = GNUTLS_E_ASN1_DER_ERROR; goto cleanup; } } else { /* Try decoding with both, and accept the one that * succeeds. */ key->pk_algorithm = GNUTLS_PK_DSA; key->key = decode_dsa_key (&_data, key); if (key->key == NULL) { key->pk_algorithm = GNUTLS_PK_RSA; key->key = _gnutls_privkey_decode_pkcs1_rsa_key (&_data, key); if (key->key == NULL) { gnutls_assert (); result = GNUTLS_E_ASN1_DER_ERROR; goto cleanup; } } } if (need_free) _gnutls_free_datum (&_data); /* The key has now been decoded. */ return 0; cleanup: key->pk_algorithm = GNUTLS_PK_UNKNOWN; if (need_free) _gnutls_free_datum (&_data); return result; }