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