$search
00001 /* 00002 * SSL/TLS interface functions for NSS 00003 * Copyright (c) 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 #include <nspr/prtypes.h> 00017 #include <nspr/plarenas.h> 00018 #include <nspr/plhash.h> 00019 #include <nspr/prio.h> 00020 #include <nspr/prclist.h> 00021 #include <nspr/prlock.h> 00022 #include <nspr/prinit.h> 00023 #include <nspr/prerror.h> 00024 #include <nspr/prmem.h> 00025 #include <nss/nss.h> 00026 #include <nss/nssilckt.h> 00027 #include <nss/ssl.h> 00028 #include <nss/pk11func.h> 00029 #include <nss/secerr.h> 00030 00031 #include "common.h" 00032 #include "tls.h" 00033 00034 static int tls_nss_ref_count = 0; 00035 00036 static PRDescIdentity nss_layer_id; 00037 00038 00039 struct tls_connection { 00040 PRFileDesc *fd; 00041 00042 int established; 00043 int verify_peer; 00044 u8 *push_buf, *pull_buf, *pull_buf_offset; 00045 size_t push_buf_len, pull_buf_len; 00046 }; 00047 00048 00049 static PRStatus nss_io_close(PRFileDesc *fd) 00050 { 00051 wpa_printf(MSG_DEBUG, "NSS: I/O close"); 00052 return PR_SUCCESS; 00053 } 00054 00055 00056 static PRInt32 nss_io_read(PRFileDesc *fd, void *buf, PRInt32 amount) 00057 { 00058 wpa_printf(MSG_DEBUG, "NSS: I/O read(%d)", amount); 00059 return PR_FAILURE; 00060 } 00061 00062 00063 static PRInt32 nss_io_write(PRFileDesc *fd, const void *buf, PRInt32 amount) 00064 { 00065 wpa_printf(MSG_DEBUG, "NSS: I/O write(%d)", amount); 00066 return PR_FAILURE; 00067 } 00068 00069 00070 static PRInt32 nss_io_writev(PRFileDesc *fd, const PRIOVec *iov, 00071 PRInt32 iov_size, PRIntervalTime timeout) 00072 { 00073 wpa_printf(MSG_DEBUG, "NSS: I/O writev(%d)", iov_size); 00074 return PR_FAILURE; 00075 } 00076 00077 00078 static PRInt32 nss_io_recv(PRFileDesc *fd, void *buf, PRInt32 amount, 00079 PRIntn flags, PRIntervalTime timeout) 00080 { 00081 struct tls_connection *conn = (struct tls_connection *) fd->secret; 00082 u8 *end; 00083 00084 wpa_printf(MSG_DEBUG, "NSS: I/O recv(%d)", amount); 00085 00086 if (conn->pull_buf == NULL) { 00087 wpa_printf(MSG_DEBUG, "NSS: No data available to be read yet"); 00088 return PR_FAILURE; 00089 } 00090 00091 end = conn->pull_buf + conn->pull_buf_len; 00092 if (end - conn->pull_buf_offset < amount) 00093 amount = end - conn->pull_buf_offset; 00094 os_memcpy(buf, conn->pull_buf_offset, amount); 00095 conn->pull_buf_offset += amount; 00096 if (conn->pull_buf_offset == end) { 00097 wpa_printf(MSG_DEBUG, "%s - pull_buf consumed", __func__); 00098 os_free(conn->pull_buf); 00099 conn->pull_buf = conn->pull_buf_offset = NULL; 00100 conn->pull_buf_len = 0; 00101 } else { 00102 wpa_printf(MSG_DEBUG, "%s - %lu bytes remaining in pull_buf", 00103 __func__, 00104 (unsigned long) (end - conn->pull_buf_offset)); 00105 } 00106 return amount; 00107 } 00108 00109 00110 static PRInt32 nss_io_send(PRFileDesc *fd, const void *buf, PRInt32 amount, 00111 PRIntn flags, PRIntervalTime timeout) 00112 { 00113 struct tls_connection *conn = (struct tls_connection *) fd->secret; 00114 u8 *nbuf; 00115 00116 wpa_printf(MSG_DEBUG, "NSS: I/O %s", __func__); 00117 wpa_hexdump(MSG_MSGDUMP, "NSS: I/O send data", buf, amount); 00118 00119 nbuf = os_realloc(conn->push_buf, conn->push_buf_len + amount); 00120 if (nbuf == NULL) { 00121 wpa_printf(MSG_ERROR, "NSS: Failed to allocate memory for the " 00122 "data to be sent"); 00123 return PR_FAILURE; 00124 } 00125 os_memcpy(nbuf + conn->push_buf_len, buf, amount); 00126 conn->push_buf = nbuf; 00127 conn->push_buf_len += amount; 00128 00129 return amount; 00130 } 00131 00132 00133 static PRInt32 nss_io_recvfrom(PRFileDesc *fd, void *buf, PRInt32 amount, 00134 PRIntn flags, PRNetAddr *addr, 00135 PRIntervalTime timeout) 00136 { 00137 wpa_printf(MSG_DEBUG, "NSS: I/O %s", __func__); 00138 return PR_FAILURE; 00139 } 00140 00141 00142 static PRInt32 nss_io_sendto(PRFileDesc *fd, const void *buf, PRInt32 amount, 00143 PRIntn flags, const PRNetAddr *addr, 00144 PRIntervalTime timeout) 00145 { 00146 wpa_printf(MSG_DEBUG, "NSS: I/O %s", __func__); 00147 return PR_FAILURE; 00148 } 00149 00150 00151 static PRStatus nss_io_getpeername(PRFileDesc *fd, PRNetAddr *addr) 00152 { 00153 wpa_printf(MSG_DEBUG, "NSS: I/O getpeername"); 00154 00155 /* 00156 * It Looks like NSS only supports IPv4 and IPv6 TCP sockets. Provide a 00157 * fake IPv4 address to work around this even though we are not really 00158 * using TCP. 00159 */ 00160 os_memset(addr, 0, sizeof(*addr)); 00161 addr->inet.family = PR_AF_INET; 00162 00163 return PR_SUCCESS; 00164 } 00165 00166 00167 static PRStatus nss_io_getsocketoption(PRFileDesc *fd, 00168 PRSocketOptionData *data) 00169 { 00170 switch (data->option) { 00171 case PR_SockOpt_Nonblocking: 00172 wpa_printf(MSG_DEBUG, "NSS: I/O getsocketoption(Nonblocking)"); 00173 data->value.non_blocking = PR_TRUE; 00174 return PR_SUCCESS; 00175 default: 00176 wpa_printf(MSG_DEBUG, "NSS: I/O getsocketoption(%d)", 00177 data->option); 00178 return PR_FAILURE; 00179 } 00180 } 00181 00182 00183 static const PRIOMethods nss_io = { 00184 PR_DESC_LAYERED, 00185 nss_io_close, 00186 nss_io_read, 00187 nss_io_write, 00188 NULL /* available */, 00189 NULL /* available64 */, 00190 NULL /* fsync */, 00191 NULL /* fseek */, 00192 NULL /* fseek64 */, 00193 NULL /* fileinfo */, 00194 NULL /* fileinfo64 */, 00195 nss_io_writev, 00196 NULL /* connect */, 00197 NULL /* accept */, 00198 NULL /* bind */, 00199 NULL /* listen */, 00200 NULL /* shutdown */, 00201 nss_io_recv, 00202 nss_io_send, 00203 nss_io_recvfrom, 00204 nss_io_sendto, 00205 NULL /* poll */, 00206 NULL /* acceptread */, 00207 NULL /* transmitfile */, 00208 NULL /* getsockname */, 00209 nss_io_getpeername, 00210 NULL /* reserved_fn_6 */, 00211 NULL /* reserved_fn_5 */, 00212 nss_io_getsocketoption, 00213 NULL /* setsocketoption */, 00214 NULL /* sendfile */, 00215 NULL /* connectcontinue */, 00216 NULL /* reserved_fn_3 */, 00217 NULL /* reserved_fn_2 */, 00218 NULL /* reserved_fn_1 */, 00219 NULL /* reserved_fn_0 */ 00220 }; 00221 00222 00223 static char * nss_password_cb(PK11SlotInfo *slot, PRBool retry, void *arg) 00224 { 00225 wpa_printf(MSG_ERROR, "NSS: TODO - %s", __func__); 00226 return NULL; 00227 } 00228 00229 00230 void * tls_init(const struct tls_config *conf) 00231 { 00232 char *dir; 00233 00234 tls_nss_ref_count++; 00235 if (tls_nss_ref_count > 1) 00236 return (void *) 1; 00237 00238 PR_Init(PR_SYSTEM_THREAD, PR_PRIORITY_NORMAL, 1); 00239 00240 nss_layer_id = PR_GetUniqueIdentity("wpa_supplicant"); 00241 00242 PK11_SetPasswordFunc(nss_password_cb); 00243 00244 dir = getenv("SSL_DIR"); 00245 if (dir) { 00246 if (NSS_Init(dir) != SECSuccess) { 00247 wpa_printf(MSG_ERROR, "NSS: NSS_Init(cert_dir=%s) " 00248 "failed", dir); 00249 return NULL; 00250 } 00251 } else { 00252 if (NSS_NoDB_Init(NULL) != SECSuccess) { 00253 wpa_printf(MSG_ERROR, "NSS: NSS_NoDB_Init(NULL) " 00254 "failed"); 00255 return NULL; 00256 } 00257 } 00258 00259 if (SSL_OptionSetDefault(SSL_V2_COMPATIBLE_HELLO, PR_FALSE) != 00260 SECSuccess || 00261 SSL_OptionSetDefault(SSL_ENABLE_SSL3, PR_FALSE) != SECSuccess || 00262 SSL_OptionSetDefault(SSL_ENABLE_SSL2, PR_FALSE) != SECSuccess || 00263 SSL_OptionSetDefault(SSL_ENABLE_TLS, PR_TRUE) != SECSuccess) { 00264 wpa_printf(MSG_ERROR, "NSS: SSL_OptionSetDefault failed"); 00265 return NULL; 00266 } 00267 00268 if (NSS_SetDomesticPolicy() != SECSuccess) { 00269 wpa_printf(MSG_ERROR, "NSS: NSS_SetDomesticPolicy() failed"); 00270 return NULL; 00271 } 00272 00273 return (void *) 1; 00274 } 00275 00276 void tls_deinit(void *ssl_ctx) 00277 { 00278 tls_nss_ref_count--; 00279 if (tls_nss_ref_count == 0) { 00280 if (NSS_Shutdown() != SECSuccess) 00281 wpa_printf(MSG_ERROR, "NSS: NSS_Shutdown() failed"); 00282 } 00283 } 00284 00285 00286 int tls_get_errors(void *tls_ctx) 00287 { 00288 return 0; 00289 } 00290 00291 00292 static SECStatus nss_bad_cert_cb(void *arg, PRFileDesc *fd) 00293 { 00294 struct tls_connection *conn = arg; 00295 SECStatus res = SECSuccess; 00296 PRErrorCode err; 00297 CERTCertificate *cert; 00298 char *subject, *issuer; 00299 00300 err = PR_GetError(); 00301 if (IS_SEC_ERROR(err)) 00302 wpa_printf(MSG_DEBUG, "NSS: Bad Server Certificate (sec err " 00303 "%d)", err - SEC_ERROR_BASE); 00304 else 00305 wpa_printf(MSG_DEBUG, "NSS: Bad Server Certificate (err %d)", 00306 err); 00307 cert = SSL_PeerCertificate(fd); 00308 subject = CERT_NameToAscii(&cert->subject); 00309 issuer = CERT_NameToAscii(&cert->issuer); 00310 wpa_printf(MSG_DEBUG, "NSS: Peer certificate subject='%s' issuer='%s'", 00311 subject, issuer); 00312 CERT_DestroyCertificate(cert); 00313 PR_Free(subject); 00314 PR_Free(issuer); 00315 if (conn->verify_peer) 00316 res = SECFailure; 00317 00318 return res; 00319 } 00320 00321 00322 static void nss_handshake_cb(PRFileDesc *fd, void *client_data) 00323 { 00324 struct tls_connection *conn = client_data; 00325 wpa_printf(MSG_DEBUG, "NSS: Handshake completed"); 00326 conn->established = 1; 00327 } 00328 00329 00330 struct tls_connection * tls_connection_init(void *tls_ctx) 00331 { 00332 struct tls_connection *conn; 00333 00334 conn = os_zalloc(sizeof(*conn)); 00335 if (conn == NULL) 00336 return NULL; 00337 00338 conn->fd = PR_CreateIOLayerStub(nss_layer_id, &nss_io); 00339 if (conn->fd == NULL) { 00340 os_free(conn); 00341 return NULL; 00342 } 00343 conn->fd->secret = (void *) conn; 00344 00345 conn->fd = SSL_ImportFD(NULL, conn->fd); 00346 if (conn->fd == NULL) { 00347 os_free(conn); 00348 return NULL; 00349 } 00350 00351 if (SSL_OptionSet(conn->fd, SSL_SECURITY, PR_TRUE) != SECSuccess || 00352 SSL_OptionSet(conn->fd, SSL_HANDSHAKE_AS_CLIENT, PR_TRUE) != 00353 SECSuccess || 00354 SSL_OptionSet(conn->fd, SSL_HANDSHAKE_AS_SERVER, PR_FALSE) != 00355 SECSuccess || 00356 SSL_OptionSet(conn->fd, SSL_ENABLE_TLS, PR_TRUE) != SECSuccess || 00357 SSL_BadCertHook(conn->fd, nss_bad_cert_cb, conn) != SECSuccess || 00358 SSL_HandshakeCallback(conn->fd, nss_handshake_cb, conn) != 00359 SECSuccess) { 00360 wpa_printf(MSG_ERROR, "NSS: Failed to set options"); 00361 PR_Close(conn->fd); 00362 os_free(conn); 00363 return NULL; 00364 } 00365 00366 SSL_ResetHandshake(conn->fd, PR_FALSE); 00367 00368 return conn; 00369 } 00370 00371 00372 void tls_connection_deinit(void *tls_ctx, struct tls_connection *conn) 00373 { 00374 PR_Close(conn->fd); 00375 os_free(conn->push_buf); 00376 os_free(conn->pull_buf); 00377 os_free(conn); 00378 } 00379 00380 00381 int tls_connection_established(void *tls_ctx, struct tls_connection *conn) 00382 { 00383 return conn->established; 00384 } 00385 00386 00387 int tls_connection_shutdown(void *tls_ctx, struct tls_connection *conn) 00388 { 00389 return -1; 00390 } 00391 00392 00393 int tls_connection_set_params(void *tls_ctx, struct tls_connection *conn, 00394 const struct tls_connection_params *params) 00395 { 00396 wpa_printf(MSG_ERROR, "NSS: TODO - %s", __func__); 00397 return 0; 00398 } 00399 00400 00401 int tls_global_set_params(void *tls_ctx, 00402 const struct tls_connection_params *params) 00403 { 00404 return -1; 00405 } 00406 00407 00408 int tls_global_set_verify(void *tls_ctx, int check_crl) 00409 { 00410 return -1; 00411 } 00412 00413 00414 int tls_connection_set_verify(void *tls_ctx, struct tls_connection *conn, 00415 int verify_peer) 00416 { 00417 conn->verify_peer = verify_peer; 00418 return 0; 00419 } 00420 00421 00422 int tls_connection_set_ia(void *tls_ctx, struct tls_connection *conn, 00423 int tls_ia) 00424 { 00425 return -1; 00426 } 00427 00428 00429 int tls_connection_get_keys(void *tls_ctx, struct tls_connection *conn, 00430 struct tls_keys *keys) 00431 { 00432 /* NSS does not export master secret or client/server random. */ 00433 return -1; 00434 } 00435 00436 00437 int tls_connection_prf(void *tls_ctx, struct tls_connection *conn, 00438 const char *label, int server_random_first, 00439 u8 *out, size_t out_len) 00440 { 00441 if (conn == NULL || server_random_first) { 00442 wpa_printf(MSG_INFO, "NSS: Unsupported PRF request " 00443 "(server_random_first=%d)", 00444 server_random_first); 00445 return -1; 00446 } 00447 00448 if (SSL_ExportKeyingMaterial(conn->fd, label, NULL, 0, out, out_len) != 00449 SECSuccess) { 00450 wpa_printf(MSG_INFO, "NSS: Failed to use TLS extractor " 00451 "(label='%s' out_len=%d", label, (int) out_len); 00452 return -1; 00453 } 00454 00455 return 0; 00456 } 00457 00458 00459 struct wpabuf * tls_connection_handshake(void *tls_ctx, 00460 struct tls_connection *conn, 00461 const struct wpabuf *in_data, 00462 struct wpabuf **appl_data) 00463 { 00464 struct wpabuf *out_data; 00465 00466 wpa_printf(MSG_DEBUG, "NSS: handshake: in_len=%u", 00467 in_data ? (unsigned int) wpabuf_len(in_data) : 0); 00468 00469 if (appl_data) 00470 *appl_data = NULL; 00471 00472 if (in_data && wpabuf_len(in_data) > 0) { 00473 if (conn->pull_buf) { 00474 wpa_printf(MSG_DEBUG, "%s - %lu bytes remaining in " 00475 "pull_buf", __func__, 00476 (unsigned long) conn->pull_buf_len); 00477 os_free(conn->pull_buf); 00478 } 00479 conn->pull_buf = os_malloc(wpabuf_len(in_data)); 00480 if (conn->pull_buf == NULL) 00481 return NULL; 00482 os_memcpy(conn->pull_buf, wpabuf_head(in_data), 00483 wpabuf_len(in_data)); 00484 conn->pull_buf_offset = conn->pull_buf; 00485 conn->pull_buf_len = wpabuf_len(in_data); 00486 } 00487 00488 SSL_ForceHandshake(conn->fd); 00489 00490 if (conn->established && conn->push_buf == NULL) { 00491 /* Need to return something to get final TLS ACK. */ 00492 conn->push_buf = os_malloc(1); 00493 } 00494 00495 if (conn->push_buf == NULL) 00496 return NULL; 00497 out_data = wpabuf_alloc_ext_data(conn->push_buf, conn->push_buf_len); 00498 if (out_data == NULL) 00499 os_free(conn->push_buf); 00500 conn->push_buf = NULL; 00501 conn->push_buf_len = 0; 00502 return out_data; 00503 } 00504 00505 00506 struct wpabuf * tls_connection_server_handshake(void *tls_ctx, 00507 struct tls_connection *conn, 00508 const struct wpabuf *in_data, 00509 struct wpabuf **appl_data) 00510 { 00511 return NULL; 00512 } 00513 00514 00515 struct wpabuf * tls_connection_encrypt(void *tls_ctx, 00516 struct tls_connection *conn, 00517 const struct wpabuf *in_data) 00518 { 00519 PRInt32 res; 00520 struct wpabuf *buf; 00521 00522 wpa_printf(MSG_DEBUG, "NSS: encrypt %d bytes", 00523 (int) wpabuf_len(in_data)); 00524 res = PR_Send(conn->fd, wpabuf_head(in_data), wpabuf_len(in_data), 0, 00525 0); 00526 if (res < 0) { 00527 wpa_printf(MSG_ERROR, "NSS: Encryption failed"); 00528 return NULL; 00529 } 00530 if (conn->push_buf == NULL) 00531 return NULL; 00532 buf = wpabuf_alloc_ext_data(conn->push_buf, conn->push_buf_len); 00533 if (buf == NULL) 00534 os_free(conn->push_buf); 00535 conn->push_buf = NULL; 00536 conn->push_buf_len = 0; 00537 return buf; 00538 } 00539 00540 00541 struct wpabuf * tls_connection_decrypt(void *tls_ctx, 00542 struct tls_connection *conn, 00543 const struct wpabuf *in_data) 00544 { 00545 PRInt32 res; 00546 struct wpabuf *out; 00547 00548 wpa_printf(MSG_DEBUG, "NSS: decrypt %d bytes", 00549 (int) wpabuf_len(in_data)); 00550 if (conn->pull_buf) { 00551 wpa_printf(MSG_DEBUG, "%s - %lu bytes remaining in " 00552 "pull_buf", __func__, 00553 (unsigned long) conn->pull_buf_len); 00554 os_free(conn->pull_buf); 00555 } 00556 conn->pull_buf = os_malloc(wpabuf_len(in_data)); 00557 if (conn->pull_buf == NULL) 00558 return NULL; 00559 os_memcpy(conn->pull_buf, wpabuf_head(in_data), wpabuf_len(in_data)); 00560 conn->pull_buf_offset = conn->pull_buf; 00561 conn->pull_buf_len = wpabuf_len(in_data); 00562 00563 /* 00564 * Even though we try to disable TLS compression, it is possible that 00565 * this cannot be done with all TLS libraries. Add extra buffer space 00566 * to handle the possibility of the decrypted data being longer than 00567 * input data. 00568 */ 00569 out = wpabuf_alloc((wpabuf_len(in_data) + 500) * 3); 00570 if (out == NULL) 00571 return NULL; 00572 00573 res = PR_Recv(conn->fd, wpabuf_mhead(out), wpabuf_size(out), 0, 0); 00574 wpa_printf(MSG_DEBUG, "NSS: PR_Recv: %d", res); 00575 if (res < 0) { 00576 wpabuf_free(out); 00577 return NULL; 00578 } 00579 wpabuf_put(out, res); 00580 00581 return out; 00582 } 00583 00584 00585 int tls_connection_resumed(void *tls_ctx, struct tls_connection *conn) 00586 { 00587 return 0; 00588 } 00589 00590 00591 int tls_connection_set_cipher_list(void *tls_ctx, struct tls_connection *conn, 00592 u8 *ciphers) 00593 { 00594 return -1; 00595 } 00596 00597 00598 int tls_get_cipher(void *tls_ctx, struct tls_connection *conn, 00599 char *buf, size_t buflen) 00600 { 00601 return -1; 00602 } 00603 00604 00605 int tls_connection_enable_workaround(void *tls_ctx, 00606 struct tls_connection *conn) 00607 { 00608 return -1; 00609 } 00610 00611 00612 int tls_connection_client_hello_ext(void *tls_ctx, struct tls_connection *conn, 00613 int ext_type, const u8 *data, 00614 size_t data_len) 00615 { 00616 return -1; 00617 } 00618 00619 00620 int tls_connection_get_failed(void *tls_ctx, struct tls_connection *conn) 00621 { 00622 return 0; 00623 } 00624 00625 00626 int tls_connection_get_read_alerts(void *tls_ctx, struct tls_connection *conn) 00627 { 00628 return 0; 00629 } 00630 00631 00632 int tls_connection_get_write_alerts(void *tls_ctx, 00633 struct tls_connection *conn) 00634 { 00635 return 0; 00636 } 00637 00638 00639 int tls_connection_get_keyblock_size(void *tls_ctx, 00640 struct tls_connection *conn) 00641 { 00642 return -1; 00643 } 00644 00645 00646 unsigned int tls_capabilities(void *tls_ctx) 00647 { 00648 return 0; 00649 } 00650 00651 00652 struct wpabuf * tls_connection_ia_send_phase_finished( 00653 void *tls_ctx, struct tls_connection *conn, int final) 00654 { 00655 return NULL; 00656 } 00657 00658 00659 int tls_connection_ia_final_phase_finished(void *tls_ctx, 00660 struct tls_connection *conn) 00661 { 00662 return -1; 00663 } 00664 00665 00666 int tls_connection_ia_permute_inner_secret(void *tls_ctx, 00667 struct tls_connection *conn, 00668 const u8 *key, size_t key_len) 00669 { 00670 return -1; 00671 } 00672 00673 00674 int tls_connection_set_session_ticket_cb(void *tls_ctx, 00675 struct tls_connection *conn, 00676 tls_session_ticket_cb cb, 00677 void *ctx) 00678 { 00679 return -1; 00680 }