int cf_ccm_decrypt(const cf_prp *prp, void *prpctx, const uint8_t *cipher, size_t ncipher, size_t L, const uint8_t *header, size_t nheader, const uint8_t *nonce, size_t nnonce, const uint8_t *tag, size_t ntag, uint8_t *plain) { uint8_t block[CF_MAXBLOCK]; assert(ntag >= 4 && ntag <= 16 && ntag % 2 == 0); assert(L >= 2 && L <= 8); assert(nnonce == prp->blocksz - L - 1); uint8_t ctr_nonce[CF_MAXBLOCK]; build_ctr_nonce(ctr_nonce, L, nonce, nnonce); cf_ctr ctr; cf_ctr_init(&ctr, prp, prpctx, ctr_nonce); cf_ctr_custom_counter(&ctr, prp->blocksz - L, L); /* Decrypt tag. */ uint8_t plain_tag[CF_MAXBLOCK]; cf_ctr_cipher(&ctr, tag, plain_tag, ntag); cf_ctr_discard_block(&ctr); /* Decrypt message. */ cf_ctr_cipher(&ctr, cipher, plain, ncipher); cf_cbcmac_stream cm; cf_cbcmac_stream_init(&cm, prp, prpctx); /* Add first block. */ add_block0(&cm, block, prp->blocksz, nonce, nnonce, L, ncipher, nheader, ntag); if (nheader) add_aad(&cm, block, header, nheader); cf_cbcmac_stream_update(&cm, plain, ncipher); zero_pad(&cm); /* Finish tag. */ cf_cbcmac_stream_nopad_final(&cm, block); int err = 0; if (!mem_eq(block, plain_tag, ntag)) { err = 1; mem_clean(plain, ncipher); } mem_clean(block, sizeof block); mem_clean(plain_tag, sizeof plain_tag); return err; }
void cf_ccm_encrypt(const cf_prp *prp, void *prpctx, const uint8_t *plain, size_t nplain, size_t L, const uint8_t *header, size_t nheader, const uint8_t *nonce, size_t nnonce, uint8_t *cipher, uint8_t *tag, size_t ntag) { uint8_t block[CF_MAXBLOCK]; assert(ntag >= 4 && ntag <= 16 && ntag % 2 == 0); assert(L >= 2 && L <= 8); assert(nnonce == prp->blocksz - L - 1); cf_cbcmac_stream cm; cf_cbcmac_stream_init(&cm, prp, prpctx); /* Add first block. */ add_block0(&cm, block, prp->blocksz, nonce, nnonce, L, nplain, nheader, ntag); /* Add AAD with length prefix, if present. */ if (nheader) add_aad(&cm, block, header, nheader); /* Add message. */ cf_cbcmac_stream_update(&cm, plain, nplain); zero_pad(&cm); /* Finish tag. */ cf_cbcmac_stream_nopad_final(&cm, block); /* Start encryption. */ /* Construct A_0 */ uint8_t ctr_nonce[CF_MAXBLOCK]; build_ctr_nonce(ctr_nonce, L, nonce, nnonce); cf_ctr ctr; cf_ctr_init(&ctr, prp, prpctx, ctr_nonce); cf_ctr_custom_counter(&ctr, prp->blocksz - L, L); /* Encrypt tag first. */ cf_ctr_cipher(&ctr, block, block, prp->blocksz); memcpy(tag, block, ntag); /* Then encrypt message. */ cf_ctr_cipher(&ctr, plain, cipher, nplain); }
static void cbcmac_vector(const void *tag_expect, size_t ntag, const void *key, size_t nkey, const void *msg, size_t nmsg) { uint8_t tag[16]; cf_aes_context aes; cf_aes_init(&aes, key, nkey); cf_cbcmac_stream cm; cf_cbcmac_stream_init(&cm, &cf_aes, &aes); cf_cbcmac_stream_update(&cm, msg, nmsg); cf_cbcmac_stream_pad_final(&cm, tag); TEST_CHECK(sizeof tag == ntag); TEST_CHECK(memcmp(tag, tag_expect, sizeof tag) == 0); }