$search
00001 /* 00002 * EAP-TLS/PEAP/TTLS/FAST server common functions 00003 * Copyright (c) 2004-2009, Jouni Malinen <j@w1.fi> 00004 * 00005 * This program is free software; you can redistribute it and/or modify 00006 * it under the terms of the GNU General Public License version 2 as 00007 * published by the Free Software Foundation. 00008 * 00009 * Alternatively, this software may be distributed under the terms of BSD 00010 * license. 00011 * 00012 * See README and COPYING for more details. 00013 */ 00014 00015 #include "includes.h" 00016 00017 #include "common.h" 00018 #include "crypto/sha1.h" 00019 #include "crypto/tls.h" 00020 #include "eap_i.h" 00021 #include "eap_tls_common.h" 00022 00023 00024 static void eap_server_tls_free_in_buf(struct eap_ssl_data *data); 00025 00026 00027 int eap_server_tls_ssl_init(struct eap_sm *sm, struct eap_ssl_data *data, 00028 int verify_peer) 00029 { 00030 data->eap = sm; 00031 data->phase2 = sm->init_phase2; 00032 00033 data->conn = tls_connection_init(sm->ssl_ctx); 00034 if (data->conn == NULL) { 00035 wpa_printf(MSG_INFO, "SSL: Failed to initialize new TLS " 00036 "connection"); 00037 return -1; 00038 } 00039 00040 if (tls_connection_set_verify(sm->ssl_ctx, data->conn, verify_peer)) { 00041 wpa_printf(MSG_INFO, "SSL: Failed to configure verification " 00042 "of TLS peer certificate"); 00043 tls_connection_deinit(sm->ssl_ctx, data->conn); 00044 data->conn = NULL; 00045 return -1; 00046 } 00047 00048 /* TODO: make this configurable */ 00049 data->tls_out_limit = 1398; 00050 if (data->phase2) { 00051 /* Limit the fragment size in the inner TLS authentication 00052 * since the outer authentication with EAP-PEAP does not yet 00053 * support fragmentation */ 00054 if (data->tls_out_limit > 100) 00055 data->tls_out_limit -= 100; 00056 } 00057 return 0; 00058 } 00059 00060 00061 void eap_server_tls_ssl_deinit(struct eap_sm *sm, struct eap_ssl_data *data) 00062 { 00063 tls_connection_deinit(sm->ssl_ctx, data->conn); 00064 eap_server_tls_free_in_buf(data); 00065 wpabuf_free(data->tls_out); 00066 data->tls_out = NULL; 00067 } 00068 00069 00070 u8 * eap_server_tls_derive_key(struct eap_sm *sm, struct eap_ssl_data *data, 00071 char *label, size_t len) 00072 { 00073 struct tls_keys keys; 00074 u8 *rnd = NULL, *out; 00075 00076 out = os_malloc(len); 00077 if (out == NULL) 00078 return NULL; 00079 00080 if (tls_connection_prf(sm->ssl_ctx, data->conn, label, 0, out, len) == 00081 0) 00082 return out; 00083 00084 if (tls_connection_get_keys(sm->ssl_ctx, data->conn, &keys)) 00085 goto fail; 00086 00087 if (keys.client_random == NULL || keys.server_random == NULL || 00088 keys.master_key == NULL) 00089 goto fail; 00090 00091 rnd = os_malloc(keys.client_random_len + keys.server_random_len); 00092 if (rnd == NULL) 00093 goto fail; 00094 os_memcpy(rnd, keys.client_random, keys.client_random_len); 00095 os_memcpy(rnd + keys.client_random_len, keys.server_random, 00096 keys.server_random_len); 00097 00098 if (tls_prf(keys.master_key, keys.master_key_len, 00099 label, rnd, keys.client_random_len + 00100 keys.server_random_len, out, len)) 00101 goto fail; 00102 00103 os_free(rnd); 00104 return out; 00105 00106 fail: 00107 os_free(out); 00108 os_free(rnd); 00109 return NULL; 00110 } 00111 00112 00113 struct wpabuf * eap_server_tls_build_msg(struct eap_ssl_data *data, 00114 int eap_type, int version, u8 id) 00115 { 00116 struct wpabuf *req; 00117 u8 flags; 00118 size_t send_len, plen; 00119 00120 wpa_printf(MSG_DEBUG, "SSL: Generating Request"); 00121 if (data->tls_out == NULL) { 00122 wpa_printf(MSG_ERROR, "SSL: tls_out NULL in %s", __func__); 00123 return NULL; 00124 } 00125 00126 flags = version; 00127 send_len = wpabuf_len(data->tls_out) - data->tls_out_pos; 00128 if (1 + send_len > data->tls_out_limit) { 00129 send_len = data->tls_out_limit - 1; 00130 flags |= EAP_TLS_FLAGS_MORE_FRAGMENTS; 00131 if (data->tls_out_pos == 0) { 00132 flags |= EAP_TLS_FLAGS_LENGTH_INCLUDED; 00133 send_len -= 4; 00134 } 00135 } 00136 00137 plen = 1 + send_len; 00138 if (flags & EAP_TLS_FLAGS_LENGTH_INCLUDED) 00139 plen += 4; 00140 00141 req = eap_msg_alloc(EAP_VENDOR_IETF, eap_type, plen, 00142 EAP_CODE_REQUEST, id); 00143 if (req == NULL) 00144 return NULL; 00145 00146 wpabuf_put_u8(req, flags); /* Flags */ 00147 if (flags & EAP_TLS_FLAGS_LENGTH_INCLUDED) 00148 wpabuf_put_be32(req, wpabuf_len(data->tls_out)); 00149 00150 wpabuf_put_data(req, wpabuf_head_u8(data->tls_out) + data->tls_out_pos, 00151 send_len); 00152 data->tls_out_pos += send_len; 00153 00154 if (data->tls_out_pos == wpabuf_len(data->tls_out)) { 00155 wpa_printf(MSG_DEBUG, "SSL: Sending out %lu bytes " 00156 "(message sent completely)", 00157 (unsigned long) send_len); 00158 wpabuf_free(data->tls_out); 00159 data->tls_out = NULL; 00160 data->tls_out_pos = 0; 00161 data->state = MSG; 00162 } else { 00163 wpa_printf(MSG_DEBUG, "SSL: Sending out %lu bytes " 00164 "(%lu more to send)", (unsigned long) send_len, 00165 (unsigned long) wpabuf_len(data->tls_out) - 00166 data->tls_out_pos); 00167 data->state = WAIT_FRAG_ACK; 00168 } 00169 00170 return req; 00171 } 00172 00173 00174 struct wpabuf * eap_server_tls_build_ack(u8 id, int eap_type, int version) 00175 { 00176 struct wpabuf *req; 00177 00178 req = eap_msg_alloc(EAP_VENDOR_IETF, eap_type, 1, EAP_CODE_REQUEST, 00179 id); 00180 if (req == NULL) 00181 return NULL; 00182 wpa_printf(MSG_DEBUG, "SSL: Building ACK"); 00183 wpabuf_put_u8(req, version); /* Flags */ 00184 return req; 00185 } 00186 00187 00188 static int eap_server_tls_process_cont(struct eap_ssl_data *data, 00189 const u8 *buf, size_t len) 00190 { 00191 /* Process continuation of a pending message */ 00192 if (len > wpabuf_tailroom(data->tls_in)) { 00193 wpa_printf(MSG_DEBUG, "SSL: Fragment overflow"); 00194 return -1; 00195 } 00196 00197 wpabuf_put_data(data->tls_in, buf, len); 00198 wpa_printf(MSG_DEBUG, "SSL: Received %lu bytes, waiting for %lu " 00199 "bytes more", (unsigned long) len, 00200 (unsigned long) wpabuf_tailroom(data->tls_in)); 00201 00202 return 0; 00203 } 00204 00205 00206 static int eap_server_tls_process_fragment(struct eap_ssl_data *data, 00207 u8 flags, u32 message_length, 00208 const u8 *buf, size_t len) 00209 { 00210 /* Process a fragment that is not the last one of the message */ 00211 if (data->tls_in == NULL && !(flags & EAP_TLS_FLAGS_LENGTH_INCLUDED)) { 00212 wpa_printf(MSG_DEBUG, "SSL: No Message Length field in a " 00213 "fragmented packet"); 00214 return -1; 00215 } 00216 00217 if (data->tls_in == NULL) { 00218 /* First fragment of the message */ 00219 00220 /* Limit length to avoid rogue peers from causing large 00221 * memory allocations. */ 00222 if (message_length > 65536) { 00223 wpa_printf(MSG_INFO, "SSL: Too long TLS fragment (size" 00224 " over 64 kB)"); 00225 return -1; 00226 } 00227 00228 data->tls_in = wpabuf_alloc(message_length); 00229 if (data->tls_in == NULL) { 00230 wpa_printf(MSG_DEBUG, "SSL: No memory for message"); 00231 return -1; 00232 } 00233 wpabuf_put_data(data->tls_in, buf, len); 00234 wpa_printf(MSG_DEBUG, "SSL: Received %lu bytes in first " 00235 "fragment, waiting for %lu bytes more", 00236 (unsigned long) len, 00237 (unsigned long) wpabuf_tailroom(data->tls_in)); 00238 } 00239 00240 return 0; 00241 } 00242 00243 00244 int eap_server_tls_phase1(struct eap_sm *sm, struct eap_ssl_data *data) 00245 { 00246 if (data->tls_out) { 00247 /* This should not happen.. */ 00248 wpa_printf(MSG_INFO, "SSL: pending tls_out data when " 00249 "processing new message"); 00250 wpabuf_free(data->tls_out); 00251 WPA_ASSERT(data->tls_out == NULL); 00252 } 00253 00254 data->tls_out = tls_connection_server_handshake(sm->ssl_ctx, 00255 data->conn, 00256 data->tls_in, NULL); 00257 if (data->tls_out == NULL) { 00258 wpa_printf(MSG_INFO, "SSL: TLS processing failed"); 00259 return -1; 00260 } 00261 if (tls_connection_get_failed(sm->ssl_ctx, data->conn)) { 00262 /* TLS processing has failed - return error */ 00263 wpa_printf(MSG_DEBUG, "SSL: Failed - tls_out available to " 00264 "report error"); 00265 return -1; 00266 } 00267 00268 return 0; 00269 } 00270 00271 00272 static int eap_server_tls_reassemble(struct eap_ssl_data *data, u8 flags, 00273 const u8 **pos, size_t *left) 00274 { 00275 unsigned int tls_msg_len = 0; 00276 const u8 *end = *pos + *left; 00277 00278 if (flags & EAP_TLS_FLAGS_LENGTH_INCLUDED) { 00279 if (*left < 4) { 00280 wpa_printf(MSG_INFO, "SSL: Short frame with TLS " 00281 "length"); 00282 return -1; 00283 } 00284 tls_msg_len = WPA_GET_BE32(*pos); 00285 wpa_printf(MSG_DEBUG, "SSL: TLS Message Length: %d", 00286 tls_msg_len); 00287 *pos += 4; 00288 *left -= 4; 00289 } 00290 00291 wpa_printf(MSG_DEBUG, "SSL: Received packet: Flags 0x%x " 00292 "Message Length %u", flags, tls_msg_len); 00293 00294 if (data->state == WAIT_FRAG_ACK) { 00295 if (*left != 0) { 00296 wpa_printf(MSG_DEBUG, "SSL: Unexpected payload in " 00297 "WAIT_FRAG_ACK state"); 00298 return -1; 00299 } 00300 wpa_printf(MSG_DEBUG, "SSL: Fragment acknowledged"); 00301 return 1; 00302 } 00303 00304 if (data->tls_in && 00305 eap_server_tls_process_cont(data, *pos, end - *pos) < 0) 00306 return -1; 00307 00308 if (flags & EAP_TLS_FLAGS_MORE_FRAGMENTS) { 00309 if (eap_server_tls_process_fragment(data, flags, tls_msg_len, 00310 *pos, end - *pos) < 0) 00311 return -1; 00312 00313 data->state = FRAG_ACK; 00314 return 1; 00315 } 00316 00317 if (data->state == FRAG_ACK) { 00318 wpa_printf(MSG_DEBUG, "SSL: All fragments received"); 00319 data->state = MSG; 00320 } 00321 00322 if (data->tls_in == NULL) { 00323 /* Wrap unfragmented messages as wpabuf without extra copy */ 00324 wpabuf_set(&data->tmpbuf, *pos, end - *pos); 00325 data->tls_in = &data->tmpbuf; 00326 } 00327 00328 return 0; 00329 } 00330 00331 00332 static void eap_server_tls_free_in_buf(struct eap_ssl_data *data) 00333 { 00334 if (data->tls_in != &data->tmpbuf) 00335 wpabuf_free(data->tls_in); 00336 data->tls_in = NULL; 00337 } 00338 00339 00340 struct wpabuf * eap_server_tls_encrypt(struct eap_sm *sm, 00341 struct eap_ssl_data *data, 00342 const struct wpabuf *plain) 00343 { 00344 struct wpabuf *buf; 00345 00346 buf = tls_connection_encrypt(sm->ssl_ctx, data->conn, 00347 plain); 00348 if (buf == NULL) { 00349 wpa_printf(MSG_INFO, "SSL: Failed to encrypt Phase 2 data"); 00350 return NULL; 00351 } 00352 00353 return buf; 00354 } 00355 00356 00357 int eap_server_tls_process(struct eap_sm *sm, struct eap_ssl_data *data, 00358 struct wpabuf *respData, void *priv, int eap_type, 00359 int (*proc_version)(struct eap_sm *sm, void *priv, 00360 int peer_version), 00361 void (*proc_msg)(struct eap_sm *sm, void *priv, 00362 const struct wpabuf *respData)) 00363 { 00364 const u8 *pos; 00365 u8 flags; 00366 size_t left; 00367 int ret, res = 0; 00368 00369 pos = eap_hdr_validate(EAP_VENDOR_IETF, eap_type, respData, &left); 00370 if (pos == NULL || left < 1) 00371 return 0; /* Should not happen - frame already validated */ 00372 flags = *pos++; 00373 left--; 00374 wpa_printf(MSG_DEBUG, "SSL: Received packet(len=%lu) - Flags 0x%02x", 00375 (unsigned long) wpabuf_len(respData), flags); 00376 00377 if (proc_version && 00378 proc_version(sm, priv, flags & EAP_TLS_VERSION_MASK) < 0) 00379 return -1; 00380 00381 ret = eap_server_tls_reassemble(data, flags, &pos, &left); 00382 if (ret < 0) { 00383 res = -1; 00384 goto done; 00385 } else if (ret == 1) 00386 return 0; 00387 00388 if (proc_msg) 00389 proc_msg(sm, priv, respData); 00390 00391 if (tls_connection_get_write_alerts(sm->ssl_ctx, data->conn) > 1) { 00392 wpa_printf(MSG_INFO, "SSL: Locally detected fatal error in " 00393 "TLS processing"); 00394 res = -1; 00395 } 00396 00397 done: 00398 eap_server_tls_free_in_buf(data); 00399 00400 return res; 00401 }