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;
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
///////////////////////////////////////////////////////////////////////////////
// sparkle256s_v7m.asm: Size-optimized ARMv7-M implementation of SPARKLE256. //
// 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/>. //
///////////////////////////////////////////////////////////////////////////////
.syntax unified
.thumb
.arch armv7-m
.eabi_attribute Tag_ABI_align_preserved, 1
.section .text
.balign 4
.global sparkle256_arm
///////////////////////////////////////////////////////////////////////////////
//////////////////////// REGISTER NAMES AND CONSTANTS /////////////////////////
///////////////////////////////////////////////////////////////////////////////
// register sptr holds the start address of array 'state'
sptr .req r0
// register cptr holds the start address of array 'rcon'
cptr .req lr
// register cnt holds the step counter (for loop termination)
cnt .req r12
// register step holds the number of steps (parameter 'steps')
step .req r1
// registers c0w to c3w hold round constants from array 'rcon'
c0w .req r2
c1w .req r3
c2w .req r2
c3w .req r3
// registers tmpx, tmpy hold temporary values
tmpx .req r2
tmpy .req r3
// registers x0w to y3w hold 8 words from array 'state'
x0w .req r4
y0w .req r5
x1w .req r6
y1w .req r7
x2w .req r8
y2w .req r9
x3w .req r10
y3w .req r11
///////////////////////////////////////////////////////////////////////////////
//////////////////////////// MACROS FOR SPARKLE256 ////////////////////////////
///////////////////////////////////////////////////////////////////////////////
.macro PROLOGUE_256
push {r4-r12,lr}
ldr.w cptr, =RCON
ldm sptr, {x0w-y3w}
.endm
.macro EPILOGUE_256
stm sptr, {x0w-y3w}
pop {r4-r12,pc}
.endm
.macro ADD_STEP_CNT_256
eor y1w, y1w, cnt
and c0w, cnt, #7
ldr c0w, [cptr, c0w, lsl #2]
eor y0w, y0w, c0w
.endm
.macro ARX_BOX xi:req, yi:req, ci:req
add \xi, \xi, \yi, ror #31
eor \yi, \yi, \xi, ror #24
eor \xi, \xi, \ci
add \xi, \xi, \yi, ror #17
eor \yi, \yi, \xi, ror #17
eors \xi, \xi, \ci
adds \xi, \xi, \yi
eor \yi, \yi, \xi, ror #31
eor \xi, \xi, \ci
add \xi, \xi, \yi, ror #24
eor \yi, \yi, \xi, ror #16
eor \xi, \xi, \ci
.endm
.macro LL_TMPX xi:req, xj:req
eor tmpx, \xi, \xj
eor tmpx, tmpx, tmpx, lsl #16
.endm
.macro LL_TMPY yi:req, yj:req
eor tmpy, \yi, \yj
eor tmpy, tmpy, tmpy, lsl #16
.endm
.macro ARXBOX_LAYER_256
// ARX-box computations for the two left-side branches (i.e. x[0]-y[1]).
ldmia cptr!, {c0w,c1w}
ARX_BOX x0w, y0w, c0w
ARX_BOX x1w, y1w, c1w
// ARX-box computations for the two right-side branches (i.e. x[2]-y[3]).
ldmia cptr!, {c2w,c3w}
ARX_BOX x2w, y2w, c2w
ARX_BOX x3w, y3w, c3w
sub cptr, cptr, #16
.endm
.macro LINEAR_LAYER_256
// First part of Feistel round: tmpx and tmpy are computed and XORED to the
// y-words and x-words of the right-side branches (i.e. to y[2], y[3] and
// to x[2], x[3]). Note that y[3] and x[3] are stored in register tmpx and
// tmpy (and not in register y3w and x3w) to reduce the execution time of
// the subsequent branch permutation.
LL_TMPX x0w, x1w
eor y2w, y2w, tmpx, ror #16
eor tmpx, y3w, tmpx, ror #16
LL_TMPY y0w, y1w
eor x2w, x2w, tmpy, ror #16
eor tmpy, x3w, tmpy, ror #16
// Branch permutation: 1-branch left-rotation of the right-side branches
// along with a swap of the left and right branches (via register writes).
// Also combined with the branch permutation is the second Feistel part,
// in which the left-side branches are XORed with the result of the first
// Feistel part.
mov.w y3w, y1w
eor y1w, y2w, y0w
mov.w y2w, y0w
eor y0w, tmpx, y3w
mov.w x3w, x1w
eor x1w, x2w, x0w
mov.w x2w, x0w
eor x0w, tmpy, x3w
.endm
///////////////////////////////////////////////////////////////////////////////
////////////////// SPARKLE256 PERMUTATION (BRANCH-UNROLLED) ///////////////////
///////////////////////////////////////////////////////////////////////////////
// Function prototype:
// -------------------
// void sparkle256_arm(uint32_t *state, int steps)
//
// Parameters:
// -----------
// state: pointer to an uint32_t-array containing the 8 state words
// steps: number of steps
//
// Return value:
// -------------
// None
.type sparkle256_arm, %function
.func sparkle256_arm
sparkle256_arm:
PROLOGUE_256 // push callee-saved registers and load state
mov cnt, #0 // initialize step-counter
.Lloop_256: // start of loop
ADD_STEP_CNT_256 // macro to add step-counter to state
ARXBOX_LAYER_256 // macro for the ARXBOX layer
LINEAR_LAYER_256 // macro for the linear layer
add cnt, #1 // increment step-counter
teq cnt, step // test whether step-counter equals 'steps'
bne .Lloop_256 // if not then branch to start of loop
EPILOGUE_256 // store state and pop callee-saved registers
.endfunc
.size sparkle256_arm, .-sparkle256_arm
///////////////////////////////////////////////////////////////////////////////
/////////////////////////// SPARKLE ROUND CONSTANTS ///////////////////////////
///////////////////////////////////////////////////////////////////////////////
// This implementation places the round constants in the .data segment, which
// means they are loaded from RAM during the computation of the ARX-boxes. It
// would also be possible to place them in the .rodata segment (by replacing
// the ".section .data" directive below by ".section .rodata") so that they are
// loaded from flash, which reduces the RAM consumption by 32 bytes, but may
// increase the execution time on devices with a high number of flash wait
// states.
.section .data
.balign 4
.type RCON, %object
.size RCON, 32
RCON:
.word 0xB7E15162, 0xBF715880, 0x38B4DA56, 0x324E7738
.word 0xBB1185EB, 0x4F7C7B57, 0xCFBFA1C8, 0xC2B3293D
.end
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; sparkle256s_v7m.asm: Size-optimized ARMv7-M implementation of SPARKLE256. ;;
;; 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/>. ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
THUMB
PRESERVE8
AREA sparkle_code, CODE, READONLY, ALIGN=2
EXPORT sparkle256_arm [CODE]
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;; REGISTER NAMES AND CONSTANTS ;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; register sptr holds the start address of array 'state'
sptr RN r0
;; register cptr holds the start address of array 'rcon'
cptr RN lr
;; register cnt holds the step counter (for loop termination)
cnt RN r12
;; register step holds the number of steps (parameter 'steps')
step RN r1
;; registers c0w to c3w hold round constants from array 'rcon'
c0w RN r2
c1w RN r3
c2w RN r2
c3w RN r3
;; registers tmpx, tmpy hold temporary values
tmpx RN r2
tmpy RN r3
;; registers x0w to y3w hold 8 words from array 'state'
x0w RN r4
y0w RN r5
x1w RN r6
y1w RN r7
x2w RN r8
y2w RN r9
x3w RN r10
y3w RN r11
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;; MACROS FOR SPARKLE256 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
MACRO
PROLOGUE_256
push {r4-r12,lr}
ldr.w cptr, =RCON
ldm sptr, {x0w-y3w}
MEND
MACRO
EPILOGUE_256
stm sptr, {x0w-y3w}
pop {r4-r12,pc}
MEND
MACRO
ADD_STEP_CNT_256
eor y1w, y1w, cnt
and c0w, cnt, #7
ldr c0w, [cptr, c0w, lsl #2]
eor y0w, y0w, c0w
MEND
MACRO
ARX_BOX $xi, $yi, $ci
add $xi, $xi, $yi, ror #31
eor $yi, $yi, $xi, ror #24
eor $xi, $xi, $ci
add $xi, $xi, $yi, ror #17
eor $yi, $yi, $xi, ror #17
eors $xi, $xi, $ci
adds $xi, $xi, $yi
eor $yi, $yi, $xi, ror #31
eor $xi, $xi, $ci
add $xi, $xi, $yi, ror #24
eor $yi, $yi, $xi, ror #16
eor $xi, $xi, $ci
MEND
MACRO
LL_TMPX $xi, $xj
eor tmpx, $xi, $xj
eor tmpx, tmpx, tmpx, lsl #16
MEND
MACRO
LL_TMPY $yi, $yj
eor tmpy, $yi, $yj
eor tmpy, tmpy, tmpy, lsl #16
MEND
MACRO
ARXBOX_LAYER_256
;; ARX-box computations for the two left-side branches (i.e. x[0]-y[1]).
ldmia cptr!, {c0w,c1w}
ARX_BOX x0w, y0w, c0w
ARX_BOX x1w, y1w, c1w
;; ARX-box computations for the two right-side branches (i.e. x[2]-y[3]).
ldmia cptr!, {c2w,c3w}
ARX_BOX x2w, y2w, c2w
ARX_BOX x3w, y3w, c3w
sub cptr, cptr, #16
MEND
MACRO
LINEAR_LAYER_256
;; First part of Feistel round: tmpx and tmpy are computed and XORED to the
;; y-words and x-words of the right-side branches (i.e. to y[2], y[3] and
;; to x[2], x[3]). Note that y[3] and x[3] are stored in register tmpx and
;; tmpy (and not in register y3w and x3w) to reduce the execution time of
;; the subsequent branch permutation.
LL_TMPX x0w, x1w
eor y2w, y2w, tmpx, ror #16
eor tmpx, y3w, tmpx, ror #16
LL_TMPY y0w, y1w
eor x2w, x2w, tmpy, ror #16
eor tmpy, x3w, tmpy, ror #16
;; Branch permutation: 1-branch left-rotation of the right-side branches
;; along with a swap of the left and right branches (via register writes).
;; Also combined with the branch permutation is the second Feistel part,
;; in which the left-side branches are XORed with the result of the first
;; Feistel part.
mov.w y3w, y1w
eor y1w, y2w, y0w
mov.w y2w, y0w
eor y0w, tmpx, y3w
mov.w x3w, x1w
eor x1w, x2w, x0w
mov.w x2w, x0w
eor x0w, tmpy, x3w
MEND
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;; SPARKLE256 PERMUTATION (BRANCH-UNROLLED) ;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Function prototype:
;; -------------------
;; void sparkle256_arm(uint32_t *state, int steps)
;;
;; Parameters:
;; -----------
;; state: pointer to an uint32_t-array containing the 8 state words
;; steps: number of steps
;;
;; Return value:
;; -------------
;; None
sparkle256_arm PROC
PROLOGUE_256 ;; push callee-saved registers and load state
mov cnt, #0 ;; initialize step-counter
loop_256 ;; start of loop
ADD_STEP_CNT_256 ;; macro to add step-counter to state
ARXBOX_LAYER_256 ;; macro for the ARXBOX layer
LINEAR_LAYER_256 ;; macro for the linear layer
add cnt, #1 ;; increment step-counter
teq cnt, step ;; test whether step-counter equals 'steps'
bne loop_256 ;; if not then branch to start of loop
EPILOGUE_256 ;; store state and pop callee-saved registers
ENDP
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;; SPARKLE ROUND CONSTANTS ;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; This implementation places the round constants in the .data segment, which
;; means they are loaded from RAM during the computation of the ARX-boxes. It
;; would also be possible to place them in the .rodata segment (by replacing
;; the "READWRITE" attribute in the AREA directive below by "READONLY") so that
;; they are loaded from flash, which reduces the RAM consumption by 32 bytes,
;; but may increase the execution time on devices with a high number of flash
;; wait states.
AREA sparkle_rcon, DATA, READWRITE, ALIGN=2
;; round constants
RCON DCD 0xB7E15162, 0xBF715880, 0x38B4DA56, 0x324E7738, \
0xBB1185EB, 0x4F7C7B57, 0xCFBFA1C8, 0xC2B3293D
END
///////////////////////////////////////////////////////////////////////////////
// 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;
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;
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
///////////////////////////
#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;
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
///////////////////////////
#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_ref.c: Reference 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 <assert.h>
#include <stdio.h>
#include "sparkle_ref.h"
#define ROT(x, n) (((x) >> (n)) | ((x) << (32-(n))))
#define ELL(x) (ROT(((x) ^ ((x) << 16)), 16))
// 4-round ARX-box
#define ARXBOX(x, y, c) \
(x) += ROT((y), 31), (y) ^= ROT((x), 24), \
(x) ^= (c), \
(x) += ROT((y), 17), (y) ^= ROT((x), 17), \
(x) ^= (c), \
(x) += (y), (y) ^= ROT((x), 31), \
(x) ^= (c), \
(x) += ROT((y), 24), (y) ^= ROT((x), 16), \
(x) ^= (c)
// Inverse of 4-round ARX-box
#define ARXBOX_INV(x, y, c) \
(x) ^= (c), \
(y) ^= ROT((x), 16), (x) -= ROT((y), 24), \
(x) ^= (c), \
(y) ^= ROT((x), 31), (x) -= (y), \
(x) ^= (c), \
(y) ^= ROT((x), 17), (x) -= ROT((y), 17), \
(x) ^= (c), \
(y) ^= ROT((x), 24), (x) -= ROT((y), 31)
// Round constants
static const uint32_t RCON[MAX_BRANCHES] = { \
0xB7E15162, 0xBF715880, 0x38B4DA56, 0x324E7738, \
0xBB1185EB, 0x4F7C7B57, 0xCFBFA1C8, 0xC2B3293D \
};
void linear_layer(SparkleState *state, int brans)
{
int i, b = brans/2;
uint32_t *x = state->x, *y = state->y;
uint32_t tmp;
// Feistel function (adding to y part)
tmp = 0;
for(i = 0; i < b; i++)
tmp ^= x[i];
tmp = ELL(tmp);
for(i = 0; i < b; i ++)
y[i+b] ^= (tmp ^ y[i]);
// Feistel function (adding to x part)
tmp = 0;
for(i = 0; i < b; i++)
tmp ^= y[i];
tmp = ELL(tmp);
for(i = 0; i < b; i ++)
x[i+b] ^= (tmp ^ x[i]);
// Branch swap with 1-branch left-rotation of right side
// <------- left side --------> <------- right side ------->
// 0 1 2 ... B-2 B-1 B B+1 B+2 ... 2B-2 2B-1
// B+1 B+2 B+3 ... 2B-1 B 0 1 2 ... B-2 B-1
// Branch swap of the x part
tmp = x[0];
for (i = 0; i < b - 1; i++) {
x[i] = x[i+b+1];
x[i+b+1] = x[i+1];
}
x[b-1] = x[b];
x[b] = tmp;
// Branch swap of the y part
tmp = y[0];
for (i = 0; i < b - 1; i++) {
y[i] = y[i+b+1];
y[i+b+1] = y[i+1];
}
y[b-1] = y[b];
y[b] = tmp;
}
void sparkle_ref(SparkleState *state, int brans, int steps)
{
int i, j; // Step and branch counter
// The number of branches must be even and not bigger than MAX_BRANCHES.
assert(((brans & 1) == 0) && (brans >= 4) && (brans <= MAX_BRANCHES));
for(i = 0; i < steps; i++) {
// Add step counter
state->y[0] ^= RCON[i%MAX_BRANCHES];
state->y[1] ^= i;
// ARXBox layer
for(j = 0; j < brans; j ++)
ARXBOX(state->x[j], state->y[j], RCON[j]);
// Linear layer
linear_layer(state, brans);
}
}
void linear_layer_inv(SparkleState *state, int brans)
{
int i, b = brans/2;
uint32_t *x = state->x, *y = state->y;
uint32_t tmp;
// Branch swap with 1-branch right-rotation of left side
// <------- left side --------> <------- right side ------->
// 0 1 2 ... B-2 B-1 B B+1 B+2 ... 2B-2 2B-1
// B B+1 B+2 ... 2B-2 2B-1 B-1 0 1 ... B-3 B-2
// Branch swap of the x part
tmp = x[b-1];
for (i = b - 1; i > 0; i--) {
x[i] = x[i+b];
x[i+b] = x[i-1];
}
x[0] = x[b];
x[b] = tmp;
// Branch swap of the y part
tmp = y[b-1];
for (i = b - 1; i > 0; i--) {
y[i] = y[i+b];
y[i+b] = y[i-1];
}
y[0] = y[b];
y[b] = tmp;
// Feistel function (adding to x part)
tmp = 0;
for(i = 0; i < b; i ++)
tmp ^= y[i];
tmp = ELL(tmp);
for(i = 0; i < b; i ++)
x[i+b] ^= (tmp ^ x[i]);
// Feistel function (adding to y part)
tmp = 0;
for(i = 0; i < b; i ++)
tmp ^= x[i];
tmp = ELL(tmp);
for(i = 0; i < b; i ++)
y[i+b] ^= (tmp ^ y[i]);
}
void sparkle_inv_ref(SparkleState *state, int brans, int steps)
{
int i, j; // Step and branch counter
// The number of branches must be even and not bigger than MAX_BRANCHES.
assert(((brans & 1) == 0) && (brans >= 4) && (brans <= MAX_BRANCHES));
for(i = steps - 1; i >= 0; i--) {
// Linear layer
linear_layer_inv(state, brans);
// ARXbox layer
for(j = 0; j < brans; j ++)
ARXBOX_INV(state->x[j], state->y[j], RCON[j]);
// Add step counter
state->y[1] ^= i;
state->y[0] ^= RCON[i%MAX_BRANCHES];
}
}
void clear_state_ref(SparkleState *state, int brans)
{
int i;
for (i = 0; i < brans; i ++) {
state->x[i] = state->y[i] = 0;
}
}
void print_state_ref(const SparkleState *state, int brans)
{
uint8_t *xbytes = (uint8_t *) state->x;
uint8_t *ybytes = (uint8_t *) state->y;
int i, j;
for (i = 0; i < brans; i ++) {
j = 4*i;
printf("(%02x%02x%02x%02x %02x%02x%02x%02x)", \
xbytes[j], xbytes[j+1], xbytes[j+2], xbytes[j+3], \
ybytes[j], ybytes[j+1], ybytes[j+2], ybytes[j+3]);
if (i < brans-1) printf(" ");
}
printf("\n");
}
void test_sparkle_ref(int brans, int steps)
{
SparkleState state = {{0}, {0}};
printf("input:\n");
print_state_ref(&state, brans);
sparkle_ref(&state, brans, steps);
printf("sparkle:\n");
print_state_ref(&state, brans);
sparkle_inv_ref(&state, brans, steps);
printf("sparkle inv:\n");
print_state_ref(&state, brans);
printf("\n");
}
///////////////////////////////////////////////////////////////////////////////
// sparkle_ref.h: Reference 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_REF_H
#define SPARKLE_REF_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
typedef struct {
uint32_t x[MAX_BRANCHES];
uint32_t y[MAX_BRANCHES];
} SparkleState;
void sparkle_ref(SparkleState *state, int brans, int steps);
void sparkle_inv_ref(SparkleState *state, int brans, int steps);
void clear_state_ref(SparkleState *state, int brans);
void print_state_ref(const SparkleState *state, int brans);
void test_sparkle_ref(int brans, int steps);
#endif // SPARKLE_REF_H
This source diff could not be displayed because it is too large. You can view the blob instead.
#define CRYPTO_KEYBYTES 24
#define CRYPTO_NSECBYTES 0
#define CRYPTO_NPUBBYTES 24
#define CRYPTO_ABYTES 24
#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 SCHWAEMM192_192
// 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 24
#define CRYPTO_NSECBYTES 0
#define CRYPTO_NPUBBYTES 24
#define CRYPTO_ABYTES 24
#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 SCHWAEMM192_192
// 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
///////////////////////////////////////////////////////////////////////////////
// sparkle384s_v7m.asm: Size-optimized ARMv7-M implementation of SPARKLE384. //
// 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/>. //
///////////////////////////////////////////////////////////////////////////////
.syntax unified
.thumb
.arch armv7-m
.eabi_attribute Tag_ABI_align_preserved, 1
.section .text
.balign 4
.global sparkle384_arm
///////////////////////////////////////////////////////////////////////////////
//////////////////////// REGISTER NAMES AND CONSTANTS /////////////////////////
///////////////////////////////////////////////////////////////////////////////
// register sptr holds the start address of array 'state'
sptr .req r0
// register cptr holds the start address of array 'rcon'
cptr .req r1
// register cnt holds the step counter (for loop termination)
cnt .req r0
// register step holds the number of steps (parameter 'steps')
step .req r1
// registers c0w to c5w hold round constants from array 'rcon'
c0w .req r0
c1w .req r0
c2w .req r0
c3w .req r0
c4w .req r0
c5w .req r1
// registers tmpx, tmpy hold temporary values
tmpx .req r0
tmpy .req r1
// registers x0w to y5w hold 12 words from array 'state'
x0w .req r2
y0w .req r3
x1w .req r4
y1w .req r5
x2w .req r6
y2w .req r7
x3w .req r8
y3w .req r9
x4w .req r10
y4w .req r11
x5w .req r12
y5w .req lr
///////////////////////////////////////////////////////////////////////////////
//////////////////////////// MACROS FOR SPARKLE384 ////////////////////////////
///////////////////////////////////////////////////////////////////////////////
.macro PROLOGUE_384
push {r4-r12,lr}
ldm sptr, {x0w-x5w,y5w}
push {sptr,step}
.endm
.macro EPILOGUE_384
pop.w {sptr,step}
stm sptr, {x0w-x5w,y5w}
pop {r4-r12,pc}
.endm
.macro ADD_STEP_CNT_384
ldr.w cptr, =RCON
eor y1w, y1w, cnt
and c0w, cnt, #7
ldr c0w, [cptr, c0w, lsl #2]
eor y0w, y0w, c0w
.endm
.macro ARX_BOX xi:req, yi:req, ci:req
add \xi, \xi, \yi, ror #31
eor \yi, \yi, \xi, ror #24
eor \xi, \xi, \ci
add \xi, \xi, \yi, ror #17
eor \yi, \yi, \xi, ror #17
eors \xi, \xi, \ci
adds \xi, \xi, \yi
eor \yi, \yi, \xi, ror #31
eor \xi, \xi, \ci
add \xi, \xi, \yi, ror #24
eor \yi, \yi, \xi, ror #16
eor \xi, \xi, \ci
.endm
.macro LL_TMPX xi:req, xj:req, xk:req
eor tmpx, \xi, \xj
eor tmpx, tmpx, \xk
eor tmpx, tmpx, tmpx, lsl #16
.endm
.macro LL_TMPY yi:req, yj:req, yk:req
eor tmpy, \yi, \yj
eor tmpy, tmpy, \yk
eor tmpy, tmpy, tmpy, lsl #16
.endm
.macro ARXBOX_LAYER_384
// ARX-box computations for the three left-side branches (i.e. x[0]-y[2]).
ldr c0w, [cptr], #4
ARX_BOX x0w, y0w, c0w
ldr c1w, [cptr], #4
ARX_BOX x1w, y1w, c1w
ldr c2w, [cptr], #4
ARX_BOX x2w, y2w, c2w
// ARX-box computations for the three right-side branches (i.e. x[3]-y[5]).
ldr c3w, [cptr], #4
ARX_BOX x3w, y3w, c3w
ldm.w cptr, {c4w,c5w}
ARX_BOX x4w, y4w, c4w
ARX_BOX x5w, y5w, c5w
.endm
.macro LINEAR_LAYER_384
// First part of Feistel round: tmpx and tmpy are computed and XORED to the
// y-words and x-words of the right-side branches (i.e. to y[3], y[4], y[5]
// and to x[3], x[4], x[5]). Note that y[5] and x[5] are stored in register
// tmpx and tmpy (and not in register y5w and x5w) to reduce the execution
// time of the subsequent branch permutation.
LL_TMPX x0w, x1w, x2w
eor y3w, y3w, tmpx, ror #16
eor y4w, y4w, tmpx, ror #16
eor tmpx, y5w, tmpx, ror #16
LL_TMPY y0w, y1w, y2w
eor x3w, x3w, tmpy, ror #16
eor x4w, x4w, tmpy, ror #16
eor tmpy, x5w, tmpy, ror #16
// Branch permutation: 1-branch left-rotation of the right-side branches
// along with a swap of the left and right branches (via register writes).
// Also combined with the branch permutation is the second Feistel part,
// in which the left-side branches are XORed with the result of the first
// Feistel part.
mov.w y5w, y2w
eor y2w, y3w, y0w
mov.w y3w, y0w
eor y0w, y4w, y1w
mov.w y4w, y1w
eor y1w, tmpx, y5w
mov.w x5w, x2w
eor x2w, x3w, x0w
mov.w x3w, x0w
eor x0w, x4w, x1w
mov.w x4w, x1w
eor x1w, tmpy, x5w
.endm
///////////////////////////////////////////////////////////////////////////////
////////////////// SPARKLE384 PERMUTATION (BRANCH-UNROLLED) ///////////////////
///////////////////////////////////////////////////////////////////////////////
// Function prototype:
// -------------------
// void sparkle384_arm(uint32_t *state, int steps)
//
// Parameters:
// -----------
// state: pointer to an uint32_t-array containing the 12 state words
// steps: number of steps
//
// Return value:
// -------------
// None
.type sparkle384_arm, %function
.func sparkle384_arm
sparkle384_arm:
PROLOGUE_384 // push callee-saved registers and load state
movs cnt, #0 // initialize step-counter
.Lloop_384: // start of loop
push.w {cnt,step} // push step-counter and 'steps' to free registers
ADD_STEP_CNT_384 // macro to add step-counter to state
ARXBOX_LAYER_384 // macro for the ARXBOX layer
LINEAR_LAYER_384 // macro for the linear layer
pop {cnt,step} // restore step-counter and 'steps' from stack
adds cnt, #1 // increment step-counter
teq cnt, step // test whether step-counter equals 'steps'
bne .Lloop_384 // if not then branch to start of loop
EPILOGUE_384 // store state and pop callee-saved registers
.endfunc
.size sparkle384_arm, .-sparkle384_arm
///////////////////////////////////////////////////////////////////////////////
/////////////////////////// SPARKLE ROUND CONSTANTS ///////////////////////////
///////////////////////////////////////////////////////////////////////////////
// This implementation places the round constants in the .data segment, which
// means they are loaded from RAM during the computation of the ARX-boxes. It
// would also be possible to place them in the .rodata segment (by replacing
// the ".section .data" directive below by ".section .rodata") so that they are
// loaded from flash, which reduces the RAM consumption by 32 bytes, but may
// increase the execution time on devices with a high number of flash wait
// states.
.section .data
.balign 4
.type RCON, %object
.size RCON, 32
RCON:
.word 0xB7E15162, 0xBF715880, 0x38B4DA56, 0x324E7738
.word 0xBB1185EB, 0x4F7C7B57, 0xCFBFA1C8, 0xC2B3293D
.end
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; sparkle384s_v7m.asm: Size-optimized ARMv7-M implementation of SPARKLE384. ;;
;; 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/>. ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
THUMB
PRESERVE8
AREA sparkle_code, CODE, READONLY, ALIGN=2
EXPORT sparkle384_arm [CODE]
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;; REGISTER NAMES AND CONSTANTS ;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; register sptr holds the start address of array 'state'
sptr RN r0
;; register cptr holds the start address of array 'rcon'
cptr RN r1
;; register cnt holds the step counter (for loop termination)
cnt RN r0
;; register step holds the number of steps (parameter 'steps')
step RN r1
;; registers c0w to c5w hold round constants from array 'rcon'
c0w RN r0
c1w RN r0
c2w RN r0
c3w RN r0
c4w RN r0
c5w RN r1
;; registers tmpx, tmpy hold temporary values
tmpx RN r0
tmpy RN r1
;; registers x0w to y5w hold 12 words from array 'state'
x0w RN r2
y0w RN r3
x1w RN r4
y1w RN r5
x2w RN r6
y2w RN r7
x3w RN r8
y3w RN r9
x4w RN r10
y4w RN r11
x5w RN r12
y5w RN lr
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;; MACROS FOR SPARKLE384 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
MACRO
PROLOGUE_384
push {r4-r12,lr}
ldm sptr, {x0w-x5w,y5w}
push {sptr,step}
MEND
MACRO
EPILOGUE_384
pop.w {sptr,step}
stm sptr, {x0w-x5w,y5w}
pop {r4-r12,pc}
MEND
MACRO
ADD_STEP_CNT_384
ldr.w cptr, =RCON
eor y1w, y1w, cnt
and c0w, cnt, #7
ldr c0w, [cptr, c0w, lsl #2]
eor y0w, y0w, c0w
MEND
MACRO
ARX_BOX $xi, $yi, $ci
add $xi, $xi, $yi, ror #31
eor $yi, $yi, $xi, ror #24
eor $xi, $xi, $ci
add $xi, $xi, $yi, ror #17
eor $yi, $yi, $xi, ror #17
eors $xi, $xi, $ci
adds $xi, $xi, $yi
eor $yi, $yi, $xi, ror #31
eor $xi, $xi, $ci
add $xi, $xi, $yi, ror #24
eor $yi, $yi, $xi, ror #16
eor $xi, $xi, $ci
MEND
MACRO
LL_TMPX $xi, $xj, $xk
eor tmpx, $xi, $xj
eor tmpx, tmpx, $xk
eor tmpx, tmpx, tmpx, lsl #16
MEND
MACRO
LL_TMPY $yi, $yj, $yk
eor tmpy, $yi, $yj
eor tmpy, tmpy, $yk
eor tmpy, tmpy, tmpy, lsl #16
MEND
MACRO
ARXBOX_LAYER_384
;; ARX-box computations for the three left-side branches (i.e. x[0]-y[2]).
ldr c0w, [cptr], #4
ARX_BOX x0w, y0w, c0w
ldr c1w, [cptr], #4
ARX_BOX x1w, y1w, c1w
ldr c2w, [cptr], #4
ARX_BOX x2w, y2w, c2w
;; ARX-box computations for the three right-side branches (i.e. x[3]-y[5]).
ldr c3w, [cptr], #4
ARX_BOX x3w, y3w, c3w
ldm.w cptr, {c4w,c5w}
ARX_BOX x4w, y4w, c4w
ARX_BOX x5w, y5w, c5w
MEND
MACRO
LINEAR_LAYER_384
;; First part of Feistel round: tmpx and tmpy are computed and XORED to the
;; y-words and x-words of the right-side branches (i.e. to y[3], y[4], y[5]
;; and to x[3], x[4], x[5]). Note that y[5] and x[5] are stored in register
;; tmpx and tmpy (and not in register y5w and x5w) to reduce the execution
;; time of the subsequent branch permutation.
LL_TMPX x0w, x1w, x2w
eor y3w, y3w, tmpx, ror #16
eor y4w, y4w, tmpx, ror #16
eor tmpx, y5w, tmpx, ror #16
LL_TMPY y0w, y1w, y2w
eor x3w, x3w, tmpy, ror #16
eor x4w, x4w, tmpy, ror #16
eor tmpy, x5w, tmpy, ror #16
;; Branch permutation: 1-branch left-rotation of the right-side branches
;; along with a swap of the left and right branches (via register writes).
;; Also combined with the branch permutation is the second Feistel part,
;; in which the left-side branches are XORed with the result of the first
;; Feistel part.
mov.w y5w, y2w
eor y2w, y3w, y0w
mov.w y3w, y0w
eor y0w, y4w, y1w
mov.w y4w, y1w
eor y1w, tmpx, y5w
mov.w x5w, x2w
eor x2w, x3w, x0w
mov.w x3w, x0w
eor x0w, x4w, x1w
mov.w x4w, x1w
eor x1w, tmpy, x5w
MEND
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;; SPARKLE384 PERMUTATION (BRANCH-UNROLLED) ;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Function prototype:
;; -------------------
;; void sparkle384_arm(uint32_t *state, int steps)
;;
;; Parameters:
;; -----------
;; state: pointer to an uint32_t-array containing the 12 state words
;; steps: number of steps
;;
;; Return value:
;; -------------
;; None
sparkle384_arm PROC
PROLOGUE_384 ;; push callee-saved registers and load state
movs cnt, #0 ;; initialize step-counter
loop_384 ;; start of loop
push.w {cnt,step} ;; push step-counter and 'steps' to free registers
ADD_STEP_CNT_384 ;; macro to add step-counter to state
ARXBOX_LAYER_384 ;; macro for the ARXBOX layer
LINEAR_LAYER_384 ;; macro for the linear layer
pop {cnt,step} ;; restore step-counter and 'steps' from stack
adds cnt, #1 ;; increment step-counter
teq cnt, step ;; test whether step-counter equals 'steps'
bne loop_384 ;; if not then branch to start of loop
EPILOGUE_384 ;; store state and pop callee-saved registers
ENDP
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;; SPARKLE ROUND CONSTANTS ;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; This implementation places the round constants in the .data segment, which
;; means they are loaded from RAM during the computation of the ARX-boxes. It
;; would also be possible to place them in the .rodata segment (by replacing
;; the "READWRITE" attribute in the AREA directive below by "READONLY") so that
;; they are loaded from flash, which reduces the RAM consumption by 32 bytes,
;; but may increase the execution time on devices with a high number of flash
;; wait states.
AREA sparkle_rcon, DATA, READWRITE, ALIGN=2
;; round constants
RCON DCD 0xB7E15162, 0xBF715880, 0x38B4DA56, 0x324E7738, \
0xBB1185EB, 0x4F7C7B57, 0xCFBFA1C8, 0xC2B3293D
END
///////////////////////////////////////////////////////////////////////////////
// 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 24
#define CRYPTO_NSECBYTES 0
#define CRYPTO_NPUBBYTES 24
#define CRYPTO_ABYTES 24
#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 SCHWAEMM192_192
// 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 24
#define CRYPTO_NSECBYTES 0
#define CRYPTO_NPUBBYTES 24
#define CRYPTO_ABYTES 24
#define CRYPTO_NOOVERLAP 1
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment