6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20 * Copyright 2002 Axis Communications AB
21 * Copyright 2006 The FreeRADIUS server project
22 * Authors: Henrik Eriksson <henriken@axis.com> & Lars Viklund <larsv@axis.com>
25 #include <freeradius-devel/ident.h>
28 #include <openssl/hmac.h>
32 * Add value pair to reply
34 static void add_reply(VALUE_PAIR** vp,
35 const char* name, const uint8_t * value, int len)
37 VALUE_PAIR *reply_attr;
38 reply_attr = pairmake(name, "", T_OP_EQ);
41 "add_reply failed to create attribute %s: %s\n",
46 memcpy(reply_attr->vp_octets, value, len);
47 reply_attr->length = len;
48 pairadd(vp, reply_attr);
52 * TLS PRF from RFC 2246
54 static void P_hash(const EVP_MD *evp_md,
55 const unsigned char *secret, unsigned int secret_len,
56 const unsigned char *seed, unsigned int seed_len,
57 unsigned char *out, unsigned int out_len)
59 HMAC_CTX ctx_a, ctx_out;
60 unsigned char a[HMAC_MAX_MD_CBLOCK];
63 HMAC_CTX_init(&ctx_a);
64 HMAC_CTX_init(&ctx_out);
65 HMAC_Init_ex(&ctx_a, secret, secret_len, evp_md, NULL);
66 HMAC_Init_ex(&ctx_out, secret, secret_len, evp_md, NULL);
68 size = HMAC_size(&ctx_out);
71 HMAC_Update(&ctx_a, seed, seed_len);
72 HMAC_Final(&ctx_a, a, NULL);
75 /* Calculate next part of output */
76 HMAC_Update(&ctx_out, a, size);
77 HMAC_Update(&ctx_out, seed, seed_len);
79 /* Check if last part */
81 HMAC_Final(&ctx_out, a, NULL);
82 memcpy(out, a, out_len);
86 /* Place digest in output buffer */
87 HMAC_Final(&ctx_out, out, NULL);
88 HMAC_Init_ex(&ctx_out, NULL, 0, NULL, NULL);
92 /* Calculate next A(i) */
93 HMAC_Init_ex(&ctx_a, NULL, 0, NULL, NULL);
94 HMAC_Update(&ctx_a, a, size);
95 HMAC_Final(&ctx_a, a, NULL);
98 HMAC_CTX_cleanup(&ctx_a);
99 HMAC_CTX_cleanup(&ctx_out);
100 memset(a, 0, sizeof(a));
103 static void PRF(const unsigned char *secret, unsigned int secret_len,
104 const unsigned char *seed, unsigned int seed_len,
105 unsigned char *out, unsigned char *buf, unsigned int out_len)
108 unsigned int len = (secret_len + 1) / 2;
109 const unsigned char *s1 = secret;
110 const unsigned char *s2 = secret + (secret_len - len);
112 P_hash(EVP_md5(), s1, len, seed, seed_len, out, out_len);
113 P_hash(EVP_sha1(), s2, len, seed, seed_len, buf, out_len);
115 for (i=0; i < out_len; i++) {
120 #define EAPTLS_MPPE_KEY_LEN 32
122 #define EAPTLS_PRF_LABEL "ttls keying material"
125 * Generate keys according to RFC 2716 and add to reply
127 void eaptls_gen_mppe_keys(VALUE_PAIR **reply_vps, SSL *s,
128 const char *prf_label)
130 unsigned char out[4*EAPTLS_MPPE_KEY_LEN], buf[4*EAPTLS_MPPE_KEY_LEN];
131 unsigned char seed[64 + 2*SSL3_RANDOM_SIZE];
132 unsigned char *p = seed;
135 prf_size = strlen(prf_label);
137 memcpy(p, prf_label, prf_size);
140 memcpy(p, s->s3->client_random, SSL3_RANDOM_SIZE);
141 p += SSL3_RANDOM_SIZE;
142 prf_size += SSL3_RANDOM_SIZE;
144 memcpy(p, s->s3->server_random, SSL3_RANDOM_SIZE);
145 prf_size += SSL3_RANDOM_SIZE;
147 PRF(s->session->master_key, s->session->master_key_length,
148 seed, prf_size, out, buf, sizeof(out));
151 add_reply(reply_vps, "MS-MPPE-Recv-Key", p, EAPTLS_MPPE_KEY_LEN);
152 p += EAPTLS_MPPE_KEY_LEN;
153 add_reply(reply_vps, "MS-MPPE-Send-Key", p, EAPTLS_MPPE_KEY_LEN);
155 add_reply(reply_vps, "EAP-MSK", out, 64);
156 add_reply(reply_vps, "EAP-EMSK", out + 64, 64);
160 #define EAPTLS_PRF_CHALLENGE "ttls challenge"
163 * Generate the TTLS challenge
165 * It's in the TLS module simply because it's only a few lines
166 * of code, and it needs access to the TLS PRF functions.
168 void eapttls_gen_challenge(SSL *s, uint8_t *buffer, size_t size)
170 uint8_t out[32], buf[32];
171 uint8_t seed[sizeof(EAPTLS_PRF_CHALLENGE)-1 + 2*SSL3_RANDOM_SIZE];
174 memcpy(p, EAPTLS_PRF_CHALLENGE, sizeof(EAPTLS_PRF_CHALLENGE)-1);
175 p += sizeof(EAPTLS_PRF_CHALLENGE)-1;
176 memcpy(p, s->s3->client_random, SSL3_RANDOM_SIZE);
177 p += SSL3_RANDOM_SIZE;
178 memcpy(p, s->s3->server_random, SSL3_RANDOM_SIZE);
180 PRF(s->session->master_key, s->session->master_key_length,
181 seed, sizeof(seed), out, buf, sizeof(out));
183 memcpy(buffer, out, size);