/* Simplified PKCS#12 routines */
-static int parse_pk12( PKCS12 *p12, const char *pass, int passlen, EVP_PKEY **pkey, X509 **cert, STACK **ca);
-static int parse_bags( STACK *bags, const char *pass, int passlen, EVP_PKEY **pkey, X509 **cert, STACK **ca, ASN1_OCTET_STRING **keyid, char *keymatch);
-static int parse_bag( PKCS12_SAFEBAG *bag, const char *pass, int passlen, EVP_PKEY **pkey, X509 **cert, STACK **ca, ASN1_OCTET_STRING **keyid, char *keymatch);
+static int parse_pk12( PKCS12 *p12, const char *pass, int passlen,
+ EVP_PKEY **pkey, X509 **cert, STACK_OF(X509) **ca);
+
+static int parse_bags( STACK *bags, const char *pass, int passlen,
+ EVP_PKEY **pkey, X509 **cert, STACK_OF(X509) **ca,
+ ASN1_OCTET_STRING **keyid, char *keymatch);
+
+static int parse_bag( PKCS12_SAFEBAG *bag, const char *pass, int passlen,
+ EVP_PKEY **pkey, X509 **cert, STACK_OF(X509) **ca,
+ ASN1_OCTET_STRING **keyid, char *keymatch);
+
/* Parse and decrypt a PKCS#12 structure returning user key, user cert
* and other (CA) certs. Note either ca should be NULL, *ca should be NULL,
* or it should point to a valid STACK structure. pkey and cert can be
*/
int PKCS12_parse (PKCS12 *p12, const char *pass, EVP_PKEY **pkey, X509 **cert,
- STACK **ca)
+ STACK_OF(X509) **ca)
{
/* Check for NULL PKCS12 structure */
/* Allocate stack for ca certificates if needed */
if ((ca != NULL) && (*ca == NULL))
{
- if (!(*ca = sk_new(NULL)))
+ if (!(*ca = sk_X509_new(NULL)))
{
PKCS12err(PKCS12_F_PKCS12_PARSE,ERR_R_MALLOC_FAILURE);
return 0;
/* Check the mac */
- if (!PKCS12_verify_mac (p12, pass, -1))
- {
+ /* If password is zero length or NULL then try verifying both cases
+ * to determine which password is correct. The reason for this is that
+ * under PKCS#12 password based encryption no password and a zero length
+ * password are two different things...
+ */
+
+ if(!pass || !*pass) {
+ if(PKCS12_verify_mac(p12, NULL, 0)) pass = NULL;
+ else if(PKCS12_verify_mac(p12, "", 0)) pass = "";
+ else {
+ PKCS12err(PKCS12_F_PKCS12_PARSE,PKCS12_R_MAC_VERIFY_FAILURE);
+ goto err;
+ }
+ } else if (!PKCS12_verify_mac(p12, pass, -1)) {
PKCS12err(PKCS12_F_PKCS12_PARSE,PKCS12_R_MAC_VERIFY_FAILURE);
goto err;
- }
+ }
if (!parse_pk12 (p12, pass, -1, pkey, cert, ca))
{
if (pkey && *pkey) EVP_PKEY_free (*pkey);
if (cert && *cert) X509_free (*cert);
- if (ca) sk_pop_free (*ca, X509_free);
+ if (ca) sk_X509_pop_free (*ca, X509_free);
return 0;
}
/* Parse the outer PKCS#12 structure */
static int parse_pk12 (PKCS12 *p12, const char *pass, int passlen,
- EVP_PKEY **pkey, X509 **cert, STACK **ca)
+ EVP_PKEY **pkey, X509 **cert, STACK_OF(X509) **ca)
{
STACK *asafes, *bags;
int i, bagnid;
static int parse_bags (STACK *bags, const char *pass, int passlen,
- EVP_PKEY **pkey, X509 **cert, STACK **ca,
+ EVP_PKEY **pkey, X509 **cert, STACK_OF(X509) **ca,
ASN1_OCTET_STRING **keyid, char *keymatch)
{
int i;
#define MATCH_ALL 0x3
static int parse_bag(PKCS12_SAFEBAG *bag, const char *pass, int passlen,
- EVP_PKEY **pkey, X509 **cert, STACK **ca,
+ EVP_PKEY **pkey, X509 **cert, STACK_OF(X509) **ca,
ASN1_OCTET_STRING **keyid,
char *keymatch)
{
if (lkey) {
*keymatch |= MATCH_CERT;
if (cert) *cert = x509;
- } else if (ca) sk_push (*ca, (char *)x509);
+ } else {
+ if(ca) sk_X509_push (*ca, x509);
+ else X509_free(x509);
+ }
break;
case NID_safeContentsBag: