From: James Rouzier Date: Tue, 6 Sep 2016 15:46:56 +0000 (-0400) Subject: T_PRF X-Git-Tag: release_3_0_12~74^2~26 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=780344501b960affc479148209f00f507839f7fd;p=thirdparty%2Ffreeradius-server.git T_PRF --- diff --git a/src/modules/rlm_eap/libeap/eap_tls.h b/src/modules/rlm_eap/libeap/eap_tls.h index 7510cf6249e..091921d885d 100644 --- a/src/modules/rlm_eap/libeap/eap_tls.h +++ b/src/modules/rlm_eap/libeap/eap_tls.h @@ -63,6 +63,7 @@ int eaptls_request(EAP_DS *eap_ds, tls_session_t *ssn) CC_HINT(nonnull); /* MPPE key generation */ +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_mppe_keys(REQUEST *request, SSL *s, char const *prf_label); void eapttls_gen_challenge(SSL *s, uint8_t *buffer, size_t size); void eaptls_gen_eap_key(RADIUS_PACKET *packet, SSL *s, uint32_t header); diff --git a/src/modules/rlm_eap/libeap/mppe_keys.c b/src/modules/rlm_eap/libeap/mppe_keys.c index b016c2b885a..16be5d15800 100644 --- a/src/modules/rlm_eap/libeap/mppe_keys.c +++ b/src/modules/rlm_eap/libeap/mppe_keys.c @@ -86,6 +86,49 @@ static void P_hash(EVP_MD const *evp_md, memset(a, 0, sizeof(a)); } +/* EAP-FAST Pseudo-Random Function (T-PRF): RFC 4851, Section 5.5 */ +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) +{ + size_t prf_size = strlen(prf_label); + size_t pos; + uint8_t *buf; + + if (prf_size > 128) prf_size = 128; + prf_size++; /* include trailing zero */ + + buf = talloc_size(NULL, SHA1_DIGEST_LENGTH + prf_size + seed_len + 2 + 1); + + memcpy(buf + SHA1_DIGEST_LENGTH, prf_label, prf_size); + if (seed) memcpy(buf + SHA1_DIGEST_LENGTH + prf_size, seed, seed_len); + *(uint16_t *)&buf[SHA1_DIGEST_LENGTH + prf_size + seed_len] = htons(out_len); + buf[SHA1_DIGEST_LENGTH + prf_size + seed_len + 2] = 1; + + // T1 is just the seed + fr_hmac_sha1(buf, buf + SHA1_DIGEST_LENGTH, prf_size + seed_len + 2 + 1, secret, secret_len); + +#define MIN(a,b) (((a)>(b)) ? (b) : (a)) + memcpy(out, buf, MIN(out_len, SHA1_DIGEST_LENGTH)); + + pos = SHA1_DIGEST_LENGTH; + while (pos < out_len) { + buf[SHA1_DIGEST_LENGTH + prf_size + seed_len + 2]++; + + fr_hmac_sha1(buf, buf, SHA1_DIGEST_LENGTH + prf_size + seed_len + 2 + 1, secret, secret_len); + memcpy(&out[pos], buf, MIN(out_len - pos, SHA1_DIGEST_LENGTH)); + + if (out_len - pos <= SHA1_DIGEST_LENGTH) + break; + + pos += SHA1_DIGEST_LENGTH; + } + + memset(buf, 0, SHA1_DIGEST_LENGTH + prf_size + seed_len + 2 + 1); + talloc_free(buf); +} + static void PRF(unsigned char const *secret, unsigned int secret_len, unsigned char const *seed, unsigned int seed_len, unsigned char *out, unsigned char *buf, unsigned int out_len)