Annotation of embedaddon/strongswan/src/libstrongswan/plugins/sha3/sha3_keccak.c, revision 1.1
1.1 ! misho 1: /*
! 2: * Copyright (C) 2015-2016 Andreas Steffen
! 3: * HSR Hochschule fuer Technik Rapperswil
! 4: *
! 5: * Based on the implementation by the Keccak, Keyak and Ketje Teams, namely,
! 6: * Guido Bertoni, Joan Daemen, Michaël Peeters, Gilles Van Assche and
! 7: * Ronny Van Keer, hereby denoted as "the implementer".
! 8: *
! 9: * To the extent possible under law, the implementer has waived all copyright
! 10: * and related or neighboring rights to the source code in this file.
! 11: * http://creativecommons.org/publicdomain/zero/1.0/
! 12: */
! 13:
! 14: #include <string.h>
! 15:
! 16: #include "sha3_keccak.h"
! 17:
! 18: typedef struct private_sha3_keccak_t private_sha3_keccak_t;
! 19:
! 20: #define KECCAK_STATE_SIZE 200 /* bytes */
! 21: #define KECCAK_MAX_RATE 168 /* bytes */
! 22:
! 23: static const uint64_t round_constants[] = {
! 24: 0x0000000000000001ULL,
! 25: 0x0000000000008082ULL,
! 26: 0x800000000000808aULL,
! 27: 0x8000000080008000ULL,
! 28: 0x000000000000808bULL,
! 29: 0x0000000080000001ULL,
! 30: 0x8000000080008081ULL,
! 31: 0x8000000000008009ULL,
! 32: 0x000000000000008aULL,
! 33: 0x0000000000000088ULL,
! 34: 0x0000000080008009ULL,
! 35: 0x000000008000000aULL,
! 36: 0x000000008000808bULL,
! 37: 0x800000000000008bULL,
! 38: 0x8000000000008089ULL,
! 39: 0x8000000000008003ULL,
! 40: 0x8000000000008002ULL,
! 41: 0x8000000000000080ULL,
! 42: 0x000000000000800aULL,
! 43: 0x800000008000000aULL,
! 44: 0x8000000080008081ULL,
! 45: 0x8000000000008080ULL,
! 46: 0x0000000080000001ULL,
! 47: 0x8000000080008008ULL
! 48: };
! 49:
! 50: /**
! 51: * Private data structure with hashing context for SHA-3
! 52: */
! 53: struct private_sha3_keccak_t {
! 54:
! 55: /**
! 56: * Public interface for this hasher.
! 57: */
! 58: sha3_keccak_t public;
! 59:
! 60: /**
! 61: * Internal state of 1600 bits as defined by FIPS-202
! 62: */
! 63: uint8_t state[KECCAK_STATE_SIZE];
! 64:
! 65: /**
! 66: * Rate in bytes
! 67: */
! 68: u_int rate;
! 69:
! 70: /**
! 71: * Rate input buffer
! 72: */
! 73: uint8_t rate_buffer[KECCAK_MAX_RATE];
! 74:
! 75: /**
! 76: * Index pointing to the current position in the rate buffer
! 77: */
! 78: u_int rate_index;
! 79:
! 80: /**
! 81: * Suffix delimiting the input message
! 82: */
! 83: uint8_t delimited_suffix;
! 84:
! 85: };
! 86:
! 87: #if BYTE_ORDER != LITTLE_ENDIAN
! 88: /**
! 89: * Function to load a 64-bit value using the little-endian (LE) convention.
! 90: * On a LE platform, this could be greatly simplified using a cast.
! 91: */
! 92: static uint64_t load64(const uint8_t *x)
! 93: {
! 94: int i;
! 95: uint64_t u = 0;
! 96:
! 97: for (i = 7; i >= 0; --i)
! 98: {
! 99: u <<= 8;
! 100: u |= x[i];
! 101: }
! 102: return u;
! 103: }
! 104:
! 105: /**
! 106: * Function to store a 64-bit value using the little-endian (LE) convention.
! 107: * On a LE platform, this could be greatly simplified using a cast.
! 108: */
! 109: static void store64(uint8_t *x, uint64_t u)
! 110: {
! 111: u_int i;
! 112:
! 113: for (i = 0; i < 8; ++i)
! 114: {
! 115: x[i] = u;
! 116: u >>= 8;
! 117: }
! 118: }
! 119:
! 120: /**
! 121: * Function to XOR into a 64-bit value using the little-endian (LE) convention.
! 122: * On a LE platform, this could be greatly simplified using a cast.
! 123: */
! 124: static void xor64(uint8_t *x, uint64_t u)
! 125: {
! 126: u_int i;
! 127:
! 128: for (i = 0; i < 8; ++i)
! 129: {
! 130: x[i] ^= u;
! 131: u >>= 8;
! 132: }
! 133: }
! 134: #endif
! 135:
! 136: /**
! 137: * Some macros used by the Keccak-f[1600] permutation.
! 138: */
! 139: #define ROL64(a, offset) ((((uint64_t)a) << offset) ^ (((uint64_t)a) >> (64-offset)))
! 140:
! 141: #if BYTE_ORDER == LITTLE_ENDIAN
! 142: #define readLane(i) (((uint64_t*)state)[i])
! 143: #define writeLane(i, lane) (((uint64_t*)state)[i]) = (lane)
! 144: #define XORLane(i, lane) (((uint64_t*)state)[i]) ^= (lane)
! 145: #elif BYTE_ORDER == BIG_ENDIAN
! 146: #define readLane(i) load64((uint8_t*)state+sizeof(uint64_t)*i)
! 147: #define writeLane(i, lane) store64((uint8_t*)state+sizeof(uint64_t)*i, lane)
! 148: #define XORLane(i, lane) xor64((uint8_t*)state+sizeof(uint64_t)*i, lane)
! 149: #endif
! 150:
! 151: /**
! 152: * Function that computes the Keccak-f[1600] permutation on the given state.
! 153: */
! 154: static void keccak_f1600_state_permute(void *state)
! 155: {
! 156: int round;
! 157:
! 158: for (round = 0; round < 24; round++)
! 159: {
! 160: { /* θ step (see [Keccak Reference, Section 2.3.2]) */
! 161:
! 162: uint64_t C[5], D;
! 163:
! 164: /* Compute the parity of the columns */
! 165: C[0] = readLane(0) ^ readLane( 5) ^ readLane(10)
! 166: ^ readLane(15) ^ readLane(20);
! 167: C[1] = readLane(1) ^ readLane( 6) ^ readLane(11)
! 168: ^ readLane(16) ^ readLane(21);
! 169: C[2] = readLane(2) ^ readLane( 7) ^ readLane(12)
! 170: ^ readLane(17) ^ readLane(22);
! 171: C[3] = readLane(3) ^ readLane( 8) ^ readLane(13)
! 172: ^ readLane(18) ^ readLane(23);
! 173: C[4] = readLane(4) ^ readLane( 9) ^ readLane(14)
! 174: ^ readLane(19) ^ readLane(24);
! 175:
! 176: /* Compute and add the θ effect to the whole column */
! 177: D = C[4] ^ ROL64(C[1], 1);
! 178: XORLane( 0, D);
! 179: XORLane( 5, D);
! 180: XORLane(10, D);
! 181: XORLane(15, D);
! 182: XORLane(20, D);
! 183:
! 184: D = C[0] ^ ROL64(C[2], 1);
! 185: XORLane( 1, D);
! 186: XORLane( 6, D);
! 187: XORLane(11, D);
! 188: XORLane(16, D);
! 189: XORLane(21, D);
! 190:
! 191: D = C[1] ^ ROL64(C[3], 1);
! 192: XORLane( 2, D);
! 193: XORLane( 7, D);
! 194: XORLane(12, D);
! 195: XORLane(17, D);
! 196: XORLane(22, D);
! 197:
! 198: D = C[2] ^ ROL64(C[4], 1);
! 199: XORLane( 3, D);
! 200: XORLane( 8, D);
! 201: XORLane(13, D);
! 202: XORLane(18, D);
! 203: XORLane(23, D);
! 204:
! 205: D = C[3] ^ ROL64(C[0], 1);
! 206: XORLane( 4, D);
! 207: XORLane( 9, D);
! 208: XORLane(14, D);
! 209: XORLane(19, D);
! 210: XORLane(24, D);
! 211: }
! 212:
! 213: { /* ρ and π steps (see [Keccak Reference, Sections 2.3.3 and 2.3.4]) */
! 214:
! 215: uint64_t t1, t2;
! 216:
! 217: t1 = readLane( 1);
! 218:
! 219: t2 = readLane(10);
! 220: writeLane(10, ROL64(t1, 1));
! 221:
! 222: t1 = readLane( 7);
! 223: writeLane( 7, ROL64(t2, 3));
! 224:
! 225: t2 = readLane(11);
! 226: writeLane(11, ROL64(t1, 6));
! 227:
! 228: t1 = readLane(17);
! 229: writeLane(17, ROL64(t2, 10));
! 230:
! 231: t2 = readLane(18);
! 232: writeLane(18, ROL64(t1, 15));
! 233:
! 234: t1 = readLane( 3);
! 235: writeLane( 3, ROL64(t2, 21));
! 236:
! 237: t2 = readLane( 5);
! 238: writeLane( 5, ROL64(t1, 28));
! 239:
! 240: t1 = readLane(16);
! 241: writeLane(16, ROL64(t2, 36));
! 242:
! 243: t2 = readLane( 8);
! 244: writeLane( 8, ROL64(t1, 45));
! 245:
! 246: t1 = readLane(21);
! 247: writeLane(21, ROL64(t2, 55));
! 248:
! 249: t2 = readLane(24);
! 250: writeLane(24, ROL64(t1, 2));
! 251:
! 252: t1 = readLane( 4);
! 253: writeLane( 4, ROL64(t2, 14));
! 254:
! 255: t2 = readLane(15);
! 256: writeLane(15, ROL64(t1, 27));
! 257:
! 258: t1 = readLane(23);
! 259: writeLane(23, ROL64(t2, 41));
! 260:
! 261: t2 = readLane(19);
! 262: writeLane(19, ROL64(t1, 56));
! 263:
! 264: t1 = readLane(13);
! 265: writeLane(13, ROL64(t2, 8));
! 266:
! 267: t2 = readLane(12);
! 268: writeLane(12, ROL64(t1, 25));
! 269:
! 270: t1 = readLane( 2);
! 271: writeLane( 2, ROL64(t2, 43));
! 272:
! 273: t2 = readLane(20);
! 274: writeLane(20, ROL64(t1, 62));
! 275:
! 276: t1 = readLane(14);
! 277: writeLane(14, ROL64(t2, 18));
! 278:
! 279: t2 = readLane(22);
! 280: writeLane(22, ROL64(t1, 39));
! 281:
! 282: t1 = readLane( 9);
! 283: writeLane( 9, ROL64(t2, 61));
! 284:
! 285: t2 = readLane( 6);
! 286: writeLane( 6, ROL64(t1, 20));
! 287:
! 288: writeLane( 1, ROL64(t2, 44));
! 289: }
! 290:
! 291: { /* χ step (see [Keccak Reference, Section 2.3.1]) */
! 292:
! 293: uint64_t t[5];
! 294:
! 295: t[0] = readLane(0);
! 296: t[1] = readLane(1);
! 297: t[2] = readLane(2);
! 298: t[3] = readLane(3);
! 299: t[4] = readLane(4);
! 300:
! 301: writeLane(0, t[0] ^ ((~t[1]) & t[2]));
! 302: writeLane(1, t[1] ^ ((~t[2]) & t[3]));
! 303: writeLane(2, t[2] ^ ((~t[3]) & t[4]));
! 304: writeLane(3, t[3] ^ ((~t[4]) & t[0]));
! 305: writeLane(4, t[4] ^ ((~t[0]) & t[1]));
! 306:
! 307: t[0] = readLane(5);
! 308: t[1] = readLane(6);
! 309: t[2] = readLane(7);
! 310: t[3] = readLane(8);
! 311: t[4] = readLane(9);
! 312:
! 313: writeLane(5, t[0] ^ ((~t[1]) & t[2]));
! 314: writeLane(6, t[1] ^ ((~t[2]) & t[3]));
! 315: writeLane(7, t[2] ^ ((~t[3]) & t[4]));
! 316: writeLane(8, t[3] ^ ((~t[4]) & t[0]));
! 317: writeLane(9, t[4] ^ ((~t[0]) & t[1]));
! 318:
! 319: t[0] = readLane(10);
! 320: t[1] = readLane(11);
! 321: t[2] = readLane(12);
! 322: t[3] = readLane(13);
! 323: t[4] = readLane(14);
! 324:
! 325: writeLane(10, t[0] ^ ((~t[1]) & t[2]));
! 326: writeLane(11, t[1] ^ ((~t[2]) & t[3]));
! 327: writeLane(12, t[2] ^ ((~t[3]) & t[4]));
! 328: writeLane(13, t[3] ^ ((~t[4]) & t[0]));
! 329: writeLane(14, t[4] ^ ((~t[0]) & t[1]));
! 330:
! 331: t[0] = readLane(15);
! 332: t[1] = readLane(16);
! 333: t[2] = readLane(17);
! 334: t[3] = readLane(18);
! 335: t[4] = readLane(19);
! 336:
! 337: writeLane(15, t[0] ^ ((~t[1]) & t[2]));
! 338: writeLane(16, t[1] ^ ((~t[2]) & t[3]));
! 339: writeLane(17, t[2] ^ ((~t[3]) & t[4]));
! 340: writeLane(18, t[3] ^ ((~t[4]) & t[0]));
! 341: writeLane(19, t[4] ^ ((~t[0]) & t[1]));
! 342:
! 343: t[0] = readLane(20);
! 344: t[1] = readLane(21);
! 345: t[2] = readLane(22);
! 346: t[3] = readLane(23);
! 347: t[4] = readLane(24);
! 348:
! 349: writeLane(20, t[0] ^ ((~t[1]) & t[2]));
! 350: writeLane(21, t[1] ^ ((~t[2]) & t[3]));
! 351: writeLane(22, t[2] ^ ((~t[3]) & t[4]));
! 352: writeLane(23, t[3] ^ ((~t[4]) & t[0]));
! 353: writeLane(24, t[4] ^ ((~t[0]) & t[1]));
! 354: }
! 355:
! 356: { /* ι step (see [Keccak Reference, Section 2.3.5]) */
! 357:
! 358: XORLane(0, round_constants[round]);
! 359: }
! 360: }
! 361: }
! 362:
! 363: METHOD(sha3_keccak_t, get_rate, u_int,
! 364: private_sha3_keccak_t *this)
! 365: {
! 366: return this->rate;
! 367: }
! 368:
! 369: METHOD(sha3_keccak_t, reset, void,
! 370: private_sha3_keccak_t *this)
! 371: {
! 372: memset(this->state, 0x00, KECCAK_STATE_SIZE);
! 373: this->rate_index = 0;
! 374: }
! 375:
! 376:
! 377: METHOD(sha3_keccak_t, absorb, void,
! 378: private_sha3_keccak_t *this, chunk_t data)
! 379: {
! 380: uint64_t *buffer_lanes, *state_lanes;
! 381: size_t len, rate_lanes;
! 382: int i;
! 383:
! 384: buffer_lanes = (uint64_t*)this->rate_buffer;
! 385: state_lanes = (uint64_t*)this->state;
! 386: rate_lanes = this->rate / sizeof(uint64_t);
! 387:
! 388: while (data.len)
! 389: {
! 390: len = min(data.len, this->rate - this->rate_index);
! 391: memcpy(this->rate_buffer + this->rate_index, data.ptr, len);
! 392: this->rate_index += len;
! 393: data.ptr += len;
! 394: data.len -= len;
! 395:
! 396: if (this->rate_index == this->rate)
! 397: {
! 398: for (i = 0; i < rate_lanes; i++)
! 399: {
! 400: state_lanes[i] ^= buffer_lanes[i];
! 401: }
! 402: this->rate_index = 0;
! 403:
! 404: keccak_f1600_state_permute(this->state);
! 405: }
! 406: }
! 407: }
! 408:
! 409: METHOD(sha3_keccak_t, finalize, void,
! 410: private_sha3_keccak_t *this)
! 411: {
! 412: uint64_t *buffer_lanes, *state_lanes;
! 413: size_t rate_lanes, remainder;
! 414: int i;
! 415:
! 416: /* Add the delimitedSuffix as the first bit of padding */
! 417: this->rate_buffer[this->rate_index++] = this->delimited_suffix;
! 418:
! 419: buffer_lanes = (uint64_t*)this->rate_buffer;
! 420: state_lanes = (uint64_t*)this->state;
! 421: rate_lanes = this->rate_index / sizeof(uint64_t);
! 422:
! 423: remainder = this->rate_index - rate_lanes * sizeof(uint64_t);
! 424: if (remainder)
! 425: {
! 426: memset(this->rate_buffer + this->rate_index, 0x00,
! 427: sizeof(uint64_t) - remainder);
! 428: rate_lanes++;
! 429: }
! 430: for (i = 0; i < rate_lanes; i++)
! 431: {
! 432: state_lanes[i] ^= buffer_lanes[i];
! 433: }
! 434:
! 435: /* Add the second bit of padding */
! 436: this->state[this->rate - 1] ^= 0x80;
! 437:
! 438: /* Switch to the squeezing phase */
! 439: keccak_f1600_state_permute(this->state);
! 440: this->rate_index = 0;
! 441: }
! 442:
! 443: METHOD(sha3_keccak_t, squeeze, void,
! 444: private_sha3_keccak_t *this, size_t out_len, uint8_t *out)
! 445: {
! 446: size_t index = 0, len;
! 447:
! 448: while (index < out_len)
! 449: {
! 450: if (this->rate_index == this->rate)
! 451: {
! 452: keccak_f1600_state_permute(this->state);
! 453: this->rate_index = 0;
! 454: }
! 455: len = min(out_len - index, this->rate - this->rate_index);
! 456: memcpy(out, &this->state[this->rate_index], len);
! 457: out += len;
! 458: index += len;
! 459: this->rate_index += len;
! 460: }
! 461: }
! 462:
! 463: METHOD(sha3_keccak_t, destroy, void,
! 464: private_sha3_keccak_t *this)
! 465: {
! 466: free(this);
! 467: }
! 468:
! 469: /*
! 470: * Described in header.
! 471: */
! 472: sha3_keccak_t *sha3_keccak_create(u_int capacity, uint8_t delimited_suffix)
! 473: {
! 474: private_sha3_keccak_t *this;
! 475: int rate;
! 476:
! 477: rate = KECCAK_STATE_SIZE - capacity;
! 478:
! 479: if (rate <= 0 || rate > KECCAK_MAX_RATE)
! 480: {
! 481: return NULL;
! 482: }
! 483:
! 484: INIT(this,
! 485: .public = {
! 486: .get_rate = _get_rate,
! 487: .reset = _reset,
! 488: .absorb = _absorb,
! 489: .finalize = _finalize,
! 490: .squeeze = _squeeze,
! 491: .destroy = _destroy,
! 492: },
! 493: .rate = rate,
! 494: .delimited_suffix = delimited_suffix,
! 495: );
! 496:
! 497: return &this->public;
! 498: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>