Page MenuHomec4science

paef.c
No OneTemporary

File Metadata

Created
Tue, Jul 8, 04:37
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include "paef.h"
#include "extra_api.h"
#include "forkskinny.h"
#define DEBUG_PAEF
#define DEBUG_FATIH
#define MAX_COUNTER_BITS ((((CRYPTO_TWEAKSIZE-CRYPTO_NPUBBYTES) << 3) - 3))
void print_tweakey(unsigned char* tweakey, int i){
#ifdef DEBUG_PAEF
int j;
printf("\nTweakey at block %i: ", i);
for (j = 0; j < CRYPTO_TWEAKEYSIZE; j++)
printf("%02x ", tweakey[j]);
printf("\n");
#endif
}
void print_fork_call(unsigned char* tweakey, unsigned char* plaintext, unsigned char* c0, unsigned char* c1){
#ifdef DEBUG_FATIH
int j;
printf("FORKSKINNY CALL:\n");
printf("TK:\t"); for (j = 0; j < CRYPTO_TWEAKEYSIZE; j++) printf("%02x ", tweakey[j]);
printf("\nPT:\t"); for (j = 0; j < 16; j++) printf("%02x ", plaintext[j]);
printf("\nC0:\t"); for (j = 0; j < 16; j++) printf("%02x ", c0[j]);
printf("\nC1:\t"); for (j = 0; j < 16; j++) printf("%02x ", c1[j]);
printf("\n");
#endif
}
void print_running_tag(unsigned char* running_tag, int i){
#ifdef DEBUG_PAEF
int j;
printf("\nRunning tag after block %i: ", i);
for (j = 0; j < CRYPTO_BLOCKSIZE; j++)
printf("%02x ", running_tag[j]);
printf("\n");
#endif
}
void print_plain_cipher(unsigned char* state, int i){
#ifdef DEBUG_PAEF
int j;
printf("\nBlock %i of plaintext/ciphertext: ", i);
for (j = 0; j < CRYPTO_BLOCKSIZE; j++)
printf("%02x ", state[j]);
printf("\n");
#endif
}
int paef_encrypt(
unsigned char *c,
const unsigned char *m, unsigned long long mlen,
const unsigned char *ad, unsigned long long adlen,
const unsigned char *npub, // nonce, of which the length is specified in api.h
const unsigned char *k) { // key, of which the length is specified in api.h
/* Declarations */
uint64_t i, j;
unsigned char A_j[CRYPTO_BLOCKSIZE], M_j[CRYPTO_BLOCKSIZE];
unsigned char C0[CRYPTO_BLOCKSIZE], C1[CRYPTO_BLOCKSIZE];
unsigned char tweakey[TWEAKEY_BLOCKSIZE_RATIO*CRYPTO_BLOCKSIZE];
unsigned char running_tag[CRYPTO_BLOCKSIZE];
uint64_t nbABlocks = adlen / CRYPTO_BLOCKSIZE;
uint64_t nbMBlocks = mlen / CRYPTO_BLOCKSIZE;
unsigned char AD[(nbABlocks+1)*CRYPTO_BLOCKSIZE], M[(nbMBlocks+1)*CRYPTO_BLOCKSIZE]; /* Allocate one more block in case padding is needed */
uint64_t last_m_block_size = mlen % CRYPTO_BLOCKSIZE;
uint8_t ad_incomplete = (adlen != nbABlocks*CRYPTO_BLOCKSIZE) | ((adlen == 0) & (mlen == 0)); /* Boolean flag to indicate whether the final block is complete */
uint8_t m_incomplete = (last_m_block_size != 0); /* Boolean flag to indicate whether the final block is complete */
/* Check if ad length not too large */
if ((uint64_t)(adlen / (uint64_t) CRYPTO_BLOCKSIZE) > (uint64_t) ((uint64_t)1 << MAX_COUNTER_BITS)){
printf("Error: AD too long! Terminating. \n");
return -1;
}
/* Check if message length not too large */
if ((uint64_t)(mlen / (uint64_t) CRYPTO_BLOCKSIZE) > (uint64_t) ((uint64_t)1 << MAX_COUNTER_BITS)){
printf("Error: M too long! Terminating. \n");
return -1;
}
memset(running_tag, 0, CRYPTO_BLOCKSIZE); /* Set running tag to zero */
/* Padding of A */
for (i = 0; i < adlen; i++)
AD[i] = ad[i];
/* Pad A if it is incomplete OR if it is empty and there is no message either*/
if (ad_incomplete)
nbABlocks++;
AD[adlen] = 0x80;
for (i = adlen+1; i < nbABlocks*CRYPTO_BLOCKSIZE; i++)
AD[i] = 0x00;
/* Pad M if it is incomplete */
if (last_m_block_size != 0)
nbMBlocks++;
for (i = 0; i < mlen; i++)
M[i] = m[i];
M[mlen] = 0x80;
for (i = mlen+1; i < nbMBlocks*CRYPTO_BLOCKSIZE; i++)
M[i] = 0x00;
/* Construct baseline tweakey: key and nonce part remains unchanged throughout the execution. Initialize the remainder of the tweakey state to zero. */
// Key
for (i = 0; i < CRYPTO_KEYBYTES; i++)
tweakey[i] = k[i];
// Nonce
for (i = 0; i < CRYPTO_NPUBBYTES; i++)
tweakey[CRYPTO_KEYBYTES+i] = npub[i];
// Flags and counter to zero
for (i = 0; i < CRYPTO_TWEAKEYSIZE-CRYPTO_KEYBYTES-CRYPTO_NPUBBYTES; i++) {
tweakey[CRYPTO_KEYBYTES+CRYPTO_NPUBBYTES+i] = 0;
}
// For ForkSkinny-128-192 and ForkSkinny-128-288, the tweakey state needs to be zero-padded.
for (i = CRYPTO_TWEAKEYSIZE; i < TWEAKEY_BLOCKSIZE_RATIO*CRYPTO_BLOCKSIZE; i++)
tweakey[i] = 0;
/* Processing associated data */
#ifdef DEBUG_PAEF
printf("\n/* Processing associated data */ \n");
#endif
for (j = 1; j <= nbABlocks; j++) {
/* Load next block */
for (i = 0; i < CRYPTO_BLOCKSIZE; i++)
A_j[i] = AD[(j-1)*CRYPTO_BLOCKSIZE+i];
/* Tweakey flags */
if ((j==nbABlocks) & ad_incomplete)
tweakey[CRYPTO_KEYBYTES+CRYPTO_NPUBBYTES] = 0x60; // Flag 011
else if (j==nbABlocks)
tweakey[CRYPTO_KEYBYTES+CRYPTO_NPUBBYTES] = 0x20; // Flag 001
else
tweakey[CRYPTO_KEYBYTES+CRYPTO_NPUBBYTES] = 0x00; // Flag 000
/* Counter */
for (i = 1; i < CRYPTO_TWEAKSIZE-CRYPTO_NPUBBYTES; i++)
tweakey[CRYPTO_TWEAKEYSIZE-i] = (j >> 8*(i-1)) & 0xff;
/* Special treatment for the tweak byte that is shared between the counter and the flags */
tweakey[CRYPTO_KEYBYTES+CRYPTO_NPUBBYTES] ^= (j >> 8*(CRYPTO_TWEAKSIZE-CRYPTO_NPUBBYTES-1)) & 0xff;
print_tweakey(tweakey, j);
/* ForkEncrypt */
forkEncrypt(C0, C1, A_j, tweakey, ENC_C1);
print_fork_call(tweakey, A_j, C0, C1);
/* Update running tag */
for (i = 0; i < CRYPTO_BLOCKSIZE; i++)
running_tag[i] ^= C1[i];
print_running_tag(running_tag, j);
}
if (mlen == 0) /* If message is empty, copy tag to output buffer */
for (i = 0; i < CRYPTO_BLOCKSIZE; i++)
c[i] = running_tag[i];
/* Processing message */
#ifdef DEBUG_PAEF
printf("\n/* Processing message */\n");
#endif
for (j = 1; j <= nbMBlocks; j++) {
/* Load next block */
for (i = 0; i < CRYPTO_BLOCKSIZE; i++)
M_j[i] = M[(j-1)*CRYPTO_BLOCKSIZE+i];
/* Tweakey flags */
if ((j==nbMBlocks) & m_incomplete)
tweakey[CRYPTO_KEYBYTES+CRYPTO_NPUBBYTES] = 0xE0; // Flag 111
else if (j==nbMBlocks)
tweakey[CRYPTO_KEYBYTES+CRYPTO_NPUBBYTES] = 0xA0; // Flag 101
else
tweakey[CRYPTO_KEYBYTES+CRYPTO_NPUBBYTES] = 0x80; // Flag 100
/* Counter */
for (i = 1; i < CRYPTO_TWEAKSIZE-CRYPTO_NPUBBYTES; i++)
tweakey[CRYPTO_TWEAKEYSIZE-i] = (j >> 8*(i-1)) & 0xff;
/* Special treatment for the tweak byte that is shared between the counter and the flags */
tweakey[CRYPTO_KEYBYTES+CRYPTO_NPUBBYTES] ^= (j >> 8*(CRYPTO_TWEAKSIZE-CRYPTO_NPUBBYTES-1)) & 0xff;
print_tweakey(tweakey, j);
/* ForkEncrypt */
forkEncrypt(C0, C1, M_j, tweakey, ENC_BOTH);
print_fork_call(tweakey, M_j, C0, C1);
/* Final incomplete block */
if ((j==nbMBlocks) & m_incomplete){
//printf("\n\n\n INCOMPFINAL \n\n\n");
/* Add running tag to C0 and move to ciphertext output */
for (i = 0; i < CRYPTO_BLOCKSIZE; i++)
c[(j-1)*CRYPTO_BLOCKSIZE+i] = C0[i] ^ running_tag[i];
/* C1 now contains the tag. Move it to ciphertext output */
for (i = 0; i < last_m_block_size; i++)
c[mlen+CRYPTO_BLOCKSIZE-last_m_block_size+i] = C1[i];
print_plain_cipher(c, j);
print_running_tag(C1, j);
}
/* Final complete block */
else if (j==nbMBlocks){
//printf("\n\n\n GOODFINAL \n\n\n");
/* Add running tag to C0 and move to ciphertext output */
for (i = 0; i < CRYPTO_BLOCKSIZE; i++)
c[(j-1)*CRYPTO_BLOCKSIZE+i] = C0[i] ^ running_tag[i];
//print_plain_cipher(C0, 99);
//print_plain_cipher(running_tag, 100);
//print_plain_cipher(c+(j-1)*CRYPTO_BLOCKSIZE,101);
/* C1 now contains the tag. Move it to ciphertext output */
for (i = 0; i < CRYPTO_BLOCKSIZE; i++)
c[mlen+i] = C1[i];
print_plain_cipher(c, j);
print_running_tag(C1, j);
}
/* Non-final block */
else{
/* C0 contains ciphertext block. Move it to ciphertext output */
for (i = 0; i < CRYPTO_BLOCKSIZE; i++)
c[(j-1)*CRYPTO_BLOCKSIZE+i] = C0[i];
/* Update running tag with C1 value */
for (i = 0; i < CRYPTO_BLOCKSIZE; i++)
running_tag[i] ^= C1[i];
print_plain_cipher(C0, j);
print_running_tag(running_tag, j);
}
}
return 0; // all is well
}
int paef_decrypt(
unsigned char *m,
const unsigned char *c,unsigned long long clen,
const unsigned char *ad,unsigned long long adlen,
const unsigned char *npub,
const unsigned char *k){
}

Event Timeline