|
Packit Service |
4684c1 |
/* siv-cmac.c
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
SIV-CMAC, RFC5297
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
Copyright (C) 2017 Nikos Mavrogiannopoulos
|
|
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 <string.h>
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
#include <nettle/aes.h>
|
|
Packit Service |
4684c1 |
#include "siv-cmac.h"
|
|
Packit Service |
4684c1 |
#ifdef HAVE_NETTLE_CMAC128_UPDATE
|
|
Packit Service |
4684c1 |
#include <nettle/cmac.h>
|
|
Packit Service |
4684c1 |
#else
|
|
Packit Service |
4684c1 |
#include "cmac.h"
|
|
Packit Service |
4684c1 |
#endif
|
|
Packit Service |
4684c1 |
#include <nettle/ctr.h>
|
|
Packit Service |
4684c1 |
#include <nettle/memxor.h>
|
|
Packit Service |
4684c1 |
#include <nettle/memops.h>
|
|
Packit Service |
4684c1 |
#include "nettle-alloca.h"
|
|
Packit Service |
4684c1 |
#include "block-internal.h"
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/* This is an implementation of S2V for the AEAD case where
|
|
Packit Service |
4684c1 |
* vectors if zero, are considered as S empty components */
|
|
Packit Service |
4684c1 |
static void
|
|
Packit Service |
4684c1 |
_siv_s2v (const struct nettle_cipher *nc,
|
|
Packit Service |
4684c1 |
const struct cmac128_key *cmac_key,
|
|
Packit Service |
4684c1 |
const void *cmac_cipher,
|
|
Packit Service |
4684c1 |
size_t alength, const uint8_t * adata,
|
|
Packit Service |
4684c1 |
size_t nlength, const uint8_t * nonce,
|
|
Packit Service |
4684c1 |
size_t plength, const uint8_t * pdata, uint8_t * v)
|
|
Packit Service |
4684c1 |
{
|
|
Packit Service |
4684c1 |
union nettle_block16 D, S, T;
|
|
Packit Service |
4684c1 |
static const union nettle_block16 const_zero = {.b = 0 };
|
|
Packit Service |
4684c1 |
struct cmac128_ctx cmac_ctx;
|
|
Packit Service |
4684c1 |
assert (nlength >= SIV_MIN_NONCE_SIZE);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
cmac128_init(&cmac_ctx);
|
|
Packit Service |
4684c1 |
cmac128_update (&cmac_ctx, cmac_cipher, nc->encrypt, 16, const_zero.b);
|
|
Packit Service |
4684c1 |
cmac128_digest (&cmac_ctx, cmac_key, cmac_cipher, nc->encrypt, 16, D.b);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
block16_mulx_be (&D, &D);
|
|
Packit Service |
4684c1 |
cmac128_update (&cmac_ctx, cmac_cipher, nc->encrypt, alength, adata);
|
|
Packit Service |
4684c1 |
cmac128_digest (&cmac_ctx, cmac_key, cmac_cipher, nc->encrypt, 16, S.b);
|
|
Packit Service |
4684c1 |
block16_xor (&D, &S);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
block16_mulx_be (&D, &D);
|
|
Packit Service |
4684c1 |
cmac128_update (&cmac_ctx, cmac_cipher, nc->encrypt, nlength, nonce);
|
|
Packit Service |
4684c1 |
cmac128_digest (&cmac_ctx, cmac_key, cmac_cipher, nc->encrypt, 16, S.b);
|
|
Packit Service |
4684c1 |
block16_xor (&D, &S);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/* Sn */
|
|
Packit Service |
4684c1 |
if (plength >= 16)
|
|
Packit Service |
4684c1 |
{
|
|
Packit Service |
4684c1 |
cmac128_update (&cmac_ctx, cmac_cipher, nc->encrypt, plength - 16, pdata);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
pdata += plength - 16;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
block16_xor_bytes (&T, &D, pdata);
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
else
|
|
Packit Service |
4684c1 |
{
|
|
Packit Service |
4684c1 |
union nettle_block16 pad;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
block16_mulx_be (&T, &D);
|
|
Packit Service |
4684c1 |
memcpy (pad.b, pdata, plength);
|
|
Packit Service |
4684c1 |
pad.b[plength] = 0x80;
|
|
Packit Service |
4684c1 |
if (plength + 1 < 16)
|
|
Packit Service |
4684c1 |
memset (&pad.b[plength + 1], 0, 16 - plength - 1);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
block16_xor (&T, &pad;;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
cmac128_update (&cmac_ctx, cmac_cipher, nc->encrypt, 16, T.b);
|
|
Packit Service |
4684c1 |
cmac128_digest (&cmac_ctx, cmac_key, cmac_cipher, nc->encrypt, 16, v);
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
void
|
|
Packit Service |
4684c1 |
siv_cmac_set_key (struct cmac128_key *cmac_key, void *cmac_cipher, void *siv_cipher,
|
|
Packit Service |
4684c1 |
const struct nettle_cipher *nc, const uint8_t * key)
|
|
Packit Service |
4684c1 |
{
|
|
Packit Service |
4684c1 |
nc->set_encrypt_key (cmac_cipher, key);
|
|
Packit Service |
4684c1 |
cmac128_set_key (cmac_key, cmac_cipher, nc->encrypt);
|
|
Packit Service |
4684c1 |
nc->set_encrypt_key (siv_cipher, key + nc->key_size);
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
void
|
|
Packit Service |
4684c1 |
siv_cmac_encrypt_message (const struct cmac128_key *cmac_key,
|
|
Packit Service |
4684c1 |
const void *cmac_cipher,
|
|
Packit Service |
4684c1 |
const struct nettle_cipher *nc,
|
|
Packit Service |
4684c1 |
const void *ctr_cipher,
|
|
Packit Service |
4684c1 |
size_t nlength, const uint8_t * nonce,
|
|
Packit Service |
4684c1 |
size_t alength, const uint8_t * adata,
|
|
Packit Service |
4684c1 |
size_t clength, uint8_t * dst, const uint8_t * src)
|
|
Packit Service |
4684c1 |
{
|
|
Packit Service |
4684c1 |
union nettle_block16 siv;
|
|
Packit Service |
4684c1 |
size_t slength;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
assert (clength >= SIV_DIGEST_SIZE);
|
|
Packit Service |
4684c1 |
slength = clength - SIV_DIGEST_SIZE;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/* create CTR nonce */
|
|
Packit Service |
4684c1 |
_siv_s2v (nc, cmac_key, cmac_cipher, alength, adata, nlength, nonce, slength, src, siv.b);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
memcpy (dst, siv.b, SIV_DIGEST_SIZE);
|
|
Packit Service |
4684c1 |
siv.b[8] &= ~0x80;
|
|
Packit Service |
4684c1 |
siv.b[12] &= ~0x80;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
ctr_crypt (ctr_cipher, nc->encrypt, AES_BLOCK_SIZE, siv.b, slength,
|
|
Packit Service |
4684c1 |
dst + SIV_DIGEST_SIZE, src);
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
int
|
|
Packit Service |
4684c1 |
siv_cmac_decrypt_message (const struct cmac128_key *cmac_key,
|
|
Packit Service |
4684c1 |
const void *cmac_cipher,
|
|
Packit Service |
4684c1 |
const struct nettle_cipher *nc,
|
|
Packit Service |
4684c1 |
const void *ctr_cipher,
|
|
Packit Service |
4684c1 |
size_t nlength, const uint8_t * nonce,
|
|
Packit Service |
4684c1 |
size_t alength, const uint8_t * adata,
|
|
Packit Service |
4684c1 |
size_t mlength, uint8_t * dst, const uint8_t * src)
|
|
Packit Service |
4684c1 |
{
|
|
Packit Service |
4684c1 |
union nettle_block16 siv;
|
|
Packit Service |
4684c1 |
union nettle_block16 ctr;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
memcpy (ctr.b, src, SIV_DIGEST_SIZE);
|
|
Packit Service |
4684c1 |
ctr.b[8] &= ~0x80;
|
|
Packit Service |
4684c1 |
ctr.b[12] &= ~0x80;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
ctr_crypt (ctr_cipher, nc->encrypt, AES_BLOCK_SIZE, ctr.b,
|
|
Packit Service |
4684c1 |
mlength, dst, src + SIV_DIGEST_SIZE);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/* create CTR nonce */
|
|
Packit Service |
4684c1 |
_siv_s2v (nc,
|
|
Packit Service |
4684c1 |
cmac_key, cmac_cipher, alength, adata,
|
|
Packit Service |
4684c1 |
nlength, nonce, mlength, dst, siv.b);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
return memeql_sec (siv.b, src, SIV_DIGEST_SIZE);
|
|
Packit Service |
4684c1 |
}
|