All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
mppe_keys.c
Go to the documentation of this file.
1 /*
2  * mppe_keys.c
3  *
4  * Version: $Id: 684e9d178e020282f1caf6907143369ef3a96dec $
5  *
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.
10  *
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.
15  *
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
19  *
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>
23  */
24 
25 RCSID("$Id: 684e9d178e020282f1caf6907143369ef3a96dec $")
26 USES_APPLE_DEPRECATED_API /* OpenSSL API has been deprecated by Apple */
27 
28 #include "eap_tls.h"
29 #include <openssl/hmac.h>
30 
31 
32 #if OPENSSL_VERSION_NUMBER < 0x10001000L
33 /*
34  * TLS PRF from RFC 2246
35  */
36 static void P_hash(EVP_MD const *evp_md,
37  unsigned char const *secret, unsigned int secret_len,
38  unsigned char const *seed, unsigned int seed_len,
39  unsigned char *out, unsigned int out_len)
40 {
41  HMAC_CTX ctx_a, ctx_out;
42  unsigned char a[HMAC_MAX_MD_CBLOCK];
43  unsigned int size;
44 
45  HMAC_CTX_init(&ctx_a);
46  HMAC_CTX_init(&ctx_out);
47  HMAC_Init_ex(&ctx_a, secret, secret_len, evp_md, NULL);
48  HMAC_Init_ex(&ctx_out, secret, secret_len, evp_md, NULL);
49 
50  size = HMAC_size(&ctx_out);
51 
52  /* Calculate A(1) */
53  HMAC_Update(&ctx_a, seed, seed_len);
54  HMAC_Final(&ctx_a, a, NULL);
55 
56  while (1) {
57  /* Calculate next part of output */
58  HMAC_Update(&ctx_out, a, size);
59  HMAC_Update(&ctx_out, seed, seed_len);
60 
61  /* Check if last part */
62  if (out_len < size) {
63  HMAC_Final(&ctx_out, a, NULL);
64  memcpy(out, a, out_len);
65  break;
66  }
67 
68  /* Place digest in output buffer */
69  HMAC_Final(&ctx_out, out, NULL);
70  HMAC_Init_ex(&ctx_out, NULL, 0, NULL, NULL);
71  out += size;
72  out_len -= size;
73 
74  /* Calculate next A(i) */
75  HMAC_Init_ex(&ctx_a, NULL, 0, NULL, NULL);
76  HMAC_Update(&ctx_a, a, size);
77  HMAC_Final(&ctx_a, a, NULL);
78  }
79 
80  HMAC_CTX_cleanup(&ctx_a);
81  HMAC_CTX_cleanup(&ctx_out);
82  memset(a, 0, sizeof(a));
83 }
84 
85 static void PRF(unsigned char const *secret, unsigned int secret_len,
86  unsigned char const *seed, unsigned int seed_len,
87  unsigned char *out, unsigned char *buf, unsigned int out_len)
88 {
89  unsigned int i;
90  unsigned int len = (secret_len + 1) / 2;
91  uint8_t const *s1 = secret;
92  uint8_t const *s2 = secret + (secret_len - len);
93 
94  P_hash(EVP_md5(), s1, len, seed, seed_len, out, out_len);
95  P_hash(EVP_sha1(), s2, len, seed, seed_len, buf, out_len);
96 
97  for (i=0; i < out_len; i++) {
98  out[i] ^= buf[i];
99  }
100 }
101 #endif
102 
103 #define EAPTLS_MPPE_KEY_LEN 32
104 
105 /** Generate keys according to RFC 2716 and add to the reply
106  *
107  */
108 void eap_tls_gen_mppe_keys(REQUEST *request, SSL *s, char const *prf_label)
109 {
110  uint8_t out[4 * EAPTLS_MPPE_KEY_LEN];
111  uint8_t *p;
112  size_t prf_size;
113 
114  prf_size = strlen(prf_label);
115 
116 #if OPENSSL_VERSION_NUMBER >= 0x10001000L
117  if (SSL_export_keying_material(s, out, sizeof(out), prf_label, prf_size, NULL, 0, 0) != 1) {
118  ERROR("Failed generating keying material");
119  return;
120  }
121 #else
122  {
123  uint8_t seed[64 + (2 * SSL3_RANDOM_SIZE)];
124  uint8_t buf[4 * EAPTLS_MPPE_KEY_LEN];
125 
126  p = seed;
127 
128  memcpy(p, prf_label, prf_size);
129  p += prf_size;
130 
131  memcpy(p, s->s3->client_random, SSL3_RANDOM_SIZE);
132  p += SSL3_RANDOM_SIZE;
133  prf_size += SSL3_RANDOM_SIZE;
134 
135  memcpy(p, s->s3->server_random, SSL3_RANDOM_SIZE);
136  prf_size += SSL3_RANDOM_SIZE;
137 
138  PRF(s->session->master_key, s->session->master_key_length,
139  seed, prf_size, out, buf, sizeof(out));
140  }
141 #endif
142 
143  p = out;
144  eap_add_reply(request, "MS-MPPE-Recv-Key", p, EAPTLS_MPPE_KEY_LEN);
145  p += EAPTLS_MPPE_KEY_LEN;
146  eap_add_reply(request, "MS-MPPE-Send-Key", p, EAPTLS_MPPE_KEY_LEN);
147 
148  eap_add_reply(request, "EAP-MSK", out, 64);
149  eap_add_reply(request, "EAP-EMSK", out + 64, 64);
150 }
151 
152 
153 #define FR_TLS_PRF_CHALLENGE "ttls challenge"
154 
155 /*
156  * Generate the TTLS challenge
157  *
158  * It's in the TLS module simply because it's only a few lines
159  * of code, and it needs access to the TLS PRF functions.
160  */
161 void eap_ttls_gen_challenge(SSL *s, uint8_t *buffer, size_t size)
162 {
163 #if OPENSSL_VERSION_NUMBER >= 0x10001000L
164  SSL_export_keying_material(s, buffer, size, FR_TLS_PRF_CHALLENGE,
165  sizeof(FR_TLS_PRF_CHALLENGE) - 1, NULL, 0, 0);
166 
167 #else
168  uint8_t out[32], buf[32];
169  uint8_t seed[sizeof(FR_TLS_PRF_CHALLENGE)-1 + 2*SSL3_RANDOM_SIZE];
170  uint8_t *p = seed;
171 
172  memcpy(p, FR_TLS_PRF_CHALLENGE, sizeof(FR_TLS_PRF_CHALLENGE)-1);
173  p += sizeof(FR_TLS_PRF_CHALLENGE)-1;
174  memcpy(p, s->s3->client_random, SSL3_RANDOM_SIZE);
175  p += SSL3_RANDOM_SIZE;
176  memcpy(p, s->s3->server_random, SSL3_RANDOM_SIZE);
177 
178  PRF(s->session->master_key, s->session->master_key_length,
179  seed, sizeof(seed), out, buf, sizeof(out));
180  memcpy(buffer, out, size);
181 #endif
182 }
183 
184 /*
185  * Actually generates EAP-Session-Id, which is an internal server
186  * attribute. Not all systems want to send EAP-Key-Name
187  */
188 void eap_tls_gen_eap_key(RADIUS_PACKET *packet, SSL *s, uint32_t header)
189 {
190  VALUE_PAIR *vp;
191  uint8_t *p;
192 
193  vp = fr_pair_afrom_num(packet, 0, PW_EAP_SESSION_ID);
194  if (!vp) return;
195 
196  p = talloc_array(vp, uint8_t, 1 + 2 * SSL3_RANDOM_SIZE);
197  p[0] = header & 0xff;
198 
199 #ifdef HAVE_SSL_GET_CLIENT_RANDOM
200  SSL_get_client_random(s, p + 1, SSL3_RANDOM_SIZE);
201  SSL_get_server_random(s, p + 1 + SSL3_RANDOM_SIZE, SSL3_RANDOM_SIZE);
202 #else
203  memcpy(p + 1, s->s3->client_random, SSL3_RANDOM_SIZE);
204  memcpy(p + 1 + SSL3_RANDOM_SIZE,
205  s->s3->server_random, SSL3_RANDOM_SIZE);
206 #endif
207  fr_pair_value_memsteal(vp, p);
208  fr_pair_add(&packet->vps, vp);
209 }
VALUE_PAIR * fr_pair_afrom_num(TALLOC_CTX *ctx, unsigned int vendor, unsigned int attr)
Create a new valuepair.
Definition: pair.c:106
static USES_APPLE_DEPRECATED_API void P_hash(EVP_MD const *evp_md, unsigned char const *secret, unsigned int secret_len, unsigned char const *seed, unsigned int seed_len, unsigned char *out, unsigned int out_len)
Definition: mppe_keys.c:36
VALUE_PAIR * vps
Result of decoding the packet into VALUE_PAIRs.
Definition: libradius.h:162
void eap_tls_gen_eap_key(RADIUS_PACKET *packet, SSL *s, uint32_t header)
Definition: mppe_keys.c:188
#define EAPTLS_MPPE_KEY_LEN
Definition: mppe_keys.c:103
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)
Definition: mppe_keys.c:85
void fr_pair_add(VALUE_PAIR **head, VALUE_PAIR *vp)
Add a VP to the end of the list.
Definition: pair.c:659
Stores an attribute, a value and various bits of other data.
Definition: pair.h:112
void eap_ttls_gen_challenge(SSL *s, uint8_t *buffer, size_t size)
Definition: mppe_keys.c:161
void eap_tls_gen_mppe_keys(REQUEST *request, SSL *s, char const *prf_label)
Generate keys according to RFC 2716 and add to the reply.
Definition: mppe_keys.c:108
void fr_pair_value_memsteal(VALUE_PAIR *vp, uint8_t const *src)
Reparent an allocated octet buffer to a VALUE_PAIR.
Definition: pair.c:1933
#define FR_TLS_PRF_CHALLENGE
Definition: mppe_keys.c:153
static char const * secret
Definition: radclient.c:44
#define RCSID(id)
Definition: build.h:135
#define ERROR(fmt,...)
Definition: log.h:145
void eap_add_reply(REQUEST *request, char const *name, uint8_t const *value, int len)
Definition: eapcommon.c:388
#define USES_APPLE_DEPRECATED_API
Definition: build.h:122