Commit 0f49c046 by Johann Großschädl Committed by Sebastian Renner

sparkle

parent 5055ea5a
This source diff could not be displayed because it is too large. You can view the blob instead.
#define CRYPTO_KEYBYTES 16
#define CRYPTO_NSECBYTES 0
#define CRYPTO_NPUBBYTES 16
#define CRYPTO_ABYTES 16
#define CRYPTO_NOOVERLAP 1
// NIST-developed software is provided by NIST as a public service. You may
// use, copy and distribute copies of the software in any medium, provided that
// you keep intact this entire notice. You may improve, modify and create
// derivative works of the software or any portion of the software, and you may
// copy and distribute such modifications or works. Modified works should carry
// a notice stating that you changed the software and should note the date and
// nature of any such change. Please explicitly acknowledge the National
// Institute of Standards and Technology as the source of the software.
//
// NIST-developed software is expressly provided "AS IS." NIST MAKES NO
// WARRANTY OF ANY KIND, EXPRESS, IMPLIED, IN FACT OR ARISING BY OPERATION OF
// LAW, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTY OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE, NON-INFRINGEMENT AND DATA ACCURACY. NIST
// NEITHER REPRESENTS NOR WARRANTS THAT THE OPERATION OF THE SOFTWARE WILL BE
// UNINTERRUPTED OR ERROR-FREE, OR THAT ANY DEFECTS WILL BE CORRECTED. NIST
// DOES NOT WARRANT OR MAKE ANY REPRESENTATIONS REGARDING THE USE OF THE
// SOFTWARE OR THE RESULTS THEREOF, INCLUDING BUT NOT LIMITED TO THE
// CORRECTNESS, ACCURACY, RELIABILITY, OR USEFULNESS OF THE SOFTWARE.
//
// You are solely responsible for determining the appropriateness of using and
// distributing the software and you assume all risks associated with its use,
// including but not limited to the risks and costs of program errors,
// compliance with applicable laws, damage to or loss of data, programs or
// equipment, and the unavailability or interruption of operation. This
// software is not intended to be used in any situation where a failure could
// cause risk of injury or damage to property. The software developed by NIST
// employees is not subject to copyright protection within the United States.
// disable deprecation for sprintf and fopen
#ifdef _MSC_VER
#define _CRT_SECURE_NO_WARNINGS
#endif
#include <stdio.h>
#include <string.h>
#include "crypto_aead.h"
#include "api.h"
#define KAT_SUCCESS 0
#define KAT_FILE_OPEN_ERROR -1
#define KAT_DATA_ERROR -3
#define KAT_CRYPTO_FAILURE -4
#define MAX_FILE_NAME 256
#define MAX_MESSAGE_LENGTH 32
#define MAX_ASSOCIATED_DATA_LENGTH 32
typedef unsigned char UChar;
typedef unsigned long long int ULLInt;
void init_buffer(UChar *buffer, ULLInt numbytes);
void fprint_bstr(FILE *fp, const char *label, const UChar *data, \
ULLInt length);
int generate_test_vectors(void);
/*
int main(void)
{
int ret;
ret = generate_test_vectors();
if (ret != KAT_SUCCESS) {
fprintf(stderr, "test vector generation failed with code %d\n", ret);
}
return ret;
}
*/
int generate_test_vectors(void)
{
FILE *fp;
char fileName[MAX_FILE_NAME];
UChar key[CRYPTO_KEYBYTES];
UChar nonce[CRYPTO_NPUBBYTES];
UChar msg[MAX_MESSAGE_LENGTH];
UChar msg2[MAX_MESSAGE_LENGTH];
UChar ad[MAX_ASSOCIATED_DATA_LENGTH];
UChar ct[MAX_MESSAGE_LENGTH + CRYPTO_ABYTES];
ULLInt clen, mlen2;
ULLInt mlen, adlen;
int count = 1;
int func_ret, ret_val = KAT_SUCCESS;
init_buffer(key, sizeof(key));
init_buffer(nonce, sizeof(nonce));
init_buffer(msg, sizeof(msg));
init_buffer(ad, sizeof(ad));
sprintf(fileName, "LWC_AEAD_KAT_%d_%d.txt", (CRYPTO_KEYBYTES*8), \
(CRYPTO_NPUBBYTES*8));
if ((fp = fopen(fileName, "w")) == NULL) {
fprintf(stderr, "Couldn't open <%s> for write\n", fileName);
return KAT_FILE_OPEN_ERROR;
}
for (mlen = 0; (mlen<=MAX_MESSAGE_LENGTH)&&(ret_val==KAT_SUCCESS); mlen++) {
for(adlen = 0; adlen <= MAX_ASSOCIATED_DATA_LENGTH; adlen++) {
fprintf(fp, "Count = %d\n", count++);
fprint_bstr(fp, "Key = ", key, CRYPTO_KEYBYTES);
fprint_bstr(fp, "Nonce = ", nonce, CRYPTO_NPUBBYTES);
fprint_bstr(fp, "PT = ", msg, mlen);
fprint_bstr(fp, "AD = ", ad, adlen);
func_ret = crypto_aead_encrypt(ct, &clen, msg, mlen, ad, adlen, NULL, \
nonce, key);
if (func_ret != 0) {
fprintf(fp, "crypto_aead_encrypt returned <%d>\n", func_ret);
ret_val = KAT_CRYPTO_FAILURE;
break;
}
fprint_bstr(fp, "CT = ", ct, clen);
fprintf(fp, "\n");
func_ret = crypto_aead_decrypt(msg2, &mlen2, NULL, ct, clen, ad, adlen, \
nonce, key);
if (func_ret != 0) {
fprintf(fp, "crypto_aead_decrypt returned <%d>\n", func_ret);
ret_val = KAT_CRYPTO_FAILURE;
break;
}
if (mlen != mlen2) {
fprintf(fp, "crypto_aead_decrypt returned bad 'mlen': Got <%llu>, \
expected <%llu>\n", mlen2, mlen);
ret_val = KAT_CRYPTO_FAILURE;
break;
}
if (memcmp(msg, msg2, ((size_t) mlen))) {
fprintf(fp, "crypto_aead_decrypt did not recover the plaintext\n");
ret_val = KAT_CRYPTO_FAILURE;
break;
}
}
}
fclose(fp);
return ret_val;
}
void fprint_bstr(FILE *fp, const char *label, const UChar *data, ULLInt length)
{
ULLInt i;
fprintf(fp, "%s", label);
for (i = 0; i < length; i++)
fprintf(fp, "%02X", data[i]);
fprintf(fp, "\n");
}
void init_buffer(UChar *buffer, ULLInt numbytes)
{
ULLInt i;
for (i = 0; i < numbytes; i++)
buffer[i] = (UChar)i;
}
///////////////////////////////////////////////////////////////////////////////
// schwaemm_cfg.h: Configuration of instances of AEAD algorithm SCHWAEMM. //
// This file is part of the SPARKLE submission to NIST's LW Crypto Project. //
// Version 1.1.2 (2020-10-30), see <http://www.cryptolux.org/> for updates. //
// Authors: The SPARKLE Group (C. Beierle, A. Biryukov, L. Cardoso dos //
// Santos, J. Groszschaedl, L. Perrin, A. Udovenko, V. Velichkov, Q. Wang). //
// License: GPLv3 (see LICENSE file), other licenses available upon request. //
// Copyright (C) 2019-2020 University of Luxembourg <http://www.uni.lu/>. //
// ------------------------------------------------------------------------- //
// 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 3 of the License, or (at your //
// option) any later version. This program is distributed in the hope that //
// it will be useful, but WITHOUT ANY WARRANTY; without even the implied //
// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
// GNU General Public License for more details. You should have received a //
// copy of the GNU General Public License along with this program. If not, //
// see <http://www.gnu.org/licenses/>. //
///////////////////////////////////////////////////////////////////////////////
#ifndef SCHWAEMM_CFG_H
#define SCHWAEMM_CFG_H
// Define the SCHWAEMM instance here (api.h has to match!). The main instance
// is SCHWAEMM256_128, which has a block size of 256 bits and a key size of 128
// bits. Other instances of SCHWAEMM are SCHWAEMM128_128, SCHWAEMM192_192, and
// SCHWAEMM256_256.
#define SCHWAEMM128_128
// The identifier SPARKLE_ASSEMBLER determines whether the low-level functions
// in encrypt.c use the C implementation or an assembler implementation of the
// SPARKLE permutation. Currently, assembler code for SPARKLE exists for the
// AVR and ARM architecture.
#define SPARKLE_ASSEMBLER
///////////////////////////
#if defined SCHWAEMM128_128
///////////////////////////
#define SCHWAEMM_KEY_LEN 128
#define SCHWAEMM_NONCE_LEN 128
#define SCHWAEMM_TAG_LEN 128
#define SPARKLE_STATE 256
#define SPARKLE_RATE 128
#define SPARKLE_CAPACITY 128
#define SPARKLE_STEPS_SLIM 7
#define SPARKLE_STEPS_BIG 10
/////////////////////////////
#elif defined SCHWAEMM256_128
/////////////////////////////
#define SCHWAEMM_KEY_LEN 128
#define SCHWAEMM_NONCE_LEN 256
#define SCHWAEMM_TAG_LEN 128
#define SPARKLE_STATE 384
#define SPARKLE_RATE 256
#define SPARKLE_CAPACITY 128
#define SPARKLE_STEPS_SLIM 7
#define SPARKLE_STEPS_BIG 11
/////////////////////////////
#elif defined SCHWAEMM192_192
/////////////////////////////
#define SCHWAEMM_KEY_LEN 192
#define SCHWAEMM_NONCE_LEN 192
#define SCHWAEMM_TAG_LEN 192
#define SPARKLE_STATE 384
#define SPARKLE_RATE 192
#define SPARKLE_CAPACITY 192
#define SPARKLE_STEPS_SLIM 7
#define SPARKLE_STEPS_BIG 11
/////////////////////////////
#elif defined SCHWAEMM256_256
/////////////////////////////
#define SCHWAEMM_KEY_LEN 256
#define SCHWAEMM_NONCE_LEN 256
#define SCHWAEMM_TAG_LEN 256
#define SPARKLE_STATE 512
#define SPARKLE_RATE 256
#define SPARKLE_CAPACITY 256
#define SPARKLE_STEPS_SLIM 8
#define SPARKLE_STEPS_BIG 12
#else
#error "Invalid definition of SCHWAEMM instance!"
#endif
#endif // SCHWAEMM_CFG_H
///////////////////////////////////////////////////////////////////////////////
// sparkle_opt.c: Optimized C99 implementation of the SPARKLE permutation. //
// This file is part of the SPARKLE submission to NIST's LW Crypto Project. //
// Version 1.1.2 (2020-10-30), see <http://www.cryptolux.org/> for updates. //
// Authors: The SPARKLE Group (C. Beierle, A. Biryukov, L. Cardoso dos //
// Santos, J. Groszschaedl, L. Perrin, A. Udovenko, V. Velichkov, Q. Wang). //
// License: GPLv3 (see LICENSE file), other licenses available upon request. //
// Copyright (C) 2019-2020 University of Luxembourg <http://www.uni.lu/>. //
// ------------------------------------------------------------------------- //
// 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 3 of the License, or (at your //
// option) any later version. This program is distributed in the hope that //
// it will be useful, but WITHOUT ANY WARRANTY; without even the implied //
// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
// GNU General Public License for more details. You should have received a //
// copy of the GNU General Public License along with this program. If not, //
// see <http://www.gnu.org/licenses/>. //
///////////////////////////////////////////////////////////////////////////////
#include <stdio.h>
#include "sparkle_opt.h"
#define ROT(x, n) (((x) >> (n)) | ((x) << (32-(n))))
#define ELL(x) (ROT(((x) ^ ((x) << 16)), 16))
// Round constants
static const uint32_t RCON[MAX_BRANCHES] = { \
0xB7E15162, 0xBF715880, 0x38B4DA56, 0x324E7738, \
0xBB1185EB, 0x4F7C7B57, 0xCFBFA1C8, 0xC2B3293D \
};
void sparkle_opt(uint32_t *state, int brans, int steps)
{
int i, j; // Step and branch counter
uint32_t rc, tmpx, tmpy, x0, y0;
for(i = 0; i < steps; i ++) {
// Add round constant
state[1] ^= RCON[i%MAX_BRANCHES];
state[3] ^= i;
// ARXBOX layer
for(j = 0; j < 2*brans; j += 2) {
rc = RCON[j>>1];
state[j] += ROT(state[j+1], 31);
state[j+1] ^= ROT(state[j], 24);
state[j] ^= rc;
state[j] += ROT(state[j+1], 17);
state[j+1] ^= ROT(state[j], 17);
state[j] ^= rc;
state[j] += state[j+1];
state[j+1] ^= ROT(state[j], 31);
state[j] ^= rc;
state[j] += ROT(state[j+1], 24);
state[j+1] ^= ROT(state[j], 16);
state[j] ^= rc;
}
// Linear layer
tmpx = x0 = state[0];
tmpy = y0 = state[1];
for(j = 2; j < brans; j += 2) {
tmpx ^= state[j];
tmpy ^= state[j+1];
}
tmpx = ELL(tmpx);
tmpy = ELL(tmpy);
for (j = 2; j < brans; j += 2) {
state[j-2] = state[j+brans] ^ state[j] ^ tmpy;
state[j+brans] = state[j];
state[j-1] = state[j+brans+1] ^ state[j+1] ^ tmpx;
state[j+brans+1] = state[j+1];
}
state[brans-2] = state[brans] ^ x0 ^ tmpy;
state[brans] = x0;
state[brans-1] = state[brans+1] ^ y0 ^ tmpx;
state[brans+1] = y0;
}
}
void sparkle_inv_opt(uint32_t *state, int brans, int steps)
{
int i, j; // Step and branch counter
uint32_t rc, tmpx, tmpy, xb1, yb1;
for(i = steps-1; i >= 0; i --) {
// Linear layer
tmpx = tmpy = 0;
xb1 = state[brans-2];
yb1 = state[brans-1];
for (j = brans-2; j > 0; j -= 2) {
tmpx ^= (state[j] = state[j+brans]);
state[j+brans] = state[j-2];
tmpy ^= (state[j+1] = state[j+brans+1]);
state[j+brans+1] = state[j-1];
}
tmpx ^= (state[0] = state[brans]);
state[brans] = xb1;
tmpy ^= (state[1] = state[brans+1]);
state[brans+1] = yb1;
tmpx = ELL(tmpx);
tmpy = ELL(tmpy);
for(j = brans-2; j >= 0; j -= 2) {
state[j+brans] ^= (tmpy ^ state[j]);
state[j+brans+1] ^= (tmpx ^ state[j+1]);
}
// ARXBOX layer
for(j = 0; j < 2*brans; j += 2) {
rc = RCON[j>>1];
state[j] ^= rc;
state[j+1] ^= ROT(state[j], 16);
state[j] -= ROT(state[j+1], 24);
state[j] ^= rc;
state[j+1] ^= ROT(state[j], 31);
state[j] -= state[j+1];
state[j] ^= rc;
state[j+1] ^= ROT(state[j], 17);
state[j] -= ROT(state[j+1], 17);
state[j] ^= rc;
state[j+1] ^= ROT(state[j], 24);
state[j] -= ROT(state[j+1], 31);
}
// Add round constant
state[1] ^= RCON[i%MAX_BRANCHES];
state[3] ^= i;
}
}
void clear_state_opt(uint32_t *state, int brans)
{
int i;
for (i = 0; i < 2*brans; i ++)
state[i] = 0;
}
void print_state_opt(const uint32_t *state, int brans)
{
uint8_t *sbytes = (uint8_t *) state;
int i, j;
for (i = 0; i < brans; i ++) {
j = 8*i;
printf("(%02x%02x%02x%02x %02x%02x%02x%02x)", \
sbytes[j], sbytes[j+1], sbytes[j+2], sbytes[j+3], \
sbytes[j+4], sbytes[j+5], sbytes[j+6], sbytes[j+7]);
if (i < brans-1) printf(" ");
}
printf("\n");
}
void test_sparkle_opt(int brans, int steps)
{
uint32_t state[2*MAX_BRANCHES] = { 0 };
printf("input:\n");
print_state_opt(state, brans);
sparkle_opt(state, brans, steps);
printf("sparkle:\n");
print_state_opt(state, brans);
sparkle_inv_opt(state, brans, steps);
printf("sparkle inv:\n");
print_state_opt(state, brans);
printf("\n");
}
///////////////////////////////////////////////////////////////////////////////
// sparkle_opt.h: Optimized C99 implementation of the SPARKLE permutation. //
// This file is part of the SPARKLE submission to NIST's LW Crypto Project. //
// Version 1.1.2 (2020-10-30), see <http://www.cryptolux.org/> for updates. //
// Authors: The SPARKLE Group (C. Beierle, A. Biryukov, L. Cardoso dos //
// Santos, J. Groszschaedl, L. Perrin, A. Udovenko, V. Velichkov, Q. Wang). //
// License: GPLv3 (see LICENSE file), other licenses available upon request. //
// Copyright (C) 2019-2020 University of Luxembourg <http://www.uni.lu/>. //
// ------------------------------------------------------------------------- //
// 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 3 of the License, or (at your //
// option) any later version. This program is distributed in the hope that //
// it will be useful, but WITHOUT ANY WARRANTY; without even the implied //
// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
// GNU General Public License for more details. You should have received a //
// copy of the GNU General Public License along with this program. If not, //
// see <http://www.gnu.org/licenses/>. //
///////////////////////////////////////////////////////////////////////////////
#ifndef SPARKLE_OPT_H
#define SPARKLE_OPT_H
#if defined(_MSC_VER) && !defined(__clang__) && !defined(__ICL)
typedef unsigned __int8 uint8_t;
typedef unsigned __int32 uint32_t;
#else
#include <stdint.h>
#endif // _MSC_VER
#define MAX_BRANCHES 8
void sparkle_opt(uint32_t *state, int brans, int steps);
void sparkle_inv_opt(uint32_t *state, int brans, int steps);
void clear_state_opt(uint32_t *state, int brans);
void print_state_opt(const uint32_t *state, int brans);
void test_sparkle_opt(int brans, int steps);
#endif // SPARKLE_OPT_H
#define CRYPTO_KEYBYTES 16
#define CRYPTO_NSECBYTES 0
#define CRYPTO_NPUBBYTES 16
#define CRYPTO_ABYTES 16
#define CRYPTO_NOOVERLAP 1
// NIST-developed software is provided by NIST as a public service. You may
// use, copy and distribute copies of the software in any medium, provided that
// you keep intact this entire notice. You may improve, modify and create
// derivative works of the software or any portion of the software, and you may
// copy and distribute such modifications or works. Modified works should carry
// a notice stating that you changed the software and should note the date and
// nature of any such change. Please explicitly acknowledge the National
// Institute of Standards and Technology as the source of the software.
//
// NIST-developed software is expressly provided "AS IS." NIST MAKES NO
// WARRANTY OF ANY KIND, EXPRESS, IMPLIED, IN FACT OR ARISING BY OPERATION OF
// LAW, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTY OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE, NON-INFRINGEMENT AND DATA ACCURACY. NIST
// NEITHER REPRESENTS NOR WARRANTS THAT THE OPERATION OF THE SOFTWARE WILL BE
// UNINTERRUPTED OR ERROR-FREE, OR THAT ANY DEFECTS WILL BE CORRECTED. NIST
// DOES NOT WARRANT OR MAKE ANY REPRESENTATIONS REGARDING THE USE OF THE
// SOFTWARE OR THE RESULTS THEREOF, INCLUDING BUT NOT LIMITED TO THE
// CORRECTNESS, ACCURACY, RELIABILITY, OR USEFULNESS OF THE SOFTWARE.
//
// You are solely responsible for determining the appropriateness of using and
// distributing the software and you assume all risks associated with its use,
// including but not limited to the risks and costs of program errors,
// compliance with applicable laws, damage to or loss of data, programs or
// equipment, and the unavailability or interruption of operation. This
// software is not intended to be used in any situation where a failure could
// cause risk of injury or damage to property. The software developed by NIST
// employees is not subject to copyright protection within the United States.
// disable deprecation for sprintf and fopen
#ifdef _MSC_VER
#define _CRT_SECURE_NO_WARNINGS
#endif
#include <stdio.h>
#include <string.h>
#include "crypto_aead.h"
#include "api.h"
#define KAT_SUCCESS 0
#define KAT_FILE_OPEN_ERROR -1
#define KAT_DATA_ERROR -3
#define KAT_CRYPTO_FAILURE -4
#define MAX_FILE_NAME 256
#define MAX_MESSAGE_LENGTH 32
#define MAX_ASSOCIATED_DATA_LENGTH 32
typedef unsigned char UChar;
typedef unsigned long long int ULLInt;
void init_buffer(UChar *buffer, ULLInt numbytes);
void fprint_bstr(FILE *fp, const char *label, const UChar *data, \
ULLInt length);
int generate_test_vectors(void);
/*
int main(void)
{
int ret;
ret = generate_test_vectors();
if (ret != KAT_SUCCESS) {
fprintf(stderr, "test vector generation failed with code %d\n", ret);
}
return ret;
}
*/
int generate_test_vectors(void)
{
FILE *fp;
char fileName[MAX_FILE_NAME];
UChar key[CRYPTO_KEYBYTES];
UChar nonce[CRYPTO_NPUBBYTES];
UChar msg[MAX_MESSAGE_LENGTH];
UChar msg2[MAX_MESSAGE_LENGTH];
UChar ad[MAX_ASSOCIATED_DATA_LENGTH];
UChar ct[MAX_MESSAGE_LENGTH + CRYPTO_ABYTES];
ULLInt clen, mlen2;
ULLInt mlen, adlen;
int count = 1;
int func_ret, ret_val = KAT_SUCCESS;
init_buffer(key, sizeof(key));
init_buffer(nonce, sizeof(nonce));
init_buffer(msg, sizeof(msg));
init_buffer(ad, sizeof(ad));
sprintf(fileName, "LWC_AEAD_KAT_%d_%d.txt", (CRYPTO_KEYBYTES*8), \
(CRYPTO_NPUBBYTES*8));
if ((fp = fopen(fileName, "w")) == NULL) {
fprintf(stderr, "Couldn't open <%s> for write\n", fileName);
return KAT_FILE_OPEN_ERROR;
}
for (mlen = 0; (mlen<=MAX_MESSAGE_LENGTH)&&(ret_val==KAT_SUCCESS); mlen++) {
for(adlen = 0; adlen <= MAX_ASSOCIATED_DATA_LENGTH; adlen++) {
fprintf(fp, "Count = %d\n", count++);
fprint_bstr(fp, "Key = ", key, CRYPTO_KEYBYTES);
fprint_bstr(fp, "Nonce = ", nonce, CRYPTO_NPUBBYTES);
fprint_bstr(fp, "PT = ", msg, mlen);
fprint_bstr(fp, "AD = ", ad, adlen);
func_ret = crypto_aead_encrypt(ct, &clen, msg, mlen, ad, adlen, NULL, \
nonce, key);
if (func_ret != 0) {
fprintf(fp, "crypto_aead_encrypt returned <%d>\n", func_ret);
ret_val = KAT_CRYPTO_FAILURE;
break;
}
fprint_bstr(fp, "CT = ", ct, clen);
fprintf(fp, "\n");
func_ret = crypto_aead_decrypt(msg2, &mlen2, NULL, ct, clen, ad, adlen, \
nonce, key);
if (func_ret != 0) {
fprintf(fp, "crypto_aead_decrypt returned <%d>\n", func_ret);
ret_val = KAT_CRYPTO_FAILURE;