1 /* 2 * SSL/TLS interface functions for NSS 3 * Copyright (c) 2009, Jouni Malinen <j (at) 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 #include <nspr/prtypes.h> 11 #include <nspr/plarenas.h> 12 #include <nspr/plhash.h> 13 #include <nspr/prio.h> 14 #include <nspr/prclist.h> 15 #include <nspr/prlock.h> 16 #include <nspr/prinit.h> 17 #include <nspr/prerror.h> 18 #include <nspr/prmem.h> 19 #include <nss/nss.h> 20 #include <nss/nssilckt.h> 21 #include <nss/ssl.h> 22 #include <nss/pk11func.h> 23 #include <nss/secerr.h> 24 25 #include "common.h" 26 #include "tls.h" 27 28 static int tls_nss_ref_count = 0; 29 30 static PRDescIdentity nss_layer_id; 31 32 33 struct tls_connection { 34 PRFileDesc *fd; 35 36 int established; 37 int verify_peer; 38 u8 *push_buf, *pull_buf, *pull_buf_offset; 39 size_t push_buf_len, pull_buf_len; 40 }; 41 42 43 static PRStatus nss_io_close(PRFileDesc *fd) 44 { 45 wpa_printf(MSG_DEBUG, "NSS: I/O close"); 46 return PR_SUCCESS; 47 } 48 49 50 static PRInt32 nss_io_read(PRFileDesc *fd, void *buf, PRInt32 amount) 51 { 52 wpa_printf(MSG_DEBUG, "NSS: I/O read(%d)", amount); 53 return PR_FAILURE; 54 } 55 56 57 static PRInt32 nss_io_write(PRFileDesc *fd, const void *buf, PRInt32 amount) 58 { 59 wpa_printf(MSG_DEBUG, "NSS: I/O write(%d)", amount); 60 return PR_FAILURE; 61 } 62 63 64 static PRInt32 nss_io_writev(PRFileDesc *fd, const PRIOVec *iov, 65 PRInt32 iov_size, PRIntervalTime timeout) 66 { 67 wpa_printf(MSG_DEBUG, "NSS: I/O writev(%d)", iov_size); 68 return PR_FAILURE; 69 } 70 71 72 static PRInt32 nss_io_recv(PRFileDesc *fd, void *buf, PRInt32 amount, 73 PRIntn flags, PRIntervalTime timeout) 74 { 75 struct tls_connection *conn = (struct tls_connection *) fd->secret; 76 u8 *end; 77 78 wpa_printf(MSG_DEBUG, "NSS: I/O recv(%d)", amount); 79 80 if (conn->pull_buf == NULL) { 81 wpa_printf(MSG_DEBUG, "NSS: No data available to be read yet"); 82 return PR_FAILURE; 83 } 84 85 end = conn->pull_buf + conn->pull_buf_len; 86 if (end - conn->pull_buf_offset < amount) 87 amount = end - conn->pull_buf_offset; 88 os_memcpy(buf, conn->pull_buf_offset, amount); 89 conn->pull_buf_offset += amount; 90 if (conn->pull_buf_offset == end) { 91 wpa_printf(MSG_DEBUG, "%s - pull_buf consumed", __func__); 92 os_free(conn->pull_buf); 93 conn->pull_buf = conn->pull_buf_offset = NULL; 94 conn->pull_buf_len = 0; 95 } else { 96 wpa_printf(MSG_DEBUG, "%s - %lu bytes remaining in pull_buf", 97 __func__, 98 (unsigned long) (end - conn->pull_buf_offset)); 99 } 100 return amount; 101 } 102 103 104 static PRInt32 nss_io_send(PRFileDesc *fd, const void *buf, PRInt32 amount, 105 PRIntn flags, PRIntervalTime timeout) 106 { 107 struct tls_connection *conn = (struct tls_connection *) fd->secret; 108 u8 *nbuf; 109 110 wpa_printf(MSG_DEBUG, "NSS: I/O %s", __func__); 111 wpa_hexdump(MSG_MSGDUMP, "NSS: I/O send data", buf, amount); 112 113 nbuf = os_realloc(conn->push_buf, conn->push_buf_len + amount); 114 if (nbuf == NULL) { 115 wpa_printf(MSG_ERROR, "NSS: Failed to allocate memory for the " 116 "data to be sent"); 117 return PR_FAILURE; 118 } 119 os_memcpy(nbuf + conn->push_buf_len, buf, amount); 120 conn->push_buf = nbuf; 121 conn->push_buf_len += amount; 122 123 return amount; 124 } 125 126 127 static PRInt32 nss_io_recvfrom(PRFileDesc *fd, void *buf, PRInt32 amount, 128 PRIntn flags, PRNetAddr *addr, 129 PRIntervalTime timeout) 130 { 131 wpa_printf(MSG_DEBUG, "NSS: I/O %s", __func__); 132 return PR_FAILURE; 133 } 134 135 136 static PRInt32 nss_io_sendto(PRFileDesc *fd, const void *buf, PRInt32 amount, 137 PRIntn flags, const PRNetAddr *addr, 138 PRIntervalTime timeout) 139 { 140 wpa_printf(MSG_DEBUG, "NSS: I/O %s", __func__); 141 return PR_FAILURE; 142 } 143 144 145 static PRStatus nss_io_getpeername(PRFileDesc *fd, PRNetAddr *addr) 146 { 147 wpa_printf(MSG_DEBUG, "NSS: I/O getpeername"); 148 149 /* 150 * It Looks like NSS only supports IPv4 and IPv6 TCP sockets. Provide a 151 * fake IPv4 address to work around this even though we are not really 152 * using TCP. 153 */ 154 os_memset(addr, 0, sizeof(*addr)); 155 addr->inet.family = PR_AF_INET; 156 157 return PR_SUCCESS; 158 } 159 160 161 static PRStatus nss_io_getsocketoption(PRFileDesc *fd, 162 PRSocketOptionData *data) 163 { 164 switch (data->option) { 165 case PR_SockOpt_Nonblocking: 166 wpa_printf(MSG_DEBUG, "NSS: I/O getsocketoption(Nonblocking)"); 167 data->value.non_blocking = PR_TRUE; 168 return PR_SUCCESS; 169 default: 170 wpa_printf(MSG_DEBUG, "NSS: I/O getsocketoption(%d)", 171 data->option); 172 return PR_FAILURE; 173 } 174 } 175 176 177 static const PRIOMethods nss_io = { 178 PR_DESC_LAYERED, 179 nss_io_close, 180 nss_io_read, 181 nss_io_write, 182 NULL /* available */, 183 NULL /* available64 */, 184 NULL /* fsync */, 185 NULL /* fseek */, 186 NULL /* fseek64 */, 187 NULL /* fileinfo */, 188 NULL /* fileinfo64 */, 189 nss_io_writev, 190 NULL /* connect */, 191 NULL /* accept */, 192 NULL /* bind */, 193 NULL /* listen */, 194 NULL /* shutdown */, 195 nss_io_recv, 196 nss_io_send, 197 nss_io_recvfrom, 198 nss_io_sendto, 199 NULL /* poll */, 200 NULL /* acceptread */, 201 NULL /* transmitfile */, 202 NULL /* getsockname */, 203 nss_io_getpeername, 204 NULL /* reserved_fn_6 */, 205 NULL /* reserved_fn_5 */, 206 nss_io_getsocketoption, 207 NULL /* setsocketoption */, 208 NULL /* sendfile */, 209 NULL /* connectcontinue */, 210 NULL /* reserved_fn_3 */, 211 NULL /* reserved_fn_2 */, 212 NULL /* reserved_fn_1 */, 213 NULL /* reserved_fn_0 */ 214 }; 215 216 217 static char * nss_password_cb(PK11SlotInfo *slot, PRBool retry, void *arg) 218 { 219 wpa_printf(MSG_ERROR, "NSS: TODO - %s", __func__); 220 return NULL; 221 } 222 223 224 void * tls_init(const struct tls_config *conf) 225 { 226 char *dir; 227 228 tls_nss_ref_count++; 229 if (tls_nss_ref_count > 1) 230 return (void *) 1; 231 232 PR_Init(PR_SYSTEM_THREAD, PR_PRIORITY_NORMAL, 1); 233 234 nss_layer_id = PR_GetUniqueIdentity("wpa_supplicant"); 235 236 PK11_SetPasswordFunc(nss_password_cb); 237 238 dir = getenv("SSL_DIR"); 239 if (dir) { 240 if (NSS_Init(dir) != SECSuccess) { 241 wpa_printf(MSG_ERROR, "NSS: NSS_Init(cert_dir=%s) " 242 "failed", dir); 243 return NULL; 244 } 245 } else { 246 if (NSS_NoDB_Init(NULL) != SECSuccess) { 247 wpa_printf(MSG_ERROR, "NSS: NSS_NoDB_Init(NULL) " 248 "failed"); 249 return NULL; 250 } 251 } 252 253 if (SSL_OptionSetDefault(SSL_V2_COMPATIBLE_HELLO, PR_FALSE) != 254 SECSuccess || 255 SSL_OptionSetDefault(SSL_ENABLE_SSL3, PR_FALSE) != SECSuccess || 256 SSL_OptionSetDefault(SSL_ENABLE_SSL2, PR_FALSE) != SECSuccess || 257 SSL_OptionSetDefault(SSL_ENABLE_TLS, PR_TRUE) != SECSuccess) { 258 wpa_printf(MSG_ERROR, "NSS: SSL_OptionSetDefault failed"); 259 return NULL; 260 } 261 262 if (NSS_SetDomesticPolicy() != SECSuccess) { 263 wpa_printf(MSG_ERROR, "NSS: NSS_SetDomesticPolicy() failed"); 264 return NULL; 265 } 266 267 return (void *) 1; 268 } 269 270 void tls_deinit(void *ssl_ctx) 271 { 272 tls_nss_ref_count--; 273 if (tls_nss_ref_count == 0) { 274 if (NSS_Shutdown() != SECSuccess) 275 wpa_printf(MSG_ERROR, "NSS: NSS_Shutdown() failed"); 276 } 277 } 278 279 280 int tls_get_errors(void *tls_ctx) 281 { 282 return 0; 283 } 284 285 286 static SECStatus nss_bad_cert_cb(void *arg, PRFileDesc *fd) 287 { 288 struct tls_connection *conn = arg; 289 SECStatus res = SECSuccess; 290 PRErrorCode err; 291 CERTCertificate *cert; 292 char *subject, *issuer; 293 294 err = PR_GetError(); 295 if (IS_SEC_ERROR(err)) 296 wpa_printf(MSG_DEBUG, "NSS: Bad Server Certificate (sec err " 297 "%d)", err - SEC_ERROR_BASE); 298 else 299 wpa_printf(MSG_DEBUG, "NSS: Bad Server Certificate (err %d)", 300 err); 301 cert = SSL_PeerCertificate(fd); 302 subject = CERT_NameToAscii(&cert->subject); 303 issuer = CERT_NameToAscii(&cert->issuer); 304 wpa_printf(MSG_DEBUG, "NSS: Peer certificate subject='%s' issuer='%s'", 305 subject, issuer); 306 CERT_DestroyCertificate(cert); 307 PR_Free(subject); 308 PR_Free(issuer); 309 if (conn->verify_peer) 310 res = SECFailure; 311 312 return res; 313 } 314 315 316 static void nss_handshake_cb(PRFileDesc *fd, void *client_data) 317 { 318 struct tls_connection *conn = client_data; 319 wpa_printf(MSG_DEBUG, "NSS: Handshake completed"); 320 conn->established = 1; 321 } 322 323 324 struct tls_connection * tls_connection_init(void *tls_ctx) 325 { 326 struct tls_connection *conn; 327 328 conn = os_zalloc(sizeof(*conn)); 329 if (conn == NULL) 330 return NULL; 331 332 conn->fd = PR_CreateIOLayerStub(nss_layer_id, &nss_io); 333 if (conn->fd == NULL) { 334 os_free(conn); 335 return NULL; 336 } 337 conn->fd->secret = (void *) conn; 338 339 conn->fd = SSL_ImportFD(NULL, conn->fd); 340 if (conn->fd == NULL) { 341 os_free(conn); 342 return NULL; 343 } 344 345 if (SSL_OptionSet(conn->fd, SSL_SECURITY, PR_TRUE) != SECSuccess || 346 SSL_OptionSet(conn->fd, SSL_HANDSHAKE_AS_CLIENT, PR_TRUE) != 347 SECSuccess || 348 SSL_OptionSet(conn->fd, SSL_HANDSHAKE_AS_SERVER, PR_FALSE) != 349 SECSuccess || 350 SSL_OptionSet(conn->fd, SSL_ENABLE_TLS, PR_TRUE) != SECSuccess || 351 SSL_BadCertHook(conn->fd, nss_bad_cert_cb, conn) != SECSuccess || 352 SSL_HandshakeCallback(conn->fd, nss_handshake_cb, conn) != 353 SECSuccess) { 354 wpa_printf(MSG_ERROR, "NSS: Failed to set options"); 355 PR_Close(conn->fd); 356 os_free(conn); 357 return NULL; 358 } 359 360 SSL_ResetHandshake(conn->fd, PR_FALSE); 361 362 return conn; 363 } 364 365 366 void tls_connection_deinit(void *tls_ctx, struct tls_connection *conn) 367 { 368 PR_Close(conn->fd); 369 os_free(conn->push_buf); 370 os_free(conn->pull_buf); 371 os_free(conn); 372 } 373 374 375 int tls_connection_established(void *tls_ctx, struct tls_connection *conn) 376 { 377 return conn->established; 378 } 379 380 381 int tls_connection_shutdown(void *tls_ctx, struct tls_connection *conn) 382 { 383 return -1; 384 } 385 386 387 int tls_connection_set_params(void *tls_ctx, struct tls_connection *conn, 388 const struct tls_connection_params *params) 389 { 390 wpa_printf(MSG_ERROR, "NSS: TODO - %s", __func__); 391 return 0; 392 } 393 394 395 int tls_global_set_params(void *tls_ctx, 396 const struct tls_connection_params *params) 397 { 398 return -1; 399 } 400 401 402 int tls_global_set_verify(void *tls_ctx, int check_crl) 403 { 404 return -1; 405 } 406 407 408 int tls_connection_set_verify(void *tls_ctx, struct tls_connection *conn, 409 int verify_peer) 410 { 411 conn->verify_peer = verify_peer; 412 return 0; 413 } 414 415 416 int tls_connection_get_keys(void *tls_ctx, struct tls_connection *conn, 417 struct tls_keys *keys) 418 { 419 /* NSS does not export master secret or client/server random. */ 420 return -1; 421 } 422 423 424 int tls_connection_prf(void *tls_ctx, struct tls_connection *conn, 425 const char *label, int server_random_first, 426 u8 *out, size_t out_len) 427 { 428 if (conn == NULL || server_random_first) { 429 wpa_printf(MSG_INFO, "NSS: Unsupported PRF request " 430 "(server_random_first=%d)", 431 server_random_first); 432 return -1; 433 } 434 435 if (SSL_ExportKeyingMaterial(conn->fd, label, NULL, 0, out, out_len) != 436 SECSuccess) { 437 wpa_printf(MSG_INFO, "NSS: Failed to use TLS extractor " 438 "(label='%s' out_len=%d", label, (int) out_len); 439 return -1; 440 } 441 442 return 0; 443 } 444 445 446 struct wpabuf * tls_connection_handshake(void *tls_ctx, 447 struct tls_connection *conn, 448 const struct wpabuf *in_data, 449 struct wpabuf **appl_data) 450 { 451 struct wpabuf *out_data; 452 453 wpa_printf(MSG_DEBUG, "NSS: handshake: in_len=%u", 454 in_data ? (unsigned int) wpabuf_len(in_data) : 0); 455 456 if (appl_data) 457 *appl_data = NULL; 458 459 if (in_data && wpabuf_len(in_data) > 0) { 460 if (conn->pull_buf) { 461 wpa_printf(MSG_DEBUG, "%s - %lu bytes remaining in " 462 "pull_buf", __func__, 463 (unsigned long) conn->pull_buf_len); 464 os_free(conn->pull_buf); 465 } 466 conn->pull_buf = os_malloc(wpabuf_len(in_data)); 467 if (conn->pull_buf == NULL) 468 return NULL; 469 os_memcpy(conn->pull_buf, wpabuf_head(in_data), 470 wpabuf_len(in_data)); 471 conn->pull_buf_offset = conn->pull_buf; 472 conn->pull_buf_len = wpabuf_len(in_data); 473 } 474 475 SSL_ForceHandshake(conn->fd); 476 477 if (conn->established && conn->push_buf == NULL) { 478 /* Need to return something to get final TLS ACK. */ 479 conn->push_buf = os_malloc(1); 480 } 481 482 if (conn->push_buf == NULL) 483 return NULL; 484 out_data = wpabuf_alloc_ext_data(conn->push_buf, conn->push_buf_len); 485 if (out_data == NULL) 486 os_free(conn->push_buf); 487 conn->push_buf = NULL; 488 conn->push_buf_len = 0; 489 return out_data; 490 } 491 492 493 struct wpabuf * tls_connection_server_handshake(void *tls_ctx, 494 struct tls_connection *conn, 495 const struct wpabuf *in_data, 496 struct wpabuf **appl_data) 497 { 498 return NULL; 499 } 500 501 502 struct wpabuf * tls_connection_encrypt(void *tls_ctx, 503 struct tls_connection *conn, 504 const struct wpabuf *in_data) 505 { 506 PRInt32 res; 507 struct wpabuf *buf; 508 509 wpa_printf(MSG_DEBUG, "NSS: encrypt %d bytes", 510 (int) wpabuf_len(in_data)); 511 res = PR_Send(conn->fd, wpabuf_head(in_data), wpabuf_len(in_data), 0, 512 0); 513 if (res < 0) { 514 wpa_printf(MSG_ERROR, "NSS: Encryption failed"); 515 return NULL; 516 } 517 if (conn->push_buf == NULL) 518 return NULL; 519 buf = wpabuf_alloc_ext_data(conn->push_buf, conn->push_buf_len); 520 if (buf == NULL) 521 os_free(conn->push_buf); 522 conn->push_buf = NULL; 523 conn->push_buf_len = 0; 524 return buf; 525 } 526 527 528 struct wpabuf * tls_connection_decrypt(void *tls_ctx, 529 struct tls_connection *conn, 530 const struct wpabuf *in_data) 531 { 532 PRInt32 res; 533 struct wpabuf *out; 534 535 wpa_printf(MSG_DEBUG, "NSS: decrypt %d bytes", 536 (int) wpabuf_len(in_data)); 537 if (conn->pull_buf) { 538 wpa_printf(MSG_DEBUG, "%s - %lu bytes remaining in " 539 "pull_buf", __func__, 540 (unsigned long) conn->pull_buf_len); 541 os_free(conn->pull_buf); 542 } 543 conn->pull_buf = os_malloc(wpabuf_len(in_data)); 544 if (conn->pull_buf == NULL) 545 return NULL; 546 os_memcpy(conn->pull_buf, wpabuf_head(in_data), wpabuf_len(in_data)); 547 conn->pull_buf_offset = conn->pull_buf; 548 conn->pull_buf_len = wpabuf_len(in_data); 549 550 /* 551 * Even though we try to disable TLS compression, it is possible that 552 * this cannot be done with all TLS libraries. Add extra buffer space 553 * to handle the possibility of the decrypted data being longer than 554 * input data. 555 */ 556 out = wpabuf_alloc((wpabuf_len(in_data) + 500) * 3); 557 if (out == NULL) 558 return NULL; 559 560 res = PR_Recv(conn->fd, wpabuf_mhead(out), wpabuf_size(out), 0, 0); 561 wpa_printf(MSG_DEBUG, "NSS: PR_Recv: %d", res); 562 if (res < 0) { 563 wpabuf_free(out); 564 return NULL; 565 } 566 wpabuf_put(out, res); 567 568 return out; 569 } 570 571 572 int tls_connection_resumed(void *tls_ctx, struct tls_connection *conn) 573 { 574 return 0; 575 } 576 577 578 int tls_connection_set_cipher_list(void *tls_ctx, struct tls_connection *conn, 579 u8 *ciphers) 580 { 581 return -1; 582 } 583 584 585 int tls_get_cipher(void *tls_ctx, struct tls_connection *conn, 586 char *buf, size_t buflen) 587 { 588 return -1; 589 } 590 591 592 int tls_connection_enable_workaround(void *tls_ctx, 593 struct tls_connection *conn) 594 { 595 return -1; 596 } 597 598 599 int tls_connection_client_hello_ext(void *tls_ctx, struct tls_connection *conn, 600 int ext_type, const u8 *data, 601 size_t data_len) 602 { 603 return -1; 604 } 605 606 607 int tls_connection_get_failed(void *tls_ctx, struct tls_connection *conn) 608 { 609 return 0; 610 } 611 612 613 int tls_connection_get_read_alerts(void *tls_ctx, struct tls_connection *conn) 614 { 615 return 0; 616 } 617 618 619 int tls_connection_get_write_alerts(void *tls_ctx, 620 struct tls_connection *conn) 621 { 622 return 0; 623 } 624 625 626 int tls_connection_get_keyblock_size(void *tls_ctx, 627 struct tls_connection *conn) 628 { 629 return -1; 630 } 631 632 633 unsigned int tls_capabilities(void *tls_ctx) 634 { 635 return 0; 636 } 637 638 639 int tls_connection_set_session_ticket_cb(void *tls_ctx, 640 struct tls_connection *conn, 641 tls_session_ticket_cb cb, 642 void *ctx) 643 { 644 return -1; 645 } 646