pem: Properly handle encrypted PEM files without DEK-Info
Since `key_size` remained zero, this caused a buffer overflow when the
derived key in `pem_decrypt()` was copied to the zero-length local
buffer.
Also fixed two potential memory leaks if hashing fails and make sure
the decryption key is wiped.
Fixes: 160f4c225d ("moved PEM parsing functionality to its own plugin")
This commit is contained in:
@@ -96,6 +96,11 @@ static status_t pem_decrypt(chunk_t *blob, encryption_algorithm_t alg,
|
||||
chunk_t key = {alloca(key_size), key_size};
|
||||
uint8_t padding, *last_padding_pos, *first_padding_pos;
|
||||
|
||||
if (!key_size)
|
||||
{
|
||||
return FAILED;
|
||||
}
|
||||
|
||||
/* build key from passphrase and IV */
|
||||
hasher = lib->crypto->create_hasher(lib->crypto, HASH_MD5);
|
||||
if (hasher == NULL)
|
||||
@@ -108,6 +113,7 @@ static status_t pem_decrypt(chunk_t *blob, encryption_algorithm_t alg,
|
||||
if (!hasher->get_hash(hasher, passphrase, NULL) ||
|
||||
!hasher->get_hash(hasher, salt, hash.ptr))
|
||||
{
|
||||
hasher->destroy(hasher);
|
||||
return FAILED;
|
||||
}
|
||||
memcpy(key.ptr, hash.ptr, hash.len);
|
||||
@@ -118,6 +124,7 @@ static status_t pem_decrypt(chunk_t *blob, encryption_algorithm_t alg,
|
||||
!hasher->get_hash(hasher, passphrase, NULL) ||
|
||||
!hasher->get_hash(hasher, salt, hash.ptr))
|
||||
{
|
||||
hasher->destroy(hasher);
|
||||
return FAILED;
|
||||
}
|
||||
memcpy(key.ptr + hash.len, hash.ptr, key.len - hash.len);
|
||||
@@ -130,25 +137,29 @@ static status_t pem_decrypt(chunk_t *blob, encryption_algorithm_t alg,
|
||||
{
|
||||
DBG1(DBG_ASN, " %N encryption algorithm not available",
|
||||
encryption_algorithm_names, alg);
|
||||
memwipe(key.ptr, key.len);
|
||||
return NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
if (iv.len != crypter->get_iv_size(crypter) ||
|
||||
blob->len % crypter->get_block_size(crypter))
|
||||
{
|
||||
crypter->destroy(crypter);
|
||||
DBG1(DBG_ASN, " data size is not multiple of block size");
|
||||
crypter->destroy(crypter);
|
||||
memwipe(key.ptr, key.len);
|
||||
return PARSE_ERROR;
|
||||
}
|
||||
if (!crypter->set_key(crypter, key) ||
|
||||
!crypter->decrypt(crypter, *blob, iv, &decrypted))
|
||||
{
|
||||
crypter->destroy(crypter);
|
||||
memwipe(key.ptr, key.len);
|
||||
return FAILED;
|
||||
}
|
||||
crypter->destroy(crypter);
|
||||
memcpy(blob->ptr, decrypted.ptr, blob->len);
|
||||
chunk_clear(&decrypted);
|
||||
memwipe(key.ptr, key.len);
|
||||
|
||||
/* determine amount of padding */
|
||||
last_padding_pos = blob->ptr + blob->len - 1;
|
||||
@@ -340,6 +351,11 @@ static status_t pem_to_bin(chunk_t *blob, bool *pgp)
|
||||
{
|
||||
return SUCCESS;
|
||||
}
|
||||
if (alg == ENCR_UNDEFINED || !key_size)
|
||||
{
|
||||
DBG1(DBG_ASN, " encrypted PEM file has no valid DEK-Info");
|
||||
return PARSE_ERROR;
|
||||
}
|
||||
|
||||
enumerator = lib->credmgr->create_shared_enumerator(lib->credmgr,
|
||||
SHARED_PRIVATE_KEY_PASS, NULL, NULL);
|
||||
|
||||
Reference in New Issue
Block a user