Source
static int crypto_cmac_digest_update(struct shash_desc *pdesc, const u8 *p,
/*
* CMAC: Cipher Block Mode for Authentication
*
* Copyright © 2013 Jussi Kivilinna <jussi.kivilinna@iki.fi>
*
* Based on work by:
* Copyright © 2013 Tom St Denis <tstdenis@elliptictech.com>
* Based on crypto/xcbc.c:
* Copyright © 2006 USAGI/WIDE Project,
* Author: Kazunori Miyazawa <miyazawa@linux-ipv6.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
*/
/*
* +------------------------
* | <parent tfm>
* +------------------------
* | cmac_tfm_ctx
* +------------------------
* | consts (block size * 2)
* +------------------------
*/
struct cmac_tfm_ctx {
struct crypto_cipher *child;
u8 ctx[];
};
/*
* +------------------------
* | <shash desc>
* +------------------------
* | cmac_desc_ctx
* +------------------------
* | odds (block size)
* +------------------------
* | prev (block size)
* +------------------------
*/
struct cmac_desc_ctx {
unsigned int len;
u8 ctx[];
};
static int crypto_cmac_digest_setkey(struct crypto_shash *parent,
const u8 *inkey, unsigned int keylen)
{
unsigned long alignmask = crypto_shash_alignmask(parent);
struct cmac_tfm_ctx *ctx = crypto_shash_ctx(parent);
unsigned int bs = crypto_shash_blocksize(parent);
__be64 *consts = PTR_ALIGN((void *)ctx->ctx,
(alignmask | (__alignof__(__be64) - 1)) + 1);
u64 _const[2];
int i, err = 0;
u8 msb_mask, gfmask;
err = crypto_cipher_setkey(ctx->child, inkey, keylen);
if (err)
return err;
/* encrypt the zero block */
memset(consts, 0, bs);
crypto_cipher_encrypt_one(ctx->child, (u8 *)consts, (u8 *)consts);
switch (bs) {
case 16:
gfmask = 0x87;
_const[0] = be64_to_cpu(consts[1]);
_const[1] = be64_to_cpu(consts[0]);
/* gf(2^128) multiply zero-ciphertext with u and u^2 */
for (i = 0; i < 4; i += 2) {
msb_mask = ((s64)_const[1] >> 63) & gfmask;
_const[1] = (_const[1] << 1) | (_const[0] >> 63);
_const[0] = (_const[0] << 1) ^ msb_mask;
consts[i + 0] = cpu_to_be64(_const[1]);
consts[i + 1] = cpu_to_be64(_const[0]);
}
break;
case 8:
gfmask = 0x1B;