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