Annotation of embedaddon/strongswan/src/libcharon/plugins/eap_aka_3gpp2/eap_aka_3gpp2_functions.c, revision 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>