eap_server_tls_common.c revision 61d9df3e62aaa0e87ad05452fcb95142159a17b6
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 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 66void 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 75u8 * 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 111fail: 112 os_free(out); 113 os_free(rnd); 114 return NULL; 115} 116 117 118struct 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 178struct 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 191static 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 209static 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 data->tls_in = wpabuf_alloc(message_length); 232 if (data->tls_in == NULL) { 233 wpa_printf(MSG_DEBUG, "SSL: No memory for message"); 234 return -1; 235 } 236 wpabuf_put_data(data->tls_in, buf, len); 237 wpa_printf(MSG_DEBUG, "SSL: Received %lu bytes in first " 238 "fragment, waiting for %lu bytes more", 239 (unsigned long) len, 240 (unsigned long) wpabuf_tailroom(data->tls_in)); 241 } 242 243 return 0; 244} 245 246 247int eap_server_tls_phase1(struct eap_sm *sm, struct eap_ssl_data *data) 248{ 249 if (data->tls_out) { 250 /* This should not happen.. */ 251 wpa_printf(MSG_INFO, "SSL: pending tls_out data when " 252 "processing new message"); 253 wpabuf_free(data->tls_out); 254 WPA_ASSERT(data->tls_out == NULL); 255 } 256 257 data->tls_out = tls_connection_server_handshake(sm->ssl_ctx, 258 data->conn, 259 data->tls_in, NULL); 260 if (data->tls_out == NULL) { 261 wpa_printf(MSG_INFO, "SSL: TLS processing failed"); 262 return -1; 263 } 264 if (tls_connection_get_failed(sm->ssl_ctx, data->conn)) { 265 /* TLS processing has failed - return error */ 266 wpa_printf(MSG_DEBUG, "SSL: Failed - tls_out available to " 267 "report error"); 268 return -1; 269 } 270 271 return 0; 272} 273 274 275static int eap_server_tls_reassemble(struct eap_ssl_data *data, u8 flags, 276 const u8 **pos, size_t *left) 277{ 278 unsigned int tls_msg_len = 0; 279 const u8 *end = *pos + *left; 280 281 if (flags & EAP_TLS_FLAGS_LENGTH_INCLUDED) { 282 if (*left < 4) { 283 wpa_printf(MSG_INFO, "SSL: Short frame with TLS " 284 "length"); 285 return -1; 286 } 287 tls_msg_len = WPA_GET_BE32(*pos); 288 wpa_printf(MSG_DEBUG, "SSL: TLS Message Length: %d", 289 tls_msg_len); 290 *pos += 4; 291 *left -= 4; 292 } 293 294 wpa_printf(MSG_DEBUG, "SSL: Received packet: Flags 0x%x " 295 "Message Length %u", flags, tls_msg_len); 296 297 if (data->state == WAIT_FRAG_ACK) { 298 if (*left != 0) { 299 wpa_printf(MSG_DEBUG, "SSL: Unexpected payload in " 300 "WAIT_FRAG_ACK state"); 301 return -1; 302 } 303 wpa_printf(MSG_DEBUG, "SSL: Fragment acknowledged"); 304 return 1; 305 } 306 307 if (data->tls_in && 308 eap_server_tls_process_cont(data, *pos, end - *pos) < 0) 309 return -1; 310 311 if (flags & EAP_TLS_FLAGS_MORE_FRAGMENTS) { 312 if (eap_server_tls_process_fragment(data, flags, tls_msg_len, 313 *pos, end - *pos) < 0) 314 return -1; 315 316 data->state = FRAG_ACK; 317 return 1; 318 } 319 320 if (data->state == FRAG_ACK) { 321 wpa_printf(MSG_DEBUG, "SSL: All fragments received"); 322 data->state = MSG; 323 } 324 325 if (data->tls_in == NULL) { 326 /* Wrap unfragmented messages as wpabuf without extra copy */ 327 wpabuf_set(&data->tmpbuf, *pos, end - *pos); 328 data->tls_in = &data->tmpbuf; 329 } 330 331 return 0; 332} 333 334 335static void eap_server_tls_free_in_buf(struct eap_ssl_data *data) 336{ 337 if (data->tls_in != &data->tmpbuf) 338 wpabuf_free(data->tls_in); 339 data->tls_in = NULL; 340} 341 342 343struct wpabuf * eap_server_tls_encrypt(struct eap_sm *sm, 344 struct eap_ssl_data *data, 345 const struct wpabuf *plain) 346{ 347 struct wpabuf *buf; 348 349 buf = tls_connection_encrypt(sm->ssl_ctx, data->conn, 350 plain); 351 if (buf == NULL) { 352 wpa_printf(MSG_INFO, "SSL: Failed to encrypt Phase 2 data"); 353 return NULL; 354 } 355 356 return buf; 357} 358 359 360int eap_server_tls_process(struct eap_sm *sm, struct eap_ssl_data *data, 361 struct wpabuf *respData, void *priv, int eap_type, 362 int (*proc_version)(struct eap_sm *sm, void *priv, 363 int peer_version), 364 void (*proc_msg)(struct eap_sm *sm, void *priv, 365 const struct wpabuf *respData)) 366{ 367 const u8 *pos; 368 u8 flags; 369 size_t left; 370 int ret, res = 0; 371 372 if (eap_type == EAP_UNAUTH_TLS_TYPE) 373 pos = eap_hdr_validate(EAP_VENDOR_UNAUTH_TLS, 374 EAP_VENDOR_TYPE_UNAUTH_TLS, respData, 375 &left); 376 else 377 pos = eap_hdr_validate(EAP_VENDOR_IETF, eap_type, respData, 378 &left); 379 if (pos == NULL || left < 1) 380 return 0; /* Should not happen - frame already validated */ 381 flags = *pos++; 382 left--; 383 wpa_printf(MSG_DEBUG, "SSL: Received packet(len=%lu) - Flags 0x%02x", 384 (unsigned long) wpabuf_len(respData), flags); 385 386 if (proc_version && 387 proc_version(sm, priv, flags & EAP_TLS_VERSION_MASK) < 0) 388 return -1; 389 390 ret = eap_server_tls_reassemble(data, flags, &pos, &left); 391 if (ret < 0) { 392 res = -1; 393 goto done; 394 } else if (ret == 1) 395 return 0; 396 397 if (proc_msg) 398 proc_msg(sm, priv, respData); 399 400 if (tls_connection_get_write_alerts(sm->ssl_ctx, data->conn) > 1) { 401 wpa_printf(MSG_INFO, "SSL: Locally detected fatal error in " 402 "TLS processing"); 403 res = -1; 404 } 405 406done: 407 eap_server_tls_free_in_buf(data); 408 409 return res; 410} 411