|
Packit Service |
4684c1 |
/*
|
|
Packit Service |
4684c1 |
AES-CMAC-128 (rfc 4493)
|
|
Packit Service |
4684c1 |
Copyright (C) Stefan Metzmacher 2012
|
|
Packit Service |
4684c1 |
Copyright (C) Jeremy Allison 2012
|
|
Packit Service |
4684c1 |
Copyright (C) Michael Adam 2012
|
|
Packit Service |
4684c1 |
Copyright (C) 2017, Red Hat Inc.
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
This file is part of GNU Nettle.
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
GNU Nettle is free software: you can redistribute it and/or
|
|
Packit Service |
4684c1 |
modify it under the terms of either:
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
* the GNU Lesser General Public License as published by the Free
|
|
Packit Service |
4684c1 |
Software Foundation; either version 3 of the License, or (at your
|
|
Packit Service |
4684c1 |
option) any later version.
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
or
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
* the GNU General Public License as published by the Free
|
|
Packit Service |
4684c1 |
Software Foundation; either version 2 of the License, or (at your
|
|
Packit Service |
4684c1 |
option) any later version.
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
or both in parallel, as here.
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
GNU Nettle is distributed in the hope that it will be useful,
|
|
Packit Service |
4684c1 |
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
Packit Service |
4684c1 |
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
Packit Service |
4684c1 |
General Public License for more details.
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
You should have received copies of the GNU General Public License and
|
|
Packit Service |
4684c1 |
the GNU Lesser General Public License along with this program. If
|
|
Packit Service |
4684c1 |
not, see http://www.gnu.org/licenses/.
|
|
Packit Service |
4684c1 |
*/
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
#if HAVE_CONFIG_H
|
|
Packit Service |
4684c1 |
# include "config.h"
|
|
Packit Service |
4684c1 |
#endif
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
#include <assert.h>
|
|
Packit Service |
4684c1 |
#include <stdlib.h>
|
|
Packit Service |
4684c1 |
#include <string.h>
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
#include "cmac.h"
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
#include <nettle/memxor.h>
|
|
Packit Service |
4684c1 |
#include "nettle-alloca.h"
|
|
Packit Service |
4684c1 |
#include "block-internal.h"
|
|
Packit Service |
4684c1 |
#include <nettle/macros.h>
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
void
|
|
Packit Service |
4684c1 |
cmac128_set_key(struct cmac128_key *key, const void *cipher,
|
|
Packit Service |
4684c1 |
nettle_cipher_func *encrypt)
|
|
Packit Service |
4684c1 |
{
|
|
Packit Service |
4684c1 |
static const union nettle_block16 zero_block;
|
|
Packit Service |
4684c1 |
union nettle_block16 L;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/* step 1 - generate subkeys k1 and k2 */
|
|
Packit Service |
4684c1 |
encrypt(cipher, 16, L.b, zero_block.b);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
block16_mulx_be(&key->K1, &L);
|
|
Packit Service |
4684c1 |
block16_mulx_be(&key->K2, &key->K1);
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
void
|
|
Packit Service |
4684c1 |
cmac128_init(struct cmac128_ctx *ctx)
|
|
Packit Service |
4684c1 |
{
|
|
Packit Service |
4684c1 |
memset(&ctx->X, 0, sizeof(ctx->X));
|
|
Packit Service |
4684c1 |
ctx->index = 0;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
#define MIN(x,y) ((x)<(y)?(x):(y))
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
void
|
|
Packit Service |
4684c1 |
cmac128_update(struct cmac128_ctx *ctx, const void *cipher,
|
|
Packit Service |
4684c1 |
nettle_cipher_func *encrypt,
|
|
Packit Service |
4684c1 |
size_t msg_len, const uint8_t *msg)
|
|
Packit Service |
4684c1 |
{
|
|
Packit Service |
4684c1 |
union nettle_block16 Y;
|
|
Packit Service |
4684c1 |
/*
|
|
Packit Service |
4684c1 |
* check if we expand the block
|
|
Packit Service |
4684c1 |
*/
|
|
Packit Service |
4684c1 |
if (ctx->index < 16)
|
|
Packit Service |
4684c1 |
{
|
|
Packit Service |
4684c1 |
size_t len = MIN(16 - ctx->index, msg_len);
|
|
Packit Service |
4684c1 |
memcpy(&ctx->block.b[ctx->index], msg, len);
|
|
Packit Service |
4684c1 |
msg += len;
|
|
Packit Service |
4684c1 |
msg_len -= len;
|
|
Packit Service |
4684c1 |
ctx->index += len;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
if (msg_len == 0) {
|
|
Packit Service |
4684c1 |
/* if it is still the last block, we are done */
|
|
Packit Service |
4684c1 |
return;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/*
|
|
Packit Service |
4684c1 |
* now checksum everything but the last block
|
|
Packit Service |
4684c1 |
*/
|
|
Packit Service |
4684c1 |
block16_xor3(&Y, &ctx->X, &ctx->block);
|
|
Packit Service |
4684c1 |
encrypt(cipher, 16, ctx->X.b, Y.b);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
while (msg_len > 16)
|
|
Packit Service |
4684c1 |
{
|
|
Packit Service |
4684c1 |
block16_xor_bytes (&Y, &ctx->X, msg);
|
|
Packit Service |
4684c1 |
encrypt(cipher, 16, ctx->X.b, Y.b);
|
|
Packit Service |
4684c1 |
msg += 16;
|
|
Packit Service |
4684c1 |
msg_len -= 16;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/*
|
|
Packit Service |
4684c1 |
* copy the last block, it will be processed in
|
|
Packit Service |
4684c1 |
* cmac128_digest().
|
|
Packit Service |
4684c1 |
*/
|
|
Packit Service |
4684c1 |
memcpy(ctx->block.b, msg, msg_len);
|
|
Packit Service |
4684c1 |
ctx->index = msg_len;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
void
|
|
Packit Service |
4684c1 |
cmac128_digest(struct cmac128_ctx *ctx, const struct cmac128_key *key,
|
|
Packit Service |
4684c1 |
const void *cipher, nettle_cipher_func *encrypt,
|
|
Packit Service |
4684c1 |
unsigned length, uint8_t *dst)
|
|
Packit Service |
4684c1 |
{
|
|
Packit Service |
4684c1 |
union nettle_block16 Y;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/* re-use ctx->block for memxor output */
|
|
Packit Service |
4684c1 |
if (ctx->index < 16)
|
|
Packit Service |
4684c1 |
{
|
|
Packit Service |
4684c1 |
ctx->block.b[ctx->index] = 0x80;
|
|
Packit Service |
4684c1 |
memset(ctx->block.b + ctx->index + 1, 0, 16 - 1 - ctx->index);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
block16_xor (&ctx->block, &key->K2);
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
else
|
|
Packit Service |
4684c1 |
{
|
|
Packit Service |
4684c1 |
block16_xor (&ctx->block, &key->K1);
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
block16_xor3 (&Y, &ctx->block, &ctx->X);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
assert(length <= 16);
|
|
Packit Service |
4684c1 |
if (length == 16)
|
|
Packit Service |
4684c1 |
{
|
|
Packit Service |
4684c1 |
encrypt(cipher, 16, dst, Y.b);
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
else
|
|
Packit Service |
4684c1 |
{
|
|
Packit Service |
4684c1 |
encrypt(cipher, 16, ctx->block.b, Y.b);
|
|
Packit Service |
4684c1 |
memcpy(dst, ctx->block.b, length);
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/* reset state for re-use */
|
|
Packit Service |
4684c1 |
cmac128_init(ctx);
|
|
Packit Service |
4684c1 |
}
|