Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 17 additions & 8 deletions src/psa_aead.c
Original file line number Diff line number Diff line change
Expand Up @@ -138,10 +138,17 @@ static size_t wolfpsa_aead_tag_length(psa_algorithm_t alg)
}

#ifdef HAVE_AESGCM
static int wolfpsa_aead_gcm_check_tag_size(size_t tag_length)
static psa_status_t wolfpsa_aead_gcm_check_tag_size(size_t tag_length)
{
return tag_length == 4 || tag_length == 8 ||
(tag_length >= 12 && tag_length <= WC_AES_BLOCK_SIZE);
if (tag_length != 4 && tag_length != 8 &&
(tag_length < 12 || tag_length > WC_AES_BLOCK_SIZE)) {
return PSA_ERROR_INVALID_ARGUMENT;
}
/* Valid for PSA, but below the minimum wolfCrypt was built with. */
if (tag_length < WOLFSSL_MIN_AUTH_TAG_SZ) {
return PSA_ERROR_NOT_SUPPORTED;
}
return PSA_SUCCESS;
}
#endif

Expand Down Expand Up @@ -349,11 +356,13 @@ static psa_status_t wolfpsa_aead_setup(psa_aead_operation_t *operation,
}
#endif
#ifdef HAVE_AESGCM
if (PSA_ALG_AEAD_EQUAL(alg, PSA_ALG_GCM) &&
!wolfpsa_aead_gcm_check_tag_size(ctx->tag_length)) {
wolfpsa_forcezero_free_key_data(key_data, key_data_length);
XFREE(ctx, NULL, DYNAMIC_TYPE_TMP_BUFFER);
return PSA_ERROR_INVALID_ARGUMENT;
if (PSA_ALG_AEAD_EQUAL(alg, PSA_ALG_GCM)) {
status = wolfpsa_aead_gcm_check_tag_size(ctx->tag_length);
if (status != PSA_SUCCESS) {
wolfpsa_forcezero_free_key_data(key_data, key_data_length);
XFREE(ctx, NULL, DYNAMIC_TYPE_TMP_BUFFER);
return status;
}
}
#endif
#if defined(HAVE_CHACHA) && defined(HAVE_POLY1305)
Expand Down
99 changes: 99 additions & 0 deletions test/psa_server/psa_api_test.c
Original file line number Diff line number Diff line change
Expand Up @@ -3866,6 +3866,99 @@ static int test_aead_gcm_rejects_short_tags(void)
return ret;
}

/* A shortened GCM tag round trips, or is NOT_SUPPORTED when below
* WOLFSSL_MIN_AUTH_TAG_SZ. */
static int test_aead_gcm_shortened_tags(void)
{
static const uint8_t key[16] = { 0 };
static const uint8_t nonce[12] = { 0 };
static const uint8_t plaintext[16] = { 0 };
/* Ciphertext and full tag, as in test_aead_gcm. */
static const uint8_t expected[sizeof(plaintext) + 16] = {
0x03,0x88,0xda,0xce,0x60,0xb6,0xa3,0x92,
0xf3,0x28,0xc2,0xb9,0x71,0xb2,0xfe,0x78,
0xab,0x6e,0x47,0xd4,0x2c,0xec,0x13,0xbd,
0xf5,0x3a,0x67,0xb2,0x12,0x57,0xbd,0xdf
};
static const size_t tag_lengths[] = { 4, 8, 12 };
uint8_t out[sizeof(expected)];
uint8_t dec[sizeof(plaintext)];
size_t out_len;
size_t dec_len;
size_t tag_len;
size_t i;
psa_algorithm_t alg;
psa_key_id_t key_id = 0;
psa_key_attributes_t attrs = psa_key_attributes_init();
psa_status_t st;
int ret = TEST_OK;

psa_set_key_type(&attrs, PSA_KEY_TYPE_AES);
psa_set_key_bits(&attrs, 128);
psa_set_key_usage_flags(&attrs,
PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT);
psa_set_key_algorithm(&attrs,
PSA_ALG_AEAD_WITH_AT_LEAST_THIS_LENGTH_TAG(
PSA_ALG_GCM, 4));

st = psa_import_key(&attrs, key, sizeof(key), &key_id);
if (check_status(st, "psa_import_key(GCM shortened tags)") != TEST_OK) {
return TEST_FAIL;
}

for (i = 0; i < sizeof(tag_lengths) / sizeof(tag_lengths[0]) &&
ret == TEST_OK; i++) {
tag_len = tag_lengths[i];
alg = PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_GCM, tag_len);
out_len = 0;
dec_len = 0;

st = psa_aead_encrypt(key_id, alg, nonce, sizeof(nonce), NULL, 0,
plaintext, sizeof(plaintext),
out, sizeof(out), &out_len);
if (tag_len < WOLFSSL_MIN_AUTH_TAG_SZ) {
ret = check_true(st == PSA_ERROR_NOT_SUPPORTED,
"GCM shortened tag encrypt NOT_SUPPORTED");
if (ret == TEST_OK) {
st = psa_aead_decrypt(key_id, alg, nonce, sizeof(nonce),
NULL, 0, expected,
sizeof(plaintext) + tag_len,
dec, sizeof(dec), &dec_len);
ret = check_true(st == PSA_ERROR_NOT_SUPPORTED,
"GCM shortened tag decrypt NOT_SUPPORTED");
}
continue;
}
if (check_status(st, "psa_aead_encrypt(GCM shortened tag)") !=
TEST_OK ||
check_true(out_len == sizeof(plaintext) + tag_len,
"GCM shortened tag length") != TEST_OK ||
check_buf_eq("GCM shortened tag", out, expected, out_len) !=
TEST_OK) {
ret = TEST_FAIL;
continue;
}

st = psa_aead_decrypt(key_id, alg, nonce, sizeof(nonce), NULL, 0,
out, out_len, dec, sizeof(dec), &dec_len);
if (check_status(st, "psa_aead_decrypt(GCM shortened tag)") !=
TEST_OK ||
check_true(dec_len == sizeof(plaintext),
"GCM shortened tag decrypt length") != TEST_OK ||
check_buf_eq("GCM shortened tag decrypt", dec, plaintext,
sizeof(plaintext)) != TEST_OK) {
ret = TEST_FAIL;
}
}

st = psa_destroy_key(key_id);
if (check_status(st, "psa_destroy_key(GCM shortened tags)") != TEST_OK) {
return TEST_FAIL;
}

return ret;
}

/* F-4096: PSA_ALG_AEAD_WITH_AT_LEAST_THIS_LENGTH_TAG is a wildcard policy
* algorithm and must be rejected by operation setup with
* PSA_ERROR_INVALID_ARGUMENT, not accepted as a concrete tag length. */
Expand Down Expand Up @@ -8998,6 +9091,12 @@ int main(int argc, char** argv)
return TEST_FAIL;
}
}
if (only == NULL || strcmp(only, "aead_gcm_shortened_tags") == 0) {
if (run_named_test("aead_gcm_shortened_tags",
test_aead_gcm_shortened_tags) == TEST_FAIL) {
return TEST_FAIL;
}
}
if (only == NULL || strcmp(only, "aead_gcm_short_nonce") == 0) {
if (run_named_test("aead_gcm_short_nonce",
test_aead_gcm_rejects_short_nonce) == TEST_FAIL) {
Expand Down
Loading