Annotation of embedaddon/strongswan/src/libcharon/plugins/eap_aka_3gpp/eap_aka_3gpp_functions.c, revision 1.1.1.1

1.1       misho       1: /*
                      2:  * Copyright (C) 2017 Tobias Brunner
                      3:  * Copyright (C) 2008-2009 Martin Willi
                      4:  * HSR Hochschule fuer Technik Rapperswil
                      5:  *
                      6:  * This program is free software; you can redistribute it and/or modify it
                      7:  * under the terms of the GNU General Public License as published by the
                      8:  * Free Software Foundation; either version 2 of the License, or (at your
                      9:  * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
                     10:  *
                     11:  * This program is distributed in the hope that it will be useful, but
                     12:  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
                     13:  * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
                     14:  * for more details.
                     15:  */
                     16: /*
                     17:  * Copyright (C) 2015 Thomas Strangert
                     18:  * Polystar System AB, Sweden
                     19:  *
                     20:  * Permission is hereby granted, free of charge, to any person obtaining a copy
                     21:  * of this software and associated documentation files (the "Software"), to deal
                     22:  * in the Software without restriction, including without limitation the rights
                     23:  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
                     24:  * copies of the Software, and to permit persons to whom the Software is
                     25:  * furnished to do so, subject to the following conditions:
                     26:  *
                     27:  * The above copyright notice and this permission notice shall be included in
                     28:  * all copies or substantial portions of the Software.
                     29:  *
                     30:  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
                     31:  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
                     32:  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
                     33:  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
                     34:  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
                     35:  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
                     36:  * THE SOFTWARE.
                     37:  */
                     38: 
                     39: #include "eap_aka_3gpp_functions.h"
                     40: 
                     41: #include <limits.h>
                     42: #include <ctype.h>
                     43: #include <daemon.h>
                     44: 
                     45: typedef struct private_eap_aka_3gpp_functions_t private_eap_aka_3gpp_functions_t;
                     46: 
                     47: /**
                     48:  * Private data of an eap_aka_3gpp_functions_t object.
                     49:  */
                     50: struct private_eap_aka_3gpp_functions_t {
                     51: 
                     52:        /**
                     53:         * Public eap_aka_3gpp_functions_t interface.
                     54:         */
                     55:        eap_aka_3gpp_functions_t public;
                     56: 
                     57:        /**
                     58:         * AES instance
                     59:         */
                     60:        crypter_t *crypter;
                     61: };
                     62: 
                     63: /*
                     64:  * Described in header
                     65:  */
                     66: bool eap_aka_3gpp_get_k_opc(identification_t *id, uint8_t k[AKA_K_LEN],
                     67:                                                        uint8_t opc[AKA_OPC_LEN])
                     68: {
                     69:        shared_key_t *shared;
                     70:        chunk_t key;
                     71: 
                     72:        shared = lib->credmgr->get_shared(lib->credmgr, SHARED_EAP, id, NULL);
                     73:        if (!shared)
                     74:        {
                     75:                return FALSE;
                     76:        }
                     77:        key = shared->get_key(shared);
                     78: 
                     79:        if (key.len == AKA_K_LEN)
                     80:        {
                     81:                memcpy(k, key.ptr, AKA_K_LEN);
                     82:                /* set OPc to a neutral default value, harmless to XOR with */
                     83:                memset(opc, '\0', AKA_OPC_LEN);
                     84:        }
                     85:        else if (key.len == AKA_K_LEN + AKA_OPC_LEN)
                     86:        {
                     87:                memcpy(k, key.ptr, AKA_K_LEN);
                     88:                memcpy(opc, key.ptr + AKA_K_LEN, AKA_OPC_LEN);
                     89:        }
                     90:        else
                     91:        {
                     92:                DBG1(DBG_IKE, "invalid EAP K or K+OPc key found for %Y to authenticate "
                     93:                         "with AKA, should be a %d or %d byte long binary value", id,
                     94:                         AKA_K_LEN, AKA_K_LEN + AKA_OPC_LEN);
                     95:                shared->destroy(shared);
                     96:                return FALSE;
                     97:        }
                     98:        shared->destroy(shared);
                     99:        return TRUE;
                    100: }
                    101: 
                    102: /*
                    103:  * Described in header
                    104:  */
                    105: void eap_aka_3gpp_get_sqn(uint8_t sqn[AKA_SQN_LEN], int offset)
                    106: {
                    107:        timeval_t time;
                    108: 
                    109:        gettimeofday(&time, NULL);
                    110:        /* set sqn to an integer containing 4 bytes seconds + 2 bytes usecs */
                    111:        time.tv_sec = htonl(time.tv_sec + offset);
                    112:        /* usec's are never larger than 0x000f423f, so we shift the 12 first bits */
                    113:        time.tv_usec = htonl(time.tv_usec << 12);
                    114:        memcpy(sqn, (uint8_t*)&time.tv_sec + sizeof(time_t) - 4, 4);
                    115:        memcpy(sqn + 4, &time.tv_usec, 2);
                    116: }
                    117: 
                    118: static bool f1andf1star(private_eap_aka_3gpp_functions_t *this,
                    119:        const uint8_t k[AKA_K_LEN], const uint8_t opc[AKA_OPC_LEN],
                    120:        const uint8_t rand[AKA_RAND_LEN], const uint8_t sqn[AKA_SQN_LEN],
                    121:        const uint8_t amf[AKA_AMF_LEN], uint8_t mac[16])
                    122: {
                    123:        uint8_t i, data[16], in[16], iv[16] = { 0 };
                    124: 
                    125:        if (!this->crypter->set_key(this->crypter,
                    126:                                                                chunk_create((uint8_t*)k, AKA_K_LEN)))
                    127:        {
                    128:                return FALSE;
                    129:        }
                    130: 
                    131:        /* XOR RAND and OPc */
                    132:        memcpy(data, rand, sizeof(data));
                    133:        memxor(data, opc, sizeof(data));
                    134:        if (!this->crypter->encrypt(this->crypter, chunk_create(data, sizeof(data)),
                    135:                                                                chunk_create(iv, sizeof(iv)), NULL))
                    136:        {
                    137:                return FALSE;
                    138:        }
                    139: 
                    140:        /* concatenate SQN || AMF ||SQN || AMF */
                    141:        memcpy(in, sqn, 6);
                    142:        memcpy(&in[6], amf, 2);
                    143:        memcpy(&in[8], in, 8);
                    144: 
                    145:        /* XOR opc and in, rotate by r1=64, and XOR
                    146:         * on the constant c1 (which is all zeroes) and finally the output above */
                    147:        for (i = 0; i < 16; i++)
                    148:        {
                    149:                data[(i + 8) % 16] ^= in[i] ^ opc[i];
                    150:        }
                    151:        if (!this->crypter->encrypt(this->crypter, chunk_create(data, sizeof(data)),
                    152:                                                                chunk_create(iv, sizeof(iv)), NULL))
                    153:        {
                    154:                return FALSE;
                    155:        }
                    156:        memxor(data, opc, sizeof(data));
                    157:        memcpy(mac, data, 16);
                    158:        return TRUE;
                    159: }
                    160: 
                    161: METHOD(eap_aka_3gpp_functions_t, f1, bool,
                    162:        private_eap_aka_3gpp_functions_t *this, const uint8_t k[AKA_K_LEN],
                    163:        const uint8_t opc[AKA_OPC_LEN], const uint8_t rand[AKA_RAND_LEN],
                    164:        const uint8_t sqn[AKA_SQN_LEN], const uint8_t amf[AKA_AMF_LEN],
                    165:        uint8_t maca[AKA_MAC_LEN])
                    166: {
                    167:        uint8_t mac[16];
                    168: 
                    169:        if (!f1andf1star(this, k, opc, rand, sqn, amf, mac))
                    170:        {
                    171:                return FALSE;
                    172:        }
                    173:        /* only diff between f1 and f1* is here:
                    174:         * f1  uses bytes 0-7  as MAC-A
                    175:         * f1* uses bytes 8-15 as MAC-S */
                    176:        memcpy(maca, mac, AKA_MAC_LEN);
                    177:        return TRUE;
                    178: }
                    179: 
                    180: METHOD(eap_aka_3gpp_functions_t, f1star, bool,
                    181:        private_eap_aka_3gpp_functions_t *this, const uint8_t k[AKA_K_LEN],
                    182:        const uint8_t opc[AKA_OPC_LEN], const uint8_t rand[AKA_RAND_LEN],
                    183:        const uint8_t sqn[AKA_SQN_LEN], const uint8_t amf[AKA_AMF_LEN],
                    184:        uint8_t macs[AKA_MAC_LEN])
                    185: {
                    186:        uint8_t mac[16];
                    187: 
                    188:        if (!f1andf1star(this, k, opc, rand, sqn, amf, mac))
                    189:        {
                    190:                return FALSE;
                    191:        }
                    192:        /* only diff between f1 and f1* is here:
                    193:         * f1  uses bytes 0-7  as MAC-A
                    194:         * f1* uses bytes 8-15 as MAC-S */
                    195:        memcpy(macs, &mac[8], AKA_MAC_LEN);
                    196:        return TRUE;
                    197: }
                    198: 
                    199: METHOD(eap_aka_3gpp_functions_t, f2345, bool,
                    200:        private_eap_aka_3gpp_functions_t *this, const uint8_t k[AKA_K_LEN],
                    201:        const uint8_t opc[AKA_OPC_LEN], const uint8_t rand[AKA_RAND_LEN],
                    202:        uint8_t res[AKA_RES_LEN], uint8_t ck[AKA_CK_LEN], uint8_t ik[AKA_IK_LEN],
                    203:        uint8_t ak[AKA_AK_LEN])
                    204: {
                    205:        uint8_t data[16], iv[16] = { 0 };
                    206:        chunk_t temp;
                    207:        uint8_t i;
                    208: 
                    209:        if (!this->crypter->set_key(this->crypter,
                    210:                                                                chunk_create((uint8_t*)k, AKA_K_LEN)))
                    211:        {
                    212:                return FALSE;
                    213:        }
                    214: 
                    215:        /* XOR RAND and OPc */
                    216:        memcpy(data, rand, sizeof(data));
                    217:        memxor(data, opc, sizeof(data));
                    218:        if (!this->crypter->encrypt(this->crypter, chunk_create(data, sizeof(data)),
                    219:                                                                chunk_create(iv, sizeof(iv)), &temp))
                    220:        {
                    221:                return FALSE;
                    222:        }
                    223: 
                    224:        /* to obtain output block OUT2: XOR OPc and TEMP,
                    225:         * rotate by r2=0, and XOR on the constant c2 (which is all zeroes except
                    226:         * that the last bit is 1). */
                    227:        for (i = 0; i < 16; i++)
                    228:        {
                    229:                data[i] = temp.ptr[i] ^ opc[i];
                    230:        }
                    231:        data[15] ^= 1;
                    232: 
                    233:        if (!this->crypter->encrypt(this->crypter, chunk_create(data, sizeof(data)),
                    234:                                                                chunk_create(iv, sizeof(iv)), NULL))
                    235:        {
                    236:                chunk_free(&temp);
                    237:                return FALSE;
                    238:        }
                    239:        memxor(data, opc, sizeof(data));
                    240: 
                    241:        /* f5 output */
                    242:        memcpy(ak, data, 6);
                    243:        /* f2 output */
                    244:        memcpy(res, &data[8], 8);
                    245: 
                    246:        /* to obtain output block OUT3: XOR OPc and TEMP,
                    247:         * rotate by r3=32, and XOR on the constant c3 (which
                    248:         * is all zeroes except that the next to last bit is 1) */
                    249:        for (i = 0; i < 16; i++)
                    250:        {
                    251:                data[(i + 12) % 16] = temp.ptr[i] ^ opc[i];
                    252:        }
                    253:        data[15] ^= 2;
                    254: 
                    255:        if (!this->crypter->encrypt(this->crypter, chunk_create(data, sizeof(data)),
                    256:                                                                chunk_create(iv, sizeof(iv)), NULL))
                    257:        {
                    258:                chunk_free(&temp);
                    259:                return FALSE;
                    260:        }
                    261:        memxor(data, opc, sizeof(data));
                    262: 
                    263:        /* f3 output */
                    264:        memcpy(ck, data, 16);
                    265: 
                    266:        /* to obtain output block OUT4: XOR OPc and TEMP,
                    267:         * rotate by r4=64, and XOR on the constant c4 (which
                    268:         * is all zeroes except that the 2nd from last bit is 1). */
                    269:        for (i = 0; i < 16; i++)
                    270:        {
                    271:                data[(i + 8) % 16] = temp.ptr[i] ^ opc[i];
                    272:        }
                    273:        data[15] ^= 4;
                    274: 
                    275:        if (!this->crypter->encrypt(this->crypter, chunk_create(data, sizeof(data)),
                    276:                                                                chunk_create(iv, sizeof(iv)), NULL))
                    277:        {
                    278:                chunk_free(&temp);
                    279:                return FALSE;
                    280:        }
                    281:        memxor(data, opc, sizeof(data));
                    282:        /* f4 output */
                    283:        memcpy(ik, data, 16);
                    284:        chunk_free(&temp);
                    285:        return TRUE;
                    286: 
                    287: }
                    288: 
                    289: METHOD(eap_aka_3gpp_functions_t, f5star, bool,
                    290:        private_eap_aka_3gpp_functions_t *this, const uint8_t k[AKA_K_LEN],
                    291:        const uint8_t opc[AKA_OPC_LEN], const uint8_t rand[AKA_RAND_LEN],
                    292:        uint8_t aks[AKA_AK_LEN])
                    293: {
                    294:        uint8_t i, data[16], iv[16] = { 0 };
                    295:        chunk_t temp;
                    296: 
                    297:        if (!this->crypter->set_key(this->crypter,
                    298:                                                                chunk_create((uint8_t*)k, AKA_K_LEN)))
                    299:        {
                    300:                return FALSE;
                    301:        }
                    302: 
                    303:        /* XOR RAND and OPc */
                    304:        memcpy(data, rand, sizeof(data));
                    305:        memxor(data, opc, sizeof(data));
                    306:        if (!this->crypter->encrypt(this->crypter, chunk_create(data, sizeof(data)),
                    307:                                                                chunk_create(iv, sizeof(iv)), &temp))
                    308:        {
                    309:                return FALSE;
                    310:        }
                    311: 
                    312:        /* to obtain output block OUT5: XOR OPc and the output above,
                    313:         * rotate by r5=96, and XOR on the constant c5 (which
                    314:         * is all zeroes except that the 3rd from last bit is 1). */
                    315:        for (i = 0; i < 16; i++)
                    316:        {
                    317:                data[(i + 4) % 16] = temp.ptr[i] ^ opc[i];
                    318:        }
                    319:        data[15] ^= 8;
                    320:        chunk_free(&temp);
                    321: 
                    322:        if (!this->crypter->encrypt(this->crypter, chunk_create(data, sizeof(data)),
                    323:                                                                chunk_create(iv, sizeof(iv)), NULL))
                    324:        {
                    325:                return FALSE;
                    326:        }
                    327:        memxor(data, opc, sizeof(data));
                    328:        memcpy(aks, data, 6);
                    329:        return TRUE;
                    330: }
                    331: 
                    332: METHOD(eap_aka_3gpp_functions_t, destroy, void,
                    333:        private_eap_aka_3gpp_functions_t *this)
                    334: {
                    335:        this->crypter->destroy(this->crypter);
                    336:        free(this);
                    337: }
                    338: 
                    339: /**
                    340:  * See header
                    341:  */
                    342: eap_aka_3gpp_functions_t *eap_aka_3gpp_functions_create()
                    343: {
                    344:        private_eap_aka_3gpp_functions_t *this;
                    345: 
                    346:        INIT(this,
                    347:                .public = {
                    348:                        .f1 = _f1,
                    349:                        .f1star = _f1star,
                    350:                        .f2345 = _f2345,
                    351:                        .f5star = _f5star,
                    352:                        .destroy = _destroy,
                    353:                },
                    354:                .crypter = lib->crypto->create_crypter(lib->crypto, ENCR_AES_CBC, 16),
                    355:        );
                    356:        if (!this->crypter)
                    357:        {
                    358:                DBG1(DBG_IKE, "%N not supported, unable to use 3GPP algorithm",
                    359:                         encryption_algorithm_names, ENCR_AES_CBC);
                    360:                free(this);
                    361:                return NULL;
                    362:        }
                    363:        return &this->public;
                    364: }

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