Commit a28aa8ad by Alexandre Adomnicai Committed by Enrico Pozzobon

giftcofb128v1.armcortexm

parent 0bc74386
#define CRYPTO_KEYBYTES 16
#define CRYPTO_NSECBYTES 0
#define CRYPTO_NPUBBYTES 16
#define CRYPTO_ABYTES 16
#define CRYPTO_NOOVERLAP 1
/*******************************************************************************
* Constant-time 32-bit implementation of the GIFT-COFB authenticated cipher.
*
* @author Alexandre Adomnicai, Nanyang Technological University,
* alexandre.adomnicai@ntu.edu.sg
* @date January 2020
*******************************************************************************/
#include <string.h>
#include "giftb128.h"
#include "giftcofb128v1.h"
static inline void padding(u32* dest, const u32* src, const u32 no_of_bytes) {
u32 i;
if (no_of_bytes == 0) {
dest[0] = 0x00000080; // little-endian
dest[1] = 0x00000000;
dest[2] = 0x00000000;
dest[3] = 0x00000000;
}
else if (no_of_bytes < GIFT128_BLOCK_SIZE) {
for (i = 0; i < no_of_bytes/4+1; i++)
dest[i] = src[i];
dest[i-1] &= ~(0xffffffffL << (no_of_bytes % 4)*8);
dest[i-1] |= 0x00000080L << (no_of_bytes % 4)*8;
for (; i < 4; i++)
dest[i] = 0x00000000;
}
else {
dest[0] = src[0];
dest[1] = src[1];
dest[2] = src[2];
dest[3] = src[3];
}
}
/****************************************************************************
* Constant-time implementation of the GIFT-COFB authenticated cipher based on
* fixsliced GIFTb-128. Encryption/decryption is handled by the same function,
* depending on the 'mode' parameter (1/0).
****************************************************************************/
int giftcofb_crypt(u8* out, const u8* key, const u8* nonce, const u8* ad,
u32 ad_len, const u8* in, u32 in_len, const int encrypting) {
u32 tmp0, tmp1, emptyA, emptyM, offset[2];
u32 input[4], rkey[80];
u8 Y[GIFT128_BLOCK_SIZE];
if (!encrypting) {
if (in_len < TAG_SIZE)
return -1;
in_len -= TAG_SIZE;
}
if(ad_len == 0)
emptyA = 1;
else
emptyA = 0;
if(in_len == 0)
emptyM =1;
else
emptyM = 0;
gift128_keyschedule(key, rkey);
giftb128_encrypt_block(Y, rkey, nonce);
offset[0] = ((u32*)Y)[0];
offset[1] = ((u32*)Y)[1];
while(ad_len > GIFT128_BLOCK_SIZE){
RHO1(input, (u32*)Y, (u32*)ad, GIFT128_BLOCK_SIZE);
DOUBLE_HALF_BLOCK(offset);
XOR_TOP_BAR_BLOCK(input, offset);
giftb128_encrypt_block(Y, rkey, (u8*)input);
ad += GIFT128_BLOCK_SIZE;
ad_len -= GIFT128_BLOCK_SIZE;
}
TRIPLE_HALF_BLOCK(offset);
if((ad_len % GIFT128_BLOCK_SIZE != 0) || (emptyA))
TRIPLE_HALF_BLOCK(offset);
if(emptyM) {
TRIPLE_HALF_BLOCK(offset);
TRIPLE_HALF_BLOCK(offset);
}
RHO1(input, (u32*)Y, (u32*)ad, ad_len);
XOR_TOP_BAR_BLOCK(input, offset);
giftb128_encrypt_block(Y, rkey, (u8*)input);
while (in_len > GIFT128_BLOCK_SIZE){
DOUBLE_HALF_BLOCK(offset);
if (encrypting)
RHO((u32*)Y, (u32*)in, input, (u32*)out, GIFT128_BLOCK_SIZE);
else
RHO_PRIME((u32*)Y, (u32*)in, input, (u32*)out, GIFT128_BLOCK_SIZE);
XOR_TOP_BAR_BLOCK(input, offset);
giftb128_encrypt_block(Y, rkey, (u8*)input);
in += GIFT128_BLOCK_SIZE;
out += GIFT128_BLOCK_SIZE;
in_len -= GIFT128_BLOCK_SIZE;
}
if(!emptyM){
TRIPLE_HALF_BLOCK(offset);
if(in_len % GIFT128_BLOCK_SIZE != 0)
TRIPLE_HALF_BLOCK(offset);
if (encrypting) {
RHO((u32*)Y, (u32*)in, input, (u32*)out, in_len);
out += in_len;
}
else {
RHO_PRIME((u32*)Y, (u32*)in, input, (u32*)out, in_len);
in += in_len;
}
XOR_TOP_BAR_BLOCK(input, offset);
giftb128_encrypt_block(Y, rkey, (u8*)input);
}
if (encrypting) { // encryption mode
memcpy(out, Y, TAG_SIZE);
return 0;
}
// decrypting
tmp0 = 0;
for(tmp1 = 0; tmp1 < TAG_SIZE; tmp1++)
tmp0 |= in[tmp1] ^ Y[tmp1];
return tmp0;
}
/****************************************************************************
* API required by the NIST for the LWC competition.
****************************************************************************/
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) {
(void)nsec;
*clen = mlen + TAG_SIZE;
return giftcofb_crypt(c, k, npub, ad, adlen, m, mlen, COFB_ENCRYPT);
}
/****************************************************************************
* API required by the NIST for the LWC competition.
****************************************************************************/
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) {
(void)nsec;
*mlen = clen - TAG_SIZE;
return giftcofb_crypt(m, k, npub, ad, adlen, c, clen, COFB_DECRYPT);
}
#ifndef GIFT128_H_
#define GIFT128_H_
#define KEY_SIZE 16
#define GIFT128_BLOCK_SIZE 16
typedef unsigned char u8;
typedef unsigned int u32;
typedef struct param_128 {
u32 ctr;
u8 nonce[12];
u32 rkey[80];
} param_128;
extern void gift128_keyschedule(const u8* key, u32* rkey);
extern void giftb128_encrypt_block(u8* out_block, const u32* rkey, const u8* in_block);
#endif // GIFT128_H_
\ No newline at end of file
#ifndef GIFT_COFB_H_
#define GIFT_COFB_H_
#define TAG_SIZE 16
#define COFB_ENCRYPT 1
#define COFB_DECRYPT 0
typedef unsigned char u8;
typedef unsigned int u32;
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 *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);
#define DOUBLE_HALF_BLOCK(x) ({ \
tmp0 = (x)[0]; \
(x)[0] = (((x)[0] & 0x7f7f7f7f) << 1) | (((x)[0] & 0x80808080) >> 15); \
(x)[0] |= ((x)[1] & 0x80808080) << 17; \
(x)[1] = (((x)[1] & 0x7f7f7f7f) << 1) | (((x)[1] & 0x80808080) >> 15); \
(x)[1] ^= (((tmp0 >> 7) & 1) * 27) << 24; \
})
#define TRIPLE_HALF_BLOCK(x) ({ \
tmp0 = (x)[0]; \
tmp1 = (x)[1]; \
(x)[0] = (((x)[0] & 0x7f7f7f7f) << 1) | (((x)[0] & 0x80808080) >> 15); \
(x)[0] |= ((x)[1] & 0x80808080) << 17; \
(x)[1] = (((x)[1] & 0x7f7f7f7f) << 1) | (((x)[1] & 0x80808080) >> 15); \
(x)[1] ^= (((tmp0 >> 7) & 1) * 27) << 24; \
(x)[0] ^= tmp0; \
(x)[1] ^= tmp1; \
})
#define G(x) ({ \
tmp0 = (x)[0]; \
tmp1 = (x)[1]; \
(x)[0] = (x)[2]; \
(x)[1] = (x)[3]; \
(x)[2] = ((tmp0 & 0x7f7f7f7f) << 1) | ((tmp0 & 0x80808080) >> 15); \
(x)[2] |= ((tmp1 & 0x80808080) << 17); \
(x)[3] = ((tmp1 & 0x7f7f7f7f) << 1) | ((tmp1 & 0x80808080) >> 15); \
(x)[3] |= ((tmp0 & 0x80808080) << 17); \
})
#define XOR_BLOCK(x, y, z) ({ \
(x)[0] = (y)[0] ^ (z)[0]; \
(x)[1] = (y)[1] ^ (z)[1]; \
(x)[2] = (y)[2] ^ (z)[2]; \
(x)[3] = (y)[3] ^ (z)[3]; \
})
#define XOR_TOP_BAR_BLOCK(x, y) ({ \
(x)[0] ^= (y)[0]; \
(x)[1] ^= (y)[1]; \
})
#define RHO1(d, y, m, n) ({ \
G(y); \
padding(d,m,n); \
XOR_BLOCK(d, d, y); \
})
#define RHO(y, m, x, c, n) ({ \
XOR_BLOCK(c, y, m); \
RHO1(x, y, m, n); \
})
#define RHO_PRIME(y, c, x, m, n) ({ \
XOR_BLOCK(m, y, c); \
RHO1(x, y, m, n); \
})
#endif // GIFT_COFB_H_
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