Commit dba8d5c7 by Alexandre Adomnicai Committed by Enrico Pozzobon

romulus armsrc

parent e3e8b784
#define CRYPTO_KEYBYTES 16
#define CRYPTO_NSECBYTES 0
#define CRYPTO_NPUBBYTES 16
#define CRYPTO_ABYTES 16
#define CRYPTO_NOOVERLAP 1
int crypto_aead_encrypt(unsigned char *c, unsigned long long *clen,
const unsigned char *m, unsigned long long mlen,
const unsigned char *ad, unsigned long long adlen,
const unsigned char *nsec, const unsigned char *npub,
const unsigned char *k);
int crypto_aead_decrypt(unsigned char *m, unsigned long long *outputmlen,
unsigned char *nsec,
const unsigned char *c, unsigned long long clen,
const unsigned char *ad, unsigned long long adlen,
const unsigned char *npub, const unsigned char *k);
/*
* Date: 29 November 2018
* Contact: Thomas Peyrin - thomas.peyrin@gmail.com
* Mustafa Khairallah - mustafam001@e.ntu.edu.sg
*/
#include "crypto_aead.h"
#include "api.h"
#include "skinny.h"
#include <stdio.h>
#include <stdlib.h>
void pad (const unsigned char* m, unsigned char* mp, int l, int len8) {
int i;
for (i = 0; i < l; i++) {
if (i < len8) {
mp[i] = m[i];
}
else if (i == l - 1) {
mp[i] = (len8 & 0x0f);
}
else {
mp[i] = 0x00;
}
}
}
void g8A (unsigned char* s, unsigned char* c) {
unsigned int tmps[4];
unsigned int tmpc[4];
tmps[0] = *((unsigned int *)&s[0]);
tmps[1] = *((unsigned int *)&s[4]);
tmps[2] = *((unsigned int *)&s[8]);
tmps[3] = *((unsigned int *)&s[12]);
// c[i] = (s[i] >> 1) ^ (s[i] & 0x80) ^ ((s[i] & 0x01) << 7);
//
// (s[i] >> 1) -> ((s[i]>>1)&0x7f)
// (s[i] & 0x80) -> (s[i])&0x80) not changed
// ((s[i] & 0x01) << 7) -> ((s[i]<<7)&0x80)
// use word access because of speeding up
tmpc[0] = ((tmps[0]>>1) & 0x7f7f7f7f) ^ (tmps[0] & 0x80808080) ^ ((tmps[0]<<7) & 0x80808080);
tmpc[1] = ((tmps[1]>>1) & 0x7f7f7f7f) ^ (tmps[1] & 0x80808080) ^ ((tmps[1]<<7) & 0x80808080);
tmpc[2] = ((tmps[2]>>1) & 0x7f7f7f7f) ^ (tmps[2] & 0x80808080) ^ ((tmps[2]<<7) & 0x80808080);
tmpc[3] = ((tmps[3]>>1) & 0x7f7f7f7f) ^ (tmps[3] & 0x80808080) ^ ((tmps[3]<<7) & 0x80808080);
*((unsigned int *)&c[0]) = tmpc[0];
*((unsigned int *)&c[4]) = tmpc[1];
*((unsigned int *)&c[8]) = tmpc[2];
*((unsigned int *)&c[12]) = tmpc[3];
}
void g8A_for_Tag_Generation (unsigned char* s, unsigned char* c) {
unsigned int tmps[4];
unsigned int tmpc[4];
tmps[0] = *((unsigned int *)&s[0]);
tmps[1] = *((unsigned int *)&s[4]);
tmps[2] = *((unsigned int *)&s[8]);
tmps[3] = *((unsigned int *)&s[12]);
// c[i] = (s[i] >> 1) ^ (s[i] & 0x80) ^ ((s[i] & 0x01) << 7);
//
// (s[i] >> 1) -> ((s[i]>>1)&0x7f)
// (s[i] & 0x80) -> (s[i])&0x80) not changed
// ((s[i] & 0x01) << 7) -> ((s[i]<<7)&0x80)
// use word access because of speeding up
tmpc[0] = ((tmps[0]>>1) & 0x7f7f7f7f) ^ (tmps[0] & 0x80808080) ^ ((tmps[0]<<7) & 0x80808080);
tmpc[1] = ((tmps[1]>>1) & 0x7f7f7f7f) ^ (tmps[1] & 0x80808080) ^ ((tmps[1]<<7) & 0x80808080);
tmpc[2] = ((tmps[2]>>1) & 0x7f7f7f7f) ^ (tmps[2] & 0x80808080) ^ ((tmps[2]<<7) & 0x80808080);
tmpc[3] = ((tmps[3]>>1) & 0x7f7f7f7f) ^ (tmps[3] & 0x80808080) ^ ((tmps[3]<<7) & 0x80808080);
// use byte access because of memory alignment.
// c is not always in word(4 byte) alignment.
c[0] = tmpc[0] &0xFF;
c[1] = (tmpc[0]>>8) &0xFF;
c[2] = (tmpc[0]>>16)&0xFF;
c[3] = (tmpc[0]>>24)&0xFF;
c[4] = tmpc[1] &0xFF;
c[5] = (tmpc[1]>>8) &0xFF;
c[6] = (tmpc[1]>>16)&0xFF;
c[7] = (tmpc[1]>>24)&0xFF;
c[8] = tmpc[2] &0xFF;
c[9] = (tmpc[2]>>8) &0xFF;
c[10] = (tmpc[2]>>16)&0xFF;
c[11] = (tmpc[2]>>24)&0xFF;
c[12] = tmpc[3] &0xFF;
c[13] = (tmpc[3]>>8) &0xFF;
c[14] = (tmpc[3]>>16)&0xFF;
c[15] = (tmpc[3]>>24)&0xFF;
}
void rho_ad_eqov16 (const unsigned char* m,
unsigned char* s) {
*((unsigned int *)&s[0]) ^= *((unsigned int *)&m[0]);
*((unsigned int *)&s[4]) ^= *((unsigned int *)&m[4]);
*((unsigned int *)&s[8]) ^= *((unsigned int *)&m[8]);
*((unsigned int *)&s[12]) ^= *((unsigned int *)&m[12]);
}
void rho_ad_ud16 (const unsigned char* m,
unsigned char* s,
int len8) {
unsigned char mp [16];
pad(m,mp,16,len8);
*((unsigned int *)&s[0]) ^= *((unsigned int *)&mp[0]);
*((unsigned int *)&s[4]) ^= *((unsigned int *)&mp[4]);
*((unsigned int *)&s[8]) ^= *((unsigned int *)&mp[8]);
*((unsigned int *)&s[12]) ^= *((unsigned int *)&mp[12]);
}
void rho_eqov16 (const unsigned char* m,
unsigned char* c,
unsigned char* s) {
g8A(s,c);
*((unsigned int *)&s[0]) ^= *((unsigned int *)&m[0]);
*((unsigned int *)&s[4]) ^= *((unsigned int *)&m[4]);
*((unsigned int *)&s[8]) ^= *((unsigned int *)&m[8]);
*((unsigned int *)&s[12]) ^= *((unsigned int *)&m[12]);
*((unsigned int *)&c[0]) ^= *((unsigned int *)&m[0]);
*((unsigned int *)&c[4]) ^= *((unsigned int *)&m[4]);
*((unsigned int *)&c[8]) ^= *((unsigned int *)&m[8]);
*((unsigned int *)&c[12]) ^= *((unsigned int *)&m[12]);
}
void rho_ud16 (const unsigned char* m,
unsigned char* c,
unsigned char* s,
int len8,
int ver) {
int i;
unsigned char mp [16];
pad(m,mp,ver,len8);
g8A(s,c);
*((unsigned int *)&s[0]) ^= *((unsigned int *)&mp[0]);
*((unsigned int *)&s[4]) ^= *((unsigned int *)&mp[4]);
*((unsigned int *)&s[8]) ^= *((unsigned int *)&mp[8]);
*((unsigned int *)&s[12]) ^= *((unsigned int *)&mp[12]);
for (i = 0; i < ver; i++) {
if (i < len8) {
c[i] = c[i] ^ mp[i];
}
else {
c[i] = 0;
}
}
}
void irho (unsigned char* m,
const unsigned char* c,
unsigned char* s,
int len8,
int ver) {
int i;
unsigned char cp [16];
pad(c,cp,ver,len8);
g8A(s,m);
for (i = 0; i < ver; i++) {
if (i < len8) {
s[i] = s[i] ^ cp[i] ^ m[i];
}
else {
s[i] = s[i] ^ cp[i];
}
if (i < len8) {
m[i] = m[i] ^ cp[i];
}
else {
m[i] = 0;
}
}
}
void reset_lfsr_gf56 (unsigned char* CNT) {
*((unsigned int *)&CNT[0]) = 0x00000001;
*((unsigned int *)&CNT[4]) = 0x00000000;
}
void lfsr_gf56 (unsigned char* CNT) {
unsigned int tmpCNT[2];
unsigned int fb0;
tmpCNT[0] = *((unsigned int *)&CNT[0]); // CNT3 CNT2 CNT1 CNT0
tmpCNT[1] = *((unsigned int *)&CNT[4]); // CNT7 CNT6 CNT5 CNT4
fb0 = 0;
if ((tmpCNT[1] >> 23)&0x01) {
fb0 = 0x95;
}
tmpCNT[1] = tmpCNT[1] << 1 | tmpCNT[0] >> 31;
tmpCNT[0] = tmpCNT[0] << 1 ^ fb0;
*((unsigned int *)&CNT[0]) = tmpCNT[0];
*((unsigned int *)&CNT[4]) = tmpCNT[1];
}
void block_cipher(unsigned char* s,
const unsigned char* k, unsigned char* T,
unsigned char* CNT,
skinny_ctrl* p_skinny_ctrl) {
p_skinny_ctrl->func_skinny_128_384_enc (s,p_skinny_ctrl,CNT,T,k);
}
void nonce_encryption (const unsigned char* N,
unsigned char* CNT,
unsigned char*s, const unsigned char* k,
unsigned char D,
skinny_ctrl* p_skinny_ctrl) {
unsigned char T [16];
*((unsigned int *)&T[0]) = *((unsigned int *)&N[0]);
*((unsigned int *)&T[4]) = *((unsigned int *)&N[4]);
*((unsigned int *)&T[8]) = *((unsigned int *)&N[8]);
*((unsigned int *)&T[12]) = *((unsigned int *)&N[12]);
CNT[7] = D;
block_cipher(s,k,T,CNT,p_skinny_ctrl);
}
void generate_tag (unsigned char** c, unsigned char* s,
int n, unsigned long long* clen) {
g8A_for_Tag_Generation(s, *c);
*c = *c + n;
*c = *c - *clen;
}
unsigned long long msg_encryption (const unsigned char** M, unsigned char** c,
const unsigned char* N,
unsigned char* CNT,
unsigned char*s, const unsigned char* k,
unsigned char D,
unsigned long long mlen,
skinny_ctrl* p_skinny_ctrl) {
int len8;
if (mlen >= 16) {
len8 = 16;
mlen = mlen - 16;
rho_eqov16(*M, *c, s);
}
else {
len8 = mlen;
mlen = 0;
rho_ud16(*M, *c, s, len8, 16);
}
*c = *c + len8;
*M = *M + len8;
lfsr_gf56(CNT);
if (mlen != 0) {
nonce_encryption(N,CNT,s,k,D,p_skinny_ctrl);
}
return mlen;
}
unsigned long long msg_decryption (unsigned char** M, const unsigned char** c,
const unsigned char* N,
unsigned char* CNT,
unsigned char*s, const unsigned char* k,
unsigned char D,
unsigned long long clen,
skinny_ctrl* p_skinny_ctrl) {
int len8;
if (clen >= 16) {
len8 = 16;
clen = clen - 16;
}
else {
len8 = clen;
clen = 0;
}
irho(*M, *c, s, len8, 16);
*c = *c + len8;
*M = *M + len8;
lfsr_gf56(CNT);
nonce_encryption(N,CNT,s,k,D,p_skinny_ctrl);
return clen;
}
unsigned long long ad2msg_encryption (const unsigned char** M,
unsigned char* CNT,
unsigned char*s, const unsigned char* k,
unsigned char D,
unsigned long long mlen,
skinny_ctrl* p_skinny_ctrl) {
unsigned char T [16];
int len8;
if (mlen <= 16) {
len8 = mlen;
mlen = 0;
pad (*M,T,16,len8);
}
else {
len8 = 16;
mlen = mlen - 16;
unsigned char *pM = (unsigned char *)(*M);
*((unsigned int *)&T[0]) = *((unsigned int *)&pM[0]);
*((unsigned int *)&T[4]) = *((unsigned int *)&pM[4]);
*((unsigned int *)&T[8]) = *((unsigned int *)&pM[8]);
*((unsigned int *)&T[12]) = *((unsigned int *)&pM[12]);
}
CNT[7] = D;
block_cipher(s,k,T,CNT,p_skinny_ctrl);
lfsr_gf56(CNT);
*M = *M + len8;
return mlen;
}
unsigned long long ad_encryption (const unsigned char** A, unsigned char* s,
const unsigned char* k, unsigned long long adlen,
unsigned char* CNT,
unsigned char D,
skinny_ctrl* p_skinny_ctrl) {
unsigned char T [16];
int len8;
if (adlen >= 16) {
len8 = 16;
adlen = adlen - 16;
rho_ad_eqov16(*A, s);
}
else {
len8 = adlen;
adlen = 0;
rho_ad_ud16(*A, s, len8);
}
*A = *A + len8;
lfsr_gf56(CNT);
if (adlen != 0) {
if (adlen >= 16) {
len8 = 16;
adlen = adlen - 16;
unsigned char *pA = (unsigned char *)(*A);
*((unsigned int *)&T[0]) = *((unsigned int *)&pA[0]);
*((unsigned int *)&T[4]) = *((unsigned int *)&pA[4]);
*((unsigned int *)&T[8]) = *((unsigned int *)&pA[8]);
*((unsigned int *)&T[12]) = *((unsigned int *)&pA[12]);
}
else {
len8 = adlen;
adlen = 0;
pad(*A, T, 16, len8);
}
*A = *A + len8;
CNT[7] = D;
block_cipher(s,k,T,CNT,p_skinny_ctrl);
lfsr_gf56(CNT);
}
return adlen;
}
int crypto_aead_encrypt (
unsigned char* c, unsigned long long* clen,
const unsigned char* m, unsigned long long mlen,
const unsigned char* ad, unsigned long long adlen,
const unsigned char* nsec,
const unsigned char* npub,
const unsigned char* k
)
{
unsigned char s[16];
unsigned char CNT[8]; // size 7 -> 8 for word access
unsigned char T[16];
const unsigned char* N;
unsigned char w;
unsigned long long xlen;
skinny_ctrl l_skinny_ctrl;
l_skinny_ctrl.func_skinny_128_384_enc = skinny_128_384_enc123_12;
(void)nsec;
N = npub;
xlen = mlen;
*((unsigned int *)&s[0]) = 0x00000000;
*((unsigned int *)&s[4]) = 0x00000000;
*((unsigned int *)&s[8]) = 0x00000000;
*((unsigned int *)&s[12]) = 0x00000000;
reset_lfsr_gf56(CNT);
w = 48;
if (adlen == 0) {
w = w ^ 2;
if (xlen == 0) {
w =w ^ 1;
}
else if (xlen%(32) == 0) {
w = w ^ 4;
}
else if (xlen%(32) < 16) {
w = w ^ 1;
}
else if (xlen%(32) == 16) {
w = w ^ 0;
}
else {
w = w ^ 5;
}
}
else if (adlen%(32) == 0) {
w = w ^ 8;
if (xlen == 0) {
w =w ^ 1;
}
else if (xlen%(32) == 0) {
w = w ^ 4;
}
else if (xlen%(32) < 16) {
w = w ^ 1;
}
else if (xlen%(32) == 16) {
w = w ^ 0;
}
else {
w = w ^ 5;
}
}
else if (adlen%(32) < 16) {
w = w ^ 2;
if (xlen == 0) {
w =w ^ 1;
}
else if (xlen%(32) == 0) {
w = w ^ 4;
}
else if (xlen%(32) < 16) {
w = w ^ 1;
}
else if (xlen%(32) == 16) {
w = w ^ 0;
}
else {
w = w ^ 5;
}
}
else if (adlen%(32) == 16) {
w = w ^ 0;
if (xlen == 0) {
w =w ^ 1;
}
else if (xlen%(32) == 0) {
w = w ^ 4;
}
else if (xlen%(32) < 16) {
w = w ^ 1;
}
else if (xlen%(32) == 16) {
w = w ^ 0;
}
else {
w = w ^ 5;
}
}
else {
w = w ^ 10;
if (xlen == 0) {
w =w ^ 1;
}
else if (xlen%(32) == 0) {
w = w ^ 4;
}
else if (xlen%(32) < 16) {
w = w ^ 1;
}
else if (xlen%(32) == 16) {
w = w ^ 0;
}
else {
w = w ^ 5;
}
}
if (adlen == 0) { // AD is an empty string
lfsr_gf56(CNT);
}
else while (adlen > 0) {
adlen = ad_encryption(&ad,s,k,adlen,CNT,40,&l_skinny_ctrl);
}
if ((w & 8) == 0) {
xlen = ad2msg_encryption (&m,CNT,s,k,44,xlen,&l_skinny_ctrl);
}
else if (mlen == 0) {
lfsr_gf56(CNT);
}
while (xlen > 0) {
xlen = ad_encryption(&m,s,k,xlen,CNT,44,&l_skinny_ctrl);
}
nonce_encryption(N,CNT,s,k,w,&l_skinny_ctrl);
// because, nonce_encryption is called at the last block of AD encryption
l_skinny_ctrl.func_skinny_128_384_enc = skinny_128_384_enc1_1;
// Tag generation
g8A(s, T);
m = m - mlen;
reset_lfsr_gf56(CNT);
*((unsigned int *)&s[0]) = *((unsigned int *)&T[0]);
*((unsigned int *)&s[4]) = *((unsigned int *)&T[4]);
*((unsigned int *)&s[8]) = *((unsigned int *)&T[8]);
*((unsigned int *)&s[12]) = *((unsigned int *)&T[12]);
*clen = mlen + 16;
if (mlen > 0) {
nonce_encryption(N,CNT,s,k,36,&l_skinny_ctrl);
while (mlen > 16) {
mlen = msg_encryption(&m,&c,N,CNT,s,k,36,mlen,&l_skinny_ctrl);
}
rho_ud16(m, c, s, mlen, 16);
c = c + mlen;
m = m + mlen;
}
// Tag Concatenation
// use byte access because of memory alignment.
// c is not always in word(4 byte) alignment.
for (int i = 0; i < 16; i = i + 1) {
*(c + i) = T[i];
}
c = c - *clen;
return 0;
}
int crypto_aead_decrypt(
unsigned char *m,unsigned long long *mlen,
unsigned char *nsec,
const unsigned char *c,unsigned long long clen,
const unsigned char *ad,unsigned long long adlen,
const unsigned char *npub,
const unsigned char *k
)
{
unsigned char s[16];
unsigned char CNT[8]; // size 7 -> 8 for word access
unsigned char T[16];
const unsigned char* N;
unsigned char w;
unsigned long long xlen;
const unsigned char* mauth;
skinny_ctrl l_skinny_ctrl;
l_skinny_ctrl.func_skinny_128_384_enc = skinny_128_384_enc123_12;
(void)nsec;
mauth = m;
N = npub;
xlen = clen-16;
reset_lfsr_gf56(CNT);
for (int i = 0; i < 16; i++) {
T[i] = *(c + clen - 16 + i);
}
*((unsigned int *)&s[0]) = *((unsigned int *)&T[0]);
*((unsigned int *)&s[4]) = *((unsigned int *)&T[4]);
*((unsigned int *)&s[8]) = *((unsigned int *)&T[8]);
*((unsigned int *)&s[12]) = *((unsigned int *)&T[12]);
clen = clen - 16;
*mlen = clen;
if (clen > 0) {
nonce_encryption(N,CNT,s,k,36,&l_skinny_ctrl);
while (clen > 16) {
clen = msg_decryption(&m,&c,N,CNT,s,k,36,clen,&l_skinny_ctrl);
}
irho(m, c, s, clen, 16);
c = c + clen;
m = m + clen;
}
*((unsigned int *)&s[0]) = 0x00000000;
*((unsigned int *)&s[4]) = 0x00000000;
*((unsigned int *)&s[8]) = 0x00000000;
*((unsigned int *)&s[12]) = 0x00000000;
reset_lfsr_gf56(CNT);
w = 48;
if (adlen == 0) {
w = w ^ 2;
if (xlen == 0) {
w =w ^ 1;
}
else if (xlen%(32) == 0) {
w = w ^ 4;
}
else if (xlen%(32) < 16) {
w = w ^ 1;
}
else if (xlen%(32) == 16) {
w = w ^ 0;
}
else {
w = w ^ 5;
}
}
else if (adlen%(32) == 0) {
w = w ^ 8;
if (xlen == 0) {
w =w ^ 1;
}
else if (xlen%(32) == 0) {
w = w ^ 4;
}
else if (xlen%(32) < 16) {
w = w ^ 1;
}
else if (xlen%(32) == 16) {
w = w ^ 0;
}
else {
w = w ^ 5;
}
}
else if (adlen%(32) < 16) {
w = w ^ 2;
if (xlen == 0) {
w =w ^ 1;
}
else if (xlen%(32) == 0) {
w = w ^ 4;
}
else if (xlen%(32) < 16) {
w = w ^ 1;
}
else if (xlen%(32) == 16) {
w = w ^ 0;
}
else {
w = w ^ 5;
}
}
else if (adlen%(32) == 16) {
w = w ^ 0;
if (xlen == 0) {
w =w ^ 1;
}
else if (xlen%(32) == 0) {
w = w ^ 4;
}
else if (xlen%(32) < 16) {
w = w ^ 1;
}
else if (xlen%(32) == 16) {
w = w ^ 0;
}
else {
w = w ^ 5;
}
}
else {
w = w ^ 10;
if (xlen == 0) {
w =w ^ 1;
}
else if (xlen%(32) == 0) {
w = w ^ 4;
}
else if (xlen%(32) < 16) {
w = w ^ 1;
}
else if (xlen%(32) == 16) {
w = w ^ 0;
}
else {
w = w ^ 5;
}
}
if (adlen == 0) { // AD is an empty string
lfsr_gf56(CNT);
}
else while (adlen > 0) {
adlen = ad_encryption(&ad,s,k,adlen,CNT,40,&l_skinny_ctrl);
}
if ((w & 8) == 0) {
xlen = ad2msg_encryption (&mauth,CNT,s,k,44,xlen,&l_skinny_ctrl);
}
else if (clen == 0) {
lfsr_gf56(CNT);
}
while (xlen > 0) {
xlen = ad_encryption(&mauth,s,k,xlen,CNT,44,&l_skinny_ctrl);
}
nonce_encryption(N,CNT,s,k,w,&l_skinny_ctrl);
// Tag generation
g8A_for_Tag_Generation(s, T);
for (int i = 0; i < 16; i++) {
if (T[i] != (*(c+i))) {
return -1;
}
}
return 0;
}
//
// 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
void init_buffer(unsigned char *buffer, unsigned long long numbytes);
void fprint_bstr(FILE *fp, const char *label, const unsigned char *data, unsigned long long length);
int generate_test_vectors();
int main()
{
int 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()
{
FILE *fp;
char fileName[MAX_FILE_NAME];
unsigned char key[CRYPTO_KEYBYTES];
unsigned char nonce[CRYPTO_NPUBBYTES];
unsigned char msg[MAX_MESSAGE_LENGTH];
unsigned char msg2[MAX_MESSAGE_LENGTH];
unsigned char ad[MAX_ASSOCIATED_DATA_LENGTH];
unsigned char ct[MAX_MESSAGE_LENGTH + CRYPTO_ABYTES];
unsigned long long clen, mlen2;
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 (unsigned long long mlen = 0; (mlen <= MAX_MESSAGE_LENGTH) && (ret_val == KAT_SUCCESS); mlen++) {
for (unsigned long long adlen = 0; adlen <= MAX_ASSOCIATED_DATA_LENGTH; adlen++) {
printf("%0d\n", (int)clen);
fprintf(fp, "Count = %d\n", count++);
printf("Count = %d\n", count - 1);
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);
if ((func_ret = crypto_aead_encrypt(ct, &clen, msg, mlen, ad, adlen, NULL, nonce, key)) != 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");
if ((func_ret = crypto_aead_decrypt(msg2, &mlen2, NULL, ct, clen, ad, adlen, nonce, key)) != 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, 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 unsigned char *data, unsigned long long length)
{
fprintf(fp, "%s", label);
for (unsigned long long i = 0; i < length; i++)
fprintf(fp, "%02X", data[i]);
fprintf(fp, "\n");
}
void init_buffer(unsigned char *buffer, unsigned long long numbytes)
{
for (unsigned long long i = 0; i < numbytes; i++)
buffer[i] = (unsigned char)i;
}
typedef struct ___skinny_ctrl {
unsigned char roundKeys[960]; // number of round : 56
void (*func_skinny_128_384_enc)(unsigned char*, struct ___skinny_ctrl*, unsigned char* CNT, unsigned char* T, const unsigned char* K);
} skinny_ctrl;
extern void skinny_128_384_enc123_12 (unsigned char* input, skinny_ctrl* pskinny_ctrl, unsigned char* CNT, unsigned char* T, const unsigned char* K);
extern void skinny_128_384_enc12_12 (unsigned char* input, skinny_ctrl* pskinny_ctrl, unsigned char* CNT, unsigned char* T, const unsigned char* K);
extern void skinny_128_384_enc1_1 (unsigned char* input, skinny_ctrl* pskinny_ctrl, unsigned char* CNT, unsigned char* T, const unsigned char* K);
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.
#define CRYPTO_KEYBYTES 16
#define CRYPTO_NSECBYTES 0
#define CRYPTO_NPUBBYTES 16
#define CRYPTO_ABYTES 16
#define CRYPTO_NOOVERLAP 1
int crypto_aead_encrypt(unsigned char *c, unsigned long long *clen,
const unsigned char *m, unsigned long long mlen,
const unsigned char *ad, unsigned long long adlen,
const unsigned char *nsec, const unsigned char *npub,
const unsigned char *k);
int crypto_aead_decrypt(unsigned char *m, unsigned long long *outputmlen,
unsigned char *nsec,
const unsigned char *c, unsigned long long clen,
const unsigned char *ad, unsigned long long adlen,
const unsigned char *npub, const unsigned char *k);
/*
* Date: 29 November 2018
* Contact: Thomas Peyrin - thomas.peyrin@gmail.com
* Mustafa Khairallah - mustafam001@e.ntu.edu.sg
*/
#include "crypto_aead.h"
#include "api.h"
#include "skinny.h"
#include <stdio.h>
#include <stdlib.h>
void pad (const unsigned char* m, unsigned char* mp, int l, int len8) {
int i;
for (i = 0; i < l; i++) {
if (i < len8) {
mp[i] = m[i];
}
else if (i == l - 1) {
mp[i] = (len8 & 0x0f);
}
else {
mp[i] = 0x00;
}
}
}
void g8A (unsigned char* s, unsigned char* c) {
unsigned int tmps[4];
unsigned int tmpc[4];
tmps[0] = *((unsigned int *)&s[0]);
tmps[1] = *((unsigned int *)&s[4]);
tmps[2] = *((unsigned int *)&s[8]);
tmps[3] = *((unsigned int *)&s[12]);
// c[i] = (s[i] >> 1) ^ (s[i] & 0x80) ^ ((s[i] & 0x01) << 7);
//
// (s[i] >> 1) -> ((s[i]>>1)&0x7f)
// (s[i] & 0x80) -> (s[i])&0x80) not changed
// ((s[i] & 0x01) << 7) -> ((s[i]<<7)&0x80)
// use word access because of speeding up
tmpc[0] = ((tmps[0]>>1) & 0x7f7f7f7f) ^ (tmps[0] & 0x80808080) ^ ((tmps[0]<<7) & 0x80808080);
tmpc[1] = ((tmps[1]>>1) & 0x7f7f7f7f) ^ (tmps[1] & 0x80808080) ^ ((tmps[1]<<7) & 0x80808080);
tmpc[2] = ((tmps[2]>>1) & 0x7f7f7f7f) ^ (tmps[2] & 0x80808080) ^ ((tmps[2]<<7) & 0x80808080);
tmpc[3] = ((tmps[3]>>1) & 0x7f7f7f7f) ^ (tmps[3] & 0x80808080) ^ ((tmps[3]<<7) & 0x80808080);
*((unsigned int *)&c[0]) = tmpc[0];
*((unsigned int *)&c[4]) = tmpc[1];
*((unsigned int *)&c[8]) = tmpc[2];
*((unsigned int *)&c[12]) = tmpc[3];
}
void g8A_for_Tag_Generation (unsigned char* s, unsigned char* c) {
unsigned int tmps[4];
unsigned int tmpc[4];
tmps[0] = *((unsigned int *)&s[0]);
tmps[1] = *((unsigned int *)&s[4]);
tmps[2] = *((unsigned int *)&s[8]);
tmps[3] = *((unsigned int *)&s[12]);
// c[i] = (s[i] >> 1) ^ (s[i] & 0x80) ^ ((s[i] & 0x01) << 7);
//
// (s[i] >> 1) -> ((s[i]>>1)&0x7f)
// (s[i] & 0x80) -> (s[i])&0x80) not changed
// ((s[i] & 0x01) << 7) -> ((s[i]<<7)&0x80)
// use word access because of speeding up
tmpc[0] = ((tmps[0]>>1) & 0x7f7f7f7f) ^ (tmps[0] & 0x80808080) ^ ((tmps[0]<<7) & 0x80808080);
tmpc[1] = ((tmps[1]>>1) & 0x7f7f7f7f) ^ (tmps[1] & 0x80808080) ^ ((tmps[1]<<7) & 0x80808080);
tmpc[2] = ((tmps[2]>>1) & 0x7f7f7f7f) ^ (tmps[2] & 0x80808080) ^ ((tmps[2]<<7) & 0x80808080);
tmpc[3] = ((tmps[3]>>1) & 0x7f7f7f7f) ^ (tmps[3] & 0x80808080) ^ ((tmps[3]<<7) & 0x80808080);
// use byte access because of memory alignment.
// c is not always in word(4 byte) alignment.
c[0] = tmpc[0] &0xFF;
c[1] = (tmpc[0]>>8) &0xFF;
c[2] = (tmpc[0]>>16)&0xFF;
c[3] = (tmpc[0]>>24)&0xFF;
c[4] = tmpc[1] &0xFF;
c[5] = (tmpc[1]>>8) &0xFF;
c[6] = (tmpc[1]>>16)&0xFF;
c[7] = (tmpc[1]>>24)&0xFF;
c[8] = tmpc[2] &0xFF;
c[9] = (tmpc[2]>>8) &0xFF;
c[10] = (tmpc[2]>>16)&0xFF;
c[11] = (tmpc[2]>>24)&0xFF;
c[12] = tmpc[3] &0xFF;
c[13] = (tmpc[3]>>8) &0xFF;
c[14] = (tmpc[3]>>16)&0xFF;
c[15] = (tmpc[3]>>24)&0xFF;
}
void rho_ad_eqov16 (const unsigned char* m,
unsigned char* s) {
*((unsigned int *)&s[0]) ^= *((unsigned int *)&m[0]);
*((unsigned int *)&s[4]) ^= *((unsigned int *)&m[4]);
*((unsigned int *)&s[8]) ^= *((unsigned int *)&m[8]);
*((unsigned int *)&s[12]) ^= *((unsigned int *)&m[12]);
}
void rho_ad_ud16 (const unsigned char* m,
unsigned char* s,
int len8) {
unsigned char mp [16];
pad(m,mp,16,len8);
*((unsigned int *)&s[0]) ^= *((unsigned int *)&mp[0]);
*((unsigned int *)&s[4]) ^= *((unsigned int *)&mp[4]);
*((unsigned int *)&s[8]) ^= *((unsigned int *)&mp[8]);
*((unsigned int *)&s[12]) ^= *((unsigned int *)&mp[12]);
}
void rho_eqov16 (const unsigned char* m,
unsigned char* c,
unsigned char* s) {
g8A(s,c);
*((unsigned int *)&s[0]) ^= *((unsigned int *)&m[0]);
*((unsigned int *)&s[4]) ^= *((unsigned int *)&m[4]);
*((unsigned int *)&s[8]) ^= *((unsigned int *)&m[8]);
*((unsigned int *)&s[12]) ^= *((unsigned int *)&m[12]);
*((unsigned int *)&c[0]) ^= *((unsigned int *)&m[0]);
*((unsigned int *)&c[4]) ^= *((unsigned int *)&m[4]);
*((unsigned int *)&c[8]) ^= *((unsigned int *)&m[8]);
*((unsigned int *)&c[12]) ^= *((unsigned int *)&m[12]);
}
void rho_ud16 (const unsigned char* m,
unsigned char* c,
unsigned char* s,
int len8,
int ver) {
int i;
unsigned char mp [16];
pad(m,mp,ver,len8);
g8A(s,c);
*((unsigned int *)&s[0]) ^= *((unsigned int *)&mp[0]);
*((unsigned int *)&s[4]) ^= *((unsigned int *)&mp[4]);
*((unsigned int *)&s[8]) ^= *((unsigned int *)&mp[8]);
*((unsigned int *)&s[12]) ^= *((unsigned int *)&mp[12]);
for (i = 0; i < ver; i++) {
if (i < len8) {
c[i] = c[i] ^ mp[i];
}
else {
c[i] = 0;
}
}
}
void irho (unsigned char* m,
const unsigned char* c,
unsigned char* s,
int len8,
int ver) {
int i;
unsigned char cp [16];
pad(c,cp,ver,len8);
g8A(s,m);
for (i = 0; i < ver; i++) {
if (i < len8) {
s[i] = s[i] ^ cp[i] ^ m[i];
}
else {
s[i] = s[i] ^ cp[i];
}
if (i < len8) {
m[i] = m[i] ^ cp[i];
}
else {
m[i] = 0;
}
}
}
void reset_lfsr_gf56 (unsigned char* CNT) {
*((unsigned int *)&CNT[0]) = 0x00000001;
*((unsigned int *)&CNT[4]) = 0x00000000;
}
void lfsr_gf56 (unsigned char* CNT) {
unsigned int tmpCNT[2];
unsigned int fb0;
tmpCNT[0] = *((unsigned int *)&CNT[0]); // CNT3 CNT2 CNT1 CNT0
tmpCNT[1] = *((unsigned int *)&CNT[4]); // CNT7 CNT6 CNT5 CNT4
fb0 = 0;
if ((tmpCNT[1] >> 23)&0x01) {
fb0 = 0x95;
}
tmpCNT[1] = tmpCNT[1] << 1 | tmpCNT[0] >> 31;
tmpCNT[0] = tmpCNT[0] << 1 ^ fb0;
*((unsigned int *)&CNT[0]) = tmpCNT[0];
*((unsigned int *)&CNT[4]) = tmpCNT[1];
}
void block_cipher(unsigned char* s,
const unsigned char* k, unsigned char* T,
unsigned char* CNT,
skinny_ctrl* p_skinny_ctrl) {
p_skinny_ctrl->func_skinny_128_384_enc (s,p_skinny_ctrl,CNT,T,k);
}
void nonce_encryption (const unsigned char* N,
unsigned char* CNT,
unsigned char*s, const unsigned char* k,
unsigned char D,
skinny_ctrl* p_skinny_ctrl) {
unsigned char T [16];
*((unsigned int *)&T[0]) = *((unsigned int *)&N[0]);
*((unsigned int *)&T[4]) = *((unsigned int *)&N[4]);
*((unsigned int *)&T[8]) = *((unsigned int *)&N[8]);
*((unsigned int *)&T[12]) = *((unsigned int *)&N[12]);
CNT[7] = D;
block_cipher(s,k,T,CNT,p_skinny_ctrl);
}
void generate_tag (unsigned char** c, unsigned char* s,
int n, unsigned long long* clen) {
g8A_for_Tag_Generation(s, *c);
*c = *c + n;
*c = *c - *clen;
}
unsigned long long msg_encryption_eqov16 (const unsigned char** M, unsigned char** c,
const unsigned char* N,
unsigned char* CNT,
unsigned char*s, const unsigned char* k,
unsigned char D,
unsigned long long mlen,
skinny_ctrl* p_skinny_ctrl) {
rho_eqov16(*M, *c, s);
*c = *c + 16;
*M = *M + 16;
lfsr_gf56(CNT);
nonce_encryption(N,CNT,s,k,D,p_skinny_ctrl);
return mlen - 16;
}
unsigned long long msg_encryption_ud16 (const unsigned char** M, unsigned char** c,
const unsigned char* N,
unsigned char* CNT,
unsigned char*s, const unsigned char* k,
unsigned char D,
unsigned long long mlen,
skinny_ctrl* p_skinny_ctrl) {
rho_ud16(*M, *c, s, mlen, 16);
*c = *c + mlen;
*M = *M + mlen;
lfsr_gf56(CNT);
nonce_encryption(N,CNT,s,k,D,p_skinny_ctrl);
return 0;
}
unsigned long long msg_decryption (unsigned char** M, const unsigned char** c,
const unsigned char* N,
unsigned char* CNT,
unsigned char*s, const unsigned char* k,
unsigned char D,
unsigned long long clen,
skinny_ctrl* p_skinny_ctrl) {
int len8;
if (clen >= 16) {
len8 = 16;
clen = clen - 16;
}
else {
len8 = clen;
clen = 0;
}
irho(*M, *c, s, len8, 16);
*c = *c + len8;
*M = *M + len8;
lfsr_gf56(CNT);
nonce_encryption(N,CNT,s,k,D,p_skinny_ctrl);
return clen;
}
unsigned long long ad_encryption_eqov32 (const unsigned char** A, unsigned char* s,
const unsigned char* k, unsigned long long adlen,
unsigned char* CNT,
unsigned char D,
skinny_ctrl* p_skinny_ctrl) {
unsigned char T [16];
rho_ad_eqov16(*A, s);
*A = *A + 16;
lfsr_gf56(CNT);
//pad(*A, T, 16, 16);
*((unsigned int *)&T[0]) = *((unsigned int *)&(*A)[0]);
*((unsigned int *)&T[4]) = *((unsigned int *)&(*A)[4]);
*((unsigned int *)&T[8]) = *((unsigned int *)&(*A)[8]);
*((unsigned int *)&T[12]) = *((unsigned int *)&(*A)[12]);
*A = *A + 16;
CNT[7] = D;
block_cipher(s,k,T,CNT,p_skinny_ctrl);
lfsr_gf56(CNT);
return adlen - 32;
}
unsigned long long ad_encryption_ov16 (const unsigned char** A, unsigned char* s,
const unsigned char* k, unsigned long long adlen,
unsigned char* CNT,
unsigned char D,
skinny_ctrl* p_skinny_ctrl) {
unsigned char T [16];
adlen = adlen - 16;
rho_ad_eqov16(*A, s);
*A = *A + 16;
lfsr_gf56(CNT);
pad(*A, T, 16, adlen);
*A = *A + adlen;
CNT[7] = D;
block_cipher(s,k,T,CNT,p_skinny_ctrl);
lfsr_gf56(CNT);
return 0;
}
unsigned long long ad_encryption_eq16 (const unsigned char** A, unsigned char* s,
unsigned char* CNT) {
rho_ad_eqov16(*A, s);
*A = *A + 16;
lfsr_gf56(CNT);
return 0;
}
unsigned long long ad_encryption_ud16 (const unsigned char** A, unsigned char* s,
unsigned long long adlen,
unsigned char* CNT) {
rho_ad_ud16(*A, s, adlen);
*A = *A + adlen;
lfsr_gf56(CNT);
return 0;
}
int crypto_aead_encrypt (
unsigned char* c, unsigned long long* clen,
const unsigned char* m, unsigned long long mlen,
const unsigned char* ad, unsigned long long adlen,
const unsigned char* nsec,
const unsigned char* npub,
const unsigned char* k
)
{
unsigned char s[16];
// size 7 -> 8 for word access
unsigned char CNT[8];
const unsigned char* A;
const unsigned char* M;
const unsigned char* N;
skinny_ctrl l_skinny_ctrl;
(void) nsec;
A = ad;
M = m;
N = npub;
l_skinny_ctrl.func_skinny_128_384_enc = skinny_128_384_enc123_12;
*((unsigned int *)&s[0]) = 0x00000000;
*((unsigned int *)&s[4]) = 0x00000000;
*((unsigned int *)&s[8]) = 0x00000000;
*((unsigned int *)&s[12]) = 0x00000000;
reset_lfsr_gf56(CNT);
if (adlen == 0) { // AD is an empty string
lfsr_gf56(CNT);
nonce_encryption(N,CNT,s,k,0x1a,&l_skinny_ctrl);
}
else while (adlen > 0) {
if (adlen < 16) { // The last block of AD is odd and incomplete
adlen = ad_encryption_ud16(&A,s,adlen,CNT);
nonce_encryption(N,CNT,s,k,0x1a,&l_skinny_ctrl);
}
else if (adlen == 16) { // The last block of AD is odd and complete
adlen = ad_encryption_eq16(&A,s,CNT);
nonce_encryption(N,CNT,s,k,0x18,&l_skinny_ctrl);
}
else if (adlen < (32)) { // The last block of AD is even and incomplete
adlen = ad_encryption_ov16(&A,s,k,adlen,CNT,0x08,&l_skinny_ctrl);
nonce_encryption(N,CNT,s,k,0x1a,&l_skinny_ctrl);
}
else if (adlen == (32)) { // The last block of AD is even and complete
adlen = ad_encryption_eqov32(&A,s,k,adlen,CNT,0x08,&l_skinny_ctrl);
nonce_encryption(N,CNT,s,k,0x18,&l_skinny_ctrl);
}
else { // A normal full pair of blocks of AD
adlen = ad_encryption_eqov32(&A,s,k,adlen,CNT,0x08,&l_skinny_ctrl);
}
}
// because, nonce_encryption is called at the last block of AD encryption
l_skinny_ctrl.func_skinny_128_384_enc = skinny_128_384_enc1_1;
reset_lfsr_gf56(CNT);
*clen = mlen + 16;
if (mlen == 0) { // M is an empty string
lfsr_gf56(CNT);
nonce_encryption(N,CNT,s,k,0x15,&l_skinny_ctrl);
}
else while (mlen > 0) {
if (mlen < 16) { // The last block of M is incomplete
mlen = msg_encryption_ud16(&M,&c,N,CNT,s,k,0x15,mlen,&l_skinny_ctrl);
}
else if (mlen == 16) { // The last block of M is complete
mlen = msg_encryption_eqov16(&M,&c,N,CNT,s,k,0x14,mlen,&l_skinny_ctrl);
}
else { // A normal full message block
mlen = msg_encryption_eqov16(&M,&c,N,CNT,s,k,0x04,mlen,&l_skinny_ctrl);
}
}
// Tag generation
generate_tag(&c,s,16,clen);
return 0;
}
int crypto_aead_decrypt(
unsigned char *m,unsigned long long *mlen,
unsigned char *nsec,
const unsigned char *c,unsigned long long clen,
const unsigned char *ad,unsigned long long adlen,
const unsigned char *npub,
const unsigned char *k
)
{
unsigned char s[16];
unsigned char T[16];
// size 7 -> 8 for word access
unsigned char CNT[8];
const unsigned char* A;
unsigned char* M;
const unsigned char* N;
unsigned int i;
skinny_ctrl l_skinny_ctrl;
(void) nsec;
A = ad;
M = m;
N = npub;
l_skinny_ctrl.func_skinny_128_384_enc = skinny_128_384_enc123_12;
for (i = 0; i < 16; i++) {
s[i] = 0;
}
reset_lfsr_gf56(CNT);
if (adlen == 0) { // AD is an empty string
lfsr_gf56(CNT);
nonce_encryption(N,CNT,s,k,0x1a,&l_skinny_ctrl);
}
else while (adlen > 0) {
if (adlen < 16) { // The last block of AD is odd and incomplete
adlen = ad_encryption_ud16(&A,s,adlen,CNT);
nonce_encryption(N,CNT,s,k,0x1a,&l_skinny_ctrl);
}
else if (adlen == 16) { // The last block of AD is odd and complete
adlen = ad_encryption_eq16(&A,s,CNT);
nonce_encryption(N,CNT,s,k,0x18,&l_skinny_ctrl);
}
else if (adlen < (32)) { // The last block of AD is even and incomplete
adlen = ad_encryption_ov16(&A,s,k,adlen,CNT,0x08,&l_skinny_ctrl);
nonce_encryption(N,CNT,s,k,0x1a,&l_skinny_ctrl);
}
else if (adlen == (32)) { // The last block of AD is even and complete
adlen = ad_encryption_eqov32(&A,s,k,adlen,CNT,0x08,&l_skinny_ctrl);
nonce_encryption(N,CNT,s,k,0x18,&l_skinny_ctrl);
}
else { // A normal full pair of blocks of AD
adlen = ad_encryption_eqov32(&A,s,k,adlen,CNT,0x08,&l_skinny_ctrl);
}
}
reset_lfsr_gf56(CNT);
clen = clen - 16;
*mlen = clen;
if (clen == 0) { // C is an empty string
lfsr_gf56(CNT);
nonce_encryption(N,CNT,s,k,0x15,&l_skinny_ctrl);
}
else while (clen > 0) {
if (clen < 16) { // The last block of C is incomplete
clen = msg_decryption(&M,&c,N,CNT,s,k,0x15,clen,&l_skinny_ctrl);
}
else if (clen == 16) { // The last block of C is complete
clen = msg_decryption(&M,&c,N,CNT,s,k,0x14,clen,&l_skinny_ctrl);
}
else { // A normal full message block
clen = msg_decryption(&M,&c,N,CNT,s,k,0x04,clen,&l_skinny_ctrl);
}
}
// Tag generation
g8A_for_Tag_Generation(s, T);
for (i = 0; i < 16; i++) {
if (T[i] != (*(c+i))) {
return -1;
}
}
return 0;
}
//
// 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
void init_buffer(unsigned char *buffer, unsigned long long numbytes);
void fprint_bstr(FILE *fp, const char *label, const unsigned char *data, unsigned long long length);
int generate_test_vectors();
int main()
{
int 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()
{
FILE *fp;
char fileName[MAX_FILE_NAME];
unsigned char key[CRYPTO_KEYBYTES];
unsigned char nonce[CRYPTO_NPUBBYTES];
unsigned char msg[MAX_MESSAGE_LENGTH];
unsigned char msg2[MAX_MESSAGE_LENGTH];
unsigned char ad[MAX_ASSOCIATED_DATA_LENGTH];
unsigned char ct[MAX_MESSAGE_LENGTH + CRYPTO_ABYTES];
unsigned long long clen, mlen2;
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 (unsigned long long mlen = 0; (mlen <= MAX_MESSAGE_LENGTH) && (ret_val == KAT_SUCCESS); mlen++) {
for (unsigned long long adlen = 0; adlen <= MAX_ASSOCIATED_DATA_LENGTH; adlen++) {
printf("%0d\n", (int)clen);
fprintf(fp, "Count = %d\n", count++);
printf("Count = %d\n", count - 1);
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);
if ((func_ret = crypto_aead_encrypt(ct, &clen, msg, mlen, ad, adlen, NULL, nonce, key)) != 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");
if ((func_ret = crypto_aead_decrypt(msg2, &mlen2, NULL, ct, clen, ad, adlen, nonce, key)) != 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, 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 unsigned char *data, unsigned long long length)
{
fprintf(fp, "%s", label);
for (unsigned long long i = 0; i < length; i++)
fprintf(fp, "%02X", data[i]);
fprintf(fp, "\n");
}
void init_buffer(unsigned char *buffer, unsigned long long numbytes)
{
for (unsigned long long i = 0; i < numbytes; i++)
buffer[i] = (unsigned char)i;
}
typedef struct ___skinny_ctrl {
unsigned char roundKeys[960]; // number of round : 56
void (*func_skinny_128_384_enc)(unsigned char*, struct ___skinny_ctrl*, unsigned char* CNT, unsigned char* T, const unsigned char* K);
} skinny_ctrl;
extern void skinny_128_384_enc123_12 (unsigned char* input, skinny_ctrl* pskinny_ctrl, unsigned char* CNT, unsigned char* T, const unsigned char* K);
extern void skinny_128_384_enc12_12 (unsigned char* input, skinny_ctrl* pskinny_ctrl, unsigned char* CNT, unsigned char* T, const unsigned char* K);
extern void skinny_128_384_enc1_1 (unsigned char* input, skinny_ctrl* pskinny_ctrl, unsigned char* CNT, unsigned char* T, const unsigned char* K);
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