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
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."),
* 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
**/
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)
{
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 */
{
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);
goto error;
}
- asn1_delete_structure (&pkcs8_asn);
-
result = decode_private_key_info (&tmp, pkey);
_gnutls_free_datum (&tmp);
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.
* 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.
**/
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)
/* 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));