Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add SIV #319

Merged
merged 5 commits into from
Jan 9, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 39 additions & 4 deletions demos/timing.c
Original file line number Diff line number Diff line change
Expand Up @@ -1153,8 +1153,13 @@ static void time_macs(void)

static void time_encmacs_(unsigned long MAC_SIZE)
{
#if defined(LTC_EAX_MODE) || defined(LTC_OCB_MODE) || defined(LTC_OCB3_MODE) || defined(LTC_CCM_MODE) || defined(LTC_GCM_MODE)
unsigned char *buf, IV[16], key[16], tag[16];
#if defined(LTC_EAX_MODE) || defined(LTC_OCB_MODE) || defined(LTC_OCB3_MODE) || \
defined(LTC_CCM_MODE) || defined(LTC_GCM_MODE) || defined(LTC_SIV_MODE)
#if defined(LTC_SIV_MODE)
unsigned char *aad[4];
unsigned long buflen;
#endif
unsigned char *buf, IV[16], key[32], tag[16];
ulong64 t1, t2;
unsigned long x, z;
int err, cipher_idx;
Expand All @@ -1171,8 +1176,8 @@ static void time_encmacs_(unsigned long MAC_SIZE)
cipher_idx = find_cipher("aes");

yarrow_read(buf, MAC_SIZE*1024, &yarrow_prng);
yarrow_read(key, 16, &yarrow_prng);
yarrow_read(IV, 16, &yarrow_prng);
yarrow_read(key, sizeof(key), &yarrow_prng);
yarrow_read(IV, sizeof(IV), &yarrow_prng);

#ifdef LTC_EAX_MODE
t2 = -1;
Expand Down Expand Up @@ -1308,8 +1313,38 @@ __attribute__ ((aligned (16)))
}
fprintf(stderr, "GCM (precomp)\t\t%9"PRI64"u\n", t2/(ulong64)(MAC_SIZE*1024));
}
#endif

#ifdef LTC_SIV_MODE
for(z = 0; z < 4; z++) {
aad[z] = IV + z * 4;
}
for(z = 0; z < 4; z++) {
t2 = -1;
for (x = 0; x < 10000; x++) {
buflen = MAC_SIZE*1024;
t_start();
t1 = t_read();
if ((err = siv_memory(cipher_idx, LTC_ENCRYPT,
key, 32,
buf, MAC_SIZE*1024 - 16,
buf, &buflen,
aad[0], 16,
aad[1], 12,
aad[2], 8,
aad[3], 4,
NULL)) != CRYPT_OK) {
fprintf(stderr, "\nSIV error... %s\n", error_to_string(err));
exit(EXIT_FAILURE);
}
t1 = t_read() - t1;
if (t1 < t2) t2 = t1;
}
aad[3-z] = NULL;
fprintf(stderr, "SIV (%lu x AAD)\t\t%9"PRI64"u\n", 4-z, t2/(ulong64)(MAC_SIZE*1024));
}
#endif

XFREE(buf);
#else
LTC_UNUSED_PARAM(MAC_SIZE);
Expand Down
160 changes: 160 additions & 0 deletions doc/crypt.tex
Original file line number Diff line number Diff line change
Expand Up @@ -2576,6 +2576,166 @@ \subsection{One--Shot Packet}
In order to enable OpenSSH compatibility, the flag \textit{CHACHA20POLY1305\_OPENSSH\_COMPAT} has to be \textbf{OR}'ed into
the \textit{direction} parameter.


\mysection{SIV}
\label{SIV}

The SIV (Synthetic Initialization Vector) authenticated encryption is a block cipher mode of encryption
defined by \url{https://tools.ietf.org/html/rfc5297}.

In contrast to all the other AEAD modes, SIV provides no iterative API. Instead it only provides one--shot APIs.

AEAD algorithm design usually suggests using a separate Nonce (also called IV) and additional authenticated Data (AAD).
SIV treats this slightly different and does not enforce any of the two, but leaves it up to the user.
Also SIV allows passing multiple sets of data as AAD, up to a maximum of \texttt{126} elements.
In case one wants to use a Nonce in a classical style it is suggested to pass it as the last of the AAD elements,
thereby limiting the number of AAD to \texttt{125}.

\subsection{Encryption / Decryption}
To encrypt and create a tag resp. decrypt and check the tag, the following API functions can be used.

\index{siv\_encrypt\_memory()}
\begin{verbatim}
int siv_encrypt_memory( int cipher,
const unsigned char *key, unsigned long keylen,
const unsigned char *ad[], unsigned long adlen[],
const unsigned char *pt, unsigned long ptlen,
unsigned char *ct, unsigned long *ctlen);
\end{verbatim}
This encrypts the data where \textit{pt} is the plaintext and \textit{ct} is the ciphertext.
The length of the plaintext is given in \textit{ptlen} and the length of the ciphertext is given in \textit{ctlen}.
\textit{ctlen} shall contain the max buffer size allocated at \textit{ct} on input, and will be updated with the
written length on successful encryption.

The buffer of \textit{ct} shall be at least \texttt{ptlen + 16} bytes wide.

The key to the encrypt operation is passed in \textit{key} of length \textit{keylen}.

The AAD is passed as array of pointers in \textit{ad}. The length of each AAD is passed as array of
\textit{unsigned long} in \textit{adlen}.
As soon as an array element of \textit{ad} is hit which equals \texttt{NULL} or an array element of \textit{adlen}
is hit which equals \texttt{0}, processing of the AAD is stopped.

\index{siv\_decrypt\_memory()}
\begin{verbatim}
int siv_decrypt_memory( int cipher,
const unsigned char *key, unsigned long keylen,
const unsigned char *ad[], unsigned long adlen[],
const unsigned char *ct, unsigned long ctlen,
unsigned char *pt, unsigned long *ptlen);
\end{verbatim}
This decrypts the data where \textit{ct} is the ciphertext of length \textit{ctlen} and \textit{pt} is the plaintext of length \textit{ptlen}.
\textit{ptlen} shall contain the max buffer size allocated at \textit{pt} on input, and will be updated with the
written lenth on successful decryption.

The buffer of \textit{pt} shall be at least \texttt{ctlen - 16} bytes wide.

The AAD is processed in the same way as in the encrypt function.

An example of encryption and decryption with SIV using multiple AAD and a Nonce is given below.

\begin{small}
\begin{verbatim}
#include <tomcrypt.h>

int main(void)
{
int err;
unsigned char plain[16] = {0};
unsigned char ct[sizeof(plain) + 16] = {0};
unsigned long plainlen = sizeof(plain), ctlen = sizeof(ct);

register_cipher(&aes_desc);

/* We need to cast the AAD strings because the API asks for an `unsigned char*`
* but a string is on most platforms defined as a "signed" `char*`. */
if ((err = siv_encrypt_memory(find_cipher("aes"),
((unsigned char[32]) {0x0}), 32,
((const unsigned char*[]) {(void*)"aad0", (void*)"aad1",
(void*)"NONCE", NULL}),
((unsigned long[]) {4, 4, 5, 0}),
plain, plainlen,
ct, &ctlen)) != CRYPT_OK) {
whine_and_pout(err);
}

if ((err = siv_decrypt_memory(find_cipher("aes"),
((unsigned char[32]) {0x0}), 32,
((const unsigned char*[]) {(void*)"aad0", (void*)"aad1",
(void*)"NONCE", NULL}),
((unsigned long[]) {4, 4, 5, 0}),
ct, ctlen,
plain, &plainlen)) != CRYPT_OK) {
whine_and_pout(err);
}

return EXIT_SUCCESS;
}
\end{verbatim}
\end{small}

\subsection{One--Shot Packet}
To process a single packet under any given key the following helper function can be used.

\index{siv\_memory()}
\begin{verbatim}
int siv_memory( int cipher, int direction,
const unsigned char *key, unsigned long keylen,
const unsigned char *in, unsigned long inlen,
unsigned char *out, unsigned long *outlen,
...);
\end{verbatim}

This will execute a SIV operation of the \textit{direction} (\texttt{LTC\_ENCRYPT} resp. \texttt{LTC\_DECRYPT})
using the \textit{cipher} with the \textit{key} of len \textit{keylen}.
The AAD is optionally passed as varargs of the form \textit{(const unsigned char*, unsigned long)}, which musst be
NULL terminated.
The input is passed via the \textit{in} argument of length \textit{inlen}.
The output is stored in the buffer pointer to by the \textit{out} argument where the length is passed as \textit{outlen}.
\textit{outlen} shall contain the initial size of the buffer behind \textit{out} when calling the function and on
return it will contain the written size.

In case the operation is \textit{encryption} the buffer of \textit{out} shall be at least \texttt{inlen + 16} bytes wide.
In the case of \textit{decryption} the buffer of \textit{out} shall be at least \texttt{inlen - 16} bytes wide.

An example of encryption and decryption with the one--shot API of SIV using multiple AAD is given below.

\begin{small}
\begin{verbatim}
#include <tomcrypt.h>

int main(void)
{
int err;
unsigned char plain[16] = {0};
unsigned char ct[sizeof(plain) + 16] = {0};
unsigned long plainlen = sizeof(plain), ctlen = sizeof(ct);

register_cipher(&aes_desc);

/* Note that constant length values must be suffixed by `uL` in order
* to operate correctly cross-platform. */
if ((err = siv_memory(find_cipher("aes"), LTC_ENCRYPT,
((unsigned char[32]) {0x0}), 32,
plain, plainlen,
ct, &ctlen,
"aad0", 4uL, "aad1", 4uL, "NONCE", 5uL, NULL)) != CRYPT_OK) {
whine_and_pout(err);
}

if ((err = siv_memory(find_cipher("aes"), LTC_DECRYPT,
((unsigned char[32]) {0x0}), 32,
ct, ctlen,
plain, &plainlen,
"aad0", 4uL, "aad1", 4uL, "NONCE", 5uL, NULL)) != CRYPT_OK) {
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
Expand Down
8 changes: 8 additions & 0 deletions libtomcrypt_VS2008.vcproj
Original file line number Diff line number Diff line change
Expand Up @@ -835,6 +835,14 @@
>
</File>
</Filter>
<Filter
Name="siv"
>
<File
RelativePath="src\encauth\siv\siv.c"
>
</File>
</Filter>
</Filter>
<Filter
Name="hashes"
Expand Down
4 changes: 2 additions & 2 deletions makefile.mingw
Original file line number Diff line number Diff line change
Expand Up @@ -64,8 +64,8 @@ src/encauth/ocb3/ocb3_add_aad.o src/encauth/ocb3/ocb3_decrypt.o src/encauth/ocb3
src/encauth/ocb3/ocb3_decrypt_verify_memory.o src/encauth/ocb3/ocb3_done.o \
src/encauth/ocb3/ocb3_encrypt.o src/encauth/ocb3/ocb3_encrypt_authenticate_memory.o \
src/encauth/ocb3/ocb3_encrypt_last.o src/encauth/ocb3/ocb3_init.o src/encauth/ocb3/ocb3_int_ntz.o \
src/encauth/ocb3/ocb3_int_xor_blocks.o src/encauth/ocb3/ocb3_test.o src/hashes/blake2b.o \
src/hashes/blake2s.o src/hashes/chc/chc.o src/hashes/helper/hash_file.o \
src/encauth/ocb3/ocb3_int_xor_blocks.o src/encauth/ocb3/ocb3_test.o src/encauth/siv/siv.o \
src/hashes/blake2b.o src/hashes/blake2s.o src/hashes/chc/chc.o src/hashes/helper/hash_file.o \
src/hashes/helper/hash_filehandle.o src/hashes/helper/hash_memory.o \
src/hashes/helper/hash_memory_multi.o src/hashes/md2.o src/hashes/md4.o src/hashes/md5.o \
src/hashes/rmd128.o src/hashes/rmd160.o src/hashes/rmd256.o src/hashes/rmd320.o src/hashes/sha1.o \
Expand Down
4 changes: 2 additions & 2 deletions makefile.msvc
Original file line number Diff line number Diff line change
Expand Up @@ -57,8 +57,8 @@ src/encauth/ocb3/ocb3_add_aad.obj src/encauth/ocb3/ocb3_decrypt.obj src/encauth/
src/encauth/ocb3/ocb3_decrypt_verify_memory.obj src/encauth/ocb3/ocb3_done.obj \
src/encauth/ocb3/ocb3_encrypt.obj src/encauth/ocb3/ocb3_encrypt_authenticate_memory.obj \
src/encauth/ocb3/ocb3_encrypt_last.obj src/encauth/ocb3/ocb3_init.obj src/encauth/ocb3/ocb3_int_ntz.obj \
src/encauth/ocb3/ocb3_int_xor_blocks.obj src/encauth/ocb3/ocb3_test.obj src/hashes/blake2b.obj \
src/hashes/blake2s.obj src/hashes/chc/chc.obj src/hashes/helper/hash_file.obj \
src/encauth/ocb3/ocb3_int_xor_blocks.obj src/encauth/ocb3/ocb3_test.obj src/encauth/siv/siv.obj \
src/hashes/blake2b.obj src/hashes/blake2s.obj src/hashes/chc/chc.obj src/hashes/helper/hash_file.obj \
src/hashes/helper/hash_filehandle.obj src/hashes/helper/hash_memory.obj \
src/hashes/helper/hash_memory_multi.obj src/hashes/md2.obj src/hashes/md4.obj src/hashes/md5.obj \
src/hashes/rmd128.obj src/hashes/rmd160.obj src/hashes/rmd256.obj src/hashes/rmd320.obj src/hashes/sha1.obj \
Expand Down
4 changes: 2 additions & 2 deletions makefile.unix
Original file line number Diff line number Diff line change
Expand Up @@ -78,8 +78,8 @@ src/encauth/ocb3/ocb3_add_aad.o src/encauth/ocb3/ocb3_decrypt.o src/encauth/ocb3
src/encauth/ocb3/ocb3_decrypt_verify_memory.o src/encauth/ocb3/ocb3_done.o \
src/encauth/ocb3/ocb3_encrypt.o src/encauth/ocb3/ocb3_encrypt_authenticate_memory.o \
src/encauth/ocb3/ocb3_encrypt_last.o src/encauth/ocb3/ocb3_init.o src/encauth/ocb3/ocb3_int_ntz.o \
src/encauth/ocb3/ocb3_int_xor_blocks.o src/encauth/ocb3/ocb3_test.o src/hashes/blake2b.o \
src/hashes/blake2s.o src/hashes/chc/chc.o src/hashes/helper/hash_file.o \
src/encauth/ocb3/ocb3_int_xor_blocks.o src/encauth/ocb3/ocb3_test.o src/encauth/siv/siv.o \
src/hashes/blake2b.o src/hashes/blake2s.o src/hashes/chc/chc.o src/hashes/helper/hash_file.o \
src/hashes/helper/hash_filehandle.o src/hashes/helper/hash_memory.o \
src/hashes/helper/hash_memory_multi.o src/hashes/md2.o src/hashes/md4.o src/hashes/md5.o \
src/hashes/rmd128.o src/hashes/rmd160.o src/hashes/rmd256.o src/hashes/rmd320.o src/hashes/sha1.o \
Expand Down
4 changes: 2 additions & 2 deletions makefile_include.mk
Original file line number Diff line number Diff line change
Expand Up @@ -239,8 +239,8 @@ src/encauth/ocb3/ocb3_add_aad.o src/encauth/ocb3/ocb3_decrypt.o src/encauth/ocb3
src/encauth/ocb3/ocb3_decrypt_verify_memory.o src/encauth/ocb3/ocb3_done.o \
src/encauth/ocb3/ocb3_encrypt.o src/encauth/ocb3/ocb3_encrypt_authenticate_memory.o \
src/encauth/ocb3/ocb3_encrypt_last.o src/encauth/ocb3/ocb3_init.o src/encauth/ocb3/ocb3_int_ntz.o \
src/encauth/ocb3/ocb3_int_xor_blocks.o src/encauth/ocb3/ocb3_test.o src/hashes/blake2b.o \
src/hashes/blake2s.o src/hashes/chc/chc.o src/hashes/helper/hash_file.o \
src/encauth/ocb3/ocb3_int_xor_blocks.o src/encauth/ocb3/ocb3_test.o src/encauth/siv/siv.o \
src/hashes/blake2b.o src/hashes/blake2s.o src/hashes/chc/chc.o src/hashes/helper/hash_file.o \
src/hashes/helper/hash_filehandle.o src/hashes/helper/hash_memory.o \
src/hashes/helper/hash_memory_multi.o src/hashes/md2.o src/hashes/md4.o src/hashes/md5.o \
src/hashes/rmd128.o src/hashes/rmd160.o src/hashes/rmd256.o src/hashes/rmd320.o src/hashes/sha1.o \
Expand Down
1 change: 1 addition & 0 deletions sources.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@ src/encauth/ocb3/ocb3_init.c
src/encauth/ocb3/ocb3_int_ntz.c
src/encauth/ocb3/ocb3_int_xor_blocks.c
src/encauth/ocb3/ocb3_test.c
src/encauth/siv/siv.c
src/hashes/blake2b.c
src/hashes/blake2s.c
src/hashes/chc/chc.c
Expand Down
Loading