static void test_ctr(void) { uint8_t out[16]; const void *nonce = "\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff"; const void *key = "\x2b\x7e\x15\x16\x28\xae\xd2\xa6\xab\xf7\x15\x88\x09\xcf\x4f\x3c"; const void *inp = "\x6b\xc1\xbe\xe2\x2e\x40\x9f\x96\xe9\x3d\x7e\x11\x73\x93\x17\x2a"; const void *expect = "\x87\x4d\x61\x91\xb6\x20\xe3\x26\x1b\xef\x68\x64\x99\x0d\xb6\xce"; cf_aes_context aes; cf_aes_init(&aes, key, 16); cf_ctr ctr; cf_ctr_init(&ctr, &cf_aes, &aes, nonce); cf_ctr_cipher(&ctr, inp, out, 16); /* one piece */ TEST_CHECK(memcmp(expect, out, 16) == 0); cf_ctr_init(&ctr, &cf_aes, &aes, nonce); cf_ctr_cipher(&ctr, inp, out, 1); /* incremental (2 blocks) */ cf_ctr_cipher(&ctr, inp, out, 16); cf_ctr_cipher(&ctr, inp, out, 16); cf_ctr_init(&ctr, &cf_aes, &aes, nonce); cf_ctr_cipher(&ctr, inp, out, 1); /* incremental */ cf_ctr_cipher(&ctr, inp + 1, out + 1, 15); TEST_CHECK(memcmp(expect, out, 16) == 0); uint8_t decrypt[16]; cf_ctr_init(&ctr, &cf_aes, &aes, nonce); cf_ctr_cipher(&ctr, out, decrypt, 16); TEST_CHECK(memcmp(decrypt, inp, 16) == 0); /* Test we use the right number of blocks up. */ uint8_t test_nonce[16], test_inp[16]; memset(test_nonce, 0xff, 16); memset(test_inp, 0x00, 16); cf_ctr_init(&ctr, &cf_aes, &aes, test_nonce); /* Exercise cf_blockwise_xor code paths. */ for (int i = 0; i < 1024; i++) { cf_ctr_cipher(&ctr, test_inp, out, i % 16); } /* expected counter value is 1024 * 7.5 / 16 - 1: * 479 = 0x1df */ memset(test_nonce, 0, sizeof test_nonce); test_nonce[15] = 0xdf; test_nonce[14] = 0x01; TEST_CHECK(memcmp(test_nonce, ctr.nonce, 16) == 0); }
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 aesctr_init(ptls_cipher_context_t *_ctx, const void *iv) { struct aesctr_context_t *ctx = (struct aesctr_context_t *)_ctx; cf_ctr_init(&ctx->ctr, &cf_aes, &ctx->aes, iv); }