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