Annotation of embedaddon/strongswan/src/libstrongswan/plugins/aesni/aesni_key.c, revision 1.1.1.1

1.1       misho       1: /*
                      2:  * Copyright (C) 2015 Martin Willi
                      3:  * Copyright (C) 2015 revosec AG
                      4:  *
                      5:  * This program is free software; you can redistribute it and/or modify it
                      6:  * under the terms of the GNU General Public License as published by the
                      7:  * Free Software Foundation; either version 2 of the License, or (at your
                      8:  * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
                      9:  *
                     10:  * This program is distributed in the hope that it will be useful, but
                     11:  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
                     12:  * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
                     13:  * for more details.
                     14:  */
                     15: 
                     16: #include "aesni_key.h"
                     17: 
                     18: /**
                     19:  * Rounds used for each AES key size
                     20:  */
                     21: #define AES128_ROUNDS 10
                     22: #define AES192_ROUNDS 12
                     23: #define AES256_ROUNDS 14
                     24: 
                     25: typedef struct private_aesni_key_t private_aesni_key_t;
                     26: 
                     27: /**
                     28:  * Private data of an aesni_key_t object.
                     29:  */
                     30: struct private_aesni_key_t {
                     31: 
                     32:        /**
                     33:         * Public aesni_key_t interface.
                     34:         */
                     35:        aesni_key_t public;
                     36: };
                     37: 
                     38: /**
                     39:  * Invert round encryption keys to get a decryption key schedule
                     40:  */
                     41: static void reverse_key(aesni_key_t *this)
                     42: {
                     43:        __m128i t[this->rounds + 1];
                     44:        int i;
                     45: 
                     46:        for (i = 0; i <= this->rounds; i++)
                     47:        {
                     48:                t[i] = this->schedule[i];
                     49:        }
                     50:        this->schedule[this->rounds] = t[0];
                     51:        for (i = 1; i < this->rounds; i++)
                     52:        {
                     53:                this->schedule[this->rounds - i] = _mm_aesimc_si128(t[i]);
                     54:        }
                     55:        this->schedule[0] = t[this->rounds];
                     56: 
                     57:        memwipe(t, sizeof(t));
                     58: }
                     59: 
                     60: /**
                     61:  * Assist in creating a 128-bit round key
                     62:  */
                     63: static __m128i assist128(__m128i a, __m128i b)
                     64: {
                     65:        __m128i c;
                     66: 
                     67:        b = _mm_shuffle_epi32(b ,0xff);
                     68:        c = _mm_slli_si128(a, 0x04);
                     69:        a = _mm_xor_si128(a, c);
                     70:        c = _mm_slli_si128(c, 0x04);
                     71:        a = _mm_xor_si128(a, c);
                     72:        c = _mm_slli_si128(c, 0x04);
                     73:        a = _mm_xor_si128(a, c);
                     74:        a = _mm_xor_si128(a, b);
                     75: 
                     76:        return a;
                     77: }
                     78: 
                     79: /**
                     80:  * Expand a 128-bit key to encryption round keys
                     81:  */
                     82: static void expand128(__m128i *key, __m128i *schedule)
                     83: {
                     84:        __m128i t;
                     85: 
                     86:        schedule[0] = t = _mm_loadu_si128(key);
                     87:        schedule[1] = t = assist128(t, _mm_aeskeygenassist_si128(t, 0x01));
                     88:        schedule[2] = t = assist128(t, _mm_aeskeygenassist_si128(t, 0x02));
                     89:        schedule[3] = t = assist128(t, _mm_aeskeygenassist_si128(t, 0x04));
                     90:        schedule[4] = t = assist128(t, _mm_aeskeygenassist_si128(t, 0x08));
                     91:        schedule[5] = t = assist128(t, _mm_aeskeygenassist_si128(t, 0x10));
                     92:        schedule[6] = t = assist128(t, _mm_aeskeygenassist_si128(t, 0x20));
                     93:        schedule[7] = t = assist128(t, _mm_aeskeygenassist_si128(t, 0x40));
                     94:        schedule[8] = t = assist128(t, _mm_aeskeygenassist_si128(t, 0x80));
                     95:        schedule[9] = t = assist128(t, _mm_aeskeygenassist_si128(t, 0x1b));
                     96:        schedule[10]    = assist128(t, _mm_aeskeygenassist_si128(t, 0x36));
                     97: }
                     98: 
                     99: /**
                    100:  * Assist in creating a 192-bit round key
                    101:  */
                    102: static __m128i assist192(__m128i b, __m128i c, __m128i *a)
                    103: {
                    104:        __m128i t;
                    105: 
                    106:         b = _mm_shuffle_epi32(b, 0x55);
                    107:         t = _mm_slli_si128(*a, 0x04);
                    108:        *a = _mm_xor_si128(*a, t);
                    109:         t = _mm_slli_si128(t, 0x04);
                    110:        *a = _mm_xor_si128(*a, t);
                    111:         t = _mm_slli_si128(t, 0x04);
                    112:        *a = _mm_xor_si128(*a, t);
                    113:        *a = _mm_xor_si128(*a, b);
                    114:         b = _mm_shuffle_epi32(*a, 0xff);
                    115:         t = _mm_slli_si128(c, 0x04);
                    116:         t = _mm_xor_si128(c, t);
                    117:         t = _mm_xor_si128(t, b);
                    118: 
                    119:        return t;
                    120: }
                    121: 
                    122: /**
                    123:  * return a[63:0] | b[63:0] << 64
                    124:  */
                    125: static __m128i _mm_shuffle_i00(__m128i a, __m128i b)
                    126: {
                    127:        return (__m128i)_mm_shuffle_pd((__m128d)a, (__m128d)b, 0);
                    128: }
                    129: 
                    130: /**
                    131:  * return a[127:64] >> 64 | b[63:0] << 64
                    132:  */
                    133: static __m128i _mm_shuffle_i01(__m128i a, __m128i b)
                    134: {
                    135:        return (__m128i)_mm_shuffle_pd((__m128d)a, (__m128d)b, 1);
                    136: }
                    137: 
                    138: /**
                    139:  * Expand a 192-bit encryption key to round keys
                    140:  */
                    141: static void expand192(__m128i *key, __m128i *schedule)
                    142: {
                    143:        __m128i t1, t2, t3;
                    144: 
                    145:        schedule[0] = t1 = _mm_loadu_si128(key);
                    146:        t2 = t3 = _mm_loadu_si128(key + 1);
                    147: 
                    148:        t2 = assist192(_mm_aeskeygenassist_si128(t2, 0x1), t2, &t1);
                    149:        schedule[1] = _mm_shuffle_i00(t3, t1);
                    150:        schedule[2] = _mm_shuffle_i01(t1, t2);
                    151:        t2 = t3 = assist192(_mm_aeskeygenassist_si128(t2, 0x2), t2, &t1);
                    152:        schedule[3] = t1;
                    153: 
                    154:        t2 = assist192(_mm_aeskeygenassist_si128(t2, 0x4), t2, &t1);
                    155:        schedule[4] = _mm_shuffle_i00(t3, t1);
                    156:        schedule[5] = _mm_shuffle_i01(t1, t2);
                    157:        t2 = t3 = assist192(_mm_aeskeygenassist_si128(t2, 0x8), t2, &t1);
                    158:        schedule[6] = t1;
                    159: 
                    160:        t2 = assist192(_mm_aeskeygenassist_si128 (t2,0x10), t2, &t1);
                    161:        schedule[7] = _mm_shuffle_i00(t3, t1);
                    162:        schedule[8] = _mm_shuffle_i01(t1, t2);
                    163:        t2 = t3 = assist192(_mm_aeskeygenassist_si128 (t2,0x20), t2, &t1);
                    164:        schedule[9] = t1;
                    165: 
                    166:        t2 = assist192(_mm_aeskeygenassist_si128(t2, 0x40), t2, &t1);
                    167:        schedule[10] = _mm_shuffle_i00(t3, t1);
                    168:        schedule[11] = _mm_shuffle_i01(t1, t2);
                    169:        assist192(_mm_aeskeygenassist_si128(t2, 0x80), t2, &t1);
                    170:        schedule[12] = t1;
                    171: }
                    172: 
                    173: /**
                    174:  * Assist in creating a 256-bit round key
                    175:  */
                    176: static __m128i assist256_1(__m128i a, __m128i b)
                    177: {
                    178:        __m128i x, y;
                    179: 
                    180:        b = _mm_shuffle_epi32(b, 0xff);
                    181:        y = _mm_slli_si128(a, 0x04);
                    182:        x = _mm_xor_si128(a, y);
                    183:        y = _mm_slli_si128(y, 0x04);
                    184:        x = _mm_xor_si128 (x, y);
                    185:        y = _mm_slli_si128(y, 0x04);
                    186:        x = _mm_xor_si128(x, y);
                    187:        x = _mm_xor_si128(x, b);
                    188: 
                    189:        return x;
                    190: }
                    191: 
                    192: /**
                    193:  * Assist in creating a 256-bit round key
                    194:  */
                    195: static __m128i assist256_2(__m128i a, __m128i b)
                    196: {
                    197:        __m128i x, y, z;
                    198: 
                    199:        y = _mm_aeskeygenassist_si128(a, 0x00);
                    200:        z = _mm_shuffle_epi32(y, 0xaa);
                    201:        y = _mm_slli_si128(b, 0x04);
                    202:        x = _mm_xor_si128(b, y);
                    203:        y = _mm_slli_si128(y, 0x04);
                    204:        x = _mm_xor_si128(x, y);
                    205:        y = _mm_slli_si128(y, 0x04);
                    206:        x = _mm_xor_si128(x, y);
                    207:        x = _mm_xor_si128(x, z);
                    208: 
                    209:        return x;
                    210: }
                    211: 
                    212: /**
                    213:  * Expand a 256-bit encryption key to round keys
                    214:  */
                    215: static void expand256(__m128i *key, __m128i *schedule)
                    216: {
                    217:        __m128i t1, t2;
                    218: 
                    219:        schedule[0] = t1 = _mm_loadu_si128(key);
                    220:        schedule[1] = t2 = _mm_loadu_si128(key + 1);
                    221: 
                    222:        schedule[2] = t1 = assist256_1(t1, _mm_aeskeygenassist_si128(t2, 0x01));
                    223:        schedule[3] = t2 = assist256_2(t1, t2);
                    224: 
                    225:        schedule[4] = t1 = assist256_1(t1, _mm_aeskeygenassist_si128(t2, 0x02));
                    226:        schedule[5] = t2 = assist256_2(t1, t2);
                    227: 
                    228:        schedule[6] = t1 = assist256_1(t1, _mm_aeskeygenassist_si128(t2, 0x04));
                    229:        schedule[7] = t2 = assist256_2(t1, t2);
                    230: 
                    231:        schedule[8] = t1 = assist256_1(t1, _mm_aeskeygenassist_si128(t2, 0x08));
                    232:        schedule[9] = t2 = assist256_2(t1, t2);
                    233: 
                    234:        schedule[10] = t1 = assist256_1(t1, _mm_aeskeygenassist_si128(t2, 0x10));
                    235:        schedule[11] = t2 = assist256_2(t1, t2);
                    236: 
                    237:        schedule[12] = t1 = assist256_1(t1, _mm_aeskeygenassist_si128(t2, 0x20));
                    238:        schedule[13] = t2 = assist256_2(t1, t2);
                    239: 
                    240:        schedule[14] = assist256_1(t1, _mm_aeskeygenassist_si128(t2, 0x40));
                    241: }
                    242: 
                    243: METHOD(aesni_key_t, destroy, void,
                    244:        private_aesni_key_t *this)
                    245: {
                    246:        memwipe(this, sizeof(*this) + (this->public.rounds + 1) * AES_BLOCK_SIZE);
                    247:        free_align(this);
                    248: }
                    249: 
                    250: /**
                    251:  * See header
                    252:  */
                    253: aesni_key_t *aesni_key_create(bool encrypt, chunk_t key)
                    254: {
                    255:        private_aesni_key_t *this;
                    256:        int rounds;
                    257: 
                    258:        switch (key.len)
                    259:        {
                    260:                case 16:
                    261:                        rounds = AES128_ROUNDS;
                    262:                        break;
                    263:                case 24:
                    264:                        rounds = AES192_ROUNDS;
                    265:                        break;
                    266:                case 32:
                    267:                        rounds = AES256_ROUNDS;
                    268:                        break;
                    269:                default:
                    270:                        return NULL;
                    271:        }
                    272: 
                    273:        INIT_EXTRA_ALIGN(this, (rounds + 1) * AES_BLOCK_SIZE, sizeof(__m128i),
                    274:                .public = {
                    275:                        .destroy = _destroy,
                    276:                        .rounds = rounds,
                    277:                },
                    278:        );
                    279: 
                    280:        switch (key.len)
                    281:        {
                    282:                case 16:
                    283:                        expand128((__m128i*)key.ptr, this->public.schedule);
                    284:                        break;
                    285:                case 24:
                    286:                        expand192((__m128i*)key.ptr, this->public.schedule);
                    287:                        break;
                    288:                case 32:
                    289:                        expand256((__m128i*)key.ptr, this->public.schedule);
                    290:                        break;
                    291:                default:
                    292:                        break;
                    293:        }
                    294: 
                    295:        if (!encrypt)
                    296:        {
                    297:                reverse_key(&this->public);
                    298:        }
                    299: 
                    300:        return &this->public;
                    301: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>