diff --git a/demos/timing.c b/demos/timing.c index c576a4f75..d92cae95f 100644 --- a/demos/timing.c +++ b/demos/timing.c @@ -1354,7 +1354,7 @@ static void time_ccm(eac_ctx *ctx) t_start(); t1 = t_read(); z = 16; - if ((err = ccm_memory(ctx->cipher_idx, ctx->key, 16, NULL, ctx->IV, 16, NULL, 0, ctx->buf, ctx->size, ctx->buf, ctx->tag, &z, CCM_ENCRYPT)) != CRYPT_OK) { + if ((err = ccm_memory(ctx->cipher_idx, ctx->key, 16, NULL, ctx->IV, 13, NULL, 0, ctx->buf, ctx->size, ctx->buf, ctx->tag, &z, CCM_ENCRYPT)) != CRYPT_OK) { fprintf(stderr, "\nCCM error... %s\n", error_to_string(err)); exit(EXIT_FAILURE); } @@ -1369,7 +1369,7 @@ static void time_ccm(eac_ctx *ctx) t_start(); t1 = t_read(); z = 16; - if ((err = ccm_memory(ctx->cipher_idx, ctx->key, 16, &skey, ctx->IV, 16, NULL, 0, ctx->buf, ctx->size, ctx->buf, ctx->tag, &z, CCM_ENCRYPT)) != CRYPT_OK) { + if ((err = ccm_memory(ctx->cipher_idx, ctx->key, 16, &skey, ctx->IV, 13, NULL, 0, ctx->buf, ctx->size, ctx->buf, ctx->tag, &z, CCM_ENCRYPT)) != CRYPT_OK) { fprintf(stderr, "\nCCM error... %s\n", error_to_string(err)); exit(EXIT_FAILURE); } diff --git a/src/encauth/ccm/ccm_add_nonce.c b/src/encauth/ccm/ccm_add_nonce.c index 176836bbe..d187e143f 100644 --- a/src/encauth/ccm/ccm_add_nonce.c +++ b/src/encauth/ccm/ccm_add_nonce.c @@ -20,8 +20,11 @@ int ccm_add_nonce(ccm_state *ccm, LTC_ARGCHK(ccm != NULL); LTC_ARGCHK(nonce != NULL); - /* increase L to match the nonce len */ - ccm->noncelen = (noncelen > 13) ? 13 : noncelen; + /* CCM nonce is 7..13 bytes */ + if (noncelen < 7 || noncelen > 13) { + return CRYPT_INVALID_ARG; + } + ccm->noncelen = noncelen; if ((15 - ccm->noncelen) > ccm->L) { ccm->L = 15 - ccm->noncelen; } @@ -29,9 +32,9 @@ int ccm_add_nonce(ccm_state *ccm, return CRYPT_INVALID_ARG; } - /* decrease noncelen to match L */ + /* flags byte + nonce + length field must fit the 16-byte block */ if ((ccm->noncelen + ccm->L) > 15) { - ccm->noncelen = 15 - ccm->L; + return CRYPT_INVALID_ARG; } /* form B_0 == flags | Nonce N | l(m) */ diff --git a/src/encauth/ccm/ccm_memory.c b/src/encauth/ccm/ccm_memory.c index d23904463..9cee5f400 100644 --- a/src/encauth/ccm/ccm_memory.c +++ b/src/encauth/ccm/ccm_memory.c @@ -78,7 +78,8 @@ int ccm_memory(int cipher, if (*taglen < 4 || *taglen > 16 || (*taglen % 2) == 1 || headerlen > 0x7fffffffu) { return CRYPT_INVALID_ARG; } - if (noncelen < 7) { + /* CCM nonce is 7..13 bytes */ + if (noncelen < 7 || noncelen > 13) { return CRYPT_INVALID_ARG; } @@ -107,7 +108,6 @@ int ccm_memory(int cipher, } /* increase L to match the nonce len */ - noncelen = (noncelen > 13) ? 13 : noncelen; if ((15 - noncelen) > L) { L = 15 - noncelen; } @@ -115,6 +115,11 @@ int ccm_memory(int cipher, return CRYPT_INVALID_ARG; } + /* flags byte + nonce + length field must fit the 16-byte block */ + if ((noncelen + L) > 15) { + return CRYPT_INVALID_ARG; + } + /* allocate mem for the symmetric key */ if (uskey == NULL) { skey = XMALLOC(sizeof(*skey)); diff --git a/src/encauth/ccm/ccm_test.c b/src/encauth/ccm/ccm_test.c index 3aae2307a..69cf8be5b 100644 --- a/src/encauth/ccm/ccm_test.c +++ b/src/encauth/ccm/ccm_test.c @@ -267,6 +267,50 @@ int ccm_test(void) } } + /* invalid nonce lengths and nonce/L combinations must be rejected not silently adjusted */ + { + unsigned char key[16] = { 0 }; + unsigned char nonce[16] = { 0 }; + unsigned char pt[16] = { 0 }; + unsigned char ct[16]; + + /* CCM nonce is 7..13 bytes */ + taglen = 8; + if (ccm_memory(idx, key, sizeof(key), NULL, nonce, 6, NULL, 0, pt, sizeof(pt), ct, tag, &taglen, CCM_ENCRYPT) != CRYPT_INVALID_ARG) { + return CRYPT_FAIL_TESTVECTOR; + } + taglen = 8; + if (ccm_memory(idx, key, sizeof(key), NULL, nonce, 14, NULL, 0, pt, sizeof(pt), ct, tag, &taglen, CCM_ENCRYPT) != CRYPT_INVALID_ARG) { + return CRYPT_FAIL_TESTVECTOR; + } + if ((err = ccm_init(&ccm, idx, key, sizeof(key), sizeof(pt), 8, 0)) != CRYPT_OK) { + return err; + } + if (ccm_add_nonce(&ccm, nonce, 6) != CRYPT_INVALID_ARG) { + return CRYPT_FAIL_TESTVECTOR; + } + if ((err = ccm_init(&ccm, idx, key, sizeof(key), sizeof(pt), 8, 0)) != CRYPT_OK) { + return err; + } + if (ccm_add_nonce(&ccm, nonce, 14) != CRYPT_INVALID_ARG) { + return CRYPT_FAIL_TESTVECTOR; + } + /* ptlen >= 2^16 forces L=3, so a 13-byte nonce no longer fits B_0 (13+3 > 15) */ + if ((err = ccm_init(&ccm, idx, key, sizeof(key), 65536, 8, 0)) != CRYPT_OK) { + return err; + } + if (ccm_add_nonce(&ccm, nonce, 13) != CRYPT_INVALID_ARG) { + return CRYPT_FAIL_TESTVECTOR; + } + /* 12-byte nonce still fits (12+3 == 15) */ + if ((err = ccm_init(&ccm, idx, key, sizeof(key), 65536, 8, 0)) != CRYPT_OK) { + return err; + } + if ((err = ccm_add_nonce(&ccm, nonce, 12)) != CRYPT_OK) { + return err; + } + } + return CRYPT_OK; #endif }