diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-08-26 10:41:52 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-08-26 10:41:52 +0000 |
commit | 44eafeee62e6982131c62df6f74335114ca53024 (patch) | |
tree | 1cdf833b0a76e52630d717202398ced5900e11e9 /src/modules/rlm_eap/libeap | |
parent | Adding upstream version 3.2.3+dfsg. (diff) | |
download | freeradius-upstream.tar.xz freeradius-upstream.zip |
Adding upstream version 3.2.5+dfsg.upstream/3.2.5+dfsgupstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to '')
-rw-r--r-- | src/modules/rlm_eap/libeap/eap_tls.c | 215 | ||||
-rw-r--r-- | src/modules/rlm_eap/libeap/eap_tls.h | 6 | ||||
-rw-r--r-- | src/modules/rlm_eap/libeap/eap_types.h | 4 | ||||
-rw-r--r-- | src/modules/rlm_eap/libeap/eapcommon.c | 126 | ||||
-rw-r--r-- | src/modules/rlm_eap/libeap/mppe_keys.c | 56 |
5 files changed, 317 insertions, 90 deletions
diff --git a/src/modules/rlm_eap/libeap/eap_tls.c b/src/modules/rlm_eap/libeap/eap_tls.c index 2f37663..3a915bc 100644 --- a/src/modules/rlm_eap/libeap/eap_tls.c +++ b/src/modules/rlm_eap/libeap/eap_tls.c @@ -69,6 +69,9 @@ tls_session_t *eaptls_session(eap_handler_t *handler, fr_tls_server_conf_t *tls_ handler->tls = true; + tls_conf->name = dict_valnamebyattr(PW_EAP_TYPE, 0, handler->type); + if (!tls_conf->name) tls_conf->name = "???"; + /* * Every new session is started only from EAP-TLS-START. * Before Sending EAP-TLS-START, open a new SSL session. @@ -108,23 +111,22 @@ tls_session_t *eaptls_session(eap_handler_t *handler, fr_tls_server_conf_t *tls_ */ int eaptls_start(EAP_DS *eap_ds, int peap_flag) { - EAPTLS_PACKET reply; + EAPTLS_PACKET reply; - reply.code = FR_TLS_START; - reply.length = TLS_HEADER_LEN + 1/*flags*/; + reply.code = FR_TLS_START; + reply.length = TLS_HEADER_LEN + 1/*flags*/; - reply.flags = peap_flag; - reply.flags = SET_START(reply.flags); + reply.flags = peap_flag; + reply.flags = SET_START(reply.flags); - reply.data = NULL; - reply.dlen = 0; + reply.data = NULL; + reply.dlen = 0; - eaptls_compose(eap_ds, &reply); + eaptls_compose(eap_ds, &reply); - return 1; + return 1; } - /** Send an EAP-TLS success * * Composes an EAP-TLS-Success. This is a message with code EAP_TLS_ESTABLISHED. @@ -186,12 +188,11 @@ int eaptls_success(eap_handler_t *handler, int peap_flag) /* Should never happen */ rad_assert(0); return 0; - break; } eaptls_gen_mppe_keys(request, tls_session->ssl, tls_session->label, context, context_size); - } else if (handler->type != PW_EAP_FAST) { + } else if ((handler->type != PW_EAP_FAST) && (handler->type != PW_EAP_TEAP)) { RWDEBUG("(TLS) EAP Not adding MPPE keys because there is no PRF label"); } @@ -230,13 +231,21 @@ int eaptls_fail(eap_handler_t *handler, int peap_flag) * EAP-Request. We always embed the TLS-length in all EAP-TLS * packets that we send, for easy reference purpose. Handle * fragmentation and sending the next fragment etc. + * + * FIXME: support fragmented start due to TEAP outer tlvs */ -int eaptls_request(EAP_DS *eap_ds, tls_session_t *ssn) +int eaptls_request(EAP_DS *eap_ds, tls_session_t *ssn, bool start) { EAPTLS_PACKET reply; unsigned int size; - unsigned int nlen; unsigned int lbit = 0; + unsigned int obit = 0; + VALUE_PAIR *vp; + vp_cursor_t cursor; + uint32_t nlen; + uint16_t ohdr[2]; + uint32_t olen = 0; + uint32_t tls_mtu; /* This value determines whether we set (L)ength flag for EVERY packet we send and add corresponding @@ -257,16 +266,46 @@ int eaptls_request(EAP_DS *eap_ds, tls_session_t *ssn) if (ssn->length_flag) { lbit = 4; } + + /* + * This is included in the first fragment, and then never + * afterwards. + */ + if (start && ssn->outer_tlvs) { + for (vp = fr_cursor_init(&cursor, &ssn->outer_tlvs); + vp; + vp = fr_cursor_next(&cursor)) { + if (vp->da->type != PW_TYPE_OCTETS) { + DEBUG("FIXME Outer-TLV %s is of not type octets", vp->da->name); + continue; + } + obit = 4; + olen += sizeof(ohdr) + vp->vp_length; + break; + } + } + if (ssn->fragment == 0) { ssn->tls_msg_len = ssn->dirty_out.used; } - reply.code = FR_TLS_REQUEST; + reply.code = start ? FR_TLS_START : FR_TLS_REQUEST; reply.flags = ssn->peap_flag; + if (start) reply.flags = SET_START(reply.flags); + + /* + * This is only true for TEAP, so only TEAP has to check the return value of this function. + */ + if (lbit + obit + olen >= ssn->mtu) { + ERROR("fragment_size is too small for outer TLVs"); + return -1; + } + + tls_mtu = ssn->mtu - lbit - obit - olen; /* Send data, NOT more than the FRAGMENT size */ - if (ssn->dirty_out.used > ssn->mtu) { - size = ssn->mtu; + if (ssn->dirty_out.used > tls_mtu) { + size = tls_mtu; reply.flags = SET_MORE_FRAGMENTS(reply.flags); /* Length MUST be included if it is the First Fragment */ if (ssn->fragment == 0) { @@ -278,7 +317,7 @@ int eaptls_request(EAP_DS *eap_ds, tls_session_t *ssn) ssn->fragment = 0; } - reply.dlen = lbit + size; + reply.dlen = lbit + obit + size + olen; reply.length = TLS_HEADER_LEN + 1/*flags*/ + reply.dlen; reply.data = talloc_array(eap_ds, uint8_t, reply.length); @@ -286,10 +325,59 @@ int eaptls_request(EAP_DS *eap_ds, tls_session_t *ssn) if (lbit) { nlen = htonl(ssn->tls_msg_len); - memcpy(reply.data, &nlen, lbit); + memcpy(reply.data, &nlen, sizeof(nlen)); reply.flags = SET_LENGTH_INCLUDED(reply.flags); } - (ssn->record_minus)(&ssn->dirty_out, reply.data + lbit, size); + + if (obit) { + nlen = 0; + for (vp = fr_cursor_init(&cursor, &ssn->outer_tlvs); + vp; + vp = fr_cursor_next(&cursor)) { + if (vp->da->type != PW_TYPE_OCTETS) continue; + nlen += sizeof(ohdr) + vp->vp_length; + } + + ssn->outer_tlvs_octets = talloc_array(ssn, uint8_t, olen); + if (!ssn->outer_tlvs_octets) return 0; + + nlen = htonl(nlen); + memcpy(reply.data + lbit, &nlen, sizeof(nlen)); + reply.flags = SET_OUTER_TLV_INCLUDED(reply.flags); + } + + (ssn->record_minus)(&ssn->dirty_out, reply.data + lbit + obit, size); + + /* + * Tack on the outer TLVs after the TLS data. + */ + if (obit) { + olen = 0; + for (vp = fr_cursor_init(&cursor, &ssn->outer_tlvs); + vp; + vp = fr_cursor_next(&cursor)) { + if (vp->da->type != PW_TYPE_OCTETS) continue; + + /* FIXME duplicates eap_teap_tlv_append */ + + /* + * RFC7170, Section 4.3.1 - Outer TLVs must be marked optional + */ + ohdr[0] = htons((vp->da->attr >> fr_attr_shift[1]) & fr_attr_mask[1]); + ohdr[1] = htons(vp->vp_length); + + /* use by Crypto-Binding TLV */ + memcpy(ssn->outer_tlvs_octets + olen, ohdr, sizeof(ohdr)); + olen += sizeof(ohdr); + memcpy(ssn->outer_tlvs_octets + olen, vp->vp_octets, vp->vp_length); + olen += vp->vp_length; + + memcpy(reply.data + lbit + obit + size, ohdr, sizeof(ohdr)); + size += sizeof(ohdr); + memcpy(reply.data + lbit + obit + size, vp->vp_octets, vp->vp_length); + size += vp->vp_length; + } + } eaptls_compose(eap_ds, &reply); talloc_free(reply.data); @@ -425,6 +513,9 @@ static fr_tls_status_t eaptls_verify(eap_handler_t *handler) * from a fragment acknowledgement. */ if (TLS_LENGTH_INCLUDED(eaptls_packet->flags)) { + /* + * data[0] and data[1] are always zero, vi eap_vp2packet() + */ size_t total_len = eaptls_packet->data[2] * 256 | eaptls_packet->data[3]; if (frag_len > total_len) { @@ -463,6 +554,14 @@ static fr_tls_status_t eaptls_verify(eap_handler_t *handler) return FR_TLS_FIRST_FRAGMENT; } + /* + * The "O" bit is only allowed for the first fragment. + */ + if (TLS_OUTER_TLV_INCLUDED(eaptls_packet->flags)) { + REDEBUG("(TLS) EAP Peer set 'O' bit after initial fragment"); + return FR_TLS_INVALID; + } + RDEBUG2("(TLS) EAP Got additional fragment with length (%zu bytes). " "Peer says more fragments will follow", frag_len); @@ -494,6 +593,10 @@ static fr_tls_status_t eaptls_verify(eap_handler_t *handler) } /* + * eap_vp2packet() ensures that the 'O' bit is not set here. + */ + + /* * The previous packet had the M flags set, but this one doesn't, * this must be the final record fragment */ @@ -563,7 +666,7 @@ static EAPTLS_PACKET *eaptls_extract(REQUEST *request, EAP_DS *eap_ds, fr_tls_st { EAPTLS_PACKET *tlspacket; uint32_t data_len = 0; - uint32_t len = 0; + uint32_t obit = 0; uint8_t *data = NULL; if (status == FR_TLS_INVALID) return NULL; @@ -599,36 +702,8 @@ static EAPTLS_PACKET *eaptls_extract(REQUEST *request, EAP_DS *eap_ds, fr_tls_st tlspacket->flags = eap_ds->response->type.data[0]; /* - * A quick sanity check of the flags. If we've been told - * that there's a length, and there isn't one, then stop. + * eaptls_verify() ensures that all of the flags are correct. */ - if (TLS_LENGTH_INCLUDED(tlspacket->flags) && - (tlspacket->length < 5)) { /* flags + TLS message length */ - REDEBUG("(TLS) EAP Invalid packet received: Length bit is set," - "but packet too short to contain length field"); - talloc_free(tlspacket); - return NULL; - } - - /* - * If the final TLS packet is larger than we can handle, die - * now. - * - * Likewise, if the EAP packet says N bytes, and the TLS - * packet says there's fewer bytes, it's a problem. - */ - if (TLS_LENGTH_INCLUDED(tlspacket->flags)) { - memcpy(&data_len, &eap_ds->response->type.data[1], 4); - data_len = ntohl(data_len); - if (data_len > MAX_RECORD_SIZE) { - REDEBUG("(TLS) EAP Reassembled data will be %u bytes, " - "greater than the size that we can handle (" STRINGIFY(MAX_RECORD_SIZE) " bytes)", - data_len); - talloc_free(tlspacket); - return NULL; - } - } - switch (status) { /* * The TLS Message Length field is four octets, and @@ -640,39 +715,28 @@ static EAPTLS_PACKET *eaptls_extract(REQUEST *request, EAP_DS *eap_ds, fr_tls_st * length should solve the problem. */ case FR_TLS_FIRST_FRAGMENT: - case FR_TLS_LENGTH_INCLUDED: - case FR_TLS_MORE_FRAGMENTS_WITH_LENGTH: - if (tlspacket->length < 5) { /* flags + TLS message length */ - REDEBUG("(TLS) EAP Invalid packet received: Expected length, got none"); - talloc_free(tlspacket); - return NULL; - } + obit = TLS_OUTER_TLV_INCLUDED(tlspacket->flags) << 2; /* - * Extract all the TLS fragments from the - * previous eap_ds Start appending this - * fragment to the above ds + * @todo - decode outer TLVs, too */ - memcpy(&data_len, &eap_ds->response->type.data[1], sizeof(uint32_t)); - data_len = ntohl(data_len); - data = (eap_ds->response->type.data + 5/*flags+TLS-Length*/); - len = eap_ds->response->type.length - 5/*flags+TLS-Length*/; - /* - * Hmm... this should be an error, too. - */ - if (data_len > len) { - data_len = len; - } - break; + /* FALL-THROUGH */ + + case FR_TLS_LENGTH_INCLUDED: + case FR_TLS_MORE_FRAGMENTS_WITH_LENGTH: + eap_ds->response->type.data += 4 + obit; + eap_ds->response->type.length -= 4 + obit; + + /* FALL-THROUGH */ /* * Data length is implicit, from the EAP header. */ case FR_TLS_MORE_FRAGMENTS: case FR_TLS_OK: - data_len = eap_ds->response->type.length - 1/*flags*/; - data = eap_ds->response->type.data + 1/*flags*/; + data_len = eap_ds->response->type.length - 1; + data = eap_ds->response->type.data + 1; break; default: @@ -689,6 +753,7 @@ static EAPTLS_PACKET *eaptls_extract(REQUEST *request, EAP_DS *eap_ds, fr_tls_st talloc_free(tlspacket); return NULL; } + memcpy(tlspacket->data, data, data_len); } @@ -784,7 +849,7 @@ static fr_tls_status_t eaptls_operation(fr_tls_status_t status, eap_handler_t *h * TLS proper can decide what to do, then. */ if (tls_session->dirty_out.used > 0) { - eaptls_request(handler->eap_ds, tls_session); + eaptls_request(handler->eap_ds, tls_session, false); return FR_TLS_HANDLED; } @@ -890,7 +955,7 @@ fr_tls_status_t eaptls_process(eap_handler_t *handler) * of fragments" phase. */ case FR_TLS_REQUEST: - eaptls_request(handler->eap_ds, tls_session); + eaptls_request(handler->eap_ds, tls_session, false); status = FR_TLS_HANDLED; goto done; diff --git a/src/modules/rlm_eap/libeap/eap_tls.h b/src/modules/rlm_eap/libeap/eap_tls.h index 8e5fc77..1112bcb 100644 --- a/src/modules/rlm_eap/libeap/eap_tls.h +++ b/src/modules/rlm_eap/libeap/eap_tls.h @@ -59,10 +59,14 @@ fr_tls_status_t eaptls_process(eap_handler_t *handler); int eaptls_success(eap_handler_t *handler, int peap_flag) CC_HINT(nonnull); int eaptls_fail(eap_handler_t *handler, int peap_flag) CC_HINT(nonnull); -int eaptls_request(EAP_DS *eap_ds, tls_session_t *ssn) CC_HINT(nonnull); +int eaptls_request(EAP_DS *eap_ds, tls_session_t *ssn, bool start) CC_HINT(nonnull); +#if OPENSSL_VERSION_NUMBER >= 0x10101000L +void TLS_PRF(SSL *ssl, unsigned char *sec, size_t seclen, struct iovec *iov, size_t iovcnt, unsigned char *key, size_t keylen); +#endif void T_PRF(unsigned char const *secret, unsigned int secret_len, char const *prf_label, unsigned char const *seed, unsigned int seed_len, unsigned char *out, unsigned int out_len) CC_HINT(nonnull(1,3,6)); +void eaptls_gen_keys_only(REQUEST *request, SSL *s, char const *label, uint8_t const *context, UNUSED size_t context_size, uint8_t *out, size_t outlen); void eaptls_gen_mppe_keys(REQUEST *request, SSL *s, char const *label, uint8_t const *context, size_t context_size); void eapttls_gen_challenge(SSL *s, uint8_t *buffer, size_t size); void eaptls_gen_eap_key(eap_handler_t *handler); diff --git a/src/modules/rlm_eap/libeap/eap_types.h b/src/modules/rlm_eap/libeap/eap_types.h index c6568ff..beee998 100644 --- a/src/modules/rlm_eap/libeap/eap_types.h +++ b/src/modules/rlm_eap/libeap/eap_types.h @@ -98,7 +98,9 @@ typedef enum eap_method { PW_EAP_GPSK, /* 51 */ PW_EAP_PWD, /* 52 */ PW_EAP_EKE, /* 53 */ - PW_EAP_MAX_TYPES /* 54 - for validation */ + PW_EAP_PT_EAP, /* 54 */ + PW_EAP_TEAP, /* 55 */ + PW_EAP_MAX_TYPES /* 56 - for validation */ } eap_type_t; #define PW_EAP_EXPANDED_TYPE (254) diff --git a/src/modules/rlm_eap/libeap/eapcommon.c b/src/modules/rlm_eap/libeap/eapcommon.c index 96db30b..5abe47a 100644 --- a/src/modules/rlm_eap/libeap/eapcommon.c +++ b/src/modules/rlm_eap/libeap/eapcommon.c @@ -302,6 +302,7 @@ eap_packet_raw_t *eap_vp2packet(TALLOC_CTX *ctx, VALUE_PAIR *vps) uint16_t len; int total_len; vp_cursor_t cursor; + bool allow_o = false; /* * Get only EAP-Message attribute list @@ -315,7 +316,7 @@ eap_packet_raw_t *eap_vp2packet(TALLOC_CTX *ctx, VALUE_PAIR *vps) /* * Sanity check the length before doing anything. */ - if (first->vp_length < 4) { + if (first->vp_length < 5) { fr_strerror_printf("EAP packet is too short"); return NULL; } @@ -330,8 +331,8 @@ eap_packet_raw_t *eap_vp2packet(TALLOC_CTX *ctx, VALUE_PAIR *vps) /* * Take out even more weird things. */ - if (len < 4) { - fr_strerror_printf("EAP packet has invalid length (less than 4 bytes)"); + if (len < 5) { + fr_strerror_printf("EAP packet has invalid length (less than 5 bytes)"); return NULL; } @@ -379,6 +380,125 @@ eap_packet_raw_t *eap_vp2packet(TALLOC_CTX *ctx, VALUE_PAIR *vps) ptr += i->vp_length; } + /* + * Do additional sanity check for TLS-based EAP types, so + * that we don't have to do any of that later. + */ + switch (eap_packet->data[0]) { + /* + * 0 1 2 3 + * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Code | Identifier | Length | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Type | Flags | Ver | Message Length : + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * : Message Length | + * + * Flags are: + * + * 7 6 5 4 3 2 1 0 + * +-+-+-+-+-+-+-+-+ + * |L M S O R R R R| + * +-+-+-+-+-+-+-+-+ + * + * L = Length included + * M = More fragments + * S = EAP-TLS start + * O = outer TLV length included (4 octets, only for TEAP) + * R = Reserved + */ + case PW_EAP_TEAP: + allow_o = true; + /* FALL-THROUGH */ + + case PW_EAP_TLS: + case PW_EAP_TTLS: + case PW_EAP_PEAP: + case PW_EAP_FAST: + if (len < 2) { + fr_strerror_printf("Malformed EAP packet - packet is too small to contain TLS flags"); + talloc_free(eap_packet); + return NULL; + } + + /* + * L bit set means we have 4 octets of Length + * following the flags field. + */ + if ((eap_packet->data[1] & 0x80) != 0) { + uint32_t tls_len; + + if (len <= (2 + 4)) { + fr_strerror_printf("Malformed EAP packet - TLS 'L' bit is set, but packet is too small to contain 'length' field"); + talloc_free(eap_packet); + return NULL; + } + + /* + * This is arguably wrong... a single TLS + * record is max 16K in length. But a + * TLS message may span multiple TLS + * records. + */ + memcpy(&tls_len, eap_packet->data + 2, 4); + tls_len = ntohl(tls_len); + if (tls_len > 16384) { + fr_strerror_printf("Malformed EAP packet - TLS reassembled data length %u (%08x) (will be greater than the TLS maximum record size of 16384 bytes", tls_len, tls_len); + talloc_free(eap_packet); + return NULL; + } + + /* + * O bit set means we have 4 octets of Outer TLV Length + * following the Length field. + */ + if ((eap_packet->data[1] & 0x10) != 0) { + uint32_t tlv_len; + + if (!allow_o) { + fr_strerror_printf("Malformed EAP packet - TLS 'O' bit is set, but EAP method does not use it."); + talloc_free(eap_packet); + return NULL; + } + + if (len <= (2 + 4 + 4)) { + fr_strerror_printf("Malformed EAP packet - TLS 'O' bit is set, but packet is too small to contain 'outer tlv length' field"); + talloc_free(eap_packet); + return NULL; + } + + memcpy(&tlv_len, eap_packet->data + 2 + 4, 4); + tlv_len = ntohl(tlv_len); + + /* + * The EAP header includes all of + * the data in the packet. The + * outer TLV length cannot + * include the EAP header, type, + * flags, length field, or outer + * tlv length field. + */ + if ((int)tlv_len > (len - (2 + 4 + 4))) { + fr_strerror_printf("Malformed EAP packet - TLS 'O' bit is set, but 'outer tlv length' field is larger than the current fragment"); + talloc_free(eap_packet); + return NULL; + } + } + } else { + if ((eap_packet->data[1] & 0x10) != 0) { + fr_strerror_printf("Malformed EAP packet - TLS 'O' bit is set, but 'L' bit is not set."); + talloc_free(eap_packet); + return NULL; + } + + } + break; + + default: + break; + } + return eap_packet; } diff --git a/src/modules/rlm_eap/libeap/mppe_keys.c b/src/modules/rlm_eap/libeap/mppe_keys.c index 385441c..4356164 100644 --- a/src/modules/rlm_eap/libeap/mppe_keys.c +++ b/src/modules/rlm_eap/libeap/mppe_keys.c @@ -34,6 +34,35 @@ USES_APPLE_DEPRECATED_API /* OpenSSL API has been deprecated by Apple */ #include <openssl/provider.h> #endif +#if OPENSSL_VERSION_NUMBER >= 0x10101000L +#include <openssl/kdf.h> + +void TLS_PRF(SSL *ssl, + unsigned char *sec, size_t seclen, + struct iovec *iov, size_t iovcnt, + unsigned char *key, size_t keylen) +{ + const EVP_MD *md = SSL_CIPHER_get_handshake_digest(SSL_get_current_cipher(ssl)); + EVP_MD *unconst_md; + EVP_PKEY_CTX *pctx = EVP_PKEY_CTX_new_id(EVP_PKEY_TLS1_PRF, NULL); + + EVP_PKEY_derive_init(pctx); + + memcpy(&unconst_md, &md, sizeof(md)); /* const issues */ + EVP_PKEY_CTX_set_tls1_prf_md(pctx, unconst_md); + + EVP_PKEY_CTX_set1_tls1_prf_secret(pctx, sec, seclen); + + for (unsigned int i = 0; i < iovcnt; i++) { + EVP_PKEY_CTX_add1_tls1_prf_seed(pctx, iov[i].iov_base, iov[i].iov_len); + } + + EVP_PKEY_derive(pctx, key, &keylen); + + EVP_PKEY_CTX_free(pctx); +} +#endif + /* * TLS P_hash from RFC 2246/5246 section 5 */ @@ -210,23 +239,20 @@ void T_PRF(unsigned char const *secret, unsigned int secret_len, #define EAPTLS_MPPE_KEY_LEN 32 /* - * Generate keys according to RFC 2716 and add to reply + * Generate keys according to RFC 5216 (section 2.3) */ -void eaptls_gen_mppe_keys(REQUEST *request, SSL *s, char const *label, uint8_t const *context, UNUSED size_t context_size) +void eaptls_gen_keys_only(UNUSED REQUEST *request, SSL *s, char const *label, uint8_t const *context, UNUSED size_t context_size, uint8_t *out, size_t outlen) { - uint8_t out[4 * EAPTLS_MPPE_KEY_LEN]; - uint8_t *p; - size_t len; - - len = strlen(label); + size_t len = strlen(label); #if OPENSSL_VERSION_NUMBER >= 0x10001000L - if (SSL_export_keying_material(s, out, sizeof(out), label, len, context, context_size, context != NULL) != 1) { + if (SSL_export_keying_material(s, out, outlen, label, len, context, context_size, context != NULL) != 1) { ERROR("Failed generating keying material"); return; } #else { + uint8_t *p; uint8_t seed[64 + (2 * SSL3_RANDOM_SIZE) + (context ? 2 + context_size : 0)]; uint8_t buf[4 * EAPTLS_MPPE_KEY_LEN]; @@ -255,9 +281,20 @@ void eaptls_gen_mppe_keys(REQUEST *request, SSL *s, char const *label, uint8_t c } PRF(s->session->master_key, s->session->master_key_length, - seed, len, out, buf, sizeof(out)); + seed, len, out, buf, outlen); } #endif +} + +/* + * Generate keys according to RFC 5216 (section 2.3) and add to reply + */ +void eaptls_gen_mppe_keys(REQUEST *request, SSL *s, char const *label, uint8_t const *context, UNUSED size_t context_size) +{ + uint8_t out[4 * EAPTLS_MPPE_KEY_LEN]; + uint8_t *p; + + eaptls_gen_keys_only(request, s, label, context, context_size, out, sizeof(out)); p = out; eap_add_reply(request, "MS-MPPE-Recv-Key", p, EAPTLS_MPPE_KEY_LEN); @@ -268,7 +305,6 @@ void eaptls_gen_mppe_keys(REQUEST *request, SSL *s, char const *label, uint8_t c eap_add_reply(request, "EAP-EMSK", out + 64, 64); } - #define FR_TLS_PRF_CHALLENGE "ttls challenge" /* |