1c28749e9Skais /*
2c28749e9Skais * CDDL HEADER START
3c28749e9Skais *
4c28749e9Skais * The contents of this file are subject to the terms of the
5c892ebf1Skrishna * Common Development and Distribution License (the "License").
6c892ebf1Skrishna * You may not use this file except in compliance with the License.
7c28749e9Skais *
8c28749e9Skais * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9c28749e9Skais * or http://www.opensolaris.org/os/licensing.
10c28749e9Skais * See the License for the specific language governing permissions
11c28749e9Skais * and limitations under the License.
12c28749e9Skais *
13c28749e9Skais * When distributing Covered Code, include this CDDL HEADER in each
14c28749e9Skais * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15c28749e9Skais * If applicable, add the following below this CDDL HEADER, with the
16c28749e9Skais * fields enclosed by brackets "[]" replaced with your own identifying
17c28749e9Skais * information: Portions Copyright [yyyy] [name of copyright owner]
18c28749e9Skais *
19c28749e9Skais * CDDL HEADER END
20c28749e9Skais */
21c28749e9Skais /*
22*dd49f125SAnders Persson * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
23c28749e9Skais */
24c28749e9Skais
25c28749e9Skais
26c28749e9Skais /*
27c28749e9Skais * The system call and DDI interface for the kernel SSL module
28c28749e9Skais */
29c28749e9Skais
30c28749e9Skais #include <sys/types.h>
31c28749e9Skais #include <sys/modctl.h>
32c28749e9Skais #include <sys/conf.h>
33c28749e9Skais #include <sys/stat.h>
34c28749e9Skais #include <sys/ddi.h>
35c28749e9Skais #include <sys/sunddi.h>
36c28749e9Skais #include <sys/kmem.h>
37c28749e9Skais #include <sys/errno.h>
38c28749e9Skais #include <sys/file.h>
39c28749e9Skais #include <sys/open.h>
40c28749e9Skais #include <sys/cred.h>
41c28749e9Skais #include <sys/proc.h>
42c28749e9Skais #include <sys/task.h>
43c28749e9Skais #include <sys/model.h>
44c28749e9Skais #include <sys/sysmacros.h>
45c28749e9Skais #include <sys/policy.h>
46c28749e9Skais #include <sys/crypto/common.h>
47c28749e9Skais #include <sys/crypto/api.h>
48c28749e9Skais #include <c2/audit.h>
49c28749e9Skais #include <sys/kstat.h>
50c28749e9Skais
51c28749e9Skais #include "kssl.h"
52c28749e9Skais #include "ksslimpl.h"
53c28749e9Skais
54c28749e9Skais /*
55c28749e9Skais * DDI entry points.
56c28749e9Skais */
57c28749e9Skais static int kssl_attach(dev_info_t *, ddi_attach_cmd_t);
58c28749e9Skais static int kssl_detach(dev_info_t *, ddi_detach_cmd_t);
59c28749e9Skais static int kssl_getinfo(dev_info_t *, ddi_info_cmd_t, void *, void **);
60c28749e9Skais static int kssl_open(dev_t *, int, int, cred_t *);
61c28749e9Skais static int kssl_close(dev_t, int, int, cred_t *);
62c28749e9Skais static int kssl_ioctl(dev_t, int, intptr_t, int, cred_t *, int *);
63c28749e9Skais
64c28749e9Skais static int kssl_constructor(void *buf, void *arg, int kmflags);
65c28749e9Skais static void kssl_destructor(void *buf, void *arg);
66c28749e9Skais
67c28749e9Skais /*
68c28749e9Skais * Module linkage.
69c28749e9Skais */
70c28749e9Skais static struct cb_ops cbops = {
71c28749e9Skais kssl_open, /* cb_open */
72c28749e9Skais kssl_close, /* cb_close */
73c28749e9Skais nodev, /* cb_strategy */
74c28749e9Skais nodev, /* cb_print */
75c28749e9Skais nodev, /* cb_dump */
76c28749e9Skais nodev, /* cb_read */
77c28749e9Skais nodev, /* cb_write */
78c28749e9Skais kssl_ioctl, /* cb_ioctl */
79c28749e9Skais nodev, /* cb_devmap */
80c28749e9Skais nodev, /* cb_mmap */
81c28749e9Skais nodev, /* cb_segmap */
82c28749e9Skais nochpoll, /* cb_chpoll */
83c28749e9Skais ddi_prop_op, /* cb_prop_op */
84c28749e9Skais NULL, /* cb_streamtab */
85c28749e9Skais D_MP, /* cb_flag */
86c28749e9Skais CB_REV, /* cb_rev */
87c28749e9Skais nodev, /* cb_aread */
88c28749e9Skais nodev, /* cb_awrite */
89c28749e9Skais };
90c28749e9Skais
91c28749e9Skais static struct dev_ops devops = {
92c28749e9Skais DEVO_REV, /* devo_rev */
93c28749e9Skais 0, /* devo_refcnt */
94c28749e9Skais kssl_getinfo, /* devo_getinfo */
95c28749e9Skais nulldev, /* devo_identify */
96c28749e9Skais nulldev, /* devo_probe */
97c28749e9Skais kssl_attach, /* devo_attach */
98c28749e9Skais kssl_detach, /* devo_detach */
99c28749e9Skais nodev, /* devo_reset */
100c28749e9Skais &cbops, /* devo_cb_ops */
101c28749e9Skais NULL, /* devo_bus_ops */
102c28749e9Skais NULL, /* devo_power */
10319397407SSherry Moore ddi_quiesce_not_needed, /* devo_quiesce */
104c28749e9Skais };
105c28749e9Skais
106c28749e9Skais static struct modldrv modldrv = {
107c28749e9Skais &mod_driverops, /* drv_modops */
10819397407SSherry Moore "Kernel SSL Interface", /* drv_linkinfo */
109c28749e9Skais &devops,
110c28749e9Skais };
111c28749e9Skais
112c28749e9Skais static struct modlinkage modlinkage = {
113c28749e9Skais MODREV_1, /* ml_rev */
114c28749e9Skais &modldrv, /* ml_linkage */
115c28749e9Skais NULL
116c28749e9Skais };
117c28749e9Skais
118c28749e9Skais static dev_info_t *kssl_dip = NULL;
119c28749e9Skais
120c28749e9Skais crypto_mechanism_t rsa_x509_mech = {CRYPTO_MECH_INVALID, NULL, 0};
121c28749e9Skais crypto_mechanism_t hmac_md5_mech = {CRYPTO_MECH_INVALID, NULL, 0};
122c28749e9Skais crypto_mechanism_t hmac_sha1_mech = {CRYPTO_MECH_INVALID, NULL, 0};
123c28749e9Skais crypto_call_flag_t kssl_call_flag = CRYPTO_ALWAYS_QUEUE;
124c28749e9Skais
125c28749e9Skais KSSLCipherDef cipher_defs[] = { /* indexed by SSL3BulkCipher */
126c28749e9Skais /* type bsize keysz crypto_mech_type_t */
127c28749e9Skais
128c28749e9Skais {type_stream, 0, 0, CRYPTO_MECH_INVALID},
129c28749e9Skais
130c28749e9Skais /* mech_type to be initialized with CKM_RC4's */
131c28749e9Skais {type_stream, 0, 16, CRYPTO_MECH_INVALID},
132c28749e9Skais
133c28749e9Skais /* mech_type to be initialized with CKM_DES_CBC's */
134c28749e9Skais {type_block, 8, 8, CRYPTO_MECH_INVALID},
135c28749e9Skais
136c28749e9Skais /* mech_type to be initialized with CKM_DES3_CBC's */
137c28749e9Skais {type_block, 8, 24, CRYPTO_MECH_INVALID},
1382bd70d4bSkrishna
1392bd70d4bSkrishna /* mech_type to be initialized with CKM_AES_CBC with 128-bit key */
1402bd70d4bSkrishna {type_block, 16, 16, CRYPTO_MECH_INVALID},
1412bd70d4bSkrishna
1422bd70d4bSkrishna /* mech_type to be initialized with CKM_AES_CBC with 256-bit key */
1432bd70d4bSkrishna {type_block, 16, 32, CRYPTO_MECH_INVALID},
144c28749e9Skais };
145c28749e9Skais
146c28749e9Skais struct kmem_cache *kssl_cache;
147*dd49f125SAnders Persson static crypto_notify_handle_t prov_update_handle = NULL;
148c28749e9Skais
149c28749e9Skais static void kssl_global_init();
150*dd49f125SAnders Persson static void kssl_global_fini();
151c28749e9Skais static void kssl_init_mechs();
152c28749e9Skais static void kssl_event_callback(uint32_t, void *);
153c28749e9Skais
154c28749e9Skais /*
155c28749e9Skais * DDI entry points.
156c28749e9Skais */
157c28749e9Skais int
_init(void)158c28749e9Skais _init(void)
159c28749e9Skais {
160*dd49f125SAnders Persson int error;
161*dd49f125SAnders Persson
162*dd49f125SAnders Persson kssl_global_init();
163*dd49f125SAnders Persson
164*dd49f125SAnders Persson if ((error = mod_install(&modlinkage)) != 0) {
165*dd49f125SAnders Persson kssl_global_fini();
166*dd49f125SAnders Persson return (error);
167*dd49f125SAnders Persson }
168*dd49f125SAnders Persson return (0);
169*dd49f125SAnders Persson }
170*dd49f125SAnders Persson
171*dd49f125SAnders Persson int
_fini(void)172*dd49f125SAnders Persson _fini(void)
173*dd49f125SAnders Persson {
174*dd49f125SAnders Persson int error;
175*dd49f125SAnders Persson
176*dd49f125SAnders Persson if ((error = mod_remove(&modlinkage)) != 0)
177*dd49f125SAnders Persson return (error);
178*dd49f125SAnders Persson
179*dd49f125SAnders Persson if (prov_update_handle != NULL)
180*dd49f125SAnders Persson crypto_unnotify_events(prov_update_handle);
181*dd49f125SAnders Persson
182*dd49f125SAnders Persson kssl_global_fini();
183*dd49f125SAnders Persson
184*dd49f125SAnders Persson return (0);
185c28749e9Skais }
186c28749e9Skais
187c28749e9Skais int
_info(struct modinfo * modinfop)188c28749e9Skais _info(struct modinfo *modinfop)
189c28749e9Skais {
190c28749e9Skais return (mod_info(&modlinkage, modinfop));
191c28749e9Skais }
192c28749e9Skais
193c28749e9Skais /* ARGSUSED */
194c28749e9Skais static int
kssl_getinfo(dev_info_t * dip,ddi_info_cmd_t cmd,void * arg,void ** result)195c28749e9Skais kssl_getinfo(dev_info_t *dip, ddi_info_cmd_t cmd, void *arg, void **result)
196c28749e9Skais {
197c28749e9Skais switch (cmd) {
198c28749e9Skais case DDI_INFO_DEVT2DEVINFO:
199c28749e9Skais *result = kssl_dip;
200c28749e9Skais return (DDI_SUCCESS);
201c28749e9Skais
202c28749e9Skais case DDI_INFO_DEVT2INSTANCE:
203c28749e9Skais *result = (void *)0;
204c28749e9Skais return (DDI_SUCCESS);
205c28749e9Skais }
206c28749e9Skais return (DDI_FAILURE);
207c28749e9Skais }
208c28749e9Skais
209c28749e9Skais static int
kssl_attach(dev_info_t * dip,ddi_attach_cmd_t cmd)210c28749e9Skais kssl_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
211c28749e9Skais {
212c28749e9Skais if (cmd != DDI_ATTACH) {
213c28749e9Skais return (DDI_FAILURE);
214c28749e9Skais }
215c28749e9Skais
216c28749e9Skais if (ddi_get_instance(dip) != 0) {
217c28749e9Skais /* we only allow instance 0 to attach */
218c28749e9Skais return (DDI_FAILURE);
219c28749e9Skais }
220c28749e9Skais
221c28749e9Skais /* create the minor node */
222c28749e9Skais if (ddi_create_minor_node(dip, "kssl", S_IFCHR, 0, DDI_PSEUDO, 0) !=
223c28749e9Skais DDI_SUCCESS) {
224c28749e9Skais cmn_err(CE_WARN, "kssl_attach: failed creating minor node");
225c28749e9Skais ddi_remove_minor_node(dip, NULL);
226c28749e9Skais return (DDI_FAILURE);
227c28749e9Skais }
228c28749e9Skais
229c28749e9Skais kssl_dip = dip;
230c28749e9Skais
231c28749e9Skais return (DDI_SUCCESS);
232c28749e9Skais }
233c28749e9Skais
2345cd9bd63Skrishna static kstat_t *kssl_ksp = NULL;
2355cd9bd63Skrishna
236c28749e9Skais static int
kssl_detach(dev_info_t * dip,ddi_detach_cmd_t cmd)237c28749e9Skais kssl_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
238c28749e9Skais {
239c28749e9Skais if (cmd != DDI_DETACH)
240c28749e9Skais return (DDI_FAILURE);
241c28749e9Skais
242*dd49f125SAnders Persson if (kssl_entry_tab_nentries != 0)
243c28749e9Skais return (DDI_FAILURE);
244c28749e9Skais
245c28749e9Skais kssl_dip = NULL;
246c28749e9Skais
247c28749e9Skais ddi_remove_minor_node(dip, NULL);
248c28749e9Skais
249c28749e9Skais return (DDI_SUCCESS);
250c28749e9Skais }
251c28749e9Skais
252c28749e9Skais /* ARGSUSED */
253c28749e9Skais static int
kssl_open(dev_t * devp,int flag,int otyp,cred_t * credp)254c28749e9Skais kssl_open(dev_t *devp, int flag, int otyp, cred_t *credp)
255c28749e9Skais {
256c28749e9Skais if (otyp != OTYP_CHR)
257c28749e9Skais return (ENXIO);
258c28749e9Skais
259c28749e9Skais if (kssl_dip == NULL)
260c28749e9Skais return (ENXIO);
261c28749e9Skais
262c28749e9Skais /* first time here? initialize everything */
263c28749e9Skais if (rsa_x509_mech.cm_type == CRYPTO_MECH_INVALID) {
264c28749e9Skais kssl_init_mechs();
265c28749e9Skais prov_update_handle = crypto_notify_events(
266c892ebf1Skrishna kssl_event_callback, CRYPTO_EVENT_MECHS_CHANGED);
267c28749e9Skais }
268c28749e9Skais
269c28749e9Skais /* exclusive opens are not supported */
270c28749e9Skais if (flag & FEXCL)
271c28749e9Skais return (ENOTSUP);
272c28749e9Skais
273c28749e9Skais return (0);
274c28749e9Skais }
275c28749e9Skais
276c28749e9Skais /* ARGSUSED */
277c28749e9Skais static int
kssl_close(dev_t dev,int flag,int otyp,cred_t * credp)278c28749e9Skais kssl_close(dev_t dev, int flag, int otyp, cred_t *credp)
279c28749e9Skais {
280c28749e9Skais return (0);
281c28749e9Skais }
282c28749e9Skais
283c28749e9Skais #define KSSL_MAX_KEYANDCERTS 80000 /* max 64K plus a little margin */
284c28749e9Skais
285c28749e9Skais /* ARGSUSED */
286c28749e9Skais static int
kssl_ioctl(dev_t dev,int cmd,intptr_t arg,int mode,cred_t * c,int * rval)287c28749e9Skais kssl_ioctl(dev_t dev, int cmd, intptr_t arg, int mode, cred_t *c,
288c28749e9Skais int *rval)
289c28749e9Skais {
290c28749e9Skais int error = EINVAL;
291005d3febSMarek Pospisil uint32_t auditing = AU_AUDITING();
292c28749e9Skais
293c28749e9Skais #define ARG ((caddr_t)arg)
294c28749e9Skais
295c28749e9Skais if (secpolicy_net_config(c, B_FALSE) != 0) {
296c28749e9Skais return (EPERM);
297c28749e9Skais }
298c28749e9Skais
299c28749e9Skais switch (cmd) {
300c28749e9Skais case KSSL_ADD_ENTRY: {
301c28749e9Skais uint64_t len;
302c892ebf1Skrishna uint32_t ck_rv;
303c892ebf1Skrishna size_t off;
304c892ebf1Skrishna kssl_params_t *kssl_params;
305c28749e9Skais
306c892ebf1Skrishna off = offsetof(kssl_params_t, kssl_params_size);
307c892ebf1Skrishna if (copyin(ARG + off, &len, sizeof (len)) != 0) {
308c28749e9Skais return (EFAULT);
309c28749e9Skais }
310c28749e9Skais
311c28749e9Skais if (len < sizeof (kssl_params_t) ||
312c28749e9Skais len > KSSL_MAX_KEYANDCERTS) {
313c28749e9Skais return (EINVAL);
314c28749e9Skais }
315c28749e9Skais
316c28749e9Skais kssl_params = kmem_alloc(len, KM_SLEEP);
317c28749e9Skais
318c28749e9Skais /* Get the whole structure and parameters in one move */
319c28749e9Skais if (copyin(ARG, kssl_params, len) != 0) {
320c28749e9Skais kmem_free(kssl_params, len);
321c28749e9Skais return (EFAULT);
322c28749e9Skais }
323c28749e9Skais error = kssl_add_entry(kssl_params);
324005d3febSMarek Pospisil if (auditing)
325c28749e9Skais audit_kssl(KSSL_ADD_ENTRY, kssl_params, error);
326c892ebf1Skrishna off = offsetof(kssl_params_t, kssl_token) +
327c892ebf1Skrishna offsetof(kssl_tokinfo_t, ck_rv);
328c892ebf1Skrishna ck_rv = kssl_params->kssl_token.ck_rv;
329c892ebf1Skrishna if (copyout(&ck_rv, ARG + off, sizeof (ck_rv)) != 0) {
330c892ebf1Skrishna error = EFAULT;
331c892ebf1Skrishna }
332c892ebf1Skrishna
333c892ebf1Skrishna bzero(kssl_params, len);
334c28749e9Skais kmem_free(kssl_params, len);
335c28749e9Skais break;
336c28749e9Skais }
337c28749e9Skais case KSSL_DELETE_ENTRY: {
3382ec7cc7fSKrishna Yenduri struct sockaddr_in6 server_addr;
339c28749e9Skais
340c28749e9Skais if (copyin(ARG, &server_addr, sizeof (server_addr)) != 0) {
341c28749e9Skais return (EFAULT);
342c28749e9Skais }
343c28749e9Skais
344c28749e9Skais error = kssl_delete_entry(&server_addr);
345005d3febSMarek Pospisil if (auditing)
346c28749e9Skais audit_kssl(KSSL_DELETE_ENTRY, &server_addr, error);
347c28749e9Skais break;
348c28749e9Skais }
349c28749e9Skais }
350c28749e9Skais
351c28749e9Skais return (error);
352c28749e9Skais }
353c28749e9Skais
3542bd70d4bSkrishna #define NUM_MECHS 7
3552ec7cc7fSKrishna Yenduri static mech_to_cipher_t mech_to_cipher_tab[NUM_MECHS] = {
356c28749e9Skais {CRYPTO_MECH_INVALID, SUN_CKM_RSA_X_509,
357c28749e9Skais {SSL_RSA_WITH_RC4_128_MD5, SSL_RSA_WITH_RC4_128_SHA,
358c28749e9Skais SSL_RSA_WITH_DES_CBC_SHA, SSL_RSA_WITH_3DES_EDE_CBC_SHA,
3592bd70d4bSkrishna TLS_RSA_WITH_AES_128_CBC_SHA, TLS_RSA_WITH_AES_256_CBC_SHA,
360c28749e9Skais SSL_RSA_WITH_NULL_SHA}},
361c28749e9Skais {CRYPTO_MECH_INVALID, SUN_CKM_MD5_HMAC, {SSL_RSA_WITH_RC4_128_MD5}},
362c28749e9Skais {CRYPTO_MECH_INVALID, SUN_CKM_SHA1_HMAC,
363c28749e9Skais {SSL_RSA_WITH_RC4_128_SHA, SSL_RSA_WITH_DES_CBC_SHA,
3642bd70d4bSkrishna SSL_RSA_WITH_3DES_EDE_CBC_SHA, SSL_RSA_WITH_NULL_SHA,
3652bd70d4bSkrishna TLS_RSA_WITH_AES_128_CBC_SHA, TLS_RSA_WITH_AES_256_CBC_SHA}},
366c28749e9Skais {CRYPTO_MECH_INVALID, SUN_CKM_RC4,
367c28749e9Skais {SSL_RSA_WITH_RC4_128_MD5, SSL_RSA_WITH_RC4_128_SHA}},
368c28749e9Skais {CRYPTO_MECH_INVALID, SUN_CKM_DES_CBC, {SSL_RSA_WITH_DES_CBC_SHA}},
369c28749e9Skais {CRYPTO_MECH_INVALID, SUN_CKM_DES3_CBC,
3702bd70d4bSkrishna {SSL_RSA_WITH_3DES_EDE_CBC_SHA}},
3712bd70d4bSkrishna {CRYPTO_MECH_INVALID, SUN_CKM_AES_CBC,
3722bd70d4bSkrishna {TLS_RSA_WITH_AES_128_CBC_SHA, TLS_RSA_WITH_AES_256_CBC_SHA}},
373c28749e9Skais };
374c28749e9Skais
375c28749e9Skais static void
kssl_init_mechs()376c28749e9Skais kssl_init_mechs()
377c28749e9Skais {
378c28749e9Skais mech_to_cipher_tab[0].mech = rsa_x509_mech.cm_type =
379c28749e9Skais crypto_mech2id(SUN_CKM_RSA_X_509);
380c28749e9Skais mech_to_cipher_tab[1].mech = hmac_md5_mech.cm_type =
381c28749e9Skais crypto_mech2id(SUN_CKM_MD5_HMAC);
382c28749e9Skais mech_to_cipher_tab[2].mech = hmac_sha1_mech.cm_type =
383c28749e9Skais crypto_mech2id(SUN_CKM_SHA1_HMAC);
384c28749e9Skais
385c28749e9Skais mech_to_cipher_tab[3].mech = cipher_defs[cipher_rc4].mech_type =
386c28749e9Skais crypto_mech2id(SUN_CKM_RC4);
387c28749e9Skais mech_to_cipher_tab[4].mech = cipher_defs[cipher_des].mech_type =
388c28749e9Skais crypto_mech2id(SUN_CKM_DES_CBC);
389c28749e9Skais mech_to_cipher_tab[5].mech = cipher_defs[cipher_3des].mech_type =
390c28749e9Skais crypto_mech2id(SUN_CKM_DES3_CBC);
3912bd70d4bSkrishna mech_to_cipher_tab[6].mech = cipher_defs[cipher_aes128].mech_type =
3922bd70d4bSkrishna cipher_defs[cipher_aes256].mech_type =
3932bd70d4bSkrishna crypto_mech2id(SUN_CKM_AES_CBC);
394c28749e9Skais }
395c28749e9Skais
396c28749e9Skais static int
is_in_suites(uint16_t s,uint16_t * sarray)397c28749e9Skais is_in_suites(uint16_t s, uint16_t *sarray)
398c28749e9Skais {
399c28749e9Skais int i;
400c28749e9Skais
401c28749e9Skais for (i = 0; i < CIPHER_SUITE_COUNT; i++) {
402c28749e9Skais if (s == sarray[i])
403c28749e9Skais return (1);
404c28749e9Skais }
405c28749e9Skais
406c28749e9Skais return (0);
407c28749e9Skais }
408c28749e9Skais
409c28749e9Skais static int
is_in_mechlist(char * name,crypto_mech_name_t * mechs,int count)410c28749e9Skais is_in_mechlist(char *name, crypto_mech_name_t *mechs, int count)
411c28749e9Skais {
412c28749e9Skais int i;
413c28749e9Skais
414c28749e9Skais for (i = 0; i < count; i++) {
415c28749e9Skais if (strncmp(name, mechs[i], CRYPTO_MAX_MECH_NAME) == 0)
416c28749e9Skais return (1);
417c28749e9Skais }
418c28749e9Skais
419c28749e9Skais return (0);
420c28749e9Skais }
421c28749e9Skais
422c28749e9Skais /*
423c28749e9Skais * Callback function invoked by the crypto framework when a provider's
424c28749e9Skais * mechanism is available/unavailable. This callback updates entries in the
425c28749e9Skais * kssl_entry_tab[] to make changes to the cipher suites of an entry
4262ec7cc7fSKrishna Yenduri * which are affected by the mechanism.
427c28749e9Skais */
428c28749e9Skais static void
kssl_event_callback(uint32_t event,void * event_arg)429c28749e9Skais kssl_event_callback(uint32_t event, void *event_arg)
430c28749e9Skais {
431c28749e9Skais int i, j;
432c28749e9Skais int cnt, rcnt;
433c28749e9Skais uint16_t s;
434c28749e9Skais boolean_t changed;
435c28749e9Skais crypto_mech_name_t *mechs;
436c28749e9Skais uint_t mech_count;
437c28749e9Skais mech_to_cipher_t *mc;
438c28749e9Skais kssl_entry_t *old;
439c28749e9Skais kssl_entry_t *new;
440c28749e9Skais uint16_t tmp_suites[CIPHER_SUITE_COUNT];
441c28749e9Skais uint16_t dis_list[CIPHER_SUITE_COUNT];
442c28749e9Skais crypto_notify_event_change_t *prov_change =
443c28749e9Skais (crypto_notify_event_change_t *)event_arg;
444c28749e9Skais
445c28749e9Skais /* ignore events for which we didn't register */
446c892ebf1Skrishna if (event != CRYPTO_EVENT_MECHS_CHANGED) {
447c28749e9Skais return;
448c28749e9Skais }
449c28749e9Skais
450c28749e9Skais for (i = 0; i < NUM_MECHS; i++) {
451c28749e9Skais mc = &(mech_to_cipher_tab[i]);
452c28749e9Skais if (mc->mech == CRYPTO_MECH_INVALID)
453c28749e9Skais continue;
454c28749e9Skais
455c28749e9Skais /*
456c28749e9Skais * Check if this crypto framework provider mechanism being
457c28749e9Skais * added or removed affects us.
458c28749e9Skais */
459c28749e9Skais if (strncmp(mc->name, prov_change->ec_mech_name,
460c28749e9Skais CRYPTO_MAX_MECH_NAME) == 0)
461c28749e9Skais break;
462c28749e9Skais }
463c28749e9Skais
464c28749e9Skais if (i == NUM_MECHS)
465c28749e9Skais return;
466c28749e9Skais
467c28749e9Skais mechs = crypto_get_mech_list(&mech_count, KM_SLEEP);
468c28749e9Skais if (mechs == NULL)
469c28749e9Skais return;
470c28749e9Skais
471c28749e9Skais mutex_enter(&kssl_tab_mutex);
472c28749e9Skais
473c28749e9Skais for (i = 0; i < kssl_entry_tab_size; i++) {
474c28749e9Skais if ((old = kssl_entry_tab[i]) == NULL)
475c28749e9Skais continue;
476c28749e9Skais
477c28749e9Skais cnt = 0;
478c28749e9Skais rcnt = 0;
479c28749e9Skais changed = B_FALSE;
480c28749e9Skais for (j = 0; j < CIPHER_SUITE_COUNT; j++) {
481c28749e9Skais tmp_suites[j] = CIPHER_NOTSET;
482c28749e9Skais dis_list[j] = CIPHER_NOTSET;
483c28749e9Skais }
484c28749e9Skais
485c28749e9Skais /*
486c28749e9Skais * We start with the saved cipher suite list for the new entry.
487c28749e9Skais * If a mechanism is disabled, resulting in a cipher suite being
488c28749e9Skais * disabled now, we take it out from the list for the new entry.
489c28749e9Skais * If a mechanism is enabled, resulting in a cipher suite being
490c28749e9Skais * enabled now, we don't need to do any thing.
491c28749e9Skais */
492c28749e9Skais if (!is_in_mechlist(mc->name, mechs, mech_count)) {
493c28749e9Skais for (j = 0; j < CIPHER_SUITE_COUNT; j++) {
494c28749e9Skais s = mc->kssl_suites[j];
495c28749e9Skais if (s == 0)
496c28749e9Skais break;
497c28749e9Skais if (is_in_suites(s, old->kssl_saved_Suites)) {
498c28749e9Skais /* Disable this cipher suite */
499c28749e9Skais if (!is_in_suites(s, dis_list))
500c28749e9Skais dis_list[cnt++] = s;
501c28749e9Skais }
502c28749e9Skais }
503c28749e9Skais }
504c28749e9Skais
505c28749e9Skais for (j = 0; j < CIPHER_SUITE_COUNT; j++) {
506c28749e9Skais s = old->kssl_saved_Suites[j];
507c28749e9Skais if (!is_in_suites(s, dis_list))
508c28749e9Skais tmp_suites[rcnt] = s;
509c28749e9Skais
510c28749e9Skais if (!changed &&
511c28749e9Skais (tmp_suites[rcnt] != old->kssl_cipherSuites[rcnt]))
512c28749e9Skais changed = B_TRUE;
513c28749e9Skais rcnt++;
514c28749e9Skais }
515c28749e9Skais
516c28749e9Skais if (changed) {
517c28749e9Skais new = kmem_zalloc(sizeof (kssl_entry_t), KM_NOSLEEP);
518c28749e9Skais if (new == NULL)
519c28749e9Skais continue;
520c28749e9Skais
521c28749e9Skais *new = *old; /* Structure copy */
522c28749e9Skais old->ke_no_freeall = B_TRUE;
523c28749e9Skais new->ke_refcnt = 0;
524c28749e9Skais new->kssl_cipherSuites_nentries = rcnt;
525c28749e9Skais for (j = 0; j < CIPHER_SUITE_COUNT; j++)
526c28749e9Skais new->kssl_cipherSuites[j] = tmp_suites[j];
527c28749e9Skais
528c28749e9Skais KSSL_ENTRY_REFHOLD(new);
529c28749e9Skais kssl_entry_tab[i] = new;
530c28749e9Skais KSSL_ENTRY_REFRELE(old);
531c28749e9Skais }
532c28749e9Skais }
533c28749e9Skais
534c28749e9Skais mutex_exit(&kssl_tab_mutex);
535c28749e9Skais crypto_free_mech_list(mechs, mech_count);
536c28749e9Skais }
537c28749e9Skais
538c28749e9Skais
539c28749e9Skais kssl_stats_t *kssl_statp;
540c28749e9Skais
541c28749e9Skais static void
kssl_global_init()542c28749e9Skais kssl_global_init()
543c28749e9Skais {
544c28749e9Skais mutex_init(&kssl_tab_mutex, NULL, MUTEX_DRIVER, NULL);
545c28749e9Skais
546c28749e9Skais kssl_cache = kmem_cache_create("kssl_cache", sizeof (ssl_t),
547c28749e9Skais 0, kssl_constructor, kssl_destructor, NULL, NULL, NULL, 0);
548c28749e9Skais
5495cd9bd63Skrishna if ((kssl_ksp = kstat_create("kssl", 0, "kssl_stats", "crypto",
550c28749e9Skais KSTAT_TYPE_NAMED, sizeof (kssl_stats_t) / sizeof (kstat_named_t),
551c28749e9Skais KSTAT_FLAG_PERSISTENT)) != NULL) {
5525cd9bd63Skrishna kssl_statp = kssl_ksp->ks_data;
553c28749e9Skais
554c28749e9Skais kstat_named_init(&kssl_statp->sid_cache_lookups,
555c28749e9Skais "kssl_sid_cache_lookups", KSTAT_DATA_UINT64);
556c28749e9Skais kstat_named_init(&kssl_statp->sid_cache_hits,
557c28749e9Skais "kssl_sid_cache_hits", KSTAT_DATA_UINT64);
5582ec7cc7fSKrishna Yenduri kstat_named_init(&kssl_statp->sid_cached,
5592ec7cc7fSKrishna Yenduri "kssl_sid_cached", KSTAT_DATA_UINT64);
560c28749e9Skais kstat_named_init(&kssl_statp->sid_uncached,
561c28749e9Skais "kssl_sid_uncached", KSTAT_DATA_UINT64);
562c28749e9Skais
563c28749e9Skais kstat_named_init(&kssl_statp->full_handshakes,
564c28749e9Skais "kssl_full_handshakes", KSTAT_DATA_UINT64);
565c28749e9Skais kstat_named_init(&kssl_statp->resumed_sessions,
566c28749e9Skais "kssl_resumed_sessions", KSTAT_DATA_UINT64);
567c28749e9Skais kstat_named_init(&kssl_statp->fallback_connections,
568c28749e9Skais "kssl_fallback_connections", KSTAT_DATA_UINT64);
569c28749e9Skais kstat_named_init(&kssl_statp->proxy_fallback_failed,
570c28749e9Skais "kssl_proxy_fallback_failed", KSTAT_DATA_UINT64);
571c28749e9Skais kstat_named_init(&kssl_statp->appdata_record_ins,
572c28749e9Skais "kssl_appdata_record_ins", KSTAT_DATA_UINT64);
573c28749e9Skais kstat_named_init(&kssl_statp->appdata_record_outs,
574c28749e9Skais "kssl_appdata_record_outs", KSTAT_DATA_UINT64);
575c28749e9Skais
576c28749e9Skais kstat_named_init(&kssl_statp->alloc_fails, "kssl_alloc_fails",
577c28749e9Skais KSTAT_DATA_UINT64);
578c28749e9Skais kstat_named_init(&kssl_statp->fatal_alerts,
579c28749e9Skais "kssl_fatal_alerts", KSTAT_DATA_UINT64);
580c28749e9Skais kstat_named_init(&kssl_statp->warning_alerts,
581c28749e9Skais "kssl_warning_alerts", KSTAT_DATA_UINT64);
582c28749e9Skais kstat_named_init(&kssl_statp->no_suite_found,
583c28749e9Skais "kssl_no_suite_found", KSTAT_DATA_UINT64);
584c28749e9Skais kstat_named_init(&kssl_statp->compute_mac_failure,
585c28749e9Skais "kssl_compute_mac_failure", KSTAT_DATA_UINT64);
586c28749e9Skais kstat_named_init(&kssl_statp->verify_mac_failure,
587c28749e9Skais "kssl_verify_mac_failure", KSTAT_DATA_UINT64);
588c28749e9Skais kstat_named_init(&kssl_statp->record_decrypt_failure,
589c28749e9Skais "kssl_record_decrypt_failure", KSTAT_DATA_UINT64);
590c28749e9Skais kstat_named_init(&kssl_statp->bad_pre_master_secret,
591c28749e9Skais "kssl_bad_pre_master_secret", KSTAT_DATA_UINT64);
59284706141Svk199839 kstat_named_init(&kssl_statp->internal_errors,
59384706141Svk199839 "kssl_internal_errors", KSTAT_DATA_UINT64);
594c28749e9Skais
5955cd9bd63Skrishna kstat_install(kssl_ksp);
596c28749e9Skais };
597c28749e9Skais }
598c28749e9Skais
599*dd49f125SAnders Persson static void
kssl_global_fini(void)600*dd49f125SAnders Persson kssl_global_fini(void)
601*dd49f125SAnders Persson {
602*dd49f125SAnders Persson mutex_destroy(&kssl_tab_mutex);
603*dd49f125SAnders Persson
604*dd49f125SAnders Persson if (kssl_cache != NULL) {
605*dd49f125SAnders Persson kmem_cache_destroy(kssl_cache);
606*dd49f125SAnders Persson kssl_cache = NULL;
607*dd49f125SAnders Persson }
608*dd49f125SAnders Persson
609*dd49f125SAnders Persson if (kssl_ksp != NULL) {
610*dd49f125SAnders Persson kstat_delete(kssl_ksp);
611*dd49f125SAnders Persson kssl_ksp = NULL;
612*dd49f125SAnders Persson }
613*dd49f125SAnders Persson }
614*dd49f125SAnders Persson
615c28749e9Skais /*ARGSUSED*/
616c28749e9Skais static int
kssl_constructor(void * buf,void * arg,int kmflags)617c28749e9Skais kssl_constructor(void *buf, void *arg, int kmflags)
618c28749e9Skais {
619c28749e9Skais ssl_t *ssl = buf;
620c28749e9Skais
621c28749e9Skais mutex_init(&ssl->kssl_lock, NULL, MUTEX_DEFAULT, NULL);
622*dd49f125SAnders Persson cv_init(&ssl->async_cv, NULL, CV_DEFAULT, NULL);
623c28749e9Skais
624c28749e9Skais return (0);
625c28749e9Skais }
626c28749e9Skais
627c28749e9Skais /*ARGSUSED*/
628c28749e9Skais static void
kssl_destructor(void * buf,void * arg)629c28749e9Skais kssl_destructor(void *buf, void *arg)
630c28749e9Skais {
631c28749e9Skais ssl_t *ssl = buf;
632c28749e9Skais mutex_destroy(&ssl->kssl_lock);
633*dd49f125SAnders Persson cv_destroy(&ssl->async_cv);
634c28749e9Skais }
635c892ebf1Skrishna
636c892ebf1Skrishna /*
637c892ebf1Skrishna * Handler routine called by the crypto framework when a
638c892ebf1Skrishna * provider is unregistered or registered. We invalidate the
639c892ebf1Skrishna * private key handle if our provider is unregistered. We set
640c892ebf1Skrishna * a flag to reauthenticate if our provider came back.
641c892ebf1Skrishna */
642c892ebf1Skrishna void
kssl_prov_evnt(uint32_t event,void * event_arg)643c892ebf1Skrishna kssl_prov_evnt(uint32_t event, void *event_arg)
644c892ebf1Skrishna {
645c892ebf1Skrishna int i, rv;
646c892ebf1Skrishna kssl_entry_t *ep;
647c892ebf1Skrishna kssl_session_info_t *s;
648c892ebf1Skrishna crypto_provider_t prov;
649c892ebf1Skrishna crypto_provider_ext_info_t info;
650c892ebf1Skrishna
651c892ebf1Skrishna if (event != CRYPTO_EVENT_PROVIDER_UNREGISTERED &&
652c892ebf1Skrishna event != CRYPTO_EVENT_PROVIDER_REGISTERED)
653c892ebf1Skrishna return;
654c892ebf1Skrishna
655c892ebf1Skrishna prov = (crypto_provider_t)event_arg;
656c892ebf1Skrishna if (event == CRYPTO_EVENT_PROVIDER_REGISTERED) {
657c892ebf1Skrishna rv = crypto_get_provinfo(prov, &info);
658c892ebf1Skrishna if (rv != CRYPTO_SUCCESS)
659c892ebf1Skrishna return;
660c892ebf1Skrishna }
661c892ebf1Skrishna
662c892ebf1Skrishna mutex_enter(&kssl_tab_mutex);
663c892ebf1Skrishna
664c892ebf1Skrishna for (i = 0; i < kssl_entry_tab_size; i++) {
665c892ebf1Skrishna if ((ep = kssl_entry_tab[i]) == NULL)
666c892ebf1Skrishna continue;
667c892ebf1Skrishna
668c892ebf1Skrishna s = ep->ke_sessinfo;
66951dd2c77Svk199839 DTRACE_PROBE1(kssl_entry_cycle, kssl_entry_t *, ep);
670c892ebf1Skrishna switch (event) {
671c892ebf1Skrishna case CRYPTO_EVENT_PROVIDER_UNREGISTERED:
672c892ebf1Skrishna if (s->is_valid_handle && s->prov == prov) {
673c892ebf1Skrishna s->is_valid_handle = B_FALSE;
674c892ebf1Skrishna crypto_release_provider(s->prov);
675c892ebf1Skrishna }
676c892ebf1Skrishna break;
677c892ebf1Skrishna
678c892ebf1Skrishna case CRYPTO_EVENT_PROVIDER_REGISTERED:
679c892ebf1Skrishna if (s->is_valid_handle)
680c892ebf1Skrishna break;
681c892ebf1Skrishna if (bcmp(s->toklabel, info.ei_label,
682c892ebf1Skrishna CRYPTO_EXT_SIZE_LABEL) == 0) {
683c892ebf1Skrishna s->do_reauth = B_TRUE;
684c892ebf1Skrishna }
685c892ebf1Skrishna break;
686c892ebf1Skrishna }
687c892ebf1Skrishna }
688c892ebf1Skrishna
689c892ebf1Skrishna mutex_exit(&kssl_tab_mutex);
690c892ebf1Skrishna }
691