+2026-01-14 Niels Möller <nisse@lysator.liu.se>
+
+ * ccm.h (CCM_MIN_DIGEST_SIZE): New constant.
+ (struct ccm_ctx): New field tag_length, storing the size used for
+ constructing the IV in ccm_set_nonce.
+ * ccm.c (ccm_set_nonce): Check that tag length is according to
+ spec, and store in context.
+ (ccm_digest): Delete length argument. Size of digest was stored in
+ the context by ccm_set_nonce. Updated all callers.
+ * ccm-aes128.c (ccm_aes128_digest): Delete length argument.
+ * ccm-aes192.c (ccm_aes192_digest): Likewise.
+ * ccm-aes256.c: Likewise.
+ * testsuite/ccm-test.c (test_main): Delete test from IEEE
+ 802.15.4-2011, C.2.2, since it uses an invalid zero tag length.
+
2026-01-08 Niels Möller <nisse@lysator.liu.se>
* ocb.c (update_offset): Deleted function, replaced with...
}
void
-ccm_aes128_digest(struct ccm_aes128_ctx *ctx,
- size_t length, uint8_t *digest)
+ccm_aes128_digest(struct ccm_aes128_ctx *ctx, uint8_t *digest)
{
- ccm_digest(&ctx->ccm, &ctx->cipher, (nettle_cipher_func *) aes128_encrypt,
- length, digest);
+ ccm_digest(&ctx->ccm, &ctx->cipher, (nettle_cipher_func *) aes128_encrypt, digest);
}
void
}
void
-ccm_aes192_digest(struct ccm_aes192_ctx *ctx,
- size_t length, uint8_t *digest)
+ccm_aes192_digest(struct ccm_aes192_ctx *ctx, uint8_t *digest)
{
- ccm_digest(&ctx->ccm, &ctx->cipher, (nettle_cipher_func *) aes192_encrypt,
- length, digest);
+ ccm_digest(&ctx->ccm, &ctx->cipher, (nettle_cipher_func *) aes192_encrypt, digest);
}
void
}
void
-ccm_aes256_digest(struct ccm_aes256_ctx *ctx,
- size_t length, uint8_t *digest)
+ccm_aes256_digest(struct ccm_aes256_ctx *ctx, uint8_t *digest)
{
- ccm_digest(&ctx->ccm, &ctx->cipher, (nettle_cipher_func *) aes256_encrypt,
- length, digest);
+ ccm_digest(&ctx->ccm, &ctx->cipher, (nettle_cipher_func *) aes256_encrypt, digest);
}
void
size_t length, const uint8_t *nonce,
size_t authlen, size_t msglen, size_t taglen)
{
+ assert (taglen >= 4 && taglen <= 16 && !(taglen & 1));
+ ctx->tag_length = taglen;
+
/* Generate the IV for the CTR and CBC-MAC */
ctx->blength = 0;
ccm_build_iv(ctx->tag.b, length, nonce, CCM_FLAG_SET_M(taglen), msglen);
void
ccm_digest(struct ccm_ctx *ctx, const void *cipher, nettle_cipher_func *f,
- size_t length, uint8_t *digest)
+ uint8_t *digest)
{
int i = CCM_BLOCK_SIZE - CCM_FLAG_GET_L(ctx->ctr.b[CCM_OFFSET_FLAGS]);
- assert(length <= CCM_BLOCK_SIZE);
while (i < CCM_BLOCK_SIZE) ctx->ctr.b[i++] = 0;
ccm_pad(ctx, cipher, f);
- ctr_crypt(cipher, f, CCM_BLOCK_SIZE, ctx->ctr.b, length, digest, ctx->tag.b);
+ assert (ctx->tag_length <= CCM_BLOCK_SIZE);
+ ctr_crypt(cipher, f, CCM_BLOCK_SIZE, ctx->ctr.b, ctx->tag_length, digest, ctx->tag.b);
}
void
ccm_set_nonce(&ctx, cipher, f, nlength, nonce, alength, clength-tlength, tlength);
ccm_update(&ctx, cipher, f, alength, adata);
ccm_encrypt(&ctx, cipher, f, clength-tlength, dst, src);
- ccm_digest(&ctx, cipher, f, tlength, tag);
+ ccm_digest(&ctx, cipher, f, tag);
}
int
ccm_set_nonce(&ctx, cipher, f, nlength, nonce, alength, mlength, tlength);
ccm_update(&ctx, cipher, f, alength, adata);
ccm_decrypt(&ctx, cipher, f, mlength, dst, src);
- ccm_digest(&ctx, cipher, f, tlength, tag);
+ ccm_digest(&ctx, cipher, f, tag);
return memeql_sec(tag, src + mlength, tlength);
}
/* For CCM, the block size of the block cipher shall be 128 bits. */
#define CCM_BLOCK_SIZE 16
#define CCM_DIGEST_SIZE 16
+/* Digest size must be even, valid values 4, 6, 8, 10, 12, 14, 16 */
+#define CCM_MIN_DIGEST_SIZE 4
#define CCM_MIN_NONCE_SIZE 7
#define CCM_MAX_NONCE_SIZE 14
union nettle_block16 ctr; /* Counter for CTR encryption. */
union nettle_block16 tag; /* CBC-MAC message tag. */
/* Length of data processed by the CBC-MAC modulus the block size */
- unsigned int blength;
+ unsigned short blength;
+ unsigned short tag_length;
};
/*
void
ccm_digest(struct ccm_ctx *ctx, const void *cipher, nettle_cipher_func *f,
- size_t length, uint8_t *digest);
+ uint8_t *digest);
/*
* All-in-one encryption and decryption API:
size_t length, uint8_t *dst, const uint8_t *src);
void
-ccm_aes128_digest(struct ccm_aes128_ctx *ctx,
- size_t length, uint8_t *digest);
+ccm_aes128_digest(struct ccm_aes128_ctx *ctx, uint8_t *digest);
void
ccm_aes128_encrypt_message(const struct aes128_ctx *ctx,
size_t length, uint8_t *dst, const uint8_t *src);
void
-ccm_aes192_digest(struct ccm_aes192_ctx *ctx,
- size_t length, uint8_t *digest);
+ccm_aes192_digest(struct ccm_aes192_ctx *ctx, uint8_t *digest);
void
ccm_aes192_encrypt_message(const struct aes192_ctx *ctx,
size_t length, uint8_t *dst, const uint8_t *src);
void
-ccm_aes256_digest(struct ccm_aes256_ctx *ctx,
- size_t length, uint8_t *digest);
+ccm_aes256_digest(struct ccm_aes256_ctx *ctx, uint8_t *digest);
void
ccm_aes256_encrypt_message(const struct aes256_ctx *ctx,
ccm_update(&ccm, ctx, cipher->encrypt, authdata->length, authdata->data);
}
ccm_encrypt(&ccm, ctx, cipher->encrypt, cleartext->length, en_data, cleartext->data);
- ccm_digest(&ccm, ctx, cipher->encrypt, tlength, en_digest);
+ ccm_digest(&ccm, ctx, cipher->encrypt, en_digest);
/* Decrypt using the incremental API. */
ccm_set_nonce(&ccm, ctx, cipher->encrypt, nonce->length, nonce->data,
ccm_update(&ccm, ctx, cipher->encrypt, authdata->length, authdata->data);
}
ccm_decrypt(&ccm, ctx, cipher->encrypt, cleartext->length, de_data, ciphertext->data);
- ccm_digest(&ccm, ctx, cipher->encrypt, tlength, de_digest);
+ ccm_digest(&ccm, ctx, cipher->encrypt, de_digest);
/* Compare results using the generic API. */
test_compare_results("CCM", authdata,
ccm_aes128_update(&aes, authdata->length, authdata->data);
}
ccm_aes128_encrypt(&aes, cleartext->length, en_data, cleartext->data);
- ccm_aes128_digest(&aes, tlength, en_digest);
+ ccm_aes128_digest(&aes, en_digest);
/* AES-128 decrypt. */
ccm_aes128_set_nonce(&aes, nonce->length, nonce->data,
ccm_aes128_update(&aes, authdata->length, authdata->data);
}
ccm_aes128_decrypt(&aes, cleartext->length, de_data, ciphertext->data);
- ccm_aes128_digest(&aes, tlength, de_digest);
+ ccm_aes128_digest(&aes, de_digest);
test_compare_results("CCM_AES_128", authdata,
cleartext, ciphertext, de_data, en_data, de_digest);
ccm_aes256_update(&aes, authdata->length, authdata->data);
}
ccm_aes256_encrypt(&aes, cleartext->length, en_data, cleartext->data);
- ccm_aes256_digest(&aes, tlength, en_digest);
+ ccm_aes256_digest(&aes, en_digest);
/* AES-256 decrypt. */
ccm_aes256_set_nonce(&aes, nonce->length, nonce->data,
ccm_aes256_update(&aes, authdata->length, authdata->data);
}
ccm_aes256_decrypt(&aes, cleartext->length, de_data, ciphertext->data);
- ccm_aes256_digest(&aes, tlength, de_digest);
+ ccm_aes256_digest(&aes, de_digest);
test_compare_results("CCM_AES_256", authdata,
cleartext, ciphertext, de_data, en_data, de_digest);
SHEX(""),
SHEX("22 3B C1 EC 84 1A B5 53"));
- /*
- * C.2.2 MAC data frame
- */
- test_cipher_ccm(&nettle_aes128,
- SHEX("C0 C1 C2 C3 C4 C5 C6 C7 C8 C9 CA CB CC CD CE CF"),
- SHEX("AC DE 48 00 00 00 00 01 00 00 00 05 04"),
- SHEX("69 DC 84 21 43 02 00 00 00 00 48 DE AC 01 00 00 00 00 48 DE AC 04 05 00 00 00"), 1,
- SHEX("61 62 63 64"),
- SHEX("D4 3E 02 2B"));
-
/*
* C.2.3 MAC command frame
*/