Home | History | Annotate | Download | only in crc
      1 /*
      2  * Cryptographic API.
      3  *
      4  * SHA-3, as specified in
      5  * http://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.202.pdf
      6  *
      7  * SHA-3 code by Jeff Garzik <jeff (at) garzik.org>
      8  *
      9  * This program is free software; you can redistribute it and/or modify it
     10  * under the terms of the GNU General Public License as published by the Free
     11  * Software Foundation; either version 2 of the License, or (at your option)
     12  * any later version.
     13  *
     14  */
     15 #include <string.h>
     16 #include <inttypes.h>
     17 
     18 #include "../os/os.h"
     19 
     20 #include "sha3.h"
     21 
     22 #define KECCAK_ROUNDS 24
     23 
     24 #define ROTL64(x, y) (((x) << (y)) | ((x) >> (64 - (y))))
     25 
     26 static const uint64_t keccakf_rndc[24] = {
     27 	0x0000000000000001ULL, 0x0000000000008082ULL, 0x800000000000808aULL,
     28 	0x8000000080008000ULL, 0x000000000000808bULL, 0x0000000080000001ULL,
     29 	0x8000000080008081ULL, 0x8000000000008009ULL, 0x000000000000008aULL,
     30 	0x0000000000000088ULL, 0x0000000080008009ULL, 0x000000008000000aULL,
     31 	0x000000008000808bULL, 0x800000000000008bULL, 0x8000000000008089ULL,
     32 	0x8000000000008003ULL, 0x8000000000008002ULL, 0x8000000000000080ULL,
     33 	0x000000000000800aULL, 0x800000008000000aULL, 0x8000000080008081ULL,
     34 	0x8000000000008080ULL, 0x0000000080000001ULL, 0x8000000080008008ULL
     35 };
     36 
     37 static const int keccakf_rotc[24] = {
     38 	1,  3,  6,  10, 15, 21, 28, 36, 45, 55, 2,  14,
     39 	27, 41, 56, 8,  25, 43, 62, 18, 39, 61, 20, 44
     40 };
     41 
     42 static const int keccakf_piln[24] = {
     43 	10, 7,  11, 17, 18, 3, 5,  16, 8,  21, 24, 4,
     44 	15, 23, 19, 13, 12, 2, 20, 14, 22, 9,  6,  1
     45 };
     46 
     47 /* update the state with given number of rounds */
     48 
     49 static void keccakf(uint64_t st[25])
     50 {
     51 	int i, j, round;
     52 	uint64_t t, bc[5];
     53 
     54 	for (round = 0; round < KECCAK_ROUNDS; round++) {
     55 
     56 		/* Theta */
     57 		for (i = 0; i < 5; i++)
     58 			bc[i] = st[i] ^ st[i + 5] ^ st[i + 10] ^ st[i + 15]
     59 				^ st[i + 20];
     60 
     61 		for (i = 0; i < 5; i++) {
     62 			t = bc[(i + 4) % 5] ^ ROTL64(bc[(i + 1) % 5], 1);
     63 			for (j = 0; j < 25; j += 5)
     64 				st[j + i] ^= t;
     65 		}
     66 
     67 		/* Rho Pi */
     68 		t = st[1];
     69 		for (i = 0; i < 24; i++) {
     70 			j = keccakf_piln[i];
     71 			bc[0] = st[j];
     72 			st[j] = ROTL64(t, keccakf_rotc[i]);
     73 			t = bc[0];
     74 		}
     75 
     76 		/* Chi */
     77 		for (j = 0; j < 25; j += 5) {
     78 			for (i = 0; i < 5; i++)
     79 				bc[i] = st[j + i];
     80 			for (i = 0; i < 5; i++)
     81 				st[j + i] ^= (~bc[(i + 1) % 5]) &
     82 					     bc[(i + 2) % 5];
     83 		}
     84 
     85 		/* Iota */
     86 		st[0] ^= keccakf_rndc[round];
     87 	}
     88 }
     89 
     90 static void fio_sha3_init(struct fio_sha3_ctx *sctx, unsigned int digest_sz)
     91 {
     92 	memset(sctx->st, 0, sizeof(sctx->st));
     93 	sctx->md_len = digest_sz;
     94 	sctx->rsiz = 200 - 2 * digest_sz;
     95 	sctx->rsizw = sctx->rsiz / 8;
     96 	sctx->partial = 0;
     97 	memset(sctx->buf, 0, sizeof(sctx->buf));
     98 }
     99 
    100 void fio_sha3_224_init(struct fio_sha3_ctx *sctx)
    101 {
    102 	fio_sha3_init(sctx, SHA3_224_DIGEST_SIZE);
    103 }
    104 
    105 void fio_sha3_256_init(struct fio_sha3_ctx *sctx)
    106 {
    107 	fio_sha3_init(sctx, SHA3_256_DIGEST_SIZE);
    108 }
    109 
    110 void fio_sha3_384_init(struct fio_sha3_ctx *sctx)
    111 {
    112 	fio_sha3_init(sctx, SHA3_384_DIGEST_SIZE);
    113 }
    114 
    115 void fio_sha3_512_init(struct fio_sha3_ctx *sctx)
    116 {
    117 	fio_sha3_init(sctx, SHA3_512_DIGEST_SIZE);
    118 }
    119 
    120 int fio_sha3_update(struct fio_sha3_ctx *sctx, const uint8_t *data,
    121 		    unsigned int len)
    122 {
    123 	unsigned int done;
    124 	const uint8_t *src;
    125 
    126 	done = 0;
    127 	src = data;
    128 
    129 	if ((sctx->partial + len) > (sctx->rsiz - 1)) {
    130 		if (sctx->partial) {
    131 			done = -sctx->partial;
    132 			memcpy(sctx->buf + sctx->partial, data,
    133 			       done + sctx->rsiz);
    134 			src = sctx->buf;
    135 		}
    136 
    137 		do {
    138 			unsigned int i;
    139 
    140 			for (i = 0; i < sctx->rsizw; i++)
    141 				sctx->st[i] ^= ((uint64_t *) src)[i];
    142 			keccakf(sctx->st);
    143 
    144 			done += sctx->rsiz;
    145 			src = data + done;
    146 		} while (done + (sctx->rsiz - 1) < len);
    147 
    148 		sctx->partial = 0;
    149 	}
    150 	memcpy(sctx->buf + sctx->partial, src, len - done);
    151 	sctx->partial += (len - done);
    152 
    153 	return 0;
    154 }
    155 
    156 void fio_sha3_final(struct fio_sha3_ctx *sctx)
    157 {
    158 	unsigned int i, inlen = sctx->partial;
    159 
    160 	sctx->buf[inlen++] = 0x06;
    161 	memset(sctx->buf + inlen, 0, sctx->rsiz - inlen);
    162 	sctx->buf[sctx->rsiz - 1] |= 0x80;
    163 
    164 	for (i = 0; i < sctx->rsizw; i++)
    165 		sctx->st[i] ^= ((uint64_t *) sctx->buf)[i];
    166 
    167 	keccakf(sctx->st);
    168 
    169 	for (i = 0; i < sctx->rsizw; i++)
    170 		sctx->st[i] = cpu_to_le64(sctx->st[i]);
    171 
    172 	memcpy(sctx->sha, sctx->st, sctx->md_len);
    173 }
    174