Annotation of embedaddon/strongswan/src/libcharon/sa/ikev1/keymat_v1.c, revision 1.1.1.1

1.1       misho       1: /*
                      2:  * Copyright (C) 2011 Tobias Brunner
                      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 "keymat_v1.h"
                     17: 
                     18: #include <daemon.h>
                     19: #include <sa/ikev1/iv_manager.h>
                     20: #include <encoding/generator.h>
                     21: #include <encoding/payloads/nonce_payload.h>
                     22: 
                     23: typedef struct private_keymat_v1_t private_keymat_v1_t;
                     24: 
                     25: /**
                     26:  * Private data of an keymat_t object.
                     27:  */
                     28: struct private_keymat_v1_t {
                     29: 
                     30:        /**
                     31:         * Public keymat_v1_t interface.
                     32:         */
                     33:        keymat_v1_t public;
                     34: 
                     35:        /**
                     36:         * IKE_SA Role, initiator or responder
                     37:         */
                     38:        bool initiator;
                     39: 
                     40:        /**
                     41:         * General purpose PRF
                     42:         */
                     43:        prf_t *prf;
                     44: 
                     45:        /**
                     46:         * PRF to create Phase 1 HASH payloads
                     47:         */
                     48:        prf_t *prf_auth;
                     49: 
                     50:        /**
                     51:         * Crypter wrapped in an aead_t interface
                     52:         */
                     53:        aead_t *aead;
                     54: 
                     55:        /**
                     56:         * Hasher used for IV generation (and other things like e.g. NAT-T)
                     57:         */
                     58:        hasher_t *hasher;
                     59: 
                     60:        /**
                     61:         * Key to derive key material from for non-ISAKMP SAs, rekeying
                     62:         */
                     63:        chunk_t skeyid_d;
                     64: 
                     65:        /**
                     66:         * Key used for authentication after main mode
                     67:         */
                     68:        chunk_t skeyid_a;
                     69: 
                     70:        /**
                     71:         * IV and QM manager
                     72:         */
                     73:        iv_manager_t *iv_manager;
                     74: };
                     75: 
                     76: /**
                     77:  * Constants used in key derivation.
                     78:  */
                     79: static const chunk_t octet_0 = chunk_from_chars(0x00);
                     80: static const chunk_t octet_1 = chunk_from_chars(0x01);
                     81: static const chunk_t octet_2 = chunk_from_chars(0x02);
                     82: 
                     83: /**
                     84:  * Simple aead_t implementation without support for authentication.
                     85:  */
                     86: typedef struct {
                     87:        /** implements aead_t interface */
                     88:        aead_t aead;
                     89:        /** crypter to be used */
                     90:        crypter_t *crypter;
                     91: } private_aead_t;
                     92: 
                     93: 
                     94: METHOD(aead_t, encrypt, bool,
                     95:        private_aead_t *this, chunk_t plain, chunk_t assoc, chunk_t iv,
                     96:        chunk_t *encrypted)
                     97: {
                     98:        return this->crypter->encrypt(this->crypter, plain, iv, encrypted);
                     99: }
                    100: 
                    101: METHOD(aead_t, decrypt, bool,
                    102:        private_aead_t *this, chunk_t encrypted, chunk_t assoc, chunk_t iv,
                    103:        chunk_t *plain)
                    104: {
                    105:        return this->crypter->decrypt(this->crypter, encrypted, iv, plain);
                    106: }
                    107: 
                    108: METHOD(aead_t, get_block_size, size_t,
                    109:        private_aead_t *this)
                    110: {
                    111:        return this->crypter->get_block_size(this->crypter);
                    112: }
                    113: 
                    114: METHOD(aead_t, get_icv_size, size_t,
                    115:        private_aead_t *this)
                    116: {
                    117:        return 0;
                    118: }
                    119: 
                    120: METHOD(aead_t, get_iv_size, size_t,
                    121:        private_aead_t *this)
                    122: {
                    123:        /* in order to create the messages properly we return 0 here */
                    124:        return 0;
                    125: }
                    126: 
                    127: METHOD(aead_t, get_iv_gen, iv_gen_t*,
                    128:        private_aead_t *this)
                    129: {
                    130:        /* IVs are retrieved via keymat_v1.get_iv() */
                    131:        return NULL;
                    132: }
                    133: 
                    134: METHOD(aead_t, get_key_size, size_t,
                    135:        private_aead_t *this)
                    136: {
                    137:        return this->crypter->get_key_size(this->crypter);
                    138: }
                    139: 
                    140: METHOD(aead_t, set_key, bool,
                    141:        private_aead_t *this, chunk_t key)
                    142: {
                    143:        return this->crypter->set_key(this->crypter, key);
                    144: }
                    145: 
                    146: METHOD(aead_t, aead_destroy, void,
                    147:        private_aead_t *this)
                    148: {
                    149:        this->crypter->destroy(this->crypter);
                    150:        free(this);
                    151: }
                    152: 
                    153: /**
                    154:  * Expand SKEYID_e according to Appendix B in RFC 2409.
                    155:  * TODO-IKEv1: verify keys (e.g. for weak keys, see Appendix B)
                    156:  */
                    157: static bool expand_skeyid_e(chunk_t skeyid_e, size_t key_size, prf_t *prf,
                    158:                                                        chunk_t *ka)
                    159: {
                    160:        size_t block_size;
                    161:        chunk_t seed;
                    162:        int i;
                    163: 
                    164:        if (skeyid_e.len >= key_size)
                    165:        {       /* no expansion required, reduce to key_size */
                    166:                skeyid_e.len = key_size;
                    167:                *ka = skeyid_e;
                    168:                return TRUE;
                    169:        }
                    170:        block_size = prf->get_block_size(prf);
                    171:        *ka = chunk_alloc((key_size / block_size + 1) * block_size);
                    172:        ka->len = key_size;
                    173: 
                    174:        /* Ka = K1 | K2 | ..., K1 = prf(SKEYID_e, 0), K2 = prf(SKEYID_e, K1) ... */
                    175:        if (!prf->set_key(prf, skeyid_e))
                    176:        {
                    177:                chunk_clear(ka);
                    178:                chunk_clear(&skeyid_e);
                    179:                return FALSE;
                    180:        }
                    181:        seed = octet_0;
                    182:        for (i = 0; i < key_size; i += block_size)
                    183:        {
                    184:                if (!prf->get_bytes(prf, seed, ka->ptr + i))
                    185:                {
                    186:                        chunk_clear(ka);
                    187:                        chunk_clear(&skeyid_e);
                    188:                        return FALSE;
                    189:                }
                    190:                seed = chunk_create(ka->ptr + i, block_size);
                    191:        }
                    192:        chunk_clear(&skeyid_e);
                    193:        return TRUE;
                    194: }
                    195: 
                    196: /**
                    197:  * Create a simple implementation of the aead_t interface which only encrypts
                    198:  * or decrypts data.
                    199:  */
                    200: static aead_t *create_aead(proposal_t *proposal, prf_t *prf, chunk_t skeyid_e,
                    201:                                                   chunk_t *ka)
                    202: {
                    203:        private_aead_t *this;
                    204:        uint16_t alg, key_size;
                    205:        crypter_t *crypter;
                    206: 
                    207:        if (!proposal->get_algorithm(proposal, ENCRYPTION_ALGORITHM, &alg,
                    208:                                                                 &key_size))
                    209:        {
                    210:                DBG1(DBG_IKE, "no %N selected",
                    211:                         transform_type_names, ENCRYPTION_ALGORITHM);
                    212:                return NULL;
                    213:        }
                    214:        crypter = lib->crypto->create_crypter(lib->crypto, alg, key_size / 8);
                    215:        if (!crypter)
                    216:        {
                    217:                DBG1(DBG_IKE, "%N %N (key size %d) not supported!",
                    218:                         transform_type_names, ENCRYPTION_ALGORITHM,
                    219:                         encryption_algorithm_names, alg, key_size);
                    220:                return NULL;
                    221:        }
                    222:        if (!expand_skeyid_e(skeyid_e, crypter->get_key_size(crypter), prf, ka))
                    223:        {
                    224:                return NULL;
                    225:        }
                    226:        DBG4(DBG_IKE, "encryption key Ka %B", ka);
                    227:        if (!crypter->set_key(crypter, *ka))
                    228:        {
                    229:                chunk_clear(ka);
                    230:                return NULL;
                    231:        }
                    232: 
                    233:        INIT(this,
                    234:                .aead = {
                    235:                        .encrypt = _encrypt,
                    236:                        .decrypt = _decrypt,
                    237:                        .get_block_size = _get_block_size,
                    238:                        .get_icv_size = _get_icv_size,
                    239:                        .get_iv_size = _get_iv_size,
                    240:                        .get_iv_gen = _get_iv_gen,
                    241:                        .get_key_size = _get_key_size,
                    242:                        .set_key = _set_key,
                    243:                        .destroy = _aead_destroy,
                    244:                },
                    245:                .crypter = crypter,
                    246:        );
                    247:        return &this->aead;
                    248: }
                    249: 
                    250: /**
                    251:  * Converts integrity algorithm to PRF algorithm
                    252:  */
                    253: static uint16_t auth_to_prf(uint16_t alg)
                    254: {
                    255:        switch (alg)
                    256:        {
                    257:                case AUTH_HMAC_SHA1_96:
                    258:                        return PRF_HMAC_SHA1;
                    259:                case AUTH_HMAC_SHA2_256_128:
                    260:                        return PRF_HMAC_SHA2_256;
                    261:                case AUTH_HMAC_SHA2_384_192:
                    262:                        return PRF_HMAC_SHA2_384;
                    263:                case AUTH_HMAC_SHA2_512_256:
                    264:                        return PRF_HMAC_SHA2_512;
                    265:                case AUTH_HMAC_MD5_96:
                    266:                        return PRF_HMAC_MD5;
                    267:                case AUTH_AES_XCBC_96:
                    268:                        return PRF_AES128_XCBC;
                    269:                default:
                    270:                        return PRF_UNDEFINED;
                    271:        }
                    272: }
                    273: 
                    274: /**
                    275:  * Converts integrity algorithm to hash algorithm
                    276:  */
                    277: static uint16_t auth_to_hash(uint16_t alg)
                    278: {
                    279:        switch (alg)
                    280:        {
                    281:                case AUTH_HMAC_SHA1_96:
                    282:                        return HASH_SHA1;
                    283:                case AUTH_HMAC_SHA2_256_128:
                    284:                        return HASH_SHA256;
                    285:                case AUTH_HMAC_SHA2_384_192:
                    286:                        return HASH_SHA384;
                    287:                case AUTH_HMAC_SHA2_512_256:
                    288:                        return HASH_SHA512;
                    289:                case AUTH_HMAC_MD5_96:
                    290:                        return HASH_MD5;
                    291:                default:
                    292:                        return HASH_UNKNOWN;
                    293:        }
                    294: }
                    295: 
                    296: /**
                    297:  * Adjust the key length for PRF algorithms that expect a fixed key length.
                    298:  */
                    299: static void adjust_keylen(uint16_t alg, chunk_t *key)
                    300: {
                    301:        switch (alg)
                    302:        {
                    303:                case PRF_AES128_XCBC:
                    304:                        /* while rfc4434 defines variable keys for AES-XCBC, rfc3664 does
                    305:                         * not and therefore fixed key semantics apply to XCBC for key
                    306:                         * derivation. */
                    307:                        key->len = min(key->len, 16);
                    308:                        break;
                    309:                default:
                    310:                        /* all other algorithms use variable key length */
                    311:                        break;
                    312:        }
                    313: }
                    314: 
                    315: METHOD(keymat_v1_t, derive_ike_keys, bool,
                    316:        private_keymat_v1_t *this, proposal_t *proposal, diffie_hellman_t *dh,
                    317:        chunk_t dh_other, chunk_t nonce_i, chunk_t nonce_r, ike_sa_id_t *id,
                    318:        auth_method_t auth, shared_key_t *shared_key)
                    319: {
                    320:        chunk_t g_xy, g_xi, g_xr, dh_me, spi_i, spi_r, nonces, data, skeyid_e;
                    321:        chunk_t skeyid, ka;
                    322:        uint16_t alg;
                    323: 
                    324:        spi_i = chunk_alloca(sizeof(uint64_t));
                    325:        spi_r = chunk_alloca(sizeof(uint64_t));
                    326: 
                    327:        if (!proposal->get_algorithm(proposal, PSEUDO_RANDOM_FUNCTION, &alg, NULL))
                    328:        {       /* no PRF negotiated, use HMAC version of integrity algorithm instead */
                    329:                if (!proposal->get_algorithm(proposal, INTEGRITY_ALGORITHM, &alg, NULL)
                    330:                        || (alg = auth_to_prf(alg)) == PRF_UNDEFINED)
                    331:                {
                    332:                        DBG1(DBG_IKE, "no %N selected",
                    333:                                 transform_type_names, PSEUDO_RANDOM_FUNCTION);
                    334:                        return FALSE;
                    335:                }
                    336:        }
                    337:        this->prf = lib->crypto->create_prf(lib->crypto, alg);
                    338:        if (!this->prf)
                    339:        {
                    340:                DBG1(DBG_IKE, "%N %N not supported!",
                    341:                         transform_type_names, PSEUDO_RANDOM_FUNCTION,
                    342:                         pseudo_random_function_names, alg);
                    343:                return FALSE;
                    344:        }
                    345:        if (this->prf->get_block_size(this->prf) <
                    346:                this->prf->get_key_size(this->prf))
                    347:        {       /* TODO-IKEv1: support PRF output expansion (RFC 2409, Appendix B) */
                    348:                DBG1(DBG_IKE, "expansion of %N %N output not supported!",
                    349:                         transform_type_names, PSEUDO_RANDOM_FUNCTION,
                    350:                         pseudo_random_function_names, alg);
                    351:                return FALSE;
                    352:        }
                    353: 
                    354:        if (!dh->get_shared_secret(dh, &g_xy))
                    355:        {
                    356:                return FALSE;
                    357:        }
                    358:        DBG4(DBG_IKE, "shared Diffie Hellman secret %B", &g_xy);
                    359: 
                    360:        *((uint64_t*)spi_i.ptr) = id->get_initiator_spi(id);
                    361:        *((uint64_t*)spi_r.ptr) = id->get_responder_spi(id);
                    362:        nonces = chunk_cata("cc", nonce_i, nonce_r);
                    363: 
                    364:        switch (auth)
                    365:        {
                    366:                case AUTH_PSK:
                    367:                case AUTH_XAUTH_INIT_PSK:
                    368:                case AUTH_XAUTH_RESP_PSK:
                    369:                {       /* SKEYID = prf(pre-shared-key, Ni_b | Nr_b) */
                    370:                        chunk_t psk;
                    371:                        if (!shared_key)
                    372:                        {
                    373:                                chunk_clear(&g_xy);
                    374:                                return FALSE;
                    375:                        }
                    376:                        psk = shared_key->get_key(shared_key);
                    377:                        adjust_keylen(alg, &psk);
                    378:                        if (!this->prf->set_key(this->prf, psk) ||
                    379:                                !this->prf->allocate_bytes(this->prf, nonces, &skeyid))
                    380:                        {
                    381:                                chunk_clear(&g_xy);
                    382:                                return FALSE;
                    383:                        }
                    384:                        break;
                    385:                }
                    386:                case AUTH_RSA:
                    387:                case AUTH_ECDSA_256:
                    388:                case AUTH_ECDSA_384:
                    389:                case AUTH_ECDSA_521:
                    390:                case AUTH_XAUTH_INIT_RSA:
                    391:                case AUTH_XAUTH_RESP_RSA:
                    392:                case AUTH_HYBRID_INIT_RSA:
                    393:                case AUTH_HYBRID_RESP_RSA:
                    394:                {
                    395:                        if (!this->prf->set_key(this->prf, nonces) ||
                    396:                                !this->prf->allocate_bytes(this->prf, g_xy, &skeyid))
                    397:                        {
                    398:                                chunk_clear(&g_xy);
                    399:                                return FALSE;
                    400:                        }
                    401:                        break;
                    402:                }
                    403:                default:
                    404:                        /* TODO-IKEv1: implement key derivation for other schemes */
                    405:                        /* authentication class not supported */
                    406:                        chunk_clear(&g_xy);
                    407:                        return FALSE;
                    408:        }
                    409:        adjust_keylen(alg, &skeyid);
                    410:        DBG4(DBG_IKE, "SKEYID %B", &skeyid);
                    411: 
                    412:        /* SKEYID_d = prf(SKEYID, g^xy | CKY-I | CKY-R | 0) */
                    413:        data = chunk_cat("cccc", g_xy, spi_i, spi_r, octet_0);
                    414:        if (!this->prf->set_key(this->prf, skeyid) ||
                    415:                !this->prf->allocate_bytes(this->prf, data, &this->skeyid_d))
                    416:        {
                    417:                chunk_clear(&g_xy);
                    418:                chunk_clear(&data);
                    419:                chunk_clear(&skeyid);
                    420:                return FALSE;
                    421:        }
                    422:        chunk_clear(&data);
                    423:        DBG4(DBG_IKE, "SKEYID_d %B", &this->skeyid_d);
                    424: 
                    425:        /* SKEYID_a = prf(SKEYID, SKEYID_d | g^xy | CKY-I | CKY-R | 1) */
                    426:        data = chunk_cat("ccccc", this->skeyid_d, g_xy, spi_i, spi_r, octet_1);
                    427:        if (!this->prf->allocate_bytes(this->prf, data, &this->skeyid_a))
                    428:        {
                    429:                chunk_clear(&g_xy);
                    430:                chunk_clear(&data);
                    431:                chunk_clear(&skeyid);
                    432:                return FALSE;
                    433:        }
                    434:        chunk_clear(&data);
                    435:        DBG4(DBG_IKE, "SKEYID_a %B", &this->skeyid_a);
                    436: 
                    437:        /* SKEYID_e = prf(SKEYID, SKEYID_a | g^xy | CKY-I | CKY-R | 2) */
                    438:        data = chunk_cat("ccccc", this->skeyid_a, g_xy, spi_i, spi_r, octet_2);
                    439:        if (!this->prf->allocate_bytes(this->prf, data, &skeyid_e))
                    440:        {
                    441:                chunk_clear(&g_xy);
                    442:                chunk_clear(&data);
                    443:                chunk_clear(&skeyid);
                    444:                return FALSE;
                    445:        }
                    446:        chunk_clear(&data);
                    447:        DBG4(DBG_IKE, "SKEYID_e %B", &skeyid_e);
                    448: 
                    449:        chunk_clear(&g_xy);
                    450: 
                    451:        switch (auth)
                    452:        {
                    453:                case AUTH_ECDSA_256:
                    454:                        alg = PRF_HMAC_SHA2_256;
                    455:                        break;
                    456:                case AUTH_ECDSA_384:
                    457:                        alg =  PRF_HMAC_SHA2_384;
                    458:                        break;
                    459:                case AUTH_ECDSA_521:
                    460:                        alg = PRF_HMAC_SHA2_512;
                    461:                        break;
                    462:                default:
                    463:                        /* use proposal algorithm */
                    464:                        break;
                    465:        }
                    466:        this->prf_auth = lib->crypto->create_prf(lib->crypto, alg);
                    467:        if (!this->prf_auth)
                    468:        {
                    469:                DBG1(DBG_IKE, "%N %N not supported!",
                    470:                         transform_type_names, PSEUDO_RANDOM_FUNCTION,
                    471:                         pseudo_random_function_names, alg);
                    472:                chunk_clear(&skeyid);
                    473:                return FALSE;
                    474:        }
                    475:        if (!this->prf_auth->set_key(this->prf_auth, skeyid))
                    476:        {
                    477:                chunk_clear(&skeyid);
                    478:                return FALSE;
                    479:        }
                    480:        chunk_clear(&skeyid);
                    481: 
                    482:        this->aead = create_aead(proposal, this->prf, skeyid_e, &ka);
                    483:        if (!this->aead)
                    484:        {
                    485:                return FALSE;
                    486:        }
                    487:        charon->bus->ike_derived_keys(charon->bus, ka, chunk_empty, this->skeyid_a,
                    488:                                                                  chunk_empty);
                    489:        chunk_clear(&ka);
                    490:        if (!this->hasher && !this->public.create_hasher(&this->public, proposal))
                    491:        {
                    492:                return FALSE;
                    493:        }
                    494: 
                    495:        if (!dh->get_my_public_value(dh, &dh_me))
                    496:        {
                    497:                return FALSE;
                    498:        }
                    499:        g_xi = this->initiator ? dh_me : dh_other;
                    500:        g_xr = this->initiator ? dh_other : dh_me;
                    501: 
                    502:        /* initial IV = hash(g^xi | g^xr) */
                    503:        data = chunk_cata("cc", g_xi, g_xr);
                    504:        chunk_free(&dh_me);
                    505:        return this->iv_manager->init_iv_chain(this->iv_manager, data, this->hasher,
                    506:                                                                                this->aead->get_block_size(this->aead));
                    507: }
                    508: 
                    509: METHOD(keymat_v1_t, derive_child_keys, bool,
                    510:        private_keymat_v1_t *this, proposal_t *proposal, diffie_hellman_t *dh,
                    511:        uint32_t spi_i, uint32_t spi_r, chunk_t nonce_i, chunk_t nonce_r,
                    512:        chunk_t *encr_i, chunk_t *integ_i, chunk_t *encr_r, chunk_t *integ_r)
                    513: {
                    514:        uint16_t enc_alg, int_alg, enc_size = 0, int_size = 0;
                    515:        uint8_t protocol;
                    516:        prf_plus_t *prf_plus;
                    517:        chunk_t seed, secret = chunk_empty;
                    518:        bool success = FALSE;
                    519: 
                    520:        if (proposal->get_algorithm(proposal, ENCRYPTION_ALGORITHM,
                    521:                                                                &enc_alg, &enc_size))
                    522:        {
                    523:                DBG2(DBG_CHD, "  using %N for encryption",
                    524:                         encryption_algorithm_names, enc_alg);
                    525: 
                    526:                if (!enc_size)
                    527:                {
                    528:                        enc_size = keymat_get_keylen_encr(enc_alg);
                    529:                }
                    530:                if (enc_alg != ENCR_NULL && !enc_size)
                    531:                {
                    532:                        DBG1(DBG_CHD, "no keylength defined for %N",
                    533:                                 encryption_algorithm_names, enc_alg);
                    534:                        return FALSE;
                    535:                }
                    536:                /* to bytes */
                    537:                enc_size /= 8;
                    538: 
                    539:                /* CCM/GCM/CTR/GMAC needs additional bytes */
                    540:                switch (enc_alg)
                    541:                {
                    542:                        case ENCR_AES_CCM_ICV8:
                    543:                        case ENCR_AES_CCM_ICV12:
                    544:                        case ENCR_AES_CCM_ICV16:
                    545:                        case ENCR_CAMELLIA_CCM_ICV8:
                    546:                        case ENCR_CAMELLIA_CCM_ICV12:
                    547:                        case ENCR_CAMELLIA_CCM_ICV16:
                    548:                                enc_size += 3;
                    549:                                break;
                    550:                        case ENCR_AES_GCM_ICV8:
                    551:                        case ENCR_AES_GCM_ICV12:
                    552:                        case ENCR_AES_GCM_ICV16:
                    553:                        case ENCR_AES_CTR:
                    554:                        case ENCR_NULL_AUTH_AES_GMAC:
                    555:                                enc_size += 4;
                    556:                                break;
                    557:                        default:
                    558:                                break;
                    559:                }
                    560:        }
                    561: 
                    562:        if (proposal->get_algorithm(proposal, INTEGRITY_ALGORITHM,
                    563:                                                                &int_alg, &int_size))
                    564:        {
                    565:                DBG2(DBG_CHD, "  using %N for integrity",
                    566:                         integrity_algorithm_names, int_alg);
                    567: 
                    568:                if (!int_size)
                    569:                {
                    570:                        int_size = keymat_get_keylen_integ(int_alg);
                    571:                }
                    572:                if (!int_size)
                    573:                {
                    574:                        DBG1(DBG_CHD, "no keylength defined for %N",
                    575:                                 integrity_algorithm_names, int_alg);
                    576:                        return FALSE;
                    577:                }
                    578:                /* to bytes */
                    579:                int_size /= 8;
                    580:        }
                    581: 
                    582:        /* KEYMAT = prf+(SKEYID_d, [ g(qm)^xy | ] protocol | SPI | Ni_b | Nr_b) */
                    583:        if (!this->prf->set_key(this->prf, this->skeyid_d))
                    584:        {
                    585:                return FALSE;
                    586:        }
                    587:        protocol = proposal->get_protocol(proposal);
                    588:        if (dh)
                    589:        {
                    590:                if (!dh->get_shared_secret(dh, &secret))
                    591:                {
                    592:                        return FALSE;
                    593:                }
                    594:                DBG4(DBG_CHD, "DH secret %B", &secret);
                    595:        }
                    596: 
                    597:        *encr_r = *integ_r = *encr_i = *integ_i = chunk_empty;
                    598:        seed = chunk_cata("ccccc", secret, chunk_from_thing(protocol),
                    599:                                          chunk_from_thing(spi_r), nonce_i, nonce_r);
                    600:        DBG4(DBG_CHD, "initiator SA seed %B", &seed);
                    601: 
                    602:        prf_plus = prf_plus_create(this->prf, FALSE, seed);
                    603:        if (!prf_plus ||
                    604:                !prf_plus->allocate_bytes(prf_plus, enc_size, encr_i) ||
                    605:                !prf_plus->allocate_bytes(prf_plus, int_size, integ_i))
                    606:        {
                    607:                goto failure;
                    608:        }
                    609: 
                    610:        seed = chunk_cata("ccccc", secret, chunk_from_thing(protocol),
                    611:                                          chunk_from_thing(spi_i), nonce_i, nonce_r);
                    612:        DBG4(DBG_CHD, "responder SA seed %B", &seed);
                    613:        prf_plus->destroy(prf_plus);
                    614:        prf_plus = prf_plus_create(this->prf, FALSE, seed);
                    615:        if (!prf_plus ||
                    616:                !prf_plus->allocate_bytes(prf_plus, enc_size, encr_r) ||
                    617:                !prf_plus->allocate_bytes(prf_plus, int_size, integ_r))
                    618:        {
                    619:                goto failure;
                    620:        }
                    621: 
                    622:        if (enc_size)
                    623:        {
                    624:                DBG4(DBG_CHD, "encryption initiator key %B", encr_i);
                    625:                DBG4(DBG_CHD, "encryption responder key %B", encr_r);
                    626:        }
                    627:        if (int_size)
                    628:        {
                    629:                DBG4(DBG_CHD, "integrity initiator key %B", integ_i);
                    630:                DBG4(DBG_CHD, "integrity responder key %B", integ_r);
                    631:        }
                    632:        success = TRUE;
                    633: 
                    634: failure:
                    635:        if (!success)
                    636:        {
                    637:                chunk_clear(encr_i);
                    638:                chunk_clear(integ_i);
                    639:                chunk_clear(encr_r);
                    640:                chunk_clear(integ_r);
                    641:        }
                    642:        DESTROY_IF(prf_plus);
                    643:        chunk_clear(&secret);
                    644: 
                    645:        return success;
                    646: }
                    647: 
                    648: METHOD(keymat_v1_t, create_hasher, bool,
                    649:        private_keymat_v1_t *this, proposal_t *proposal)
                    650: {
                    651:        uint16_t alg;
                    652:        if (!proposal->get_algorithm(proposal, INTEGRITY_ALGORITHM, &alg, NULL) ||
                    653:                (alg = auth_to_hash(alg)) == HASH_UNKNOWN)
                    654:        {
                    655:                DBG1(DBG_IKE, "no %N selected", transform_type_names, HASH_ALGORITHM);
                    656:                return FALSE;
                    657:        }
                    658:        this->hasher = lib->crypto->create_hasher(lib->crypto, alg);
                    659:        if (!this->hasher)
                    660:        {
                    661:                DBG1(DBG_IKE, "%N %N not supported!",
                    662:                         transform_type_names, HASH_ALGORITHM,
                    663:                         hash_algorithm_names, alg);
                    664:                return FALSE;
                    665:        }
                    666:        return TRUE;
                    667: }
                    668: 
                    669: METHOD(keymat_v1_t, get_hasher, hasher_t*,
                    670:        private_keymat_v1_t *this)
                    671: {
                    672:        return this->hasher;
                    673: }
                    674: 
                    675: METHOD(keymat_v1_t, get_hash, bool,
                    676:        private_keymat_v1_t *this, bool initiator, chunk_t dh, chunk_t dh_other,
                    677:        ike_sa_id_t *ike_sa_id, chunk_t sa_i, chunk_t id, chunk_t *hash,
                    678:        signature_scheme_t *scheme)
                    679: {
                    680:        chunk_t data;
                    681:        uint64_t spi, spi_other;
                    682: 
                    683:        /* HASH_I = prf(SKEYID, g^xi | g^xr | CKY-I | CKY-R | SAi_b | IDii_b )
                    684:         * HASH_R = prf(SKEYID, g^xr | g^xi | CKY-R | CKY-I | SAi_b | IDir_b )
                    685:         */
                    686:        if (initiator)
                    687:        {
                    688:                spi = ike_sa_id->get_initiator_spi(ike_sa_id);
                    689:                spi_other = ike_sa_id->get_responder_spi(ike_sa_id);
                    690:        }
                    691:        else
                    692:        {
                    693:                spi_other = ike_sa_id->get_initiator_spi(ike_sa_id);
                    694:                spi = ike_sa_id->get_responder_spi(ike_sa_id);
                    695:        }
                    696:        data = chunk_cat("cccccc", dh, dh_other,
                    697:                                         chunk_from_thing(spi), chunk_from_thing(spi_other),
                    698:                                         sa_i, id);
                    699: 
                    700:        DBG3(DBG_IKE, "HASH_%c data %B", initiator ? 'I' : 'R', &data);
                    701: 
                    702:        if (!this->prf_auth->allocate_bytes(this->prf_auth, data, hash))
                    703:        {
                    704:                free(data.ptr);
                    705:                return FALSE;
                    706:        }
                    707: 
                    708:        DBG3(DBG_IKE, "HASH_%c %B", initiator ? 'I' : 'R', hash);
                    709: 
                    710:        free(data.ptr);
                    711:        return TRUE;
                    712: }
                    713: 
                    714: /**
                    715:  * Get the nonce value found in the given message.
                    716:  * Returns FALSE if none is found.
                    717:  */
                    718: static bool get_nonce(message_t *message, chunk_t *n)
                    719: {
                    720:        nonce_payload_t *nonce;
                    721:        nonce = (nonce_payload_t*)message->get_payload(message, PLV1_NONCE);
                    722:        if (nonce)
                    723:        {
                    724:                *n = nonce->get_nonce(nonce);
                    725:                return TRUE;
                    726:        }
                    727:        return FALSE;
                    728: }
                    729: 
                    730: /**
                    731:  * Generate the message data in order to generate the hashes.
                    732:  */
                    733: static chunk_t get_message_data(message_t *message, generator_t *generator)
                    734: {
                    735:        payload_t *payload, *next;
                    736:        enumerator_t *enumerator;
                    737:        uint32_t *lenpos;
                    738: 
                    739:        if (message->is_encoded(message))
                    740:        {       /* inbound, although the message is generated, we cannot access the
                    741:                 * cleartext message data, so generate it anyway */
                    742:                enumerator = message->create_payload_enumerator(message);
                    743:                while (enumerator->enumerate(enumerator, &payload))
                    744:                {
                    745:                        if (payload->get_type(payload) == PLV1_HASH)
                    746:                        {
                    747:                                continue;
                    748:                        }
                    749:                        generator->generate_payload(generator, payload);
                    750:                }
                    751:                enumerator->destroy(enumerator);
                    752:        }
                    753:        else
                    754:        {
                    755:                /* outbound, generate the payloads (there is no HASH payload yet) */
                    756:                enumerator = message->create_payload_enumerator(message);
                    757:                if (enumerator->enumerate(enumerator, &payload))
                    758:                {
                    759:                        while (enumerator->enumerate(enumerator, &next))
                    760:                        {
                    761:                                payload->set_next_type(payload, next->get_type(next));
                    762:                                generator->generate_payload(generator, payload);
                    763:                                payload = next;
                    764:                        }
                    765:                        payload->set_next_type(payload, PL_NONE);
                    766:                        generator->generate_payload(generator, payload);
                    767:                }
                    768:                enumerator->destroy(enumerator);
                    769:        }
                    770:        return generator->get_chunk(generator, &lenpos);
                    771: }
                    772: 
                    773: METHOD(keymat_v1_t, get_hash_phase2, bool,
                    774:        private_keymat_v1_t *this, message_t *message, chunk_t *hash)
                    775: {
                    776:        uint32_t mid, mid_n;
                    777:        chunk_t data = chunk_empty, *n_i, *n_r;
                    778:        bool add_message = TRUE;
                    779:        char *name = "Hash";
                    780: 
                    781:        if (!this->prf)
                    782:        {       /* no keys derived yet */
                    783:                return FALSE;
                    784:        }
                    785: 
                    786:        mid = message->get_message_id(message);
                    787:        mid_n = htonl(mid);
                    788: 
                    789:        /* Hashes are simple for most exchanges in Phase 2:
                    790:         *   Hash = prf(SKEYID_a, M-ID | Complete message after HASH payload)
                    791:         * For Quick Mode there are three hashes:
                    792:         *   Hash(1) = same as above
                    793:         *   Hash(2) = prf(SKEYID_a, M-ID | Ni_b | Message after HASH payload)
                    794:         *   Hash(3) = prf(SKEYID_a, 0 | M-ID | Ni_b | Nr_b)
                    795:         * So, for Quick Mode we keep track of the nonce values.
                    796:         */
                    797:        switch (message->get_exchange_type(message))
                    798:        {
                    799:                case QUICK_MODE:
                    800:                {
                    801:                        this->iv_manager->lookup_quick_mode(this->iv_manager, mid, &n_i,
                    802:                                                                                                &n_r);
                    803:                        if (!n_i->ptr)
                    804:                        {       /* Hash(1) = prf(SKEYID_a, M-ID | Message after HASH payload) */
                    805:                                name = "Hash(1)";
                    806:                                if (!get_nonce(message, n_i))
                    807:                                {
                    808:                                        return FALSE;
                    809:                                }
                    810:                                data = chunk_from_thing(mid_n);
                    811:                        }
                    812:                        else if (!n_r->ptr)
                    813:                        {       /* Hash(2) = prf(SKEYID_a, M-ID | Ni_b | Message after HASH) */
                    814:                                name = "Hash(2)";
                    815:                                if (!get_nonce(message, n_r))
                    816:                                {
                    817:                                        return FALSE;
                    818:                                }
                    819:                                data = chunk_cata("cc", chunk_from_thing(mid_n), *n_i);
                    820:                        }
                    821:                        else
                    822:                        {       /* Hash(3) = prf(SKEYID_a, 0 | M-ID | Ni_b | Nr_b) */
                    823:                                name = "Hash(3)";
                    824:                                data = chunk_cata("cccc", octet_0, chunk_from_thing(mid_n),
                    825:                                                                  *n_i, *n_r);
                    826:                                add_message = FALSE;
                    827:                                /* we don't need the state anymore */
                    828:                                this->iv_manager->remove_quick_mode(this->iv_manager, mid);
                    829:                        }
                    830:                        break;
                    831:                }
                    832:                case TRANSACTION:
                    833:                case INFORMATIONAL_V1:
                    834:                        /* Hash = prf(SKEYID_a, M-ID | Message after HASH payload) */
                    835:                        data = chunk_from_thing(mid_n);
                    836:                        break;
                    837:                default:
                    838:                        return FALSE;
                    839:        }
                    840:        if (!this->prf->set_key(this->prf, this->skeyid_a))
                    841:        {
                    842:                return FALSE;
                    843:        }
                    844:        if (add_message)
                    845:        {
                    846:                generator_t *generator;
                    847:                chunk_t msg;
                    848: 
                    849:                generator = generator_create_no_dbg();
                    850:                msg = get_message_data(message, generator);
                    851:                if (!this->prf->allocate_bytes(this->prf, data, NULL) ||
                    852:                        !this->prf->allocate_bytes(this->prf, msg, hash))
                    853:                {
                    854:                        generator->destroy(generator);
                    855:                        return FALSE;
                    856:                }
                    857:                generator->destroy(generator);
                    858:        }
                    859:        else
                    860:        {
                    861:                if (!this->prf->allocate_bytes(this->prf, data, hash))
                    862:                {
                    863:                        return FALSE;
                    864:                }
                    865:        }
                    866:        DBG3(DBG_IKE, "%s %B", name, hash);
                    867:        return TRUE;
                    868: }
                    869: 
                    870: METHOD(keymat_v1_t, get_iv, bool,
                    871:        private_keymat_v1_t *this, uint32_t mid, chunk_t *out)
                    872: {
                    873:        return this->iv_manager->get_iv(this->iv_manager, mid, out);
                    874: }
                    875: 
                    876: METHOD(keymat_v1_t, update_iv, bool,
                    877:        private_keymat_v1_t *this, uint32_t mid, chunk_t last_block)
                    878: {
                    879:        return this->iv_manager->update_iv(this->iv_manager, mid, last_block);
                    880: }
                    881: 
                    882: METHOD(keymat_v1_t, confirm_iv, bool,
                    883:        private_keymat_v1_t *this, uint32_t mid)
                    884: {
                    885:        return this->iv_manager->confirm_iv(this->iv_manager, mid);
                    886: }
                    887: 
                    888: METHOD(keymat_t, get_version, ike_version_t,
                    889:        private_keymat_v1_t *this)
                    890: {
                    891:        return IKEV1;
                    892: }
                    893: 
                    894: METHOD(keymat_t, create_dh, diffie_hellman_t*,
                    895:        private_keymat_v1_t *this, diffie_hellman_group_t group)
                    896: {
                    897:        return lib->crypto->create_dh(lib->crypto, group);
                    898: }
                    899: 
                    900: METHOD(keymat_t, create_nonce_gen, nonce_gen_t*,
                    901:        private_keymat_v1_t *this)
                    902: {
                    903:        return lib->crypto->create_nonce_gen(lib->crypto);
                    904: }
                    905: 
                    906: METHOD(keymat_t, get_aead, aead_t*,
                    907:        private_keymat_v1_t *this, bool in)
                    908: {
                    909:        return this->aead;
                    910: }
                    911: 
                    912: METHOD(keymat_t, destroy, void,
                    913:        private_keymat_v1_t *this)
                    914: {
                    915:        DESTROY_IF(this->prf);
                    916:        DESTROY_IF(this->prf_auth);
                    917:        DESTROY_IF(this->aead);
                    918:        DESTROY_IF(this->hasher);
                    919:        chunk_clear(&this->skeyid_d);
                    920:        chunk_clear(&this->skeyid_a);
                    921:        this->iv_manager->destroy(this->iv_manager);
                    922:        free(this);
                    923: }
                    924: 
                    925: /**
                    926:  * See header
                    927:  */
                    928: keymat_v1_t *keymat_v1_create(bool initiator)
                    929: {
                    930:        private_keymat_v1_t *this;
                    931: 
                    932:        INIT(this,
                    933:                .public = {
                    934:                        .keymat = {
                    935:                                .get_version = _get_version,
                    936:                                .create_dh = _create_dh,
                    937:                                .create_nonce_gen = _create_nonce_gen,
                    938:                                .get_aead = _get_aead,
                    939:                                .destroy = _destroy,
                    940:                        },
                    941:                        .derive_ike_keys = _derive_ike_keys,
                    942:                        .derive_child_keys = _derive_child_keys,
                    943:                        .create_hasher = _create_hasher,
                    944:                        .get_hasher = _get_hasher,
                    945:                        .get_hash = _get_hash,
                    946:                        .get_hash_phase2 = _get_hash_phase2,
                    947:                        .get_iv = _get_iv,
                    948:                        .update_iv = _update_iv,
                    949:                        .confirm_iv = _confirm_iv,
                    950:                },
                    951:                .initiator = initiator,
                    952:                .iv_manager = iv_manager_create(0),
                    953:        );
                    954:        return &this->public;
                    955: }

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