modernc.org/ccgo/v3@v3.16.14/lib/testdata/CompCert-3.6/test/c/sha3.c (about)

     1  /* SHA-3 (Keccak) cryptographic hash function */
     2  /* Code adapted from the "readable" implementation written by
     3     Markku-Juhani O. Saarinen <mjos@iki.fi> */
     4  
     5  #include <stdio.h>
     6  #include <string.h>
     7  
     8  typedef unsigned long long uint64;
     9  typedef unsigned char uint8;
    10  
    11  #define KECCAK_ROUNDS 24
    12  
    13  #define ROTL64(x, y) (((x) << (y)) | ((x) >> (64 - (y))))
    14  
    15  const uint64 keccakf_rndc[24] = 
    16  {
    17      0x0000000000000001, 0x0000000000008082, 0x800000000000808a,
    18      0x8000000080008000, 0x000000000000808b, 0x0000000080000001,
    19      0x8000000080008081, 0x8000000000008009, 0x000000000000008a,
    20      0x0000000000000088, 0x0000000080008009, 0x000000008000000a,
    21      0x000000008000808b, 0x800000000000008b, 0x8000000000008089,
    22      0x8000000000008003, 0x8000000000008002, 0x8000000000000080, 
    23      0x000000000000800a, 0x800000008000000a, 0x8000000080008081,
    24      0x8000000000008080, 0x0000000080000001, 0x8000000080008008
    25  };
    26  
    27  const int keccakf_rotc[24] = 
    28  {
    29      1,  3,  6,  10, 15, 21, 28, 36, 45, 55, 2,  14, 
    30      27, 41, 56, 8,  25, 43, 62, 18, 39, 61, 20, 44
    31  };
    32  
    33  const int keccakf_piln[24] = 
    34  {
    35      10, 7,  11, 17, 18, 3, 5,  16, 8,  21, 24, 4, 
    36      15, 23, 19, 13, 12, 2, 20, 14, 22, 9,  6,  1 
    37  };
    38  
    39  // update the state with KECCAK_ROUND rounds
    40  
    41  void keccakf(uint64 st[25])
    42  {
    43      int j, round;
    44      uint64 t, bc[5];
    45  
    46      for (round = 0; round < KECCAK_ROUNDS; round++) {
    47  
    48          // Theta
    49  #define THETA1(i) \
    50              bc[i] = st[i] ^ st[i + 5] ^ st[i + 10] ^ st[i + 15] ^ st[i + 20]
    51  
    52        THETA1(0); THETA1(1); THETA1(2); THETA1(3); THETA1(4);
    53  
    54  #define THETA2(i) \
    55              t = bc[(i + 4) % 5] ^ ROTL64(bc[(i + 1) % 5], 1); \
    56              st[0 + i] ^= t; \
    57              st[5 + i] ^= t; \
    58              st[10 + i] ^= t; \
    59              st[15 + i] ^= t; \
    60              st[20 + i] ^= t
    61  
    62        THETA2(0); THETA2(1); THETA2(2); THETA2(3); THETA2(4);
    63  
    64  
    65          // Rho Pi
    66  
    67  #define RHOPI(i, rotc) \
    68              j = keccakf_piln[i]; \
    69              bc[0] = st[j]; \
    70              st[j] = ROTL64(t, rotc); \
    71              t = bc[0]
    72  
    73          t = st[1];
    74          RHOPI(0, 1); RHOPI(1, 3); RHOPI(2, 6); RHOPI(3, 10);
    75          RHOPI(4, 15); RHOPI(5, 21); RHOPI(6, 28); RHOPI(7, 36);
    76          RHOPI(8, 45); RHOPI(9, 55); RHOPI(10, 2); RHOPI(11, 14);
    77          RHOPI(12, 27); RHOPI(13, 41); RHOPI(14, 56); RHOPI(15, 8);
    78          RHOPI(16, 25); RHOPI(17, 43); RHOPI(18, 62); RHOPI(19, 18);
    79          RHOPI(20, 39); RHOPI(21, 61); RHOPI(22, 20); RHOPI(23, 44);
    80  
    81          //  Chi
    82  
    83  #define CHI1(i,j) \
    84                  bc[i] = st[j + i]
    85  #define CHI2(i,j) \
    86                  st[j + i] ^= (~bc[(i + 1) % 5]) & bc[(i + 2) % 5]
    87  
    88          for (j = 0; j < 25; j += 5) {
    89            CHI1(0,j); CHI1(1,j); CHI1(2,j); CHI1(3,j); CHI1(4,j);
    90            CHI2(0,j); CHI2(1,j); CHI2(2,j); CHI2(3,j); CHI2(4,j);
    91          }
    92  
    93          //  Iota
    94          st[0] ^= keccakf_rndc[round];
    95      }
    96  }
    97  
    98  // read a 64-bit integer in little endian at the given address
    99  
   100  static inline uint64 get64le(const uint8 *p)
   101  {
   102    unsigned int l = p[0] | (p[1] << 8) | (p[2] << 16) | (p[3] << 24);
   103    unsigned int h = p[4] | (p[5] << 8) | (p[6] << 16) | (p[7] << 24);
   104    return l | ((uint64) h << 32);
   105  }
   106  
   107  // write a 64-bit integer in little endian at the given address
   108  
   109  static inline void set64le(uint8 * p, uint64 x)
   110  {
   111    p[0] = x;       p[1] = x >> 8;  p[2] = x >> 16; p[3] = x >> 24;
   112    p[4] = x >> 32; p[5] = x >> 40; p[6] = x >> 48; p[7] = x >> 56;
   113  }
   114  
   115  // compute a keccak hash (md) of the given byte length from "in"
   116  
   117  void keccak(const uint8 *in, int inlen, uint8 *md, int mdlen)
   118  {
   119      uint64 st[25];    
   120      uint8 temp[144];
   121      int i, rsiz, rsizw;
   122  
   123      rsiz = 200 - 2 * mdlen;
   124      rsizw = rsiz / 8;
   125      
   126      memset(st, 0, sizeof(st));
   127  
   128      for ( ; inlen >= rsiz; inlen -= rsiz, in += rsiz) {
   129          for (i = 0; i < rsizw; i++)
   130            st[i] ^= get64le(in + i * 8);
   131          keccakf(st);
   132      }
   133      
   134      // last block and padding
   135      memcpy(temp, in, inlen);
   136      temp[inlen++] = 1;
   137      memset(temp + inlen, 0, rsiz - inlen);
   138      temp[rsiz - 1] |= 0x80;
   139  
   140      for (i = 0; i < rsizw; i++)
   141        st[i] ^= get64le(temp + i * 8);
   142  
   143      keccakf(st);
   144  
   145      for(i = 0; i < 8; i++)
   146        set64le(temp + i * 8, st[i]);
   147  
   148      memcpy (md, temp, mdlen);
   149  }
   150  
   151  // test vectors
   152  
   153  typedef struct {
   154      int mdlen;
   155      char *msgstr;
   156      uint8 md[64];
   157  } test_triplet_t;
   158  
   159  test_triplet_t testvec[4] = {   
   160    {
   161      28, "Keccak-224 Test Hash", {
   162        0x30, 0x04, 0x5B, 0x34, 0x94, 0x6E, 0x1B, 0x2E, 
   163        0x09, 0x16, 0x13, 0x36, 0x2F, 0xD2, 0x2A, 0xA0, 
   164        0x8E, 0x2B, 0xEA, 0xFE, 0xC5, 0xE8, 0xDA, 0xEE, 
   165        0x42, 0xC2, 0xE6, 0x65 }
   166    }, {
   167      32, "Keccak-256 Test Hash", {
   168        0xA8, 0xD7, 0x1B, 0x07, 0xF4, 0xAF, 0x26, 0xA4, 
   169        0xFF, 0x21, 0x02, 0x7F, 0x62, 0xFF, 0x60, 0x26, 
   170        0x7F, 0xF9, 0x55, 0xC9, 0x63, 0xF0, 0x42, 0xC4, 
   171        0x6D, 0xA5, 0x2E, 0xE3, 0xCF, 0xAF, 0x3D, 0x3C }
   172    }, {
   173      48, "Keccak-384 Test Hash", {
   174        0xE2, 0x13, 0xFD, 0x74, 0xAF, 0x0C, 0x5F, 0xF9, 
   175        0x1B, 0x42, 0x3C, 0x8B, 0xCE, 0xEC, 0xD7, 0x01, 
   176        0xF8, 0xDD, 0x64, 0xEC, 0x18, 0xFD, 0x6F, 0x92, 
   177        0x60, 0xFC, 0x9E, 0xC1, 0xED, 0xBD, 0x22, 0x30, 
   178        0xA6, 0x90, 0x86, 0x65, 0xBC, 0xD9, 0xFB, 0xF4, 
   179        0x1A, 0x99, 0xA1, 0x8A, 0x7D, 0x9E, 0x44, 0x6E }
   180    }, {
   181      64, "Keccak-512 Test Hash", {
   182        0x96, 0xEE, 0x47, 0x18, 0xDC, 0xBA, 0x3C, 0x74, 
   183        0x61, 0x9B, 0xA1, 0xFA, 0x7F, 0x57, 0xDF, 0xE7, 
   184        0x76, 0x9D, 0x3F, 0x66, 0x98, 0xA8, 0xB3, 0x3F, 
   185        0xA1, 0x01, 0x83, 0x89, 0x70, 0xA1, 0x31, 0xE6, 
   186        0x21, 0xCC, 0xFD, 0x05, 0xFE, 0xFF, 0xBC, 0x11, 
   187        0x80, 0xF2, 0x63, 0xC2, 0x7F, 0x1A, 0xDA, 0xB4, 
   188        0x60, 0x95, 0xD6, 0xF1, 0x25, 0x33, 0x14, 0x72, 
   189        0x4B, 0x5C, 0xBF, 0x78, 0x28, 0x65, 0x8E, 0x6A }
   190    }
   191  };
   192  
   193  #define DATALEN 100000
   194  #define NITER 25
   195  
   196  int main()
   197  {
   198    static uint8 data[DATALEN];
   199    int i;
   200    uint8 md[64];
   201  
   202    // test
   203  
   204    for (i = 0; i < 4; i++) {
   205      
   206      keccak((uint8 *) testvec[i].msgstr, 
   207             strlen(testvec[i].msgstr),
   208             md, testvec[i].mdlen);
   209  
   210      printf("SHA-3 %d %s\n",
   211             testvec[i].mdlen * 8,
   212             memcmp(md, testvec[i].md, testvec[i].mdlen) == 0 ? "passed" : "FAILED");
   213  
   214    }
   215  
   216    // benchmark
   217    for (i = 0; i < DATALEN; i++) data[i] = i;
   218    for (i = 0; i < NITER; i++)
   219      keccak(data, DATALEN, md, 64);
   220  
   221    return 0;
   222  }
   223