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};
|
chunk_t key = {alloca(key_size), key_size};
|
||||||
uint8_t padding, *last_padding_pos, *first_padding_pos;
|
uint8_t padding, *last_padding_pos, *first_padding_pos;
|
||||||
|
|
||||||
|
if (!key_size)
|
||||||
|
{
|
||||||
|
return FAILED;
|
||||||
|
}
|
||||||
|
|
||||||
/* build key from passphrase and IV */
|
/* build key from passphrase and IV */
|
||||||
hasher = lib->crypto->create_hasher(lib->crypto, HASH_MD5);
|
hasher = lib->crypto->create_hasher(lib->crypto, HASH_MD5);
|
||||||
if (hasher == NULL)
|
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) ||
|
if (!hasher->get_hash(hasher, passphrase, NULL) ||
|
||||||
!hasher->get_hash(hasher, salt, hash.ptr))
|
!hasher->get_hash(hasher, salt, hash.ptr))
|
||||||
{
|
{
|
||||||
|
hasher->destroy(hasher);
|
||||||
return FAILED;
|
return FAILED;
|
||||||
}
|
}
|
||||||
memcpy(key.ptr, hash.ptr, hash.len);
|
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, passphrase, NULL) ||
|
||||||
!hasher->get_hash(hasher, salt, hash.ptr))
|
!hasher->get_hash(hasher, salt, hash.ptr))
|
||||||
{
|
{
|
||||||
|
hasher->destroy(hasher);
|
||||||
return FAILED;
|
return FAILED;
|
||||||
}
|
}
|
||||||
memcpy(key.ptr + hash.len, hash.ptr, key.len - hash.len);
|
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",
|
DBG1(DBG_ASN, " %N encryption algorithm not available",
|
||||||
encryption_algorithm_names, alg);
|
encryption_algorithm_names, alg);
|
||||||
|
memwipe(key.ptr, key.len);
|
||||||
return NOT_SUPPORTED;
|
return NOT_SUPPORTED;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (iv.len != crypter->get_iv_size(crypter) ||
|
if (iv.len != crypter->get_iv_size(crypter) ||
|
||||||
blob->len % crypter->get_block_size(crypter))
|
blob->len % crypter->get_block_size(crypter))
|
||||||
{
|
{
|
||||||
crypter->destroy(crypter);
|
|
||||||
DBG1(DBG_ASN, " data size is not multiple of block size");
|
DBG1(DBG_ASN, " data size is not multiple of block size");
|
||||||
|
crypter->destroy(crypter);
|
||||||
|
memwipe(key.ptr, key.len);
|
||||||
return PARSE_ERROR;
|
return PARSE_ERROR;
|
||||||
}
|
}
|
||||||
if (!crypter->set_key(crypter, key) ||
|
if (!crypter->set_key(crypter, key) ||
|
||||||
!crypter->decrypt(crypter, *blob, iv, &decrypted))
|
!crypter->decrypt(crypter, *blob, iv, &decrypted))
|
||||||
{
|
{
|
||||||
crypter->destroy(crypter);
|
crypter->destroy(crypter);
|
||||||
|
memwipe(key.ptr, key.len);
|
||||||
return FAILED;
|
return FAILED;
|
||||||
}
|
}
|
||||||
crypter->destroy(crypter);
|
crypter->destroy(crypter);
|
||||||
memcpy(blob->ptr, decrypted.ptr, blob->len);
|
memcpy(blob->ptr, decrypted.ptr, blob->len);
|
||||||
chunk_clear(&decrypted);
|
chunk_clear(&decrypted);
|
||||||
|
memwipe(key.ptr, key.len);
|
||||||
|
|
||||||
/* determine amount of padding */
|
/* determine amount of padding */
|
||||||
last_padding_pos = blob->ptr + blob->len - 1;
|
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;
|
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,
|
enumerator = lib->credmgr->create_shared_enumerator(lib->credmgr,
|
||||||
SHARED_PRIVATE_KEY_PASS, NULL, NULL);
|
SHARED_PRIVATE_KEY_PASS, NULL, NULL);
|
||||||
|
|||||||
Reference in New Issue
Block a user