mirror of
https://github.com/libtom/libtomcrypt
synced 2026-08-25 20:26:07 -04:00
AES-GCM-SIV
This commit is contained in:
parent
8512e3e891
commit
37a2e345a4
8 changed files with 864 additions and 5 deletions
107
doc/crypt.tex
107
doc/crypt.tex
|
|
@ -2690,6 +2690,113 @@ int main(void)
|
|||
\end{verbatim}
|
||||
\end{small}
|
||||
|
||||
\mysection{GCM-SIV}
|
||||
\label{GCM-SIV}
|
||||
|
||||
AES--GCM--SIV is a nonce--misuse--resistant authenticated encryption mode defined by \url{https://tools.ietf.org/html/rfc8452}.
|
||||
Unlike AES--GCM, reusing a nonce with the same key does not break confidentiality or authenticity.
|
||||
|
||||
\textbf{There is no streaming API}. The algorithm needs two passes: during encryption, the tag is computed over the whole plaintext
|
||||
and then used as the AES--CTR starting counter, so ciphertext cannot be produced early. During decryption, plaintext must not be
|
||||
returned before the tag is verified.
|
||||
|
||||
The following parameters are fixed by RFC 8452:
|
||||
\begin{itemize}
|
||||
\item \textbf{Cipher}: AES. Any 128--bit block cipher registered with libtomcrypt will work, but only AES is interoperable with the RFC.
|
||||
\item \textbf{Key length}: 16 bytes (AEAD\_AES\_128\_GCM\_SIV) or 32 bytes (AEAD\_AES\_256\_GCM\_SIV).
|
||||
\item \textbf{Nonce length}: exactly 12 bytes.
|
||||
\item \textbf{Tag length}: exactly 16 bytes.
|
||||
\item \textbf{Plaintext and AAD length}: at most $2^{36}$ bytes each.
|
||||
\end{itemize}
|
||||
|
||||
The implementation reuses the GHASH field multiplier (\textit{gcm\_gf\_mult()}) for POLYVAL via the byte--reversal trick from RFC 8452 Appendix A.
|
||||
It therefore inherits the same hardware acceleration: Intel PCLMUL, ARMv8 PMULL, or the \texttt{LTC\_FAST} table fallback.
|
||||
|
||||
\index{gcm\_siv\_memory()}
|
||||
\begin{verbatim}
|
||||
int gcm_siv_memory( int cipher,
|
||||
const unsigned char *key, unsigned long keylen,
|
||||
const unsigned char *nonce, unsigned long noncelen,
|
||||
const unsigned char *aad, unsigned long aadlen,
|
||||
unsigned char *in, unsigned long inlen,
|
||||
unsigned char *out,
|
||||
unsigned char *tag, unsigned long *taglen,
|
||||
int direction);
|
||||
\end{verbatim}
|
||||
|
||||
This runs a single AES--GCM--SIV operation in the given \textit{direction} (\texttt{LTC\_ENCRYPT} or \texttt{LTC\_DECRYPT}).
|
||||
|
||||
\textit{cipher} is the index of a registered 128--bit block cipher; use \texttt{find\_cipher("aes")} for the standard mode.
|
||||
|
||||
\textit{key} (of length \textit{keylen} = 16 or 32) is the key from which the message--authentication key and the message--encryption key
|
||||
are derived, together with the 12--byte \textit{nonce}, as described in RFC 8452 Section 4.
|
||||
|
||||
\textit{aad} of length \textit{aadlen} is the optional associated data. Pass \texttt{NULL} and \texttt{0} for an empty AAD.
|
||||
|
||||
\textit{in} of length \textit{inlen} is the input buffer:
|
||||
\begin{itemize}
|
||||
\item on \texttt{LTC\_ENCRYPT} it holds the plaintext, and \textit{out} (of the same length) receives the ciphertext;
|
||||
\item on \texttt{LTC\_DECRYPT} it holds the ciphertext, and \textit{out} receives the plaintext.
|
||||
\end{itemize}
|
||||
|
||||
\textit{in} and \textit{out} may point at the same buffer for in--place processing.
|
||||
|
||||
\textit{tag} is the 16--byte authentication tag:
|
||||
\begin{itemize}
|
||||
\item on \texttt{LTC\_ENCRYPT} the function writes it and sets \textit{taglen} to \texttt{16};
|
||||
\item on \texttt{LTC\_DECRYPT} the caller must place the expected tag into \textit{tag} before calling. The function recomputes the tag,
|
||||
compares the two in constant time, and on a mismatch returns \texttt{CRYPT\_ERROR} after zeroing \textit{out}. The decrypted
|
||||
plaintext is never returned to the caller when authentication fails.
|
||||
\end{itemize}
|
||||
|
||||
\textit{taglen} must be at least \texttt{16} on input.
|
||||
|
||||
A short worked example of encryption and decryption with AES--GCM--SIV follows.
|
||||
|
||||
\begin{small}
|
||||
\begin{verbatim}
|
||||
#include <tomcrypt.h>
|
||||
|
||||
int main(void)
|
||||
{
|
||||
int err;
|
||||
unsigned char key[32] = {0}; /* AEAD_AES_256_GCM_SIV */
|
||||
unsigned char nonce[12] = {0};
|
||||
unsigned char aad[] = "header";
|
||||
unsigned char plain[16] = {0};
|
||||
unsigned char ct[sizeof(plain)] = {0};
|
||||
unsigned char dec[sizeof(plain)] = {0};
|
||||
unsigned char tag[16];
|
||||
unsigned long taglen = sizeof(tag);
|
||||
|
||||
register_cipher(&aes_desc);
|
||||
|
||||
if ((err = gcm_siv_memory(find_cipher("aes"),
|
||||
key, sizeof(key),
|
||||
nonce, sizeof(nonce),
|
||||
aad, sizeof(aad) - 1,
|
||||
plain, sizeof(plain), ct,
|
||||
tag, &taglen,
|
||||
LTC_ENCRYPT)) != CRYPT_OK) {
|
||||
whine_and_pout(err);
|
||||
}
|
||||
|
||||
if ((err = gcm_siv_memory(find_cipher("aes"),
|
||||
key, sizeof(key),
|
||||
nonce, sizeof(nonce),
|
||||
aad, sizeof(aad) - 1,
|
||||
ct, sizeof(ct), dec,
|
||||
tag, &taglen,
|
||||
LTC_DECRYPT)) != CRYPT_OK) {
|
||||
/* CRYPT_ERROR here means the tag did not match -- dec has been zeroed */
|
||||
whine_and_pout(err);
|
||||
}
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
\end{verbatim}
|
||||
\end{small}
|
||||
|
||||
\chapter{One-Way Cryptographic Hash Functions}
|
||||
\mysection{Core Functions}
|
||||
Like the ciphers, there are hash core functions and a universal data type to hold the hash state called \textit{hash\_state}. To initialize hash
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@
|
|||
*/
|
||||
#include "tomcrypt_private.h"
|
||||
|
||||
#if defined(LTC_GCM_MODE) || defined(LTC_LRW_MODE)
|
||||
#if defined(LTC_GCM_MODE) || defined(LTC_LRW_MODE) || defined(LTC_GCM_SIV_MODE)
|
||||
#if defined(LTC_GCM_PCLMUL)
|
||||
|
||||
#define LTC_GCM_PCLMUL_TARGET LTC_TARGET("pclmul,ssse3")
|
||||
|
|
@ -263,7 +263,7 @@ static void s_gcm_gf_mult_pmull(const unsigned char *a, const unsigned char *b,
|
|||
#endif /* defined(LTC_GCM_PMULL) */
|
||||
#endif /* defined(LTC_GCM_MODE) || defined(LTC_LRW_MODE) */
|
||||
|
||||
#if defined(LTC_GCM_TABLES) || defined(LTC_LRW_TABLES) || (defined(LTC_GCM_MODE) && defined(LTC_FAST))
|
||||
#if defined(LTC_GCM_TABLES) || defined(LTC_LRW_TABLES) || ((defined(LTC_GCM_MODE) || defined(LTC_GCM_SIV_MODE)) && defined(LTC_FAST))
|
||||
|
||||
/* this is x*2^128 mod p(x) ... the results are 16 bytes each stored in a packed format. Since only the
|
||||
* lower 16 bits are not zero'ed I removed the upper 14 bytes */
|
||||
|
|
@ -304,7 +304,7 @@ const unsigned char gcm_shift_table[256*2] = {
|
|||
#endif
|
||||
|
||||
|
||||
#if defined(LTC_GCM_MODE) || defined(LTC_LRW_MODE)
|
||||
#if defined(LTC_GCM_MODE) || defined(LTC_LRW_MODE) || defined(LTC_GCM_SIV_MODE)
|
||||
|
||||
|
||||
#ifndef LTC_FAST
|
||||
|
|
|
|||
244
src/encauth/gcm_siv/gcm_siv.c
Normal file
244
src/encauth/gcm_siv/gcm_siv.c
Normal file
|
|
@ -0,0 +1,244 @@
|
|||
/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
|
||||
/* SPDX-License-Identifier: Unlicense */
|
||||
#include "tomcrypt_private.h"
|
||||
|
||||
/**
|
||||
@file gcm_siv.c
|
||||
RFC 8452 - AES-GCM-SIV: Nonce Misuse-Resistant AEAD
|
||||
*/
|
||||
|
||||
#ifdef LTC_GCM_SIV_MODE
|
||||
|
||||
/* Multiply by x in the GHASH field GF(2^128) defined by
|
||||
x^128 + x^7 + x^2 + x + 1, using GHASH's bit-byte ordering
|
||||
(bit 7 of byte 0 is x^0, bit 0 of byte 15 is x^127). This is used
|
||||
once during key derivation per RFC 8452 Appendix A: the POLYVAL
|
||||
authentication key is computed as mulX_GHASH(ByteReverse(H_polyval))
|
||||
so that GHASH multiplication can be reused for POLYVAL.
|
||||
*/
|
||||
static void s_mulx_ghash(unsigned char *b)
|
||||
{
|
||||
unsigned int carry = b[15] & 1;
|
||||
int x;
|
||||
|
||||
for (x = 15; x > 0; x--) {
|
||||
b[x] = (unsigned char)((b[x] >> 1) | ((b[x-1] & 1) << 7));
|
||||
}
|
||||
b[0] >>= 1;
|
||||
if (carry) b[0] ^= 0xe1;
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
unsigned char H[16]; /* GHASH-form authentication key */
|
||||
unsigned char S[16]; /* GHASH-form accumulator */
|
||||
} polyval_state;
|
||||
|
||||
static void s_polyval_init(polyval_state *st, const unsigned char *auth_key)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 16; i++) st->H[i] = auth_key[15 - i];
|
||||
s_mulx_ghash(st->H);
|
||||
zeromem(st->S, 16);
|
||||
}
|
||||
|
||||
static void s_polyval_block(polyval_state *st, const unsigned char *X)
|
||||
{
|
||||
unsigned char T[16];
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 16; i++) st->S[i] ^= X[15 - i];
|
||||
gcm_gf_mult(st->S, st->H, T);
|
||||
XMEMCPY(st->S, T, 16);
|
||||
}
|
||||
|
||||
static void s_polyval_data(polyval_state *st, const unsigned char *data, unsigned long len)
|
||||
{
|
||||
unsigned long full = len / 16;
|
||||
unsigned long rem = len % 16;
|
||||
unsigned long i;
|
||||
unsigned char block[16];
|
||||
|
||||
for (i = 0; i < full; i++) s_polyval_block(st, data + i * 16);
|
||||
if (rem) {
|
||||
zeromem(block, 16);
|
||||
XMEMCPY(block, data + full * 16, rem);
|
||||
s_polyval_block(st, block);
|
||||
}
|
||||
}
|
||||
|
||||
static void s_polyval_done(polyval_state *st, unsigned char *out)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < 16; i++) out[i] = st->S[15 - i];
|
||||
}
|
||||
|
||||
/* Derive the POLYVAL authentication key and the AES message-encryption key from K and N as specified
|
||||
in RFC 8452 Section 4. The cipher is scheduled with the message-encryption key in *enc_ecb on success
|
||||
*/
|
||||
static int s_gcm_siv_derive_keys(int cipher,
|
||||
const unsigned char *K, unsigned long keylen,
|
||||
const unsigned char *N,
|
||||
unsigned char *auth_key,
|
||||
unsigned char *enc_key,
|
||||
symmetric_ECB *enc_ecb)
|
||||
{
|
||||
int err;
|
||||
unsigned char input[16], block[16];
|
||||
unsigned long ctr, num_blocks;
|
||||
symmetric_ECB ecb;
|
||||
|
||||
if ((err = ecb_start(cipher, K, (int)keylen, 0, &ecb)) != CRYPT_OK) return err;
|
||||
|
||||
XMEMCPY(input + 4, N, 12);
|
||||
|
||||
/* counters 0..1 yield the 16-byte authentication key, counters 2.. yield the encryption key (16 or 32 bytes) */
|
||||
num_blocks = (keylen == 16) ? 4 : 6;
|
||||
for (ctr = 0; ctr < num_blocks; ctr++) {
|
||||
STORE32L((ulong32)ctr, input);
|
||||
if ((err = ecb_encrypt_block(input, block, &ecb)) != CRYPT_OK) goto cleanup;
|
||||
if (ctr < 2) {
|
||||
XMEMCPY(auth_key + 8 * ctr, block, 8);
|
||||
} else {
|
||||
XMEMCPY(enc_key + 8 * (ctr - 2), block, 8);
|
||||
}
|
||||
}
|
||||
|
||||
err = ecb_start(cipher, enc_key, (int)keylen, 0, enc_ecb);
|
||||
|
||||
cleanup:
|
||||
ecb_done(&ecb);
|
||||
#ifdef LTC_CLEAN_STACK
|
||||
zeromem(input, sizeof(input));
|
||||
zeromem(block, sizeof(block));
|
||||
#endif
|
||||
return err;
|
||||
}
|
||||
|
||||
/**
|
||||
AES-GCM-SIV one-shot encryption/decryption (RFC 8452).
|
||||
|
||||
@param cipher The index of the cipher (must be a 128-bit block cipher; AES per RFC)
|
||||
@param key The 16- or 32-byte key
|
||||
@param keylen The length of the key (16 or 32)
|
||||
@param nonce The 12-byte nonce
|
||||
@param noncelen The length of the nonce (must be 12)
|
||||
@param aad The associated data
|
||||
@param aadlen The length of the associated data
|
||||
@param in The input (plaintext on encrypt, ciphertext on decrypt)
|
||||
@param inlen The length of the input
|
||||
@param out The output (ciphertext on encrypt, plaintext on decrypt)
|
||||
@param tag [in/out] The 16-byte tag (output on encrypt, input on decrypt)
|
||||
@param taglen [in/out] The length of the tag (must be >= 16; set to 16 on output)
|
||||
@param direction LTC_ENCRYPT or LTC_DECRYPT
|
||||
@return CRYPT_OK on success, CRYPT_ERROR on tag mismatch during decrypt
|
||||
*/
|
||||
int gcm_siv_memory( int cipher,
|
||||
const unsigned char *key, unsigned long keylen,
|
||||
const unsigned char *nonce, unsigned long noncelen,
|
||||
const unsigned char *aad, unsigned long aadlen,
|
||||
unsigned char *in, unsigned long inlen,
|
||||
unsigned char *out,
|
||||
unsigned char *tag, unsigned long *taglen,
|
||||
int direction)
|
||||
{
|
||||
int err, ecb_started = 0, ctr_started = 0;
|
||||
unsigned char auth_key[16];
|
||||
unsigned char enc_key[32];
|
||||
unsigned char S[16], IC[16], expected_tag[16];
|
||||
unsigned char lenblk[16];
|
||||
const unsigned char *plaintext;
|
||||
symmetric_ECB enc_ecb;
|
||||
symmetric_CTR ctr;
|
||||
polyval_state pv;
|
||||
unsigned long i;
|
||||
|
||||
LTC_ARGCHK(key != NULL);
|
||||
LTC_ARGCHK(nonce != NULL);
|
||||
LTC_ARGCHK(aad != NULL || aadlen == 0);
|
||||
LTC_ARGCHK(in != NULL || inlen == 0);
|
||||
LTC_ARGCHK(out != NULL || inlen == 0);
|
||||
LTC_ARGCHK(tag != NULL);
|
||||
LTC_ARGCHK(taglen != NULL);
|
||||
|
||||
if ((err = cipher_is_valid(cipher)) != CRYPT_OK) return err;
|
||||
if (cipher_descriptor[cipher].block_length != 16) return CRYPT_INVALID_CIPHER;
|
||||
if (keylen != 16 && keylen != 32) return CRYPT_INVALID_KEYSIZE;
|
||||
if (noncelen != 12) return CRYPT_INVALID_ARG;
|
||||
if (*taglen < 16) {
|
||||
*taglen = 16;
|
||||
return CRYPT_BUFFER_OVERFLOW;
|
||||
}
|
||||
|
||||
if ((err = s_gcm_siv_derive_keys(cipher, key, keylen, nonce, auth_key, enc_key, &enc_ecb)) != CRYPT_OK) goto cleanup;
|
||||
ecb_started = 1;
|
||||
|
||||
if (direction == LTC_DECRYPT) {
|
||||
/* CTR mode in RFC 8452: the supplied tag is the initial counter block with the MSB of the last
|
||||
byte forced to 1; only the first 4 bytes (interpreted as little-endian uint32) advance
|
||||
*/
|
||||
XMEMCPY(IC, tag, 16);
|
||||
IC[15] |= 0x80;
|
||||
if ((err = ctr_start(cipher, IC, enc_key, (int)keylen, 0, CTR_COUNTER_LITTLE_ENDIAN | 4, &ctr)) != CRYPT_OK) goto cleanup;
|
||||
ctr_started = 1;
|
||||
if (inlen) {
|
||||
if ((err = ctr_decrypt(in, out, inlen, &ctr)) != CRYPT_OK) goto cleanup;
|
||||
}
|
||||
ctr_done(&ctr);
|
||||
ctr_started = 0;
|
||||
plaintext = out;
|
||||
}
|
||||
else {
|
||||
plaintext = in;
|
||||
}
|
||||
|
||||
s_polyval_init(&pv, auth_key);
|
||||
s_polyval_data(&pv, aad, aadlen);
|
||||
s_polyval_data(&pv, plaintext, inlen);
|
||||
STORE64L((ulong64)aadlen * 8, lenblk);
|
||||
STORE64L((ulong64)inlen * 8, lenblk + 8);
|
||||
s_polyval_block(&pv, lenblk);
|
||||
s_polyval_done(&pv, S);
|
||||
|
||||
for (i = 0; i < 12; i++) S[i] ^= nonce[i];
|
||||
S[15] &= 0x7f;
|
||||
|
||||
if ((err = ecb_encrypt_block(S, expected_tag, &enc_ecb)) != CRYPT_OK) goto cleanup;
|
||||
|
||||
if (direction == LTC_DECRYPT) {
|
||||
err = XMEM_NEQ(expected_tag, tag, 16);
|
||||
if (err != CRYPT_OK) {
|
||||
if (inlen) zeromem(out, inlen); /* tag mismatch: do not release plaintext */
|
||||
goto cleanup;
|
||||
}
|
||||
}
|
||||
else {
|
||||
XMEMCPY(IC, expected_tag, 16);
|
||||
IC[15] |= 0x80;
|
||||
if ((err = ctr_start(cipher, IC, enc_key, (int)keylen, 0, CTR_COUNTER_LITTLE_ENDIAN | 4, &ctr)) != CRYPT_OK) {
|
||||
goto cleanup;
|
||||
}
|
||||
ctr_started = 1;
|
||||
if (inlen) {
|
||||
if ((err = ctr_encrypt(in, out, inlen, &ctr)) != CRYPT_OK) goto cleanup;
|
||||
}
|
||||
XMEMCPY(tag, expected_tag, 16);
|
||||
*taglen = 16;
|
||||
}
|
||||
|
||||
cleanup:
|
||||
if (ctr_started) ctr_done(&ctr);
|
||||
if (ecb_started) ecb_done(&enc_ecb);
|
||||
#ifdef LTC_CLEAN_STACK
|
||||
zeromem(auth_key, sizeof(auth_key));
|
||||
zeromem(enc_key, sizeof(enc_key));
|
||||
zeromem(S, sizeof(S));
|
||||
zeromem(IC, sizeof(IC));
|
||||
zeromem(expected_tag, sizeof(expected_tag));
|
||||
zeromem(lenblk, sizeof(lenblk));
|
||||
zeromem(&pv, sizeof(pv));
|
||||
#endif
|
||||
return err;
|
||||
}
|
||||
|
||||
#endif
|
||||
489
src/encauth/gcm_siv/gcm_siv_test.c
Normal file
489
src/encauth/gcm_siv/gcm_siv_test.c
Normal file
|
|
@ -0,0 +1,489 @@
|
|||
/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
|
||||
/* SPDX-License-Identifier: Unlicense */
|
||||
#include "tomcrypt_private.h"
|
||||
|
||||
#ifdef LTC_GCM_SIV_MODE
|
||||
|
||||
#ifdef LTC_TEST
|
||||
|
||||
typedef struct {
|
||||
const char *key; /* 32 (AES128) or 64 (AES256) hex chars */
|
||||
const char *nonce; /* 24 hex chars */
|
||||
const char *aad; /* hex */
|
||||
const char *pt; /* hex */
|
||||
const char *result; /* ciphertext || tag, hex */
|
||||
} gcm_siv_kat_t;
|
||||
|
||||
/* RFC 8452 Appendix C.1 - AEAD_AES_128_GCM_SIV */
|
||||
static const gcm_siv_kat_t s_kat_128[] = {
|
||||
{
|
||||
"01000000000000000000000000000000",
|
||||
"030000000000000000000000",
|
||||
"",
|
||||
"",
|
||||
"dc20e2d83f25705bb49e439eca56de25"
|
||||
},
|
||||
{
|
||||
"01000000000000000000000000000000",
|
||||
"030000000000000000000000",
|
||||
"",
|
||||
"0100000000000000",
|
||||
"b5d839330ac7b786578782fff6013b815b287c22493a364c"
|
||||
},
|
||||
{
|
||||
"01000000000000000000000000000000",
|
||||
"030000000000000000000000",
|
||||
"",
|
||||
"010000000000000000000000",
|
||||
"7323ea61d05932260047d942a4978db357391a0bc4fdec8b0d106639"
|
||||
},
|
||||
{
|
||||
"01000000000000000000000000000000",
|
||||
"030000000000000000000000",
|
||||
"",
|
||||
"01000000000000000000000000000000",
|
||||
"743f7c8077ab25f8624e2e948579cf77303aaf90f6fe21199c6068577437a0c4"
|
||||
},
|
||||
{
|
||||
"01000000000000000000000000000000",
|
||||
"030000000000000000000000",
|
||||
"",
|
||||
"0100000000000000000000000000000002000000000000000000000000000000",
|
||||
"84e07e62ba83a6585417245d7ec413a9fe427d6315c09b57ce45f2e3936a94451a8e45dcd4578c667cd86847bf6155ff"
|
||||
},
|
||||
{
|
||||
"01000000000000000000000000000000",
|
||||
"030000000000000000000000",
|
||||
"",
|
||||
"010000000000000000000000000000000200000000000000000000000000000003000000000000000000000000000000",
|
||||
"3fd24ce1f5a67b75bf2351f181a475c7b800a5b4d3dcf70106b1eea82fa1d64df42bf7226122fa92e17a40eeaac1201b5e6e311dbf395d35b0fe39c2714388f8"
|
||||
},
|
||||
{
|
||||
"01000000000000000000000000000000",
|
||||
"030000000000000000000000",
|
||||
"",
|
||||
"01000000000000000000000000000000020000000000000000000000000000000300000000000000000000000000000004000000000000000000000000000000",
|
||||
"2433668f1058190f6d43e360f4f35cd8e475127cfca7028ea8ab5c20f7ab2af02516a2bdcbc08d521be37ff28c152bba36697f25b4cd169c6590d1dd39566d3f8a263dd317aa88d56bdf3936dba75bb8"
|
||||
},
|
||||
{
|
||||
"01000000000000000000000000000000",
|
||||
"030000000000000000000000",
|
||||
"01",
|
||||
"0200000000000000",
|
||||
"1e6daba35669f4273b0a1a2560969cdf790d99759abd1508"
|
||||
},
|
||||
{
|
||||
"01000000000000000000000000000000",
|
||||
"030000000000000000000000",
|
||||
"01",
|
||||
"020000000000000000000000",
|
||||
"296c7889fd99f41917f4462008299c5102745aaa3a0c469fad9e075a"
|
||||
},
|
||||
{
|
||||
"01000000000000000000000000000000",
|
||||
"030000000000000000000000",
|
||||
"01",
|
||||
"02000000000000000000000000000000",
|
||||
"e2b0c5da79a901c1745f700525cb335b8f8936ec039e4e4bb97ebd8c4457441f"
|
||||
},
|
||||
{
|
||||
"01000000000000000000000000000000",
|
||||
"030000000000000000000000",
|
||||
"01",
|
||||
"0200000000000000000000000000000003000000000000000000000000000000",
|
||||
"620048ef3c1e73e57e02bb8562c416a319e73e4caac8e96a1ecb2933145a1d71e6af6a7f87287da059a71684ed3498e1"
|
||||
},
|
||||
{
|
||||
"01000000000000000000000000000000",
|
||||
"030000000000000000000000",
|
||||
"01",
|
||||
"020000000000000000000000000000000300000000000000000000000000000004000000000000000000000000000000",
|
||||
"50c8303ea93925d64090d07bd109dfd9515a5a33431019c17d93465999a8b0053201d723120a8562b838cdff25bf9d1e6a8cc3865f76897c2e4b245cf31c51f2"
|
||||
},
|
||||
{
|
||||
"01000000000000000000000000000000",
|
||||
"030000000000000000000000",
|
||||
"01",
|
||||
"02000000000000000000000000000000030000000000000000000000000000000400000000000000000000000000000005000000000000000000000000000000",
|
||||
"2f5c64059db55ee0fb847ed513003746aca4e61c711b5de2e7a77ffd02da42feec601910d3467bb8b36ebbaebce5fba30d36c95f48a3e7980f0e7ac299332a80cdc46ae475563de037001ef84ae21744"
|
||||
},
|
||||
{
|
||||
"01000000000000000000000000000000",
|
||||
"030000000000000000000000",
|
||||
"010000000000000000000000",
|
||||
"02000000",
|
||||
"a8fe3e8707eb1f84fb28f8cb73de8e99e2f48a14"
|
||||
},
|
||||
{
|
||||
"01000000000000000000000000000000",
|
||||
"030000000000000000000000",
|
||||
"010000000000000000000000000000000200",
|
||||
"0300000000000000000000000000000004000000",
|
||||
"6bb0fecf5ded9b77f902c7d5da236a4391dd029724afc9805e976f451e6d87f6fe106514"
|
||||
},
|
||||
{
|
||||
"01000000000000000000000000000000",
|
||||
"030000000000000000000000",
|
||||
"0100000000000000000000000000000002000000",
|
||||
"030000000000000000000000000000000400",
|
||||
"44d0aaf6fb2f1f34add5e8064e83e12a2adabff9b2ef00fb47920cc72a0c0f13b9fd"
|
||||
},
|
||||
{
|
||||
"e66021d5eb8e4f4066d4adb9c33560e4",
|
||||
"f46e44bb3da0015c94f70887",
|
||||
"",
|
||||
"",
|
||||
"a4194b79071b01a87d65f706e3949578"
|
||||
},
|
||||
{
|
||||
"36864200e0eaf5284d884a0e77d31646",
|
||||
"bae8e37fc83441b16034566b",
|
||||
"46bb91c3c5",
|
||||
"7a806c",
|
||||
"af60eb711bd85bc1e4d3e0a462e074eea428a8"
|
||||
},
|
||||
{
|
||||
"aedb64a6c590bc84d1a5e269e4b47801",
|
||||
"afc0577e34699b9e671fdd4f",
|
||||
"fc880c94a95198874296",
|
||||
"bdc66f146545",
|
||||
"bb93a3e34d3cd6a9c45545cfc11f03ad743dba20f966"
|
||||
},
|
||||
{
|
||||
"d5cc1fd161320b6920ce07787f86743b",
|
||||
"275d1ab32f6d1f0434d8848c",
|
||||
"046787f3ea22c127aaf195d1894728",
|
||||
"1177441f195495860f",
|
||||
"4f37281f7ad12949d01d02fd0cd174c84fc5dae2f60f52fd2b"
|
||||
},
|
||||
{
|
||||
"b3fed1473c528b8426a582995929a149",
|
||||
"9e9ad8780c8d63d0ab4149c0",
|
||||
"c9882e5386fd9f92ec489c8fde2be2cf97e74e93",
|
||||
"9f572c614b4745914474e7c7",
|
||||
"f54673c5ddf710c745641c8bc1dc2f871fb7561da1286e655e24b7b0"
|
||||
},
|
||||
{
|
||||
"2d4ed87da44102952ef94b02b805249b",
|
||||
"ac80e6f61455bfac8308a2d4",
|
||||
"2950a70d5a1db2316fd568378da107b52b0da55210cc1c1b0a",
|
||||
"0d8c8451178082355c9e940fea2f58",
|
||||
"c9ff545e07b88a015f05b274540aa183b3449b9f39552de99dc214a1190b0b"
|
||||
},
|
||||
{
|
||||
"bde3b2f204d1e9f8b06bc47f9745b3d1",
|
||||
"ae06556fb6aa7890bebc18fe",
|
||||
"1860f762ebfbd08284e421702de0de18baa9c9596291b08466f37de21c7f",
|
||||
"6b3db4da3d57aa94842b9803a96e07fb6de7",
|
||||
"6298b296e24e8cc35dce0bed484b7f30d5803e377094f04709f64d7b985310a4db84"
|
||||
},
|
||||
{
|
||||
"f901cfe8a69615a93fdf7a98cad48179",
|
||||
"6245709fb18853f68d833640",
|
||||
"7576f7028ec6eb5ea7e298342a94d4b202b370ef9768ec6561c4fe6b7e7296fa859c21",
|
||||
"e42a3c02c25b64869e146d7b233987bddfc240871d",
|
||||
"391cc328d484a4f46406181bcd62efd9b3ee197d052d15506c84a9edd65e13e9d24a2a6e70"
|
||||
}
|
||||
};
|
||||
|
||||
/* RFC 8452 Appendix C.2 - AEAD_AES_256_GCM_SIV */
|
||||
static const gcm_siv_kat_t s_kat_256[] = {
|
||||
{
|
||||
"0100000000000000000000000000000000000000000000000000000000000000",
|
||||
"030000000000000000000000",
|
||||
"",
|
||||
"",
|
||||
"07f5f4169bbf55a8400cd47ea6fd400f"
|
||||
},
|
||||
{
|
||||
"0100000000000000000000000000000000000000000000000000000000000000",
|
||||
"030000000000000000000000",
|
||||
"",
|
||||
"0100000000000000",
|
||||
"c2ef328e5c71c83b843122130f7364b761e0b97427e3df28"
|
||||
},
|
||||
{
|
||||
"0100000000000000000000000000000000000000000000000000000000000000",
|
||||
"030000000000000000000000",
|
||||
"",
|
||||
"010000000000000000000000",
|
||||
"9aab2aeb3faa0a34aea8e2b18ca50da9ae6559e48fd10f6e5c9ca17e"
|
||||
},
|
||||
{
|
||||
"0100000000000000000000000000000000000000000000000000000000000000",
|
||||
"030000000000000000000000",
|
||||
"",
|
||||
"01000000000000000000000000000000",
|
||||
"85a01b63025ba19b7fd3ddfc033b3e76c9eac6fa700942702e90862383c6c366"
|
||||
},
|
||||
{
|
||||
"0100000000000000000000000000000000000000000000000000000000000000",
|
||||
"030000000000000000000000",
|
||||
"",
|
||||
"0100000000000000000000000000000002000000000000000000000000000000",
|
||||
"4a6a9db4c8c6549201b9edb53006cba821ec9cf850948a7c86c68ac7539d027fe819e63abcd020b006a976397632eb5d"
|
||||
},
|
||||
{
|
||||
"0100000000000000000000000000000000000000000000000000000000000000",
|
||||
"030000000000000000000000",
|
||||
"",
|
||||
"010000000000000000000000000000000200000000000000000000000000000003000000000000000000000000000000",
|
||||
"c00d121893a9fa603f48ccc1ca3c57ce7499245ea0046db16c53c7c66fe717e39cf6c748837b61f6ee3adcee17534ed5790bc96880a99ba804bd12c0e6a22cc4"
|
||||
},
|
||||
{
|
||||
"0100000000000000000000000000000000000000000000000000000000000000",
|
||||
"030000000000000000000000",
|
||||
"",
|
||||
"01000000000000000000000000000000020000000000000000000000000000000300000000000000000000000000000004000000000000000000000000000000",
|
||||
"c2d5160a1f8683834910acdafc41fbb1632d4a353e8b905ec9a5499ac34f96c7e1049eb080883891a4db8caaa1f99dd004d80487540735234e3744512c6f90ce112864c269fc0d9d88c61fa47e39aa08"
|
||||
},
|
||||
{
|
||||
"0100000000000000000000000000000000000000000000000000000000000000",
|
||||
"030000000000000000000000",
|
||||
"01",
|
||||
"0200000000000000",
|
||||
"1de22967237a813291213f267e3b452f02d01ae33e4ec854"
|
||||
},
|
||||
{
|
||||
"0100000000000000000000000000000000000000000000000000000000000000",
|
||||
"030000000000000000000000",
|
||||
"01",
|
||||
"020000000000000000000000",
|
||||
"163d6f9cc1b346cd453a2e4cc1a4a19ae800941ccdc57cc8413c277f"
|
||||
},
|
||||
{
|
||||
"0100000000000000000000000000000000000000000000000000000000000000",
|
||||
"030000000000000000000000",
|
||||
"01",
|
||||
"02000000000000000000000000000000",
|
||||
"c91545823cc24f17dbb0e9e807d5ec17b292d28ff61189e8e49f3875ef91aff7"
|
||||
},
|
||||
{
|
||||
"0100000000000000000000000000000000000000000000000000000000000000",
|
||||
"030000000000000000000000",
|
||||
"01",
|
||||
"0200000000000000000000000000000003000000000000000000000000000000",
|
||||
"07dad364bfc2b9da89116d7bef6daaaf6f255510aa654f920ac81b94e8bad365aea1bad12702e1965604374aab96dbbc"
|
||||
},
|
||||
{
|
||||
"0100000000000000000000000000000000000000000000000000000000000000",
|
||||
"030000000000000000000000",
|
||||
"01",
|
||||
"020000000000000000000000000000000300000000000000000000000000000004000000000000000000000000000000",
|
||||
"c67a1f0f567a5198aa1fcc8e3f21314336f7f51ca8b1af61feac35a86416fa47fbca3b5f749cdf564527f2314f42fe2503332742b228c647173616cfd44c54eb"
|
||||
},
|
||||
{
|
||||
"0100000000000000000000000000000000000000000000000000000000000000",
|
||||
"030000000000000000000000",
|
||||
"01",
|
||||
"02000000000000000000000000000000030000000000000000000000000000000400000000000000000000000000000005000000000000000000000000000000",
|
||||
"67fd45e126bfb9a79930c43aad2d36967d3f0e4d217c1e551f59727870beefc98cb933a8fce9de887b1e40799988db1fc3f91880ed405b2dd298318858467c895bde0285037c5de81e5b570a049b62a0"
|
||||
},
|
||||
{
|
||||
"0100000000000000000000000000000000000000000000000000000000000000",
|
||||
"030000000000000000000000",
|
||||
"010000000000000000000000",
|
||||
"02000000",
|
||||
"22b3f4cd1835e517741dfddccfa07fa4661b74cf"
|
||||
},
|
||||
{
|
||||
"0100000000000000000000000000000000000000000000000000000000000000",
|
||||
"030000000000000000000000",
|
||||
"010000000000000000000000000000000200",
|
||||
"0300000000000000000000000000000004000000",
|
||||
"43dd0163cdb48f9fe3212bf61b201976067f342bb879ad976d8242acc188ab59cabfe307"
|
||||
},
|
||||
{
|
||||
"0100000000000000000000000000000000000000000000000000000000000000",
|
||||
"030000000000000000000000",
|
||||
"0100000000000000000000000000000002000000",
|
||||
"030000000000000000000000000000000400",
|
||||
"462401724b5ce6588d5a54aae5375513a075cfcdf5042112aa29685c912fc2056543"
|
||||
},
|
||||
{
|
||||
"e66021d5eb8e4f4066d4adb9c33560e4f46e44bb3da0015c94f7088736864200",
|
||||
"e0eaf5284d884a0e77d31646",
|
||||
"",
|
||||
"",
|
||||
"169fbb2fbf389a995f6390af22228a62"
|
||||
},
|
||||
{
|
||||
"bae8e37fc83441b16034566b7a806c46bb91c3c5aedb64a6c590bc84d1a5e269",
|
||||
"e4b47801afc0577e34699b9e",
|
||||
"4fbdc66f14",
|
||||
"671fdd",
|
||||
"0eaccb93da9bb81333aee0c785b240d319719d"
|
||||
},
|
||||
{
|
||||
"6545fc880c94a95198874296d5cc1fd161320b6920ce07787f86743b275d1ab3",
|
||||
"2f6d1f0434d8848c1177441f",
|
||||
"6787f3ea22c127aaf195",
|
||||
"195495860f04",
|
||||
"a254dad4f3f96b62b84dc40c84636a5ec12020ec8c2c"
|
||||
},
|
||||
{
|
||||
"d1894728b3fed1473c528b8426a582995929a1499e9ad8780c8d63d0ab4149c0",
|
||||
"9f572c614b4745914474e7c7",
|
||||
"489c8fde2be2cf97e74e932d4ed87d",
|
||||
"c9882e5386fd9f92ec",
|
||||
"0df9e308678244c44bc0fd3dc6628dfe55ebb0b9fb2295c8c2"
|
||||
},
|
||||
{
|
||||
"a44102952ef94b02b805249bac80e6f61455bfac8308a2d40d8c845117808235",
|
||||
"5c9e940fea2f582950a70d5a",
|
||||
"0da55210cc1c1b0abde3b2f204d1e9f8b06bc47f",
|
||||
"1db2316fd568378da107b52b",
|
||||
"8dbeb9f7255bf5769dd56692404099c2587f64979f21826706d497d5"
|
||||
},
|
||||
{
|
||||
"9745b3d1ae06556fb6aa7890bebc18fe6b3db4da3d57aa94842b9803a96e07fb",
|
||||
"6de71860f762ebfbd08284e4",
|
||||
"f37de21c7ff901cfe8a69615a93fdf7a98cad481796245709f",
|
||||
"21702de0de18baa9c9596291b08466",
|
||||
"793576dfa5c0f88729a7ed3c2f1bffb3080d28f6ebb5d3648ce97bd5ba67fd"
|
||||
},
|
||||
{
|
||||
"b18853f68d833640e42a3c02c25b64869e146d7b233987bddfc240871d7576f7",
|
||||
"028ec6eb5ea7e298342a94d4",
|
||||
"9c2159058b1f0fe91433a5bdc20e214eab7fecef4454a10ef0657df21ac7",
|
||||
"b202b370ef9768ec6561c4fe6b7e7296fa85",
|
||||
"857e16a64915a787637687db4a9519635cdd454fc2a154fea91f8363a39fec7d0a49"
|
||||
},
|
||||
{
|
||||
"3c535de192eaed3822a2fbbe2ca9dfc88255e14a661b8aa82cc54236093bbc23",
|
||||
"688089e55540db1872504e1c",
|
||||
"734320ccc9d9bbbb19cb81b2af4ecbc3e72834321f7aa0f70b7282b4f33df23f167541",
|
||||
"ced532ce4159b035277d4dfbb7db62968b13cd4eec",
|
||||
"626660c26ea6612fb17ad91e8e767639edd6c9faee9d6c7029675b89eaf4ba1ded1a286594"
|
||||
}
|
||||
};
|
||||
|
||||
/* RFC 8452 Appendix C.3 - Counter Wrap Tests (AES-256) */
|
||||
static const gcm_siv_kat_t s_kat_wrap[] = {
|
||||
{
|
||||
"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
"000000000000000000000000",
|
||||
"",
|
||||
"000000000000000000000000000000004db923dc793ee6497c76dcc03a98e108",
|
||||
"f3f80f2cf0cb2dd9c5984fcda908456cc537703b5ba70324a6793a7bf218d3eaffffffff000000000000000000000000"
|
||||
},
|
||||
{
|
||||
"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
"000000000000000000000000",
|
||||
"",
|
||||
"eb3640277c7ffd1303c7a542d02d3e4c0000000000000000",
|
||||
"18ce4f0b8cb4d0cac65fea8f79257b20888e53e72299e56dffffffff000000000000000000000000"
|
||||
}
|
||||
};
|
||||
|
||||
static int s_run_kat(int cipher, unsigned long keylen, const gcm_siv_kat_t *vec, unsigned long n, const char *name)
|
||||
{
|
||||
unsigned char key[32], nonce[12];
|
||||
unsigned char *aad = NULL, *pt = NULL, *exp = NULL;
|
||||
unsigned char *ct = NULL, *out = NULL, tag[16];
|
||||
unsigned long aadlen, ptlen, explen, ctlen, taglen;
|
||||
unsigned long klen, nlen, slen;
|
||||
unsigned long i;
|
||||
int err = CRYPT_OK;
|
||||
|
||||
for (i = 0; i < n; i++) {
|
||||
klen = sizeof(key);
|
||||
if ((err = base16_decode(vec[i].key, XSTRLEN(vec[i].key), key, &klen)) != CRYPT_OK) return err;
|
||||
if (klen != keylen) return CRYPT_FAIL_TESTVECTOR;
|
||||
|
||||
nlen = sizeof(nonce);
|
||||
if ((err = base16_decode(vec[i].nonce, XSTRLEN(vec[i].nonce), nonce, &nlen)) != CRYPT_OK) return err;
|
||||
if (nlen != 12) return CRYPT_FAIL_TESTVECTOR;
|
||||
|
||||
aadlen = XSTRLEN(vec[i].aad) / 2;
|
||||
ptlen = XSTRLEN(vec[i].pt) / 2;
|
||||
explen = XSTRLEN(vec[i].result) / 2;
|
||||
if (explen != ptlen + 16) return CRYPT_FAIL_TESTVECTOR;
|
||||
ctlen = ptlen;
|
||||
|
||||
aad = aadlen ? XMALLOC(aadlen) : NULL;
|
||||
pt = ptlen ? XMALLOC(ptlen) : NULL;
|
||||
exp = XMALLOC(explen);
|
||||
ct = ctlen ? XMALLOC(ctlen) : NULL;
|
||||
out = ptlen ? XMALLOC(ptlen) : NULL;
|
||||
if (explen == 0 || (aadlen && !aad) || (ptlen && (!pt || !out)) || !exp || (ctlen && !ct)) {
|
||||
err = CRYPT_MEM;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if (aadlen) {
|
||||
slen = aadlen;
|
||||
if ((err = base16_decode(vec[i].aad, XSTRLEN(vec[i].aad), aad, &slen)) != CRYPT_OK) goto cleanup;
|
||||
}
|
||||
if (ptlen) {
|
||||
slen = ptlen;
|
||||
if ((err = base16_decode(vec[i].pt, XSTRLEN(vec[i].pt), pt, &slen)) != CRYPT_OK) goto cleanup;
|
||||
}
|
||||
slen = explen;
|
||||
if ((err = base16_decode(vec[i].result, XSTRLEN(vec[i].result), exp, &slen)) != CRYPT_OK) goto cleanup;
|
||||
|
||||
/* encrypt */
|
||||
taglen = sizeof(tag);
|
||||
if ((err = gcm_siv_memory(cipher, key, keylen, nonce, 12, aad, aadlen, pt, ptlen, ct, tag, &taglen, LTC_ENCRYPT)) != CRYPT_OK) {
|
||||
goto cleanup;
|
||||
}
|
||||
if (ctlen && (ltc_compare_testvector(ct, ctlen, exp, ctlen, name, (int)i) != 0)) {
|
||||
err = CRYPT_FAIL_TESTVECTOR;
|
||||
goto cleanup;
|
||||
}
|
||||
if (ltc_compare_testvector(tag, 16, exp + ctlen, 16, name, (int)(i + 0x100)) != 0) {
|
||||
err = CRYPT_FAIL_TESTVECTOR;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
/* decrypt */
|
||||
if ((err = gcm_siv_memory(cipher, key, keylen, nonce, 12, aad, aadlen, ct, ctlen, out, tag, &taglen, LTC_DECRYPT)) != CRYPT_OK) {
|
||||
goto cleanup;
|
||||
}
|
||||
if (ptlen && (ltc_compare_testvector(out, ptlen, pt, ptlen, name, (int)(i + 0x200)) != 0)) {
|
||||
err = CRYPT_FAIL_TESTVECTOR;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
/* tampered tag must fail */
|
||||
tag[0] ^= 0x80;
|
||||
err = gcm_siv_memory(cipher, key, keylen, nonce, 12, aad, aadlen, ct, ctlen, out, tag, &taglen, LTC_DECRYPT);
|
||||
if (err == CRYPT_OK) {
|
||||
err = CRYPT_FAIL_TESTVECTOR;
|
||||
goto cleanup;
|
||||
}
|
||||
err = CRYPT_OK;
|
||||
|
||||
XFREE(aad); aad = NULL;
|
||||
XFREE(pt); pt = NULL;
|
||||
XFREE(exp); exp = NULL;
|
||||
XFREE(ct); ct = NULL;
|
||||
XFREE(out); out = NULL;
|
||||
}
|
||||
|
||||
cleanup:
|
||||
if (aad) XFREE(aad);
|
||||
if (pt) XFREE(pt);
|
||||
if (exp) XFREE(exp);
|
||||
if (ct) XFREE(ct);
|
||||
if (out) XFREE(out);
|
||||
return err;
|
||||
}
|
||||
|
||||
#endif /* LTC_TEST */
|
||||
|
||||
int gcm_siv_test(void)
|
||||
{
|
||||
#ifndef LTC_TEST
|
||||
return CRYPT_NOP;
|
||||
#else
|
||||
int cipher, err;
|
||||
if ((cipher = find_cipher("aes")) == -1) return CRYPT_NOP;
|
||||
if ((err = s_run_kat(cipher, 16, s_kat_128, LTC_ARRAY_SIZE(s_kat_128), "AES-128-GCM-SIV")) != CRYPT_OK) return err;
|
||||
if ((err = s_run_kat(cipher, 32, s_kat_256, LTC_ARRAY_SIZE(s_kat_256), "AES-256-GCM-SIV")) != CRYPT_OK) return err;
|
||||
if ((err = s_run_kat(cipher, 32, s_kat_wrap, LTC_ARRAY_SIZE(s_kat_wrap), "AES-256-GCM-SIV-wrap")) != CRYPT_OK) return err;
|
||||
return CRYPT_OK;
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
@ -312,6 +312,7 @@
|
|||
#define LTC_GCM_MODE
|
||||
#define LTC_CHACHA20POLY1305_MODE
|
||||
#define LTC_SIV_MODE
|
||||
#define LTC_GCM_SIV_MODE
|
||||
|
||||
/* Use 64KiB tables */
|
||||
#ifndef LTC_NO_TABLES
|
||||
|
|
|
|||
|
|
@ -435,14 +435,14 @@ int ccm_test(void);
|
|||
|
||||
#endif /* LTC_CCM_MODE */
|
||||
|
||||
#if defined(LTC_LRW_MODE) || defined(LTC_GCM_MODE)
|
||||
#if defined(LTC_LRW_MODE) || defined(LTC_GCM_MODE) || defined(LTC_GCM_SIV_MODE)
|
||||
void gcm_gf_mult(const unsigned char *a, const unsigned char *b, unsigned char *c);
|
||||
#endif
|
||||
|
||||
int gcm_hw_pmul_is_supported(void);
|
||||
|
||||
/* table shared between GCM and LRW */
|
||||
#if defined(LTC_GCM_TABLES) || defined(LTC_LRW_TABLES) || ((defined(LTC_GCM_MODE) || defined(LTC_GCM_MODE)) && defined(LTC_FAST))
|
||||
#if defined(LTC_GCM_TABLES) || defined(LTC_LRW_TABLES) || ((defined(LTC_GCM_MODE) || defined(LTC_GCM_SIV_MODE)) && defined(LTC_FAST))
|
||||
extern const unsigned char gcm_shift_table[];
|
||||
#endif
|
||||
|
||||
|
|
@ -562,3 +562,15 @@ int siv_test(void);
|
|||
|
||||
#endif
|
||||
|
||||
#ifdef LTC_GCM_SIV_MODE
|
||||
/* RFC 8452 - AES-GCM-SIV */
|
||||
int gcm_siv_memory( int cipher,
|
||||
const unsigned char *key, unsigned long keylen,
|
||||
const unsigned char *nonce, unsigned long noncelen,
|
||||
const unsigned char *aad, unsigned long aadlen,
|
||||
unsigned char *in, unsigned long inlen,
|
||||
unsigned char *out,
|
||||
unsigned char *tag, unsigned long *taglen,
|
||||
int direction);
|
||||
int gcm_siv_test(void);
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -321,6 +321,9 @@ const char *crypt_build_settings =
|
|||
#if defined(LTC_SIV_MODE)
|
||||
" SIV\n"
|
||||
#endif
|
||||
#if defined(LTC_GCM_SIV_MODE)
|
||||
" GCM-SIV\n"
|
||||
#endif
|
||||
|
||||
"\nPRNG:\n"
|
||||
#if defined(LTC_YARROW)
|
||||
|
|
|
|||
|
|
@ -53,6 +53,9 @@ int mac_test(void)
|
|||
#ifdef LTC_SIV_MODE
|
||||
DO(siv_test());
|
||||
DO(siv_wycheproof_test());
|
||||
#endif
|
||||
#ifdef LTC_GCM_SIV_MODE
|
||||
DO(gcm_siv_test());
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue