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>