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