From bf8cf2fbaae7e86766858cd290f94de79e306723 Mon Sep 17 00:00:00 2001 From: Ingo Franzki Date: Mon, 10 Aug 2026 09:36:02 +0200 Subject: [PATCH] COMMON/PKCSCCA/PKCSTOK_MIGRATE: Prevent overflow when reading old token objects Check that the decrypted data is large enough to also hold the digest. Signed-off-by: Ingo Franzki --- usr/lib/common/loadsave.c | 5 +++-- usr/sbin/pkcscca/pkcscca.c | 3 ++- usr/sbin/pkcstok_migrate/pkcstok_migrate.c | 8 ++++++-- 3 files changed, 11 insertions(+), 5 deletions(-) diff --git a/usr/lib/common/loadsave.c b/usr/lib/common/loadsave.c index e845378e..32606879 100644 --- a/usr/lib/common/loadsave.c +++ b/usr/lib/common/loadsave.c @@ -1709,8 +1709,9 @@ CK_RV restore_private_token_object_old(STDLL_TokData_t *tokdata, CK_BYTE *data, obj_data_len = *(CK_ULONG_32 *) ptr; - // prevent buffer overflow in sha_update - if (obj_data_len > clear_len) { + // prevent buffer overflow in sha_update and memcmp + if (obj_data_len > clear_len || + sizeof(CK_ULONG_32) + obj_data_len + SHA1_HASH_SIZE > clear_len) { TRACE_ERROR("stripped length is greater than clear length\n"); rc = CKR_FUNCTION_FAILED; goto done; diff --git a/usr/sbin/pkcscca/pkcscca.c b/usr/sbin/pkcscca/pkcscca.c index acabe319..0e08dec9 100644 --- a/usr/sbin/pkcscca/pkcscca.c +++ b/usr/sbin/pkcscca/pkcscca.c @@ -342,7 +342,8 @@ int reencrypt_private_token_object(unsigned char *data, unsigned long len, /* Validate the hash */ memcpy(&obj_data_len_32, clear, sizeof(CK_ULONG_32)); - if (obj_data_len_32 >= clear_len) { + if (obj_data_len_32 >= clear_len || + sizeof(CK_ULONG_32) + (unsigned long)obj_data_len_32 + SHA1_HASH_SIZE > clear_len) { fprintf(stderr, "Decrypted object data is inconsistent. Possibly already migrated?\n"); ret = CKR_FUNCTION_FAILED; goto done; diff --git a/usr/sbin/pkcstok_migrate/pkcstok_migrate.c b/usr/sbin/pkcstok_migrate/pkcstok_migrate.c index c9282f6d..dffb9aa4 100644 --- a/usr/sbin/pkcstok_migrate/pkcstok_migrate.c +++ b/usr/sbin/pkcstok_migrate/pkcstok_migrate.c @@ -398,9 +398,13 @@ static CK_RV decrypt_OBJECT_PRIV_00(unsigned char **clear, unsigned int *clear_l goto done; } - /* Validate the length */ + /* Validate the length: the decrypted buffer must hold + * | CK_ULONG_32 | object[obj_data_len_32] | SHA1[SHA1_HASH_SIZE] | + * so check that all three regions fit within enc_len. + */ memcpy(&obj_data_len_32, tmp_clear, sizeof(CK_ULONG_32)); - if (obj_data_len_32 >= enc_len) { + if (obj_data_len_32 >= enc_len || + obj_data_len_32 > enc_len - sizeof(CK_ULONG_32) - SHA1_HASH_SIZE) { TRACE_ERROR("Decrypted object data length %d inconsistent\n", obj_data_len_32); ret = CKR_FUNCTION_FAILED;