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