Annotation of embedaddon/strongswan/src/libcharon/plugins/eap_aka_3gpp2/eap_aka_3gpp2_functions.c, revision 1.1.1.1

1.1       misho       1: /*
                      2:  * Copyright (C) 2008-2009 Martin Willi
                      3:  * HSR Hochschule fuer Technik Rapperswil
                      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 "eap_aka_3gpp2_functions.h"
                     17: 
                     18: #include <gmp.h>
                     19: #include <limits.h>
                     20: 
                     21: #include <daemon.h>
                     22: 
                     23: typedef struct private_eap_aka_3gpp2_functions_t private_eap_aka_3gpp2_functions_t;
                     24: 
                     25: /**
                     26:  * Private data of an eap_aka_3gpp2_functions_t object.
                     27:  */
                     28: struct private_eap_aka_3gpp2_functions_t {
                     29: 
                     30:        /**
                     31:         * Public eap_aka_3gpp2_functions_t interface.
                     32:         */
                     33:        eap_aka_3gpp2_functions_t public;
                     34: 
                     35:        /**
                     36:         * Used keyed SHA1 function, as PRF
                     37:         */
                     38:        prf_t *prf;
                     39: };
                     40: 
                     41: #define AKA_PAYLOAD_LEN 64
                     42: 
                     43: #define F1                       0x42
                     44: #define F1STAR           0x43
                     45: #define F2                       0x44
                     46: #define F3                       0x45
                     47: #define F4                       0x46
                     48: #define F5                       0x47
                     49: #define F5STAR           0x48
                     50: 
                     51: /** Family key, as proposed in S.S0055 */
                     52: static chunk_t fmk = chunk_from_chars(0x41, 0x48, 0x41, 0x47);
                     53: 
                     54: /**
                     55:  * Binary representation of the polynomial T^160 + T^5 + T^3 + T^2 + 1
                     56:  */
                     57: static uint8_t g[] = {
                     58:        0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                     59:        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                     60:        0x00, 0x00, 0x00, 0x00, 0x2d
                     61: };
                     62: 
                     63: /**
                     64:  * Predefined random bits from the RAND Corporation book
                     65:  */
                     66: static uint8_t a_def[] = {
                     67:        0x9d, 0xe9, 0xc9, 0xc8, 0xef, 0xd5, 0x78, 0x11,
                     68:        0x48, 0x23, 0x14, 0x01, 0x90, 0x1f, 0x2d, 0x49,
                     69:        0x3f, 0x4c, 0x63, 0x65
                     70: };
                     71: 
                     72: /**
                     73:  * Predefined random bits from the RAND Corporation book
                     74:  */
                     75: static uint8_t b_def[] = {
                     76:        0x75, 0xef, 0xd1, 0x5c, 0x4b, 0x8f, 0x8f, 0x51,
                     77:        0x4e, 0xf3, 0xbc, 0xc3, 0x79, 0x4a, 0x76, 0x5e,
                     78:        0x7e, 0xec, 0x45, 0xe0
                     79: };
                     80: 
                     81: /**
                     82:  * Multiply two mpz_t with bits interpreted as polynomials.
                     83:  */
                     84: static void mpz_mul_poly(mpz_t r, mpz_t a, mpz_t b)
                     85: {
                     86:        mpz_t bm, rm;
                     87:        int current = 0, shifted = 0, shift;
                     88: 
                     89:        mpz_init_set(bm, b);
                     90:        mpz_init_set_ui(rm, 0);
                     91:        /* scan through a, for each found bit: */
                     92:        while ((current = mpz_scan1(a, current)) != ULONG_MAX)
                     93:        {
                     94:                /* XOR shifted b into r */
                     95:                shift = current - shifted;
                     96:                mpz_mul_2exp(bm, bm, shift);
                     97:                shifted += shift;
                     98:                mpz_xor(rm, rm, bm);
                     99:                current++;
                    100:        }
                    101: 
                    102:        mpz_swap(r, rm);
                    103:        mpz_clear(rm);
                    104:        mpz_clear(bm);
                    105: }
                    106: 
                    107: /**
                    108:  * Calculate the sum of a + b interpreted as polynomials.
                    109:  */
                    110: static void mpz_add_poly(mpz_t res, mpz_t a, mpz_t b)
                    111: {
                    112:        /* addition of polynomials is just the XOR */
                    113:        mpz_xor(res, a, b);
                    114: }
                    115: 
                    116: /**
                    117:  * Calculate the remainder of a/b interpreted as polynomials.
                    118:  */
                    119: static void mpz_mod_poly(mpz_t r, mpz_t a, mpz_t b)
                    120: {
                    121:        /* Example:
                    122:         * a = 10001010
                    123:         * b = 00000101
                    124:         */
                    125:        int a_bit, b_bit, diff;
                    126:        mpz_t bm, am;
                    127: 
                    128:        mpz_init_set(am, a);
                    129:        mpz_init(bm);
                    130: 
                    131:        a_bit = mpz_sizeinbase(a, 2);
                    132:        b_bit = mpz_sizeinbase(b, 2);
                    133: 
                    134:        /* don't do anything if b > a */
                    135:        if (a_bit >= b_bit)
                    136:        {
                    137:                /* shift b left to align up most significant "1" to a:
                    138:                 * a = 10001010
                    139:                 * b = 10100000
                    140:                 */
                    141:                mpz_mul_2exp(bm, b, a_bit - b_bit);
                    142:                do
                    143:                {
                    144:                        /* XOR b into a, this kills the most significant "1":
                    145:                         * a = 00101010
                    146:                         */
                    147:                        mpz_xor(am, am, bm);
                    148:                        /* find the next most significant "1" in a, and align up b:
                    149:                         * a = 00101010
                    150:                         * b = 00101000
                    151:                         */
                    152:                        diff = a_bit - mpz_sizeinbase(am, 2);
                    153:                        mpz_div_2exp(bm, bm, diff);
                    154:                        a_bit -= diff;
                    155:                }
                    156:                while (b_bit <= mpz_sizeinbase(bm, 2));
                    157:                /* While b is not shifted to its original value */
                    158:        }
                    159:        /* after another iteration:
                    160:         * a = 00000010
                    161:         * which is the polynomial modulo
                    162:         */
                    163: 
                    164:        mpz_swap(r, am);
                    165:        mpz_clear(am);
                    166:        mpz_clear(bm);
                    167: }
                    168: 
                    169: /**
                    170:  * Step 3 of the various fx() functions:
                    171:  * XOR the key into the SHA1 IV
                    172:  */
                    173: static bool step3(prf_t *prf, u_char k[AKA_K_LEN],
                    174:                                  u_char payload[AKA_PAYLOAD_LEN], uint8_t h[HASH_SIZE_SHA1])
                    175: {
                    176:        /* use the keyed hasher to build the hash */
                    177:        return prf->set_key(prf, chunk_create(k, AKA_K_LEN)) &&
                    178:                   prf->get_bytes(prf, chunk_create(payload, AKA_PAYLOAD_LEN), h);
                    179: }
                    180: 
                    181: /**
                    182:  * Step 4 of the various fx() functions:
                    183:  * Polynomial whiten calculations
                    184:  */
                    185: static void step4(u_char x[HASH_SIZE_SHA1])
                    186: {
                    187:        mpz_t xm, am, bm, gm;
                    188: 
                    189:        mpz_init(xm);
                    190:        mpz_init(am);
                    191:        mpz_init(bm);
                    192:        mpz_init(gm);
                    193: 
                    194:        mpz_import(xm, HASH_SIZE_SHA1, 1, 1, 1, 0, x);
                    195:        mpz_import(am, sizeof(a_def), 1, 1, 1, 0, a_def);
                    196:        mpz_import(bm, sizeof(b_def), 1, 1, 1, 0, b_def);
                    197:        mpz_import(gm, sizeof(g), 1, 1, 1, 0, g);
                    198: 
                    199:        mpz_mul_poly(xm, am, xm);
                    200:        mpz_add_poly(xm, bm, xm);
                    201:        mpz_mod_poly(xm, xm, gm);
                    202: 
                    203:        mpz_export(x, NULL, 1, HASH_SIZE_SHA1, 1, 0, xm);
                    204: 
                    205:        mpz_clear(xm);
                    206:        mpz_clear(am);
                    207:        mpz_clear(bm);
                    208:        mpz_clear(gm);
                    209: }
                    210: 
                    211: /**
                    212:  * Calculation function for f2(), f3(), f4()
                    213:  */
                    214: static bool fx(prf_t *prf, u_char f, u_char k[AKA_K_LEN],
                    215:                           u_char rand[AKA_RAND_LEN], u_char out[AKA_MAC_LEN])
                    216: {
                    217:        u_char payload[AKA_PAYLOAD_LEN];
                    218:        u_char h[HASH_SIZE_SHA1];
                    219:        u_char i;
                    220: 
                    221:        for (i = 0; i < 2; i++)
                    222:        {
                    223:                memset(payload, 0x5c, AKA_PAYLOAD_LEN);
                    224:                payload[11] ^= f;
                    225:                memxor(payload + 12, fmk.ptr, fmk.len);
                    226:                memxor(payload + 24, rand, AKA_RAND_LEN);
                    227: 
                    228:                payload[3]  ^= i;
                    229:                payload[19] ^= i;
                    230:                payload[35] ^= i;
                    231:                payload[51] ^= i;
                    232: 
                    233:                if (!step3(prf, k, payload, h))
                    234:                {
                    235:                        return FALSE;
                    236:                }
                    237:                step4(h);
                    238:                memcpy(out + i * 8, h, 8);
                    239:        }
                    240:        return TRUE;
                    241: }
                    242: 
                    243: /**
                    244:  * Calculation function of f1() and f1star()
                    245:  */
                    246: static bool f1x(prf_t *prf, uint8_t f, u_char k[AKA_K_LEN],
                    247:                                u_char rand[AKA_RAND_LEN], u_char sqn[AKA_SQN_LEN],
                    248:                                u_char amf[AKA_AMF_LEN], u_char mac[AKA_MAC_LEN])
                    249: {
                    250:        /* generate MAC = f1(FMK, SQN, RAND, AMF)
                    251:         * K is loaded into hashers IV; FMK, RAND, SQN, AMF are XORed in a 512-bit
                    252:         * payload which gets hashed
                    253:         */
                    254:        u_char payload[AKA_PAYLOAD_LEN];
                    255:        u_char h[HASH_SIZE_SHA1];
                    256: 
                    257:        memset(payload, 0x5c, AKA_PAYLOAD_LEN);
                    258:        payload[11] ^= f;
                    259:        memxor(payload + 12, fmk.ptr, fmk.len);
                    260:        memxor(payload + 16, rand, AKA_RAND_LEN);
                    261:        memxor(payload + 34, sqn, AKA_SQN_LEN);
                    262:        memxor(payload + 42, amf, AKA_AMF_LEN);
                    263: 
                    264:        if (!step3(prf, k, payload, h))
                    265:        {
                    266:                return FALSE;
                    267:        }
                    268:        step4(h);
                    269:        memcpy(mac, h, AKA_MAC_LEN);
                    270:        return TRUE;
                    271: }
                    272: 
                    273: /**
                    274:  * Calculation function of f5() and f5star()
                    275:  */
                    276: static bool f5x(prf_t *prf, u_char f, u_char k[AKA_K_LEN],
                    277:                                u_char rand[AKA_RAND_LEN], u_char ak[AKA_AK_LEN])
                    278: {
                    279:        u_char payload[AKA_PAYLOAD_LEN];
                    280:        u_char h[HASH_SIZE_SHA1];
                    281: 
                    282:        memset(payload, 0x5c, AKA_PAYLOAD_LEN);
                    283:        payload[11] ^= f;
                    284:        memxor(payload + 12, fmk.ptr, fmk.len);
                    285:        memxor(payload + 16, rand, AKA_RAND_LEN);
                    286: 
                    287:        if (!step3(prf, k, payload, h))
                    288:        {
                    289:                return FALSE;
                    290:        }
                    291:        step4(h);
                    292:        memcpy(ak, h, AKA_AK_LEN);
                    293:        return TRUE;
                    294: }
                    295: 
                    296: /**
                    297:  * Calculate MAC from RAND, SQN, AMF using K
                    298:  */
                    299: METHOD(eap_aka_3gpp2_functions_t, f1, bool,
                    300:        private_eap_aka_3gpp2_functions_t *this, u_char k[AKA_K_LEN],
                    301:        u_char rand[AKA_RAND_LEN], u_char sqn[AKA_SQN_LEN],
                    302:        u_char amf[AKA_AMF_LEN], u_char mac[AKA_MAC_LEN])
                    303: {
                    304:        if (f1x(this->prf, F1, k, rand, sqn, amf, mac))
                    305:        {
                    306:                DBG3(DBG_IKE, "MAC %b", mac, AKA_MAC_LEN);
                    307:                return TRUE;
                    308:        }
                    309:        return FALSE;
                    310: }
                    311: 
                    312: /**
                    313:  * Calculate MACS from RAND, SQN, AMF using K
                    314:  */
                    315: METHOD(eap_aka_3gpp2_functions_t, f1star, bool,
                    316:        private_eap_aka_3gpp2_functions_t *this, u_char k[AKA_K_LEN],
                    317:        u_char rand[AKA_RAND_LEN], u_char sqn[AKA_SQN_LEN],
                    318:        u_char amf[AKA_AMF_LEN], u_char macs[AKA_MAC_LEN])
                    319: {
                    320:        if (f1x(this->prf, F1STAR, k, rand, sqn, amf, macs))
                    321:        {
                    322:                DBG3(DBG_IKE, "MACS %b", macs, AKA_MAC_LEN);
                    323:                return TRUE;
                    324:        }
                    325:        return FALSE;
                    326: }
                    327: 
                    328: /**
                    329:  * Calculate RES from RAND using K
                    330:  */
                    331: METHOD(eap_aka_3gpp2_functions_t, f2, bool,
                    332:        private_eap_aka_3gpp2_functions_t *this, u_char k[AKA_K_LEN],
                    333:        u_char rand[AKA_RAND_LEN], u_char res[AKA_RES_MAX])
                    334: {
                    335:        if (fx(this->prf, F2, k, rand, res))
                    336:        {
                    337:                DBG3(DBG_IKE, "RES %b", res, AKA_RES_MAX);
                    338:                return TRUE;
                    339:        }
                    340:        return FALSE;
                    341: }
                    342: 
                    343: /**
                    344:  * Calculate CK from RAND using K
                    345:  */
                    346: METHOD(eap_aka_3gpp2_functions_t, f3, bool,
                    347:        private_eap_aka_3gpp2_functions_t *this, u_char k[AKA_K_LEN],
                    348:        u_char rand[AKA_RAND_LEN], u_char ck[AKA_CK_LEN])
                    349: {
                    350:        if (fx(this->prf, F3, k, rand, ck))
                    351:        {
                    352:                DBG3(DBG_IKE, "CK %b", ck, AKA_CK_LEN);
                    353:                return TRUE;
                    354:        }
                    355:        return FALSE;
                    356: }
                    357: 
                    358: /**
                    359:  * Calculate IK from RAND using K
                    360:  */
                    361: METHOD(eap_aka_3gpp2_functions_t, f4, bool,
                    362:        private_eap_aka_3gpp2_functions_t *this, u_char k[AKA_K_LEN],
                    363:        u_char rand[AKA_RAND_LEN], u_char ik[AKA_IK_LEN])
                    364: {
                    365:        if (fx(this->prf, F4, k, rand, ik))
                    366:        {
                    367:                DBG3(DBG_IKE, "IK %b", ik, AKA_IK_LEN);
                    368:                return TRUE;
                    369:        }
                    370:        return FALSE;
                    371: }
                    372: 
                    373: /**
                    374:  * Calculate AK from a RAND using K
                    375:  */
                    376: METHOD(eap_aka_3gpp2_functions_t, f5, bool,
                    377:        private_eap_aka_3gpp2_functions_t *this, u_char k[AKA_K_LEN],
                    378:        u_char rand[AKA_RAND_LEN], u_char ak[AKA_AK_LEN])
                    379: {
                    380:        if (f5x(this->prf, F5, k, rand, ak))
                    381:        {
                    382:                DBG3(DBG_IKE, "AK %b", ak, AKA_AK_LEN);
                    383:                return TRUE;
                    384:        }
                    385:        return FALSE;
                    386: }
                    387: 
                    388: /**
                    389:  * Calculate AKS from a RAND using K
                    390:  */
                    391: METHOD(eap_aka_3gpp2_functions_t, f5star, bool,
                    392:        private_eap_aka_3gpp2_functions_t *this, u_char k[AKA_K_LEN],
                    393:        u_char rand[AKA_RAND_LEN], u_char aks[AKA_AK_LEN])
                    394: {
                    395:        if (f5x(this->prf, F5STAR, k, rand, aks))
                    396:        {
                    397:                DBG3(DBG_IKE, "AKS %b", aks, AKA_AK_LEN);
                    398:                return TRUE;
                    399:        }
                    400:        return FALSE;
                    401: }
                    402: 
                    403: METHOD(eap_aka_3gpp2_functions_t, destroy, void,
                    404:        private_eap_aka_3gpp2_functions_t *this)
                    405: {
                    406:        this->prf->destroy(this->prf);
                    407:        free(this);
                    408: }
                    409: 
                    410: /**
                    411:  * See header
                    412:  */
                    413: eap_aka_3gpp2_functions_t *eap_aka_3gpp2_functions_create()
                    414: {
                    415:        private_eap_aka_3gpp2_functions_t *this;
                    416: 
                    417:        INIT(this,
                    418:                .public = {
                    419:                        .f1 = _f1,
                    420:                        .f1star = _f1star,
                    421:                        .f2 = _f2,
                    422:                        .f3 = _f3,
                    423:                        .f4 = _f4,
                    424:                        .f5 = _f5,
                    425:                        .f5star = _f5star,
                    426:                        .destroy = _destroy,
                    427:                },
                    428:                .prf = lib->crypto->create_prf(lib->crypto, PRF_KEYED_SHA1),
                    429:        );
                    430:        if (!this->prf)
                    431:        {
                    432:                DBG1(DBG_CFG, "%N not supported, unable to use 3GPP2 algorithm",
                    433:                         pseudo_random_function_names, PRF_KEYED_SHA1);
                    434:                free(this);
                    435:                return NULL;
                    436:        }
                    437:        return &this->public;
                    438: }
                    439: 

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