eap_server_tls_common.c revision 1f69aa52ea2e0a73ac502565df8c666ee49cab6a
1/* 2 * EAP-TLS/PEAP/TTLS/FAST server common functions 3 * Copyright (c) 2004-2009, Jouni Malinen <j@w1.fi> 4 * 5 * This program is free software; you can redistribute it and/or modify 6 * it under the terms of the GNU General Public License version 2 as 7 * published by the Free Software Foundation. 8 * 9 * Alternatively, this software may be distributed under the terms of BSD 10 * license. 11 * 12 * See README and COPYING for more details. 13 */ 14 15#include "includes.h" 16 17#include "common.h" 18#include "crypto/sha1.h" 19#include "crypto/tls.h" 20#include "eap_i.h" 21#include "eap_tls_common.h" 22 23 24static void eap_server_tls_free_in_buf(struct eap_ssl_data *data); 25 26 27int eap_server_tls_ssl_init(struct eap_sm *sm, struct eap_ssl_data *data, 28 int verify_peer) 29{ 30 data->eap = sm; 31 data->phase2 = sm->init_phase2; 32 33 data->conn = tls_connection_init(sm->ssl_ctx); 34 if (data->conn == NULL) { 35 wpa_printf(MSG_INFO, "SSL: Failed to initialize new TLS " 36 "connection"); 37 return -1; 38 } 39 40 if (tls_connection_set_verify(sm->ssl_ctx, data->conn, verify_peer)) { 41 wpa_printf(MSG_INFO, "SSL: Failed to configure verification " 42 "of TLS peer certificate"); 43 tls_connection_deinit(sm->ssl_ctx, data->conn); 44 data->conn = NULL; 45 return -1; 46 } 47 48 data->tls_out_limit = sm->fragment_size > 0 ? sm->fragment_size : 1398; 49 if (data->phase2) { 50 /* Limit the fragment size in the inner TLS authentication 51 * since the outer authentication with EAP-PEAP does not yet 52 * support fragmentation */ 53 if (data->tls_out_limit > 100) 54 data->tls_out_limit -= 100; 55 } 56 return 0; 57} 58 59 60void eap_server_tls_ssl_deinit(struct eap_sm *sm, struct eap_ssl_data *data) 61{ 62 tls_connection_deinit(sm->ssl_ctx, data->conn); 63 eap_server_tls_free_in_buf(data); 64 wpabuf_free(data->tls_out); 65 data->tls_out = NULL; 66} 67 68 69u8 * eap_server_tls_derive_key(struct eap_sm *sm, struct eap_ssl_data *data, 70 char *label, size_t len) 71{ 72 struct tls_keys keys; 73 u8 *rnd = NULL, *out; 74 75 out = os_malloc(len); 76 if (out == NULL) 77 return NULL; 78 79 if (tls_connection_prf(sm->ssl_ctx, data->conn, label, 0, out, len) == 80 0) 81 return out; 82 83 if (tls_connection_get_keys(sm->ssl_ctx, data->conn, &keys)) 84 goto fail; 85 86 if (keys.client_random == NULL || keys.server_random == NULL || 87 keys.master_key == NULL) 88 goto fail; 89 90 rnd = os_malloc(keys.client_random_len + keys.server_random_len); 91 if (rnd == NULL) 92 goto fail; 93 os_memcpy(rnd, keys.client_random, keys.client_random_len); 94 os_memcpy(rnd + keys.client_random_len, keys.server_random, 95 keys.server_random_len); 96 97 if (tls_prf_sha1_md5(keys.master_key, keys.master_key_len, 98 label, rnd, keys.client_random_len + 99 keys.server_random_len, out, len)) 100 goto fail; 101 102 os_free(rnd); 103 return out; 104 105fail: 106 os_free(out); 107 os_free(rnd); 108 return NULL; 109} 110 111 112struct wpabuf * eap_server_tls_build_msg(struct eap_ssl_data *data, 113 int eap_type, int version, u8 id) 114{ 115 struct wpabuf *req; 116 u8 flags; 117 size_t send_len, plen; 118 119 wpa_printf(MSG_DEBUG, "SSL: Generating Request"); 120 if (data->tls_out == NULL) { 121 wpa_printf(MSG_ERROR, "SSL: tls_out NULL in %s", __func__); 122 return NULL; 123 } 124 125 flags = version; 126 send_len = wpabuf_len(data->tls_out) - data->tls_out_pos; 127 if (1 + send_len > data->tls_out_limit) { 128 send_len = data->tls_out_limit - 1; 129 flags |= EAP_TLS_FLAGS_MORE_FRAGMENTS; 130 if (data->tls_out_pos == 0) { 131 flags |= EAP_TLS_FLAGS_LENGTH_INCLUDED; 132 send_len -= 4; 133 } 134 } 135 136 plen = 1 + send_len; 137 if (flags & EAP_TLS_FLAGS_LENGTH_INCLUDED) 138 plen += 4; 139 140 req = eap_msg_alloc(EAP_VENDOR_IETF, eap_type, plen, 141 EAP_CODE_REQUEST, id); 142 if (req == NULL) 143 return NULL; 144 145 wpabuf_put_u8(req, flags); /* Flags */ 146 if (flags & EAP_TLS_FLAGS_LENGTH_INCLUDED) 147 wpabuf_put_be32(req, wpabuf_len(data->tls_out)); 148 149 wpabuf_put_data(req, wpabuf_head_u8(data->tls_out) + data->tls_out_pos, 150 send_len); 151 data->tls_out_pos += send_len; 152 153 if (data->tls_out_pos == wpabuf_len(data->tls_out)) { 154 wpa_printf(MSG_DEBUG, "SSL: Sending out %lu bytes " 155 "(message sent completely)", 156 (unsigned long) send_len); 157 wpabuf_free(data->tls_out); 158 data->tls_out = NULL; 159 data->tls_out_pos = 0; 160 data->state = MSG; 161 } else { 162 wpa_printf(MSG_DEBUG, "SSL: Sending out %lu bytes " 163 "(%lu more to send)", (unsigned long) send_len, 164 (unsigned long) wpabuf_len(data->tls_out) - 165 data->tls_out_pos); 166 data->state = WAIT_FRAG_ACK; 167 } 168 169 return req; 170} 171 172 173struct wpabuf * eap_server_tls_build_ack(u8 id, int eap_type, int version) 174{ 175 struct wpabuf *req; 176 177 req = eap_msg_alloc(EAP_VENDOR_IETF, eap_type, 1, EAP_CODE_REQUEST, 178 id); 179 if (req == NULL) 180 return NULL; 181 wpa_printf(MSG_DEBUG, "SSL: Building ACK"); 182 wpabuf_put_u8(req, version); /* Flags */ 183 return req; 184} 185 186 187static int eap_server_tls_process_cont(struct eap_ssl_data *data, 188 const u8 *buf, size_t len) 189{ 190 /* Process continuation of a pending message */ 191 if (len > wpabuf_tailroom(data->tls_in)) { 192 wpa_printf(MSG_DEBUG, "SSL: Fragment overflow"); 193 return -1; 194 } 195 196 wpabuf_put_data(data->tls_in, buf, len); 197 wpa_printf(MSG_DEBUG, "SSL: Received %lu bytes, waiting for %lu " 198 "bytes more", (unsigned long) len, 199 (unsigned long) wpabuf_tailroom(data->tls_in)); 200 201 return 0; 202} 203 204 205static int eap_server_tls_process_fragment(struct eap_ssl_data *data, 206 u8 flags, u32 message_length, 207 const u8 *buf, size_t len) 208{ 209 /* Process a fragment that is not the last one of the message */ 210 if (data->tls_in == NULL && !(flags & EAP_TLS_FLAGS_LENGTH_INCLUDED)) { 211 wpa_printf(MSG_DEBUG, "SSL: No Message Length field in a " 212 "fragmented packet"); 213 return -1; 214 } 215 216 if (data->tls_in == NULL) { 217 /* First fragment of the message */ 218 219 /* Limit length to avoid rogue peers from causing large 220 * memory allocations. */ 221 if (message_length > 65536) { 222 wpa_printf(MSG_INFO, "SSL: Too long TLS fragment (size" 223 " over 64 kB)"); 224 return -1; 225 } 226 227 data->tls_in = wpabuf_alloc(message_length); 228 if (data->tls_in == NULL) { 229 wpa_printf(MSG_DEBUG, "SSL: No memory for message"); 230 return -1; 231 } 232 wpabuf_put_data(data->tls_in, buf, len); 233 wpa_printf(MSG_DEBUG, "SSL: Received %lu bytes in first " 234 "fragment, waiting for %lu bytes more", 235 (unsigned long) len, 236 (unsigned long) wpabuf_tailroom(data->tls_in)); 237 } 238 239 return 0; 240} 241 242 243int eap_server_tls_phase1(struct eap_sm *sm, struct eap_ssl_data *data) 244{ 245 if (data->tls_out) { 246 /* This should not happen.. */ 247 wpa_printf(MSG_INFO, "SSL: pending tls_out data when " 248 "processing new message"); 249 wpabuf_free(data->tls_out); 250 WPA_ASSERT(data->tls_out == NULL); 251 } 252 253 data->tls_out = tls_connection_server_handshake(sm->ssl_ctx, 254 data->conn, 255 data->tls_in, NULL); 256 if (data->tls_out == NULL) { 257 wpa_printf(MSG_INFO, "SSL: TLS processing failed"); 258 return -1; 259 } 260 if (tls_connection_get_failed(sm->ssl_ctx, data->conn)) { 261 /* TLS processing has failed - return error */ 262 wpa_printf(MSG_DEBUG, "SSL: Failed - tls_out available to " 263 "report error"); 264 return -1; 265 } 266 267 return 0; 268} 269 270 271static int eap_server_tls_reassemble(struct eap_ssl_data *data, u8 flags, 272 const u8 **pos, size_t *left) 273{ 274 unsigned int tls_msg_len = 0; 275 const u8 *end = *pos + *left; 276 277 if (flags & EAP_TLS_FLAGS_LENGTH_INCLUDED) { 278 if (*left < 4) { 279 wpa_printf(MSG_INFO, "SSL: Short frame with TLS " 280 "length"); 281 return -1; 282 } 283 tls_msg_len = WPA_GET_BE32(*pos); 284 wpa_printf(MSG_DEBUG, "SSL: TLS Message Length: %d", 285 tls_msg_len); 286 *pos += 4; 287 *left -= 4; 288 } 289 290 wpa_printf(MSG_DEBUG, "SSL: Received packet: Flags 0x%x " 291 "Message Length %u", flags, tls_msg_len); 292 293 if (data->state == WAIT_FRAG_ACK) { 294 if (*left != 0) { 295 wpa_printf(MSG_DEBUG, "SSL: Unexpected payload in " 296 "WAIT_FRAG_ACK state"); 297 return -1; 298 } 299 wpa_printf(MSG_DEBUG, "SSL: Fragment acknowledged"); 300 return 1; 301 } 302 303 if (data->tls_in && 304 eap_server_tls_process_cont(data, *pos, end - *pos) < 0) 305 return -1; 306 307 if (flags & EAP_TLS_FLAGS_MORE_FRAGMENTS) { 308 if (eap_server_tls_process_fragment(data, flags, tls_msg_len, 309 *pos, end - *pos) < 0) 310 return -1; 311 312 data->state = FRAG_ACK; 313 return 1; 314 } 315 316 if (data->state == FRAG_ACK) { 317 wpa_printf(MSG_DEBUG, "SSL: All fragments received"); 318 data->state = MSG; 319 } 320 321 if (data->tls_in == NULL) { 322 /* Wrap unfragmented messages as wpabuf without extra copy */ 323 wpabuf_set(&data->tmpbuf, *pos, end - *pos); 324 data->tls_in = &data->tmpbuf; 325 } 326 327 return 0; 328} 329 330 331static void eap_server_tls_free_in_buf(struct eap_ssl_data *data) 332{ 333 if (data->tls_in != &data->tmpbuf) 334 wpabuf_free(data->tls_in); 335 data->tls_in = NULL; 336} 337 338 339struct wpabuf * eap_server_tls_encrypt(struct eap_sm *sm, 340 struct eap_ssl_data *data, 341 const struct wpabuf *plain) 342{ 343 struct wpabuf *buf; 344 345 buf = tls_connection_encrypt(sm->ssl_ctx, data->conn, 346 plain); 347 if (buf == NULL) { 348 wpa_printf(MSG_INFO, "SSL: Failed to encrypt Phase 2 data"); 349 return NULL; 350 } 351 352 return buf; 353} 354 355 356int eap_server_tls_process(struct eap_sm *sm, struct eap_ssl_data *data, 357 struct wpabuf *respData, void *priv, int eap_type, 358 int (*proc_version)(struct eap_sm *sm, void *priv, 359 int peer_version), 360 void (*proc_msg)(struct eap_sm *sm, void *priv, 361 const struct wpabuf *respData)) 362{ 363 const u8 *pos; 364 u8 flags; 365 size_t left; 366 int ret, res = 0; 367 368 pos = eap_hdr_validate(EAP_VENDOR_IETF, eap_type, respData, &left); 369 if (pos == NULL || left < 1) 370 return 0; /* Should not happen - frame already validated */ 371 flags = *pos++; 372 left--; 373 wpa_printf(MSG_DEBUG, "SSL: Received packet(len=%lu) - Flags 0x%02x", 374 (unsigned long) wpabuf_len(respData), flags); 375 376 if (proc_version && 377 proc_version(sm, priv, flags & EAP_TLS_VERSION_MASK) < 0) 378 return -1; 379 380 ret = eap_server_tls_reassemble(data, flags, &pos, &left); 381 if (ret < 0) { 382 res = -1; 383 goto done; 384 } else if (ret == 1) 385 return 0; 386 387 if (proc_msg) 388 proc_msg(sm, priv, respData); 389 390 if (tls_connection_get_write_alerts(sm->ssl_ctx, data->conn) > 1) { 391 wpa_printf(MSG_INFO, "SSL: Locally detected fatal error in " 392 "TLS processing"); 393 res = -1; 394 } 395 396done: 397 eap_server_tls_free_in_buf(data); 398 399 return res; 400} 401