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