Пример #1
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;
}
Пример #2
0
/* nb. block is general workspace. */
static void add_aad(cf_cbcmac_stream *cm, uint8_t block[CF_MAXBLOCK],
                    const uint8_t *header, size_t nheader)
{
    assert(nheader <= 0xffffffff); /* we don't support 64 bit lengths. */

    /* Add length using stupidly complicated rules. */
    if (nheader < 0xff00)
    {
        write_be(block, nheader, 2);
        cf_cbcmac_stream_update(cm, block, 2);
    } else {
        write_be(block, 0xfffe, 2);
        write_be(block + 2, nheader, 4);
        cf_cbcmac_stream_update(cm, block, 6);
    }

    cf_cbcmac_stream_update(cm, header, nheader);
    zero_pad(cm);
}
Пример #3
0
static void add_block0(cf_cbcmac_stream *cm,
                       uint8_t block[CF_MAXBLOCK], size_t nblock,
                       const uint8_t *nonce, size_t nnonce,
                       size_t L, size_t nplain,
                       size_t nheader, size_t ntag)
{
    /* Construct first block B_0. */
    block[0] = ((nheader == 0) ? 0x00 : CCM_ADATA_PRESENT) |
               ((ntag - 2) / 2) << 3 |
               (L - 1);
    memcpy(block + 1, nonce, nnonce);
    write_be(block + 1 + nnonce, nplain, L);

    cf_cbcmac_stream_update(cm, block, nblock);
}
Пример #4
0
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);
}
Пример #5
0
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);
}