hash.c 3.03 KB
Newer Older
Enrico Pozzobon committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132
/*
 * Date: 21 April 2021
 * Contact: Romulus Team (Mustafa Khairallah - mustafa.khairallah@ntu.edu.sg)
 * Romulus-H as compliant with the Romulus v1.3 specifications. 
 * This file icludes crypto_aead_decrypt()
 * It superseeds earlier versions developed by Mustafa Khairallah and maintained
 * by Mustafa Khairallah, Thomas Peyrin and Kazuhiko Minematsu
 */

#include "skinny.h"
#include "api.h"
#include "crypto_hash.h"


// The hirose double-block length (DBL) compression function.
void hirose_128_128_256 (unsigned char* h,
			 unsigned char* g,
			 const unsigned char* m) {
  unsigned char key [48];
  unsigned char hh  [16];
  int i;

  for (i = 0; i < 16; i++) { // assign the key for the
                             // hirose compresison function
    key[i] = g[i];
    g[i]   = h[i];
    hh[i]  = h[i];
  }
  g[0] ^= 0x01;
  for (i = 0; i < 32; i++) {
    key[i+16] = m[i];
  }
  
  skinny_128_384_plus_enc(h,key);
  skinny_128_384_plus_enc(g,key);

  for (i = 0; i < 16; i++) {
    h[i] ^= hh[i];
    g[i] ^= hh[i];
  }
  g[0] ^= 0x01;
  
}

// Sets the initial value to 0^2n
void initialize (unsigned char* h,
		 unsigned char* g) {
  unsigned char i;

  for (i = 0; i < 16; i++) {
    h[i] = 0;
    g[i] = 0;
  }
}

// Padding function: pads the byte length of the message mod 32 to the last incomplete block.
// For complete blocks it returns the same block. For an empty block it returns a 0^2n string.
// The function is called for full block messages to add a 0^2n block. This and the modulus are
// the only differences compared to the use in Romulus-N 
void ipad_256 (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 & 0x1f);
    }
    else {
      mp[i] = 0x00;
    }      
  }
  
}

// Padding function: pads the byte length of the message mod 32 to the last incomplete block.
// For complete blocks it returns the same block. For an empty block it returns a 0^2n string.
// The function is called for full block messages to add a 0^2n block. This and the modulus are
// the only differences compared to the use in Romulus-N 
void ipad_128 (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 & 0xf);
    }
    else {
      mp[i] = 0x00;
    }      
  }
  
}


int crypto_hash(
		unsigned char *out,
		const unsigned char *in,
		unsigned long long inlen
		)
{
  unsigned char h[16];
  unsigned char g[16];
  unsigned long long mlen;
  unsigned char p[32];
  unsigned char i;

  mlen = inlen;

  initialize(h,g);
  while (mlen >= 32) { // Normal loop
    hirose_128_128_256(h,g,in);
    in += 32;
    mlen -= 32;
  }
  // Partial block (or in case there is no partial block we add a 0^2n block
  ipad_256(in,p,32,mlen);
  h[0] ^= 2;
  hirose_128_128_256(h,g,p);
  
  for (i = 0; i < 16; i++) { // Assign the output tag
    out[i] = h[i];
    out[i+16] = g[i];
  }

  return 0;
}