openssl: Add support for unprotected PKCS#12 containers

This commit is contained in:
Tobias Brunner
2023-11-13 12:26:07 +01:00
parent bae841ea04
commit 7bb6aed5ab
@@ -139,6 +139,29 @@ static bool add_key(private_pkcs12_t *this, EVP_PKEY *private)
return key != NULL; return key != NULL;
} }
/**
* Decrypt PKCS#12 file using the given password and unpack credentials
*/
static status_t decrypt_and_unpack_pw(private_pkcs12_t *this, char *password)
{
STACK_OF(X509) *cas = NULL;
EVP_PKEY *private;
X509 *cert;
if (PKCS12_parse(this->p12, password, &private, &cert, &cas))
{
/* if at least one is successful, we accept it */
if ((int)add_key(this, private) |
(int)add_cert(this, cert) |
(int)add_cas(this, cas))
{
return SUCCESS;
}
return FAILED;
}
return PARSE_ERROR;
}
/** /**
* Decrypt PKCS#12 file and unpack credentials * Decrypt PKCS#12 file and unpack credentials
*/ */
@@ -146,13 +169,21 @@ static bool decrypt_and_unpack(private_pkcs12_t *this)
{ {
enumerator_t *enumerator; enumerator_t *enumerator;
shared_key_t *shared; shared_key_t *shared;
STACK_OF(X509) *cas = NULL;
EVP_PKEY *private;
X509 *cert;
chunk_t key; chunk_t key;
char *password; char *password;
bool success = FALSE; bool success = FALSE;
/* try without password first */
switch (decrypt_and_unpack_pw(this, NULL))
{
case PARSE_ERROR:
break;
case SUCCESS:
return TRUE;
default:
return FALSE;
}
enumerator = lib->credmgr->create_shared_enumerator(lib->credmgr, enumerator = lib->credmgr->create_shared_enumerator(lib->credmgr,
SHARED_PRIVATE_KEY_PASS, NULL, NULL); SHARED_PRIVATE_KEY_PASS, NULL, NULL);
while (enumerator->enumerate(enumerator, &shared, NULL, NULL)) while (enumerator->enumerate(enumerator, &shared, NULL, NULL))
@@ -160,17 +191,25 @@ static bool decrypt_and_unpack(private_pkcs12_t *this)
key = shared->get_key(shared); key = shared->get_key(shared);
if (!key.ptr || asprintf(&password, "%.*s", (int)key.len, key.ptr) < 0) if (!key.ptr || asprintf(&password, "%.*s", (int)key.len, key.ptr) < 0)
{ {
password = NULL; password = strdup("");
} }
if (PKCS12_parse(this->p12, password, &private, &cert, &cas)) switch (decrypt_and_unpack_pw(this, password))
{ {
success = add_key(this, private); case PARSE_ERROR:
success &= add_cert(this, cert); /* password was incorrect, try another */
success &= add_cas(this, cas); memwipe(password, strlen(password));
free(password); free(password);
break; continue;
case SUCCESS:
success = TRUE;
break;
default:
/* password was correct but we were unable to unpack anything */
break;
} }
memwipe(password, strlen(password));
free(password); free(password);
break;
} }
enumerator->destroy(enumerator); enumerator->destroy(enumerator);
return success; return success;