tls_nss.c

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

Generated on Sat Nov 21 23:16:50 2009 for hostapd by  doxygen 1.6.1