Annotation of embedaddon/strongswan/src/libtls/tls_hkdf.c, revision 1.1.1.1

1.1       misho       1: /*
                      2:  * Copyright (C) 2020 Tobias Brunner
                      3:  * Copyright (C) 2020 Pascal Knecht
                      4:  * Copyright (C) 2020 Méline Sieber
                      5:  * HSR Hochschule fuer Technik Rapperswil
                      6:  *
                      7:  * This program is free software; you can redistribute it and/or modify it
                      8:  * under the terms of the GNU General Public License as published by the
                      9:  * Free Software Foundation; either version 2 of the License, or (at your
                     10:  * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
                     11:  *
                     12:  * This program is distributed in the hope that it will be useful, but
                     13:  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
                     14:  * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
                     15:  * for more details.
                     16:  */
                     17: 
                     18: #include "tls_hkdf.h"
                     19: 
                     20: #include <bio/bio_writer.h>
                     21: #include <crypto/prf_plus.h>
                     22: 
                     23: typedef struct private_tls_hkdf_t private_tls_hkdf_t;
                     24: 
                     25: typedef struct cached_secrets_t {
                     26:        chunk_t client;
                     27:        chunk_t server;
                     28: } cached_secrets_t;
                     29: 
                     30: typedef enum hkdf_phase {
                     31:        HKDF_PHASE_0,
                     32:        HKDF_PHASE_1,
                     33:        HKDF_PHASE_2,
                     34:        HKDF_PHASE_3,
                     35: } hkdf_phase;
                     36: 
                     37: struct private_tls_hkdf_t {
                     38: 
                     39:        /**
                     40:         * Public tls_hkdf_t interface.
                     41:         */
                     42:        struct tls_hkdf_t public;
                     43: 
                     44:        /**
                     45:         * Phase we are in.
                     46:         */
                     47:        hkdf_phase phase;
                     48: 
                     49:        /**
                     50:         * Pseudorandom function used.
                     51:         */
                     52:        prf_t *prf;
                     53: 
                     54:        /**
                     55:         * Hasher used.
                     56:         */
                     57:        hasher_t *hasher;
                     58: 
                     59:        /**
                     60:         * (EC)DHE as IKM to switch from phase 1 to phase 2
                     61:         */
                     62:        chunk_t shared_secret;
                     63: 
                     64:        /**
                     65:         * PSK used.
                     66:         */
                     67:        chunk_t psk;
                     68: 
                     69:        /**
                     70:         * PRK used.
                     71:         */
                     72:        chunk_t prk;
                     73: 
                     74:        /**
                     75:         * Handshake traffic secrets.
                     76:         */
                     77:        cached_secrets_t handshake_traffic_secrets;
                     78: 
                     79:        /**
                     80:         * Current traffic secrets.
                     81:         */
                     82:        cached_secrets_t traffic_secrets;
                     83: };
                     84: 
                     85: static char *hkdf_labels[] = {
                     86:        "ext binder",
                     87:        "res binder",
                     88:        "c e traffic",
                     89:        "e exp master",
                     90:        "c hs traffic",
                     91:        "s hs traffic",
                     92:        "c ap traffic",
                     93:        "s ap traffic",
                     94:        "exp master",
                     95:        "res master",
                     96: };
                     97: 
                     98: /**
                     99:  * Step 1: Extract, as defined in RFC 5869, section 2.2:
                    100:  * HKDF-Extract(salt, IKM) -> PRK
                    101:  */
                    102: static bool extract(private_tls_hkdf_t *this, chunk_t salt, chunk_t ikm,
                    103:                                        chunk_t *prk)
                    104: {
                    105:        if (!this->prf->set_key(this->prf, salt))
                    106:        {
                    107:                DBG1(DBG_TLS, "unable to set PRF secret to salt");
                    108:                return FALSE;
                    109:        }
                    110:        chunk_clear(prk);
                    111:        if(!this->prf->allocate_bytes(this->prf, ikm, prk))
                    112:        {
                    113:                DBG1(DBG_TLS, "unable to allocate PRF result");
                    114:                return FALSE;
                    115:        }
                    116: 
                    117:        DBG4(DBG_TLS, "PRK: %B", prk);
                    118: 
                    119:        return TRUE;
                    120: }
                    121: 
                    122: /**
                    123:  * Step 2: Expand as defined in RFC 5869, section 2.3:
                    124:  * HKDF-Expand(PRK, info, L) -> OKM
                    125:  */
                    126: static bool expand(private_tls_hkdf_t *this, chunk_t prk, chunk_t info,
                    127:                                   size_t length, chunk_t *okm)
                    128: {
                    129:        prf_plus_t *prf_plus;
                    130: 
                    131:        if (!this->prf->set_key(this->prf, prk))
                    132:        {
                    133:                DBG1(DBG_TLS, "unable to set PRF secret to PRK");
                    134:                return FALSE;
                    135:        }
                    136:        prf_plus = prf_plus_create(this->prf, TRUE, info);
                    137:        if (!prf_plus || !prf_plus->allocate_bytes(prf_plus, length, okm))
                    138:        {
                    139:                DBG1(DBG_TLS, "unable to allocate PRF+ result");
                    140:                DESTROY_IF(prf_plus);
                    141:                return FALSE;
                    142:        }
                    143:        prf_plus->destroy(prf_plus);
                    144: 
                    145:        DBG4(DBG_TLS, "OKM: %B", okm);
                    146: 
                    147:        return TRUE;
                    148: }
                    149: 
                    150: /**
                    151:  * Expand-Label as defined in RFC 8446, section 7.1:
                    152:  * HKDF-Expand-Label(Secret, Label, Context, Length) -> OKM
                    153:  */
                    154: static bool expand_label(private_tls_hkdf_t *this, chunk_t secret,
                    155:                                                 chunk_t label, chunk_t context, uint16_t length,
                    156:                                                 chunk_t *key)
                    157: {
                    158:        bool success;
                    159: 
                    160:        if (!label.len || label.len > 249 || context.len > 255)
                    161:        {
                    162:                return FALSE;
                    163:        }
                    164: 
                    165:        /* HKDFLabel as defined in RFC 8446, section 7.1 */
                    166:        bio_writer_t *writer = bio_writer_create(0);
                    167:        writer->write_uint16(writer, length);
                    168:        label = chunk_cata("cc", chunk_from_str("tls13 "), label);
                    169:        writer->write_data8(writer, label);
                    170:        writer->write_data8(writer, context);
                    171: 
                    172:        success = expand(this, secret, writer->get_buf(writer), length, key);
                    173:        writer->destroy(writer);
                    174:        return success;
                    175: }
                    176: 
                    177: /**
                    178:  * Derive-Secret as defined in RFC 8446, section 7.1:
                    179:  * Derive-Secret(Secret, Label, Message) -> OKM
                    180:  */
                    181: static bool derive_secret(private_tls_hkdf_t *this, chunk_t secret,
                    182:                                                  chunk_t label, chunk_t messages, chunk_t *okm)
                    183: {
                    184:        chunk_t context;
                    185:        bool success;
                    186: 
                    187:        if (!this->hasher->allocate_hash(this->hasher, messages, &context))
                    188:        {
                    189:                return FALSE;
                    190:        }
                    191: 
                    192:        success = expand_label(this, secret, label, context,
                    193:                                                   this->hasher->get_hash_size(this->hasher), okm);
                    194:        chunk_free(&context);
                    195:        return success;
                    196: }
                    197: 
                    198: /**
                    199:  * Move to phase 1 (Early Secret)
                    200:  *
                    201:  *            0
                    202:  *            |
                    203:  *            v
                    204:  *  PSK ->  HKDF-Extract = Early Secret
                    205:  *            |
                    206:  *            +-----> Derive-Secret(., "ext binder" | "res binder", "")
                    207:  *            |                     = binder_key
                    208:  *            |
                    209:  *            +-----> Derive-Secret(., "c e traffic", ClientHello)
                    210:  *            |                     = client_early_traffic_secret
                    211:  *            |
                    212:  *            +-----> Derive-Secret(., "e exp master", ClientHello)
                    213:  *            |                     = early_exporter_master_secret
                    214:  *            v
                    215:  */
                    216: static bool move_to_phase_1(private_tls_hkdf_t *this)
                    217: {
                    218:        chunk_t salt_zero, psk = this->psk;
                    219: 
                    220:        switch (this->phase)
                    221:        {
                    222:                case HKDF_PHASE_0:
                    223:                        salt_zero = chunk_alloca(this->hasher->get_hash_size(this->hasher));
                    224:                        chunk_copy_pad(salt_zero, chunk_empty, 0);
                    225:                        if (!psk.ptr)
                    226:                        {
                    227:                                psk = salt_zero;
                    228:                        }
                    229:                        if (!extract(this, salt_zero, psk, &this->prk))
                    230:                        {
                    231:                                DBG1(DBG_TLS, "unable to extract PRK");
                    232:                                return FALSE;
                    233:                        }
                    234:                        this->phase = HKDF_PHASE_1;
                    235:                        return TRUE;
                    236:                case HKDF_PHASE_1:
                    237:                        return TRUE;
                    238:                default:
                    239:                        DBG1(DBG_TLS, "invalid HKDF phase");
                    240:                        return FALSE;
                    241:        }
                    242: }
                    243: 
                    244: /**
                    245:  * Move to phase 2 (Handshake Secret)
                    246:  *
                    247:  *      Derive-Secret(., "derived", "")
                    248:  *            |
                    249:  *            v
                    250:  *  (EC)DHE -> HKDF-Extract = Handshake Secret
                    251:  *            |
                    252:  *            +-----> Derive-Secret(., "c hs traffic",
                    253:  *            |                     ClientHello...ServerHello)
                    254:  *            |                     = client_handshake_traffic_secret
                    255:  *            |
                    256:  *            +-----> Derive-Secret(., "s hs traffic",
                    257:  *            |                     ClientHello...ServerHello)
                    258:  *            |                     = server_handshake_traffic_secret
                    259:  *            v
                    260:  */
                    261: static bool move_to_phase_2(private_tls_hkdf_t *this)
                    262: {
                    263:        chunk_t okm;
                    264: 
                    265:        switch (this->phase)
                    266:        {
                    267:                case HKDF_PHASE_0:
                    268:                        if (!move_to_phase_1(this))
                    269:                        {
                    270:                                DBG1(DBG_TLS, "unable to move to phase 1");
                    271:                                return FALSE;
                    272:                        }
                    273:                        /* fall-through */
                    274:                case HKDF_PHASE_1:
                    275:                        if (!derive_secret(this, this->prk, chunk_from_str("derived"),
                    276:                                                           chunk_empty, &okm))
                    277:                        {
                    278:                                DBG1(DBG_TLS, "unable to derive secret");
                    279:                                return FALSE;
                    280:                        }
                    281: 
                    282:                        if (!this->shared_secret.ptr)
                    283:                        {
                    284:                                DBG1(DBG_TLS, "no shared secret set");
                    285:                                chunk_clear(&okm);
                    286:                                return FALSE;
                    287:                        }
                    288: 
                    289:                        if (!extract(this, okm, this->shared_secret, &this->prk))
                    290:                        {
                    291:                                DBG1(DBG_TLS, "unable extract PRK");
                    292:                                chunk_clear(&okm);
                    293:                                return FALSE;
                    294:                        }
                    295:                        chunk_clear(&okm);
                    296:                        this->phase = HKDF_PHASE_2;
                    297:                        return TRUE;
                    298:                case HKDF_PHASE_2:
                    299:                        return TRUE;
                    300:                default:
                    301:                        DBG1(DBG_TLS, "invalid HKDF phase");
                    302:                        return FALSE;
                    303:        }
                    304: }
                    305: 
                    306: /**
                    307:  * Move to phase 3 (Master Secret)
                    308:  *
                    309:  *      Derive-Secret(., "derived", "")
                    310:  *            |
                    311:  *            v
                    312:  *  0 -> HKDF-Extract = Master Secret
                    313:  *            |
                    314:  *            +-----> Derive-Secret(., "c ap traffic",
                    315:  *            |                     ClientHello...server Finished)
                    316:  *            |                     = client_application_traffic_secret_0
                    317:  *            |
                    318:  *            +-----> Derive-Secret(., "s ap traffic",
                    319:  *            |                     ClientHello...server Finished)
                    320:  *            |                     = server_application_traffic_secret_0
                    321:  *            |
                    322:  *            +-----> Derive-Secret(., "exp master",
                    323:  *            |                     ClientHello...server Finished)
                    324:  *            |                     = exporter_master_secret
                    325:  *            |
                    326:  *            +-----> Derive-Secret(., "res master",
                    327:  *                                  ClientHello...client Finished)
                    328:  *                                  = resumption_master_secret
                    329:  */
                    330: static bool move_to_phase_3(private_tls_hkdf_t *this)
                    331: {
                    332:        chunk_t okm, ikm_zero;
                    333: 
                    334:        switch (this->phase)
                    335:        {
                    336:                case HKDF_PHASE_0:
                    337:                case HKDF_PHASE_1:
                    338:                        if (!move_to_phase_2(this))
                    339:                        {
                    340:                                DBG1(DBG_TLS, "unable to move to phase 2");
                    341:                                return FALSE;
                    342:                        }
                    343:                        /* fall-through */
                    344:                case HKDF_PHASE_2:
                    345:                        /* prepare okm for next extract */
                    346:                        if (!derive_secret(this, this->prk, chunk_from_str("derived"),
                    347:                                                           chunk_empty, &okm))
                    348:                        {
                    349:                                DBG1(DBG_TLS, "unable to derive secret");
                    350:                                return FALSE;
                    351:                        }
                    352: 
                    353:                        ikm_zero = chunk_alloca(this->hasher->get_hash_size(this->hasher));
                    354:                        chunk_copy_pad(ikm_zero, chunk_empty, 0);
                    355:                        if (!extract(this, okm, ikm_zero, &this->prk))
                    356:                        {
                    357:                                DBG1(DBG_TLS, "unable extract PRK");
                    358:                                chunk_clear(&okm);
                    359:                                return FALSE;
                    360:                        }
                    361:                        chunk_clear(&okm);
                    362:                        this->phase = HKDF_PHASE_3;
                    363:                        return TRUE;
                    364:                case HKDF_PHASE_3:
                    365:                        return TRUE;
                    366:                default:
                    367:                        DBG1(DBG_TLS, "invalid HKDF phase");
                    368:                        return FALSE;
                    369:        }
                    370: }
                    371: 
                    372: METHOD(tls_hkdf_t, set_shared_secret, void,
                    373:        private_tls_hkdf_t *this, chunk_t shared_secret)
                    374: {
                    375:        this->shared_secret = chunk_clone(shared_secret);
                    376: }
                    377: 
                    378: METHOD(tls_hkdf_t, generate_secret, bool,
                    379:        private_tls_hkdf_t *this, tls_hkdf_label_t label, chunk_t messages,
                    380:        chunk_t *secret)
                    381: {
                    382:        chunk_t okm;
                    383: 
                    384:        switch (label)
                    385:        {
                    386:                case TLS_HKDF_EXT_BINDER:
                    387:                case TLS_HKDF_RES_BINDER:
                    388:                case TLS_HKDF_C_E_TRAFFIC:
                    389:                case TLS_HKDF_E_EXP_MASTER:
                    390:                        if (!move_to_phase_1(this))
                    391:                        {
                    392:                                DBG1(DBG_TLS, "unable to move to phase 1");
                    393:                                return FALSE;
                    394:                        }
                    395:                        break;
                    396:                case TLS_HKDF_C_HS_TRAFFIC:
                    397:                case TLS_HKDF_S_HS_TRAFFIC:
                    398:                        if (!move_to_phase_2(this))
                    399:                        {
                    400:                                DBG1(DBG_TLS, "unable to move to phase 2");
                    401:                                return FALSE;
                    402:                        }
                    403:                        break;
                    404:                case TLS_HKDF_C_AP_TRAFFIC:
                    405:                case TLS_HKDF_S_AP_TRAFFIC:
                    406:                case TLS_HKDF_EXP_MASTER:
                    407:                case TLS_HKDF_RES_MASTER:
                    408:                        if (!move_to_phase_3(this))
                    409:                        {
                    410:                                DBG1(DBG_TLS, "unable to move to phase 3");
                    411:                                return FALSE;
                    412:                        }
                    413:                        break;
                    414:                case TLS_HKDF_UPD_C_TRAFFIC:
                    415:                case TLS_HKDF_UPD_S_TRAFFIC:
                    416:                        if (this->phase != HKDF_PHASE_3)
                    417:                        {
                    418:                                DBG1(DBG_TLS, "unable to update traffic keys");
                    419:                                return FALSE;
                    420:                        }
                    421:                        break;
                    422:                default:
                    423:                        DBG1(DBG_TLS, "invalid HKDF label");
                    424:                        return FALSE;
                    425:        }
                    426: 
                    427:        if (label == TLS_HKDF_UPD_C_TRAFFIC || label == TLS_HKDF_UPD_S_TRAFFIC)
                    428:        {
                    429:                chunk_t previous = this->traffic_secrets.client;
                    430: 
                    431:                if (label == TLS_HKDF_UPD_S_TRAFFIC)
                    432:                {
                    433:                        previous = this->traffic_secrets.server;
                    434:                }
                    435: 
                    436:                if (!expand_label(this, previous, chunk_from_str("traffic upd"),
                    437:                                                  chunk_empty, this->hasher->get_hash_size(this->hasher),
                    438:                                                  &okm))
                    439:                {
                    440:                        DBG1(DBG_TLS, "unable to update secret");
                    441:                        return FALSE;
                    442:                }
                    443:        }
                    444:        else
                    445:        {
                    446:                if (!derive_secret(this, this->prk, chunk_from_str(hkdf_labels[label]),
                    447:                                                   messages, &okm))
                    448:                {
                    449:                        DBG1(DBG_TLS, "unable to derive secret");
                    450:                        return FALSE;
                    451:                }
                    452:        }
                    453: 
                    454:        switch (label)
                    455:        {
                    456:                case TLS_HKDF_C_HS_TRAFFIC:
                    457:                        chunk_clear(&this->handshake_traffic_secrets.client);
                    458:                        this->handshake_traffic_secrets.client = chunk_clone(okm);
                    459:                        /* fall-through */
                    460:                case TLS_HKDF_C_AP_TRAFFIC:
                    461:                case TLS_HKDF_UPD_C_TRAFFIC:
                    462:                        chunk_clear(&this->traffic_secrets.client);
                    463:                        this->traffic_secrets.client = chunk_clone(okm);
                    464:                        break;
                    465:                case TLS_HKDF_S_HS_TRAFFIC:
                    466:                        chunk_clear(&this->handshake_traffic_secrets.server);
                    467:                        this->handshake_traffic_secrets.server = chunk_clone(okm);
                    468:                        /* fall-through */
                    469:                case TLS_HKDF_S_AP_TRAFFIC:
                    470:                case TLS_HKDF_UPD_S_TRAFFIC:
                    471:                        chunk_clear(&this->traffic_secrets.server);
                    472:                        this->traffic_secrets.server = chunk_clone(okm);
                    473:                        break;
                    474:                default:
                    475:                        break;
                    476:        }
                    477: 
                    478:        if (secret)
                    479:        {
                    480:                *secret = okm;
                    481:        }
                    482:        else
                    483:        {
                    484:                chunk_clear(&okm);
                    485:        }
                    486:        return TRUE;
                    487: }
                    488: 
                    489: /**
                    490:  * Derive keys/IVs from the current traffic secrets.
                    491:  */
                    492: static bool get_shared_label_keys(private_tls_hkdf_t *this, chunk_t label,
                    493:                                                                  cached_secrets_t *secrets,
                    494:                                                                  bool server, size_t length, chunk_t *key)
                    495: {
                    496:        chunk_t result = chunk_empty, secret;
                    497: 
                    498:        secret = server ? secrets->server : secrets->client;
                    499: 
                    500:        if (!expand_label(this, secret, label, chunk_empty, length, &result))
                    501:        {
                    502:                DBG1(DBG_TLS, "unable to derive labeled secret");
                    503:                chunk_clear(&result);
                    504:                return FALSE;
                    505:        }
                    506: 
                    507:        if (key)
                    508:        {
                    509:                *key = result;
                    510:        }
                    511:        else
                    512:        {
                    513:                chunk_clear(&result);
                    514:        }
                    515:        return TRUE;
                    516: }
                    517: 
                    518: METHOD(tls_hkdf_t, derive_key, bool,
                    519:        private_tls_hkdf_t *this, bool is_server, size_t length, chunk_t *key)
                    520: {
                    521:        return get_shared_label_keys(this, chunk_from_str("key"),
                    522:                                                                 &this->traffic_secrets, is_server, length, key);
                    523: }
                    524: 
                    525: METHOD(tls_hkdf_t, derive_iv, bool,
                    526:        private_tls_hkdf_t *this, bool is_server, size_t length, chunk_t *iv)
                    527: {
                    528:        return get_shared_label_keys(this, chunk_from_str("iv"),
                    529:                                                                 &this->traffic_secrets, is_server, length, iv);
                    530: }
                    531: 
                    532: METHOD(tls_hkdf_t, derive_finished, bool,
                    533:        private_tls_hkdf_t *this, bool server, chunk_t *finished)
                    534: {
                    535:        return get_shared_label_keys(this, chunk_from_str("finished"),
                    536:                                                                 &this->handshake_traffic_secrets, server,
                    537:                                                                 this->hasher->get_hash_size(this->hasher),
                    538:                                                                 finished);
                    539: }
                    540: 
                    541: METHOD(tls_hkdf_t, export, bool,
                    542:        private_tls_hkdf_t *this, char *label, chunk_t context,
                    543:        chunk_t messages, size_t length, chunk_t *key)
                    544: {
                    545:        chunk_t exporter_master, exporter, hash = chunk_empty;
                    546: 
                    547:        if (this->phase != HKDF_PHASE_3)
                    548:        {
                    549:                DBG1(DBG_TLS, "unable to export key material");
                    550:                return FALSE;
                    551:        }
                    552: 
                    553:        /**
                    554:         * Export key material according to RFC 8446, section 7.5:
                    555:         *
                    556:         * TLS-Exporter(label, context_value, key_length) =
                    557:         *    HKDF-Expand-Label(Derive-Secret(Secret, label, ""),
                    558:         *                      "exporter", Hash(context_value), key_length)
                    559:         */
                    560:        if (!generate_secret(this, TLS_HKDF_EXP_MASTER, messages, &exporter_master))
                    561:        {
                    562:                DBG1(DBG_TLS, "unable to derive exporter master secret");
                    563:                return FALSE;
                    564:        }
                    565: 
                    566:        if (!derive_secret(this, exporter_master, chunk_from_str(label),
                    567:                                           chunk_empty, &exporter))
                    568:        {
                    569:                DBG1(DBG_TLS, "unable to derive exporter secret");
                    570:                chunk_clear(&exporter_master);
                    571:                return FALSE;
                    572:        }
                    573:        chunk_clear(&exporter_master);
                    574: 
                    575:        if (!this->hasher->allocate_hash(this->hasher, context, &hash) ||
                    576:                !expand_label(this, exporter, chunk_from_str("exporter"), hash,
                    577:                                          length, key))
                    578:        {
                    579:                DBG1(DBG_TLS, "unable to expand key material");
                    580:                chunk_clear(&exporter);
                    581:                chunk_free(&hash);
                    582:                return FALSE;
                    583:        }
                    584:        chunk_clear(&exporter);
                    585:        chunk_free(&hash);
                    586:        return TRUE;
                    587: }
                    588: 
                    589: METHOD(tls_hkdf_t, resume, bool,
                    590:        private_tls_hkdf_t *this, chunk_t messages, chunk_t nonce, chunk_t *key)
                    591: {
                    592:        chunk_t resumption_master;
                    593: 
                    594:        if (this->phase != HKDF_PHASE_3)
                    595:        {
                    596:                DBG1(DBG_TLS, "unable to generate resumption key material");
                    597:                return FALSE;
                    598:        }
                    599:        if (!nonce.len)
                    600:        {
                    601:                DBG1(DBG_TLS, "no nonce provided");
                    602:                return FALSE;
                    603:        }
                    604: 
                    605:        /**
                    606:         * PSK associated with the ticket according to RFC 8446, section 4.6.1
                    607:         *
                    608:         *    HKDF-Expand-Label(resumption_master_secret,
                    609:         *                      "resumption", ticket_nonce, Hash.length)
                    610:         */
                    611:        if (!generate_secret(this, TLS_HKDF_RES_MASTER, messages,
                    612:                                                 &resumption_master))
                    613:        {
                    614:                DBG1(DBG_TLS, "unable to derive resumption master secret");
                    615:                return FALSE;
                    616:        }
                    617: 
                    618:        if (!expand_label(this, resumption_master, chunk_from_str("resumption"),
                    619:                                          nonce, this->hasher->get_hash_size(this->hasher), key))
                    620:        {
                    621:                chunk_clear(&resumption_master);
                    622:                DBG1(DBG_TLS, "unable to expand key material");
                    623:                return FALSE;
                    624:        }
                    625:        chunk_clear(&resumption_master);
                    626:        return TRUE;
                    627: }
                    628: 
                    629: METHOD(tls_hkdf_t, binder, bool,
                    630:        private_tls_hkdf_t *this, chunk_t seed, chunk_t *out)
                    631: {
                    632:        chunk_t binder_key, finished_key;
                    633: 
                    634:        if (!generate_secret(this, TLS_HKDF_RES_BINDER, chunk_empty, &binder_key))
                    635:        {
                    636:                DBG1(DBG_TLS, "unable to derive binder key");
                    637:                return FALSE;
                    638:        }
                    639: 
                    640:        if (!expand_label(this, binder_key, chunk_from_str("finished"), chunk_empty,
                    641:                                          this->hasher->get_hash_size(this->hasher), &finished_key))
                    642:        {
                    643:                chunk_clear(&binder_key);
                    644:                return FALSE;
                    645:        }
                    646:        chunk_clear(&binder_key);
                    647: 
                    648:        if (!this->prf->set_key(this->prf, finished_key) ||
                    649:                !this->prf->allocate_bytes(this->prf, seed, out))
                    650:        {
                    651:                chunk_clear(&finished_key);
                    652:                return FALSE;
                    653:        }
                    654:        chunk_clear(&finished_key);
                    655:        return TRUE;
                    656: }
                    657: 
                    658: METHOD(tls_hkdf_t, allocate_bytes, bool,
                    659:        private_tls_hkdf_t *this, chunk_t key, chunk_t seed,
                    660:        chunk_t *out)
                    661: {
                    662:        return this->prf->set_key(this->prf, key) &&
                    663:                   this->prf->allocate_bytes(this->prf, seed, out);
                    664: }
                    665: 
                    666: /**
                    667:  * Clean up secrets
                    668:  */
                    669: static void destroy_secrets(cached_secrets_t *secrets)
                    670: {
                    671:        chunk_clear(&secrets->client);
                    672:        chunk_clear(&secrets->server);
                    673: }
                    674: 
                    675: METHOD(tls_hkdf_t, destroy, void,
                    676:        private_tls_hkdf_t *this)
                    677: {
                    678:        chunk_clear(&this->psk);
                    679:        chunk_clear(&this->prk);
                    680:        chunk_clear(&this->shared_secret);
                    681:        destroy_secrets(&this->handshake_traffic_secrets);
                    682:        destroy_secrets(&this->traffic_secrets);
                    683:        DESTROY_IF(this->prf);
                    684:        DESTROY_IF(this->hasher);
                    685:        free(this);
                    686: }
                    687: 
                    688: tls_hkdf_t *tls_hkdf_create(hash_algorithm_t hash_algorithm, chunk_t psk)
                    689: {
                    690:        private_tls_hkdf_t *this;
                    691:        pseudo_random_function_t prf_algorithm;
                    692: 
                    693:        switch (hash_algorithm)
                    694:        {
                    695:                case HASH_SHA256:
                    696:                        prf_algorithm = PRF_HMAC_SHA2_256;
                    697:                        break;
                    698:                case HASH_SHA384:
                    699:                        prf_algorithm = PRF_HMAC_SHA2_384;
                    700:                        break;
                    701:                default:
                    702:                        DBG1(DBG_TLS, "unsupported hash algorithm %N", hash_algorithm_names,
                    703:                                 hash_algorithm);
                    704:                        return NULL;
                    705:        }
                    706: 
                    707:        INIT(this,
                    708:                .public = {
                    709:                        .set_shared_secret = _set_shared_secret,
                    710:                        .generate_secret = _generate_secret,
                    711:                        .derive_key = _derive_key,
                    712:                        .derive_iv = _derive_iv,
                    713:                        .derive_finished = _derive_finished,
                    714:                        .export = _export,
                    715:                        .resume = _resume,
                    716:                        .binder = _binder,
                    717:                        .allocate_bytes = _allocate_bytes,
                    718:                        .destroy = _destroy,
                    719:                },
                    720:                .phase = HKDF_PHASE_0,
                    721:                .psk = psk.ptr ? chunk_clone(psk) : chunk_empty,
                    722:                .prf = lib->crypto->create_prf(lib->crypto, prf_algorithm),
                    723:                .hasher = lib->crypto->create_hasher(lib->crypto, hash_algorithm),
                    724:        );
                    725: 
                    726:        if (!this->prf || !this->hasher)
                    727:        {
                    728:                if (!this->prf)
                    729:                {
                    730:                        DBG1(DBG_TLS, "%N not supported", pseudo_random_function_names,
                    731:                                 prf_algorithm);
                    732:                }
                    733:                if (!this->hasher)
                    734:                {
                    735:                        DBG1(DBG_TLS, "%N not supported", hash_algorithm_names,
                    736:                                 hash_algorithm);
                    737:                }
                    738:                DBG1(DBG_TLS, "unable to initialise HKDF");
                    739:                destroy(this);
                    740:                return NULL;
                    741:        }
                    742:        return &this->public;
                    743: }

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