PKCS#5 v2 PBES2 support and use in PKCS#8 encrypted certificates

The error code POLARSSL_ERR_X509_PASSWORD_MISMATCH is now properly
returned in case of an encryption failure in the padding. The
POLARSSL_ERR_X509_PASSWORD_REQUIRED error code is only returned for PEM
formatted private keys as for DER formatted ones it is impossible to
distinguish if a DER blob is PKCS#8 encrypted or not.
diff --git a/library/x509parse.c b/library/x509parse.c
index d2bfddc..25e3b45 100644
--- a/library/x509parse.c
+++ b/library/x509parse.c
@@ -62,6 +62,9 @@
 #endif
 #include "polarssl/dhm.h"
 #include "polarssl/pkcs12.h"
+#if defined(POLARSSL_PKCS5_C)
+#include "polarssl/pkcs5.h"
+#endif
 
 #include <string.h>
 #include <stdlib.h>
@@ -2219,6 +2222,9 @@
     p = (unsigned char *) key;
     end = p + keylen;
 
+    if( pwdlen == 0 )
+        return( POLARSSL_ERR_X509_PASSWORD_REQUIRED );
+
     /*
      * This function parses the EncryptedPrivatKeyInfo object (PKCS#8)
      *
@@ -2302,6 +2308,19 @@
             return( ret );
         }
     }
+#if defined(POLARSSL_PKCS5_C)
+    else if( OID_CMP( OID_PKCS5_PBES2, &pbe_alg_oid ) )
+    {
+        if( ( ret = pkcs5_pbes2( &pbe_params, PKCS5_DECRYPT, pwd, pwdlen,
+                                  p, len, buf ) ) != 0 )
+        {
+            if( ret == POLARSSL_ERR_PKCS5_PASSWORD_MISMATCH )
+                return( POLARSSL_ERR_X509_PASSWORD_MISMATCH );
+
+            return( ret );
+        }
+    }
+#endif /* POLARSSL_PKCS5_C */
     else
         return( POLARSSL_ERR_X509_FEATURE_UNAVAILABLE );
 
@@ -2401,14 +2420,22 @@
     }
 
     rsa_free( rsa );
+
+    if( ret == POLARSSL_ERR_X509_PASSWORD_MISMATCH )
+    {
+        return( ret );
+    }
+
     if( ( ret = x509parse_key_pkcs8_unencrypted_der( rsa, key, keylen ) ) == 0 )
         return( 0 );
 
     rsa_free( rsa );
+
     if( ( ret = x509parse_key_pkcs1_der( rsa, key, keylen ) ) == 0 )
         return( 0 );
 
     rsa_free( rsa );
+
     return( POLARSSL_ERR_X509_KEY_INVALID_FORMAT );
 }