From: Nikos Mavrogiannopoulos Date: Sun, 3 Jun 2012 18:01:11 +0000 (+0200) Subject: Introduced GNUTLS_E_ENCRYPTED_STRUCTURE error code. X-Git-Tag: gnutls_3_0_21~76 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=ca1ac3f84a4891149ea3eece155cdef6ce94b033;p=thirdparty%2Fgnutls.git Introduced GNUTLS_E_ENCRYPTED_STRUCTURE error code. This error code is returned by encrypted key import functions such as gnutls_x509_privkey_import_pkcs8() and gnutls_pkcs12_simple_parse() when an encrypted structure is provided but no password is given. --- diff --git a/NEWS b/NEWS index 64bba00a1b..959a5ec70c 100644 --- a/NEWS +++ b/NEWS @@ -27,11 +27,16 @@ to simplify parsing in most PKCS #12 use cases. the whole certificate chain (if any) to the credentials structure, instead of only the end-user certificate. +** libgnutls: Key import functions such as gnutls_pkcs12_simple_parse() +and gnutls_x509_privkey_import_pkcs8(), return GNUTLS_E_ENCRYPTED_STRUCTURE +if the input structure is encrypted but no password was provided. + ** libgnutlsxx: Added session::set_transport_vec_push_function. Patch by Alexandre Bique. ** API and ABI modifications: GNUTLS_CERT_SIGNATURE_FAILURE: Added +GNUTLS_E_ENCRYPTED_STRUCTURE: Added gnutls_pubkey_verify_hash2: Added gnutls_pkcs12_simple_parse: Added gnutls_certificate_set_x509_system_trust: Added diff --git a/lib/gnutls_errors.c b/lib/gnutls_errors.c index c70b3bfdbe..6ac73a3490 100644 --- a/lib/gnutls_errors.c +++ b/lib/gnutls_errors.c @@ -111,6 +111,7 @@ static const gnutls_error_entry error_algorithms[] = { GNUTLS_E_MPI_PRINT_FAILED, 1), ERROR_ENTRY (N_("Decryption has failed."), GNUTLS_E_DECRYPTION_FAILED, 1), ERROR_ENTRY (N_("Encryption has failed."), GNUTLS_E_ENCRYPTION_FAILED, 1), + ERROR_ENTRY (N_("The provided structure is encrypted."), GNUTLS_E_ENCRYPTED_STRUCTURE, 1), ERROR_ENTRY (N_("Public key decryption has failed."), GNUTLS_E_PK_DECRYPTION_FAILED, 1), ERROR_ENTRY (N_("Public key encryption has failed."), diff --git a/lib/includes/gnutls/gnutls.h.in b/lib/includes/gnutls/gnutls.h.in index 1a58a53ad3..39e767c8ab 100644 --- a/lib/includes/gnutls/gnutls.h.in +++ b/lib/includes/gnutls/gnutls.h.in @@ -1898,6 +1898,7 @@ gnutls_ecc_curve_t gnutls_ecc_curve_get(gnutls_session_t session); #define GNUTLS_E_NO_PRIORITIES_WERE_SET -326 #define GNUTLS_E_X509_UNSUPPORTED_EXTENSION -327 #define GNUTLS_E_SESSION_EOF -328 +#define GNUTLS_E_ENCRYPTED_STRUCTURE -329 #define GNUTLS_E_UNIMPLEMENTED_FEATURE -1250 diff --git a/lib/x509/pkcs12.c b/lib/x509/pkcs12.c index 40b3a8a2d9..452d6a5cb7 100644 --- a/lib/x509/pkcs12.c +++ b/lib/x509/pkcs12.c @@ -1366,7 +1366,11 @@ cleanup: * complexity that would make it harder to use this functionality at * all. * - * Returns: %GNUTLS_E_SUCCESS on success, or an error code. + * If the provided structure has encrypted fields but no password + * is provided then this function returns %GNUTLS_E_ENCRYPTED_STRUCTURE. + * + * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a + * negative error value. * * Since: 3.1 **/ @@ -1426,6 +1430,12 @@ gnutls_pkcs12_simple_parse (gnutls_pkcs12_t p12, if (ret == GNUTLS_BAG_ENCRYPTED) { + if (password == NULL) + { + ret = gnutls_assert_val(GNUTLS_E_ENCRYPTED_STRUCTURE); + goto done; + } + ret = gnutls_pkcs12_bag_decrypt (bag, password); if (ret < 0) { @@ -1463,6 +1473,12 @@ gnutls_pkcs12_simple_parse (gnutls_pkcs12_t p12, switch (type) { case GNUTLS_BAG_PKCS8_ENCRYPTED_KEY: + if (password == NULL) + { + ret = gnutls_assert_val(GNUTLS_E_ENCRYPTED_STRUCTURE); + goto done; + } + case GNUTLS_BAG_PKCS8_KEY: if (*key != NULL) /* too simple to continue */ { diff --git a/lib/x509/privkey_pkcs8.c b/lib/x509/privkey_pkcs8.c index b4429568ee..e921c70e63 100644 --- a/lib/x509/privkey_pkcs8.c +++ b/lib/x509/privkey_pkcs8.c @@ -811,42 +811,19 @@ error: return result; } - -/* Converts a PKCS #8 key to - * an internal structure (gnutls_private_key) - * (normally a PKCS #1 encoded RSA key) - */ -static int -decode_pkcs8_key (const gnutls_datum_t * raw_key, - const char *password, gnutls_x509_privkey_t pkey) +static int decrypt_pkcs8_key(const gnutls_datum_t * raw_key, + ASN1_TYPE pkcs8_asn, const char *password, + gnutls_x509_privkey_t pkey) { int result, len; char enc_oid[64]; gnutls_datum_t tmp; - ASN1_TYPE pbes2_asn = ASN1_TYPE_EMPTY, pkcs8_asn = ASN1_TYPE_EMPTY; + ASN1_TYPE pbes2_asn = ASN1_TYPE_EMPTY; int params_start, params_end, params_len; struct pbkdf2_params kdf_params; struct pbe_enc_params enc_params; schema_id schema; - if ((result = - asn1_create_element (_gnutls_get_pkix (), - "PKIX1.pkcs-8-EncryptedPrivateKeyInfo", - &pkcs8_asn)) != ASN1_SUCCESS) - { - gnutls_assert (); - result = _gnutls_asn2err (result); - goto error; - } - - result = asn1_der_decoding (&pkcs8_asn, raw_key->data, raw_key->size, NULL); - if (result != ASN1_SUCCESS) - { - gnutls_assert (); - result = _gnutls_asn2err (result); - goto error; - } - /* Check the encryption schema OID */ len = sizeof (enc_oid); @@ -905,8 +882,6 @@ decode_pkcs8_key (const gnutls_datum_t * raw_key, goto error; } - asn1_delete_structure (&pkcs8_asn); - result = decode_private_key_info (&tmp, pkey); _gnutls_free_datum (&tmp); @@ -939,8 +914,48 @@ decode_pkcs8_key (const gnutls_datum_t * raw_key, error: asn1_delete_structure (&pbes2_asn); + return result; +} + +/* Converts a PKCS #8 key to + * an internal structure (gnutls_private_key) + * (normally a PKCS #1 encoded RSA key) + */ +static int +decode_pkcs8_key (const gnutls_datum_t * raw_key, + const char *password, gnutls_x509_privkey_t pkey, + unsigned int decrypt) +{ + int result; + ASN1_TYPE pkcs8_asn = ASN1_TYPE_EMPTY; + + if ((result = + asn1_create_element (_gnutls_get_pkix (), + "PKIX1.pkcs-8-EncryptedPrivateKeyInfo", + &pkcs8_asn)) != ASN1_SUCCESS) + { + gnutls_assert (); + result = _gnutls_asn2err (result); + goto error; + } + + result = asn1_der_decoding (&pkcs8_asn, raw_key->data, raw_key->size, NULL); + if (result != ASN1_SUCCESS) + { + gnutls_assert (); + result = _gnutls_asn2err (result); + goto error; + } + + if (decrypt) + result = decrypt_pkcs8_key(raw_key, pkcs8_asn, password, pkey); + else + result = 0; + +error: asn1_delete_structure (&pkcs8_asn); return result; + } /* Decodes an RSA privateKey from a PKCS8 structure. @@ -1170,6 +1185,9 @@ error: * 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_ENCRYPTED_STRUCTURE is returned. + * * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a * negative error value. **/ @@ -1231,10 +1249,15 @@ gnutls_x509_privkey_import_pkcs8 (gnutls_x509_privkey_t key, if (password == NULL || (flags & GNUTLS_PKCS_PLAIN)) { result = decode_private_key_info (&_data, key); + if (result < 0) + { /* check if it is encrypted */ + if (decode_pkcs8_key(&_data, "", key, 0) == 0) + result = GNUTLS_E_ENCRYPTED_STRUCTURE; + } } else { /* encrypted. */ - result = decode_pkcs8_key (&_data, password, key); + result = decode_pkcs8_key (&_data, password, key, 1); } if (result < 0) diff --git a/src/certtool.c b/src/certtool.c index 59d6155d9a..1b48dc2e1f 100644 --- a/src/certtool.c +++ b/src/certtool.c @@ -1782,12 +1782,19 @@ privkey_info (common_info_st* cinfo) /* If we failed to import the certificate previously try PKCS #8 */ if (cinfo->pkcs8 || ret == GNUTLS_E_BASE64_UNEXPECTED_HEADER_ERROR) { - if (cinfo->password) - pass = cinfo->password; - else - pass = get_pass (); ret = gnutls_x509_privkey_import_pkcs8 (key, &pem, - incert_format, pass, 0); + incert_format, NULL, GNUTLS_PKCS8_PLAIN); + if (ret == GNUTLS_E_ENCRYPTED_STRUCTURE) + { + fprintf(stderr, "Encrypted structure detected...\n"); + if (cinfo->password) + pass = cinfo->password; + else + pass = get_pass (); + + ret = gnutls_x509_privkey_import_pkcs8 (key, &pem, + incert_format, pass, 0); + } } if (ret < 0) error (EXIT_FAILURE, 0, "import error: %s", gnutls_strerror (ret));