]> git.ipfire.org Git - thirdparty/gnutls.git/commitdiff
Introduced GNUTLS_E_ENCRYPTED_STRUCTURE error code.
authorNikos Mavrogiannopoulos <nmav@gnutls.org>
Sun, 3 Jun 2012 18:01:11 +0000 (20:01 +0200)
committerNikos Mavrogiannopoulos <nmav@gnutls.org>
Sun, 3 Jun 2012 18:01:11 +0000 (20:01 +0200)
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.

NEWS
lib/gnutls_errors.c
lib/includes/gnutls/gnutls.h.in
lib/x509/pkcs12.c
lib/x509/privkey_pkcs8.c
src/certtool.c

diff --git a/NEWS b/NEWS
index 64bba00a1b4b8389e53c3eedaca000e09ae69b28..959a5ec70c5b27771dfaf94e558595c78cd5f41d 100644 (file)
--- 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
index c70b3bfdbee29c9cfc211e1e3af015cc9d536251..6ac73a3490fdde8115369772dae56bf9cc308671 100644 (file)
@@ -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."),
index 1a58a53ad305face239ec151c5eb62f38762aae9..39e767c8abdd862bdbc3e6398e8b0ded219ca8cb 100644 (file)
@@ -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
 
index 40b3a8a2d903553a8700b073e30e8f1d09ccd29a..452d6a5cb7be52a7fafeb6a47fa1e35f569b42e3 100644 (file)
@@ -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 */
                 {
index b4429568ee81a718b5aa450ddf3d16bcaa18a95c..e921c70e638c29ac0ffdbf9ea607ad7522a8fb0e 100644 (file)
@@ -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)
index 59d6155d9ae87422b87b26285cb6de3ae14a4926..1b48dc2e1f4f3f98b19e945e56ea3f964163c912 100644 (file)
@@ -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));