4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
22 * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
25 * Copyright 2010 Nexenta Systems, Inc. All rights reserved.
35 #include <sys/types.h>
36 #include <sys/varargs.h>
38 #include <sys/crypto/ioctladmin.h>
39 #include "cryptoadm.h"
41 #define DEFAULT_DEV_NUM 5
42 #define DEFAULT_SOFT_NUM 10
44 static crypto_get_soft_info_t
*setup_get_soft_info(char *, int);
47 * Prepare the argument for the LOAD_SOFT_CONFIG ioctl call for the
48 * provider pointed by pent. Return NULL if out of memory.
50 crypto_load_soft_config_t
*
51 setup_soft_conf(entry_t
*pent
)
53 crypto_load_soft_config_t
*pload_soft_conf
;
56 size_t extra_mech_size
= 0;
63 sup_count
= pent
->sup_count
;
65 extra_mech_size
= sizeof (crypto_mech_name_t
) *
69 pload_soft_conf
= malloc(sizeof (crypto_load_soft_config_t
) +
71 if (pload_soft_conf
== NULL
) {
72 cryptodebug("out of memory.");
76 (void) strlcpy(pload_soft_conf
->sc_name
, pent
->name
, MAXNAMELEN
);
77 pload_soft_conf
->sc_count
= sup_count
;
80 plist
= pent
->suplist
;
81 while (i
< sup_count
) {
82 (void) strlcpy(pload_soft_conf
->sc_list
[i
++],
83 plist
->name
, CRYPTO_MAX_MECH_NAME
);
87 return (pload_soft_conf
);
92 * Prepare the argument for the LOAD_SOFT_DISABLED ioctl call for the
93 * provider pointed by pent. Return NULL if out of memory.
95 crypto_load_soft_disabled_t
*
96 setup_soft_dis(entry_t
*pent
)
98 crypto_load_soft_disabled_t
*pload_soft_dis
= NULL
;
99 mechlist_t
*plist
= NULL
;
100 size_t extra_mech_size
= 0;
108 dis_count
= pent
->dis_count
;
110 extra_mech_size
= sizeof (crypto_mech_name_t
) *
114 pload_soft_dis
= malloc(sizeof (crypto_load_soft_disabled_t
) +
116 if (pload_soft_dis
== NULL
) {
117 cryptodebug("out of memory.");
121 (void) strlcpy(pload_soft_dis
->sd_name
, pent
->name
, MAXNAMELEN
);
122 pload_soft_dis
->sd_count
= dis_count
;
125 plist
= pent
->dislist
;
126 while (i
< dis_count
) {
127 (void) strlcpy(pload_soft_dis
->sd_list
[i
++],
128 plist
->name
, CRYPTO_MAX_MECH_NAME
);
132 return (pload_soft_dis
);
137 * Prepare the argument for the LOAD_DEV_DISABLED ioctl call for the
138 * provider pointed by pent. Return NULL if out of memory.
140 crypto_load_dev_disabled_t
*
141 setup_dev_dis(entry_t
*pent
)
143 crypto_load_dev_disabled_t
*pload_dev_dis
= NULL
;
144 mechlist_t
*plist
= NULL
;
145 size_t extra_mech_size
= 0;
148 char pname
[MAXNAMELEN
];
155 /* get the device name and the instance number */
156 if (split_hw_provname(pent
->name
, pname
, &inst_num
) == FAILURE
) {
160 /* allocate space for pload_dev_des */
161 dis_count
= pent
->dis_count
;
163 extra_mech_size
= sizeof (crypto_mech_name_t
) *
167 pload_dev_dis
= malloc(sizeof (crypto_load_dev_disabled_t
) +
169 if (pload_dev_dis
== NULL
) {
170 cryptodebug("out of memory.");
174 /* set the values for pload_dev_dis */
175 (void) strlcpy(pload_dev_dis
->dd_dev_name
, pname
, MAXNAMELEN
);
176 pload_dev_dis
->dd_dev_instance
= inst_num
;
177 pload_dev_dis
->dd_count
= dis_count
;
180 plist
= pent
->dislist
;
181 while (i
< dis_count
) {
182 (void) strlcpy(pload_dev_dis
->dd_list
[i
++],
183 plist
->name
, CRYPTO_MAX_MECH_NAME
);
187 return (pload_dev_dis
);
192 * Prepare the calling argument of the UNLOAD_SOFT_MODULE ioctl call for the
193 * provider pointed by pent. Return NULL if out of memory.
195 crypto_unload_soft_module_t
*
196 setup_unload_soft(entry_t
*pent
)
198 crypto_unload_soft_module_t
*punload_soft
;
204 punload_soft
= malloc(sizeof (crypto_unload_soft_module_t
));
205 if (punload_soft
== NULL
) {
206 cryptodebug("out of memory.");
210 (void) strlcpy(punload_soft
->sm_name
, pent
->name
, MAXNAMELEN
);
212 return (punload_soft
);
217 * Prepare the calling argument for the GET_SOFT_INFO call for the provider
218 * with the number of mechanisms specified in the second argument.
220 * Called by get_soft_info().
222 static crypto_get_soft_info_t
*
223 setup_get_soft_info(char *provname
, int count
)
225 crypto_get_soft_info_t
*psoft_info
;
226 size_t extra_mech_size
= 0;
228 if (provname
== NULL
) {
233 extra_mech_size
= sizeof (crypto_mech_name_t
) * (count
- 1);
236 psoft_info
= malloc(sizeof (crypto_get_soft_info_t
) + extra_mech_size
);
237 if (psoft_info
== NULL
) {
238 cryptodebug("out of memory.");
242 (void) strlcpy(psoft_info
->si_name
, provname
, MAXNAMELEN
);
243 psoft_info
->si_count
= count
;
250 * Get the device list from kernel.
253 get_dev_list(crypto_get_dev_list_t
**ppdevlist
)
255 crypto_get_dev_list_t
*pdevlist
;
257 int count
= DEFAULT_DEV_NUM
;
259 pdevlist
= malloc(sizeof (crypto_get_dev_list_t
) +
260 sizeof (crypto_dev_list_entry_t
) * (count
- 1));
261 if (pdevlist
== NULL
) {
262 cryptodebug("out of memory.");
266 if ((fd
= open(ADMIN_IOCTL_DEVICE
, O_RDONLY
)) == -1) {
267 cryptoerror(LOG_STDERR
, gettext("failed to open %s: %s"),
268 ADMIN_IOCTL_DEVICE
, strerror(errno
));
272 pdevlist
->dl_dev_count
= count
;
273 if (ioctl(fd
, CRYPTO_GET_DEV_LIST
, pdevlist
) == -1) {
274 cryptodebug("CRYPTO_GET_DEV_LIST ioctl failed: %s",
281 /* BUFFER is too small, get the number of devices and retry it. */
282 if (pdevlist
->dl_return_value
== CRYPTO_BUFFER_TOO_SMALL
) {
283 count
= pdevlist
->dl_dev_count
;
285 pdevlist
= malloc(sizeof (crypto_get_dev_list_t
) +
286 sizeof (crypto_dev_list_entry_t
) * (count
- 1));
287 if (pdevlist
== NULL
) {
288 cryptodebug("out of memory.");
293 if (ioctl(fd
, CRYPTO_GET_DEV_LIST
, pdevlist
) == -1) {
294 cryptodebug("CRYPTO_GET_DEV_LIST ioctl failed: %s",
302 if (pdevlist
->dl_return_value
!= CRYPTO_SUCCESS
) {
303 cryptodebug("CRYPTO_GET_DEV_LIST ioctl failed, "
304 "return_value = %d", pdevlist
->dl_return_value
);
310 *ppdevlist
= pdevlist
;
317 * Get all the mechanisms supported by the hardware provider.
318 * The result will be stored in the second argument.
321 get_dev_info(char *devname
, int inst_num
, int count
, mechlist_t
**ppmechlist
)
323 crypto_get_dev_info_t
*dev_info
;
331 if (devname
== NULL
|| count
< 1) {
332 cryptodebug("get_dev_info(): devname is NULL or bogus count");
336 /* Set up the argument for the CRYPTO_GET_DEV_INFO ioctl call */
337 dev_info
= malloc(sizeof (crypto_get_dev_info_t
) +
338 sizeof (crypto_mech_name_t
) * (count
- 1));
339 if (dev_info
== NULL
) {
340 cryptodebug("out of memory.");
343 (void) strlcpy(dev_info
->di_dev_name
, devname
, MAXNAMELEN
);
344 dev_info
->di_dev_instance
= inst_num
;
345 dev_info
->di_count
= count
;
347 /* Open the ioctl device */
348 if ((fd
= open(ADMIN_IOCTL_DEVICE
, O_RDONLY
)) == -1) {
349 cryptoerror(LOG_STDERR
, gettext("failed to open %s: %s"),
350 ADMIN_IOCTL_DEVICE
, strerror(errno
));
355 if (ioctl(fd
, CRYPTO_GET_DEV_INFO
, dev_info
) == -1) {
356 cryptodebug("CRYPTO_GET_DEV_INFO ioctl failed: %s",
363 if (dev_info
->di_return_value
!= CRYPTO_SUCCESS
) {
364 cryptodebug("CRYPTO_GET_DEV_INFO ioctl failed, "
365 "return_value = %d", dev_info
->di_return_value
);
373 for (i
= 0; i
< dev_info
->di_count
; i
++) {
374 pmech
= create_mech(&dev_info
->di_list
[i
][0]);
380 phead
= pcur
= pmech
;
391 free_mechlist(phead
);
401 * Get the supported mechanism list of the software provider from kernel.
403 * Parameters phardlist and psoftlist are supplied by get_kcfconf_info().
404 * If NULL, this function calls get_kcfconf_info() internally.
407 get_soft_info(char *provname
, mechlist_t
**ppmechlist
,
408 entrylist_t
*phardlist
, entrylist_t
*psoftlist
)
410 boolean_t in_kernel
= B_FALSE
;
411 crypto_get_soft_info_t
*psoft_info
;
415 entry_t
*pent
= NULL
;
421 if (provname
== NULL
) {
425 if (getzoneid() == GLOBAL_ZONEID
) {
426 /* use kcf.conf for kernel software providers in global zone */
427 if ((pent
= getent_kef(provname
, phardlist
, psoftlist
)) ==
430 /* No kcf.conf entry for this provider */
431 if (check_kernel_for_soft(provname
, NULL
, &in_kernel
)
434 } else if (in_kernel
== B_FALSE
) {
435 cryptoerror(LOG_STDERR
,
436 gettext("%s does not exist."), provname
);
441 * Set mech count to 1. It will be reset to the
442 * correct value later if the setup buffer is too small.
446 count
= pent
->sup_count
;
451 * kcf.conf not there in non-global zone: set mech count to 1.
452 * It will be reset to the correct value later if the setup
453 * buffer is too small.
458 if ((psoft_info
= setup_get_soft_info(provname
, count
)) == NULL
) {
462 if ((fd
= open(ADMIN_IOCTL_DEVICE
, O_RDONLY
)) == -1) {
463 cryptoerror(LOG_STDERR
, gettext("failed to open %s: %s"),
464 ADMIN_IOCTL_DEVICE
, strerror(errno
));
469 /* make GET_SOFT_INFO ioctl call */
470 if ((rc
= ioctl(fd
, CRYPTO_GET_SOFT_INFO
, psoft_info
)) == -1) {
471 cryptodebug("CRYPTO_GET_SOFT_INFO ioctl failed: %s",
478 /* BUFFER is too small, get the number of mechanisms and retry it. */
479 if (psoft_info
->si_return_value
== CRYPTO_BUFFER_TOO_SMALL
) {
480 count
= psoft_info
->si_count
;
482 if ((psoft_info
= setup_get_soft_info(provname
, count
))
487 rc
= ioctl(fd
, CRYPTO_GET_SOFT_INFO
, psoft_info
);
489 cryptodebug("CRYPTO_GET_SOFT_INFO ioctl "
490 "failed: %s", strerror(errno
));
499 if (psoft_info
->si_return_value
!= CRYPTO_SUCCESS
) {
500 cryptodebug("CRYPTO_GET_SOFT_INFO ioctl failed, "
501 "return_value = %d", psoft_info
->si_return_value
);
507 /* Build the mechanism linked list and return it */
510 for (i
= 0; i
< psoft_info
->si_count
; i
++) {
511 pmech
= create_mech(&psoft_info
->si_list
[i
][0]);
517 phead
= pcur
= pmech
;
526 free_mechlist(phead
);
537 * Get the kernel software provider list from kernel.
540 get_soft_list(crypto_get_soft_list_t
**ppsoftlist
)
542 crypto_get_soft_list_t
*psoftlist
= NULL
;
543 int count
= DEFAULT_SOFT_NUM
;
547 if ((fd
= open(ADMIN_IOCTL_DEVICE
, O_RDONLY
)) == -1) {
548 cryptoerror(LOG_STDERR
, gettext("failed to open %s: %s"),
549 ADMIN_IOCTL_DEVICE
, strerror(errno
));
553 len
= MAXNAMELEN
* count
;
554 psoftlist
= malloc(sizeof (crypto_get_soft_list_t
) + len
);
555 if (psoftlist
== NULL
) {
556 cryptodebug("out of memory.");
560 psoftlist
->sl_soft_names
= (caddr_t
)(psoftlist
+ 1);
561 psoftlist
->sl_soft_count
= count
;
562 psoftlist
->sl_soft_len
= len
;
564 if (ioctl(fd
, CRYPTO_GET_SOFT_LIST
, psoftlist
) == -1) {
565 cryptodebug("CRYPTO_GET_SOFT_LIST ioctl failed: %s",
573 * if BUFFER is too small, get the number of software providers and
574 * the minimum length needed for names and length and retry it.
576 if (psoftlist
->sl_return_value
== CRYPTO_BUFFER_TOO_SMALL
) {
577 count
= psoftlist
->sl_soft_count
;
578 len
= psoftlist
->sl_soft_len
;
580 psoftlist
= malloc(sizeof (crypto_get_soft_list_t
) + len
);
581 if (psoftlist
== NULL
) {
582 cryptodebug("out of memory.");
586 psoftlist
->sl_soft_names
= (caddr_t
)(psoftlist
+ 1);
587 psoftlist
->sl_soft_count
= count
;
588 psoftlist
->sl_soft_len
= len
;
590 if (ioctl(fd
, CRYPTO_GET_SOFT_LIST
, psoftlist
) == -1) {
591 cryptodebug("CRYPTO_GET_SOFT_LIST ioctl failed:"
592 "%s", strerror(errno
));
599 if (psoftlist
->sl_return_value
!= CRYPTO_SUCCESS
) {
600 cryptodebug("CRYPTO_GET_SOFT_LIST ioctl failed, "
601 "return_value = %d", psoftlist
->sl_return_value
);
607 *ppsoftlist
= psoftlist
;