# # CDDL HEADER START # # The contents of this file are subject to the terms of the # Common Development and Distribution License (the "License"). # You may not use this file except in compliance with the License. # # You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE # or http://www.opensolaris.org/os/licensing. # See the License for the specific language governing permissions # and limitations under the License. # # When distributing Covered Code, include this CDDL HEADER in each # file and include the License file at usr/src/OPENSOLARIS.LICENSE. # If applicable, add the following below this CDDL HEADER, with the # fields enclosed by brackets "[]" replaced with your own identifying # information: Portions Copyright [yyyy] [name of copyright owner] # # CDDL HEADER END # # # Copyright 2006 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # include $(SRC)/lib/Makefile.lib HDRS= cryptoutil.h HDRDIR= common # Hammerhead: amd64-only SUBDIRS = $(MACH64) all : TARGET= all clean : TARGET= clean clobber : TARGET= clobber install : TARGET= install .KEEP_STATE: all clean clobber install: $(SUBDIRS) install_h: $(ROOTHDRS) check: $(CHECKHDRS) $(SUBDIRS): FRC @cd $@; pwd; $(MAKE) $(TARGET) FRC: include $(SRC)/lib/Makefile.targ # # CDDL HEADER START # # The contents of this file are subject to the terms of the # Common Development and Distribution License (the "License"). # You may not use this file except in compliance with the License. # # You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE # or http://www.opensolaris.org/os/licensing. # See the License for the specific language governing permissions # and limitations under the License. # # When distributing Covered Code, include this CDDL HEADER in each # file and include the License file at usr/src/OPENSOLARIS.LICENSE. # If applicable, add the following below this CDDL HEADER, with the # fields enclosed by brackets "[]" replaced with your own identifying # information: Portions Copyright [yyyy] [name of copyright owner] # # CDDL HEADER END # # Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved. # # Copyright (c) 2018, Joyent, Inc. LIBRARY= libcryptoutil.a VERS= .1 OBJECTS= \ debug.o \ mechstr.o \ config_parsing.o \ tohexstr.o \ mechkeygen.o \ mechkeytype.o \ pkcserror.o \ passutils.o \ random.o \ keyfile.o \ util.o \ pkcs11_uri.o include $(SRC)/lib/Makefile.lib include $(SRC)/lib/Makefile.rootfs SRCDIR= ../common LIBS = $(DYNLIB) LDLIBS += -lc CFLAGS += $(CCVERBOSE) CPPFLAGS += -D_REENTRANT -D_POSIX_PTHREAD_SEMANTICS -I$(SRCDIR) CERRWARN += -Wno-parentheses CERRWARN += $(CNOWARN_UNINIT) # not linted SMATCH=off all: $(LIBS) include $(SRC)/lib/Makefile.targ # # CDDL HEADER START # # The contents of this file are subject to the terms of the # Common Development and Distribution License (the "License"). # You may not use this file except in compliance with the License. # # You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE # or http://www.opensolaris.org/os/licensing. # See the License for the specific language governing permissions # and limitations under the License. # # When distributing Covered Code, include this CDDL HEADER in each # file and include the License file at usr/src/OPENSOLARIS.LICENSE. # If applicable, add the following below this CDDL HEADER, with the # fields enclosed by brackets "[]" replaced with your own identifying # information: Portions Copyright [yyyy] [name of copyright owner] # # CDDL HEADER END # # Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved. # This is an internal library for use only by: usr/src/cmd/cmd-crypto usr/src/lib/pkcs11 usr/src/lib/libkmf The library and the header file are installed into the proto area but are not included in any pacakges. libcryptoutil Design 1. Introduction There are a number of common code components and general utility functions needed that are shared by various userland parts of the crypto framework. The originally approved ARC materials (PSARC/2001/488 & PSARC/2001/553) didn't have a library that was included by all user land libraries, plugins and commands. The solution to this is to follow what other project teams have done in the past and create a project private util library. 2. Contents Any code that is generic enough to be shared by multiple parts of the user crypto framework is eligible. The current contents are: 2.1 Error & Debug Functions cryptodebug_init(), cryptodebug() cryptoerror() These functions log debug or error information to stderr and/or syslog or a file. Debug is off by default but the code is always compiled in. The cryptodebug_init() routine allows the caller to set a message prefix for error and debug output. The environment variable SUNW_CRYPTO_DEBUG determines wither or not debug output is generated at run time, valid values are "syslog" or "stderr" For example elfsign(1) could do: cryptodebug_init("elfsign"); and later: cryptoerror(LOG_STDERR, gettext("invalid number of arguments")); This would cause an error message on stderr thus: "elfsign: invalid number of arguments" The first argument to cryptoerror is either LOG_STDERR or a syslog(3c) priority. All messages include the PID and are logged at LOG_USER. for debug output: cryptodebug("scmd=request opts=%s", opts); This would go to the location defined by $SUNW_CRYPTO_DEBUG, ie syslog, stderr or not be generated at all. 2.2 PKCS#11 Mechanism Type to and from Strings pkcs11_mech2str() and pkcs11_str2mech() These functions use a table built at compile time from the contents of the pkcs11t.h file to map mechanism numbers to the corresponding string value. pkcs11_mech2str() returns a pointer to a string that should be free(3c)'d by the caller. Consumers: digest(1), mac(1), encrypt(1), decrypt(1) for translating command line args to mech numbers. They will need to add the "CKM_" prefix before calling pkc11_str2mech() cryptoadm(8) for output to user, and for storing in pkcs11.conf file. Debug code. 2.3 The "pkcs11.conf" configuration file Parsing code. The "pkcs11.conf" configuration file parsing code and data structures are shared between: cryptoadm(8), libpkcs11(3crypto). 2.3.1 Data Structures: #define MECH_ID_HEX_LEN 11 /* length of mechanism id in hex form */ typedef char libname_t[MAXPATHLEN]; typedef char midstr_t[MECH_ID_HEX_LEN]; /* The policy list for an entry in the config file */ typedef struct umechlist { midstr_t name; struct umechlist *next; } umechlist_t; /* An entry in the pkcs11.conf file */ typedef struct uentry { libname_t name; boolean_t flag_enabledlist; /* TRUE if an enabledlist */ umechlist_t *policylist; /* disabledlist or enabledlist */ int count; } uentry_t; /* The entry list for the entire pkcs11.conf file */ typedef struct uentrylist { uentry_t *pent; struct uentrylist *next; } uentrylist_t; 2.3.2 Functions: extern int get_pkcs11conf_info(uentrylist_t **ppliblist); $ Retrieve the user-level provider info from the pkcs11.conf file. If successful, the result is returned from the ppliblist argument. This function returns SUCCESS if successfully done; otherwise it returns FAILURE. The caller should use free_uentrylist() to free the space allocated for "ppliblist". extern umechlist_t *create_umech(char *mechname); Create one item of type umechlist_t with the mechanism name in hex form. A NULL is returned when the input name is NULL or the heap memory is insufficient. The Caller should use free_umechlist() to free the space allocated for the returning data. extern void free_uentrylist(uentrylist_t *ptr); Free space allocated for an pointer to the struct "uentrylist_t". extern void free_uentry(uentry_t *ptr); Free space allocated for an pointer to the struct "uentry_t". extern void free_umechlist(umechlist_t *ptr); Free space allocated for an pointer to the struct "umechlist_t". 2.4 PKCS#11 Mechanism Type to key type pkcs11_mech2keytype() This function is used to get the key type for a mechanism. Consumers: encrypt(1), decrypt(1), and libpkcs11(3crypto) for getting the key type when creating an object for use with a specific mechanism. 2.5 PKCS#11 return code to string pkcs11_strerror() This function returns a string representation of any given PKCS11 return code. Consumer: encrypt(1) and decrypt(1) uses this function for reporting errors. 2.5 PKCS#11 URI parsing code pkcs11_parse_uri() pkcs11_free_uri() This function parses a PKCS#11 URI and fills up a pkcs11_uri_t structure. It also reads the PIN if the PKCS#11 URI specifies a passphrase dialog. The pkcs11_uri_t is described in cryptoutil.h, explanation of the return codes for the pkcs11_parse_uri() function is in the function's comment in pk11_uri.c. The pkcs11_parse_uri() function allocates the URI's fields and the caller is responsible for calling pkcs11_free_uri() after it's done with the URI structure. Consumer: SunSSH will use the functions for parsing PKCS#11 URIs. 3. Non-Contents Code for cryptographic algorithms does not belong in here. That comes from usr/src/common/ since it is shared between user and kernel. PKCS#11 header files although they are common to various parts of the user land framework come from usr/src/pkcs11/include 4. Interface Taxonomy Everything in this library is Project Private or Internal. The exported symbols will all be marked as SUNWprivate_1.0 in the library spec file. 5. Static vs Dynamic The initial design was to only use a static archive library to avoid exposing a new interface (even though it is all private). However while this is fine for initial delivery it creates difficulties later with patching. As such a Dynamic version will be build. Libraries for lint and header files will not be shipped in any Sun packages since this is all Project Private. Similarly the abi_ file will not be shipped even though a spec file will be used in the source gate. 6. Library location At present all of the consumers of the library are in /usr/ so the library is /usr/lib/{sparcv9}/libcryptoutil.so.1. If kcfd ever moves to /lib/crypto/kcf as a result of PSARC/2002/117 allowing it, then libcryptoutil needs to move as well. # # CDDL HEADER START # # The contents of this file are subject to the terms of the # Common Development and Distribution License, Version 1.0 only # (the "License"). You may not use this file except in compliance # with the License. # # You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE # or http://www.opensolaris.org/os/licensing. # See the License for the specific language governing permissions # and limitations under the License. # # When distributing Covered Code, include this CDDL HEADER in each # file and include the License file at usr/src/OPENSOLARIS.LICENSE. # If applicable, add the following below this CDDL HEADER, with the # fields enclosed by brackets "[]" replaced with your own identifying # information: Portions Copyright [yyyy] [name of copyright owner] # # CDDL HEADER END # # # Copyright 2004 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # include ../Makefile.com include ../../Makefile.lib.64 .KEEP_STATE: install: all $(ROOTLIBS64) $(ROOTLINKS64) $(ROOTCOMPATLINKS64) /* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License (the "License"). * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at usr/src/OPENSOLARIS.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END */ /* * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ #include #include #include #include #include #include "cryptoutil.h" static int uef_interpret(char *, uentry_t **); static int parse_policylist(char *, uentry_t *); static boolean_t is_fips(char *); /* * Retrieve the user-level provider info from the pkcs11.conf file. * If successful, the result is returned from the ppliblist argument. * This function returns SUCCESS if successfully done; otherwise it returns * FAILURE. */ int get_pkcs11conf_info(uentrylist_t **ppliblist) { FILE *pfile; char buffer[BUFSIZ]; size_t len; uentry_t *pent; uentrylist_t *pentlist; uentrylist_t *pcur; int rc = SUCCESS; *ppliblist = NULL; if ((pfile = fopen(_PATH_PKCS11_CONF, "rF")) == NULL) { cryptoerror(LOG_ERR, "failed to open %s.\n", _PATH_PKCS11_CONF); return (FAILURE); } while (fgets(buffer, BUFSIZ, pfile) != NULL) { if (buffer[0] == '#' || buffer[0] == ' ' || buffer[0] == '\n'|| buffer[0] == '\t') { continue; /* ignore comment lines */ } len = strlen(buffer); if (buffer[len-1] == '\n') { /* get rid of trailing '\n' */ len--; } buffer[len] = '\0'; if ((rc = uef_interpret(buffer, &pent)) != SUCCESS) { break; } /* append pent into ppliblist */ pentlist = malloc(sizeof (uentrylist_t)); if (pentlist == NULL) { cryptoerror(LOG_ERR, "parsing %s, out of memory.\n", _PATH_PKCS11_CONF); free_uentry(pent); rc = FAILURE; break; } pentlist->puent = pent; pentlist->next = NULL; if (*ppliblist == NULL) { *ppliblist = pcur = pentlist; } else { pcur->next = pentlist; pcur = pcur->next; } } (void) fclose(pfile); if (rc != SUCCESS) { free_uentrylist(*ppliblist); *ppliblist = NULL; } return (rc); } static int parse_fips_mode(char *buf, boolean_t *mode) { char *value; if (strncmp(buf, EF_FIPS_STATUS, sizeof (EF_FIPS_STATUS) - 1) == 0) { if (value = strpbrk(buf, SEP_EQUAL)) { value++; /* get rid of = */ if (strcmp(value, DISABLED_KEYWORD) == 0) { *mode = B_FALSE; } else if (strcmp(value, ENABLED_KEYWORD) == 0) { *mode = B_TRUE; } else { cryptoerror(LOG_ERR, gettext( "Failed to parse pkcs11.conf file.\n")); return (CKR_FUNCTION_FAILED); } return (CKR_OK); } else { return (CKR_FUNCTION_FAILED); } } else { /* should not come here */ cryptoerror(LOG_ERR, gettext( "Failed to parse pkcs11.conf file.\n")); return (CKR_FUNCTION_FAILED); } } /* * This routine converts a char string into a uentry_t structure * The input string "buf" should be one of the following: * library_name * library_name:NO_RANDOM * library_name:disabledlist=m1,m2,...,mk * library_name:disabledlist=m1,m2,...,mk;NO_RANDOM * library_name:enabledlist= * library_name:enabledlist=;NO_RANDOM * library_name:enabledlist=m1,m2,...,mk * library_name:enabledlist=m1,m2,...,mk;NO_RANDOM * metaslot:status=enabled;enabledlist=m1,m2,....;slot=;\ * token= * * Note: * The mechanisms m1,..mk are in hex form. For example, "0x00000210" * for CKM_MD5. * * For the metaslot entry, "enabledlist", "slot", "auto_key_migrate" * or "token" is optional */ static int uef_interpret(char *buf, uentry_t **ppent) { uentry_t *pent; char *token1; char *token2; char *lasts; int rc; *ppent = NULL; if ((token1 = strtok_r(buf, SEP_COLON, &lasts)) == NULL) { /* buf is NULL */ return (FAILURE); }; pent = calloc(sizeof (uentry_t), 1); if (pent == NULL) { cryptoerror(LOG_ERR, "parsing %s, out of memory.\n", _PATH_PKCS11_CONF); return (FAILURE); } (void) strlcpy(pent->name, token1, sizeof (pent->name)); if (is_fips(token1)) { if ((rc = parse_fips_mode(buf + strlen(token1) + 1, &pent->flag_fips_enabled)) != SUCCESS) { free_uentry(pent); return (rc); } *ppent = pent; return (SUCCESS); } /* * in case metaslot_auto_key_migrate is not specified, it should * be default to true */ pent->flag_metaslot_auto_key_migrate = B_TRUE; while ((token2 = strtok_r(NULL, SEP_SEMICOLON, &lasts)) != NULL) { if ((rc = parse_policylist(token2, pent)) != SUCCESS) { free_uentry(pent); return (rc); } } *ppent = pent; return (SUCCESS); } /* * This routine parses the policy list and stored the result in the argument * pent. * * Arg buf: input only, its format should be one of the following: * enabledlist= * enabledlist=m1,m2,...,mk * disabledlist=m1,m2,...,mk * NO_RANDOM * metaslot_status=enabled|disabled * metaslot_token= * metaslot_slot=flag_enabledlist = B_FALSE; } else if (strncmp(buf, EF_ENABLED, sizeof (EF_ENABLED) - 1) == 0) { pent->flag_enabledlist = B_TRUE; } else if (strncmp(buf, EF_NORANDOM, sizeof (EF_NORANDOM) - 1) == 0) { pent->flag_norandom = B_TRUE; return (rc); } else if (strncmp(buf, METASLOT_TOKEN, sizeof (METASLOT_TOKEN) - 1) == 0) { if (value = strpbrk(buf, SEP_EQUAL)) { value++; /* get rid of = */ (void) strlcpy((char *)pent->metaslot_ks_token, value, sizeof (pent->metaslot_ks_token)); return (SUCCESS); } else { cryptoerror(LOG_ERR, "failed to parse %s.\n", _PATH_PKCS11_CONF); return (FAILURE); } } else if (strncmp(buf, METASLOT_SLOT, sizeof (METASLOT_SLOT) - 1) == 0) { if (value = strpbrk(buf, SEP_EQUAL)) { value++; /* get rid of = */ (void) strlcpy((char *)pent->metaslot_ks_slot, value, sizeof (pent->metaslot_ks_slot)); return (SUCCESS); } else { cryptoerror(LOG_ERR, "failed to parse %s.\n", _PATH_PKCS11_CONF); return (FAILURE); } } else if (strncmp(buf, METASLOT_STATUS, sizeof (METASLOT_STATUS) - 1) == 0) { if (value = strpbrk(buf, SEP_EQUAL)) { value++; /* get rid of = */ if (strcmp(value, DISABLED_KEYWORD) == 0) { pent->flag_metaslot_enabled = B_FALSE; } else if (strcmp(value, ENABLED_KEYWORD) == 0) { pent->flag_metaslot_enabled = B_TRUE; } else { cryptoerror(LOG_ERR, "failed to parse %s.\n", _PATH_PKCS11_CONF); return (FAILURE); } return (SUCCESS); } else { cryptoerror(LOG_ERR, "failed to parse %s.\n", _PATH_PKCS11_CONF); return (FAILURE); } } else if (strncmp(buf, METASLOT_AUTO_KEY_MIGRATE, sizeof (METASLOT_AUTO_KEY_MIGRATE) - 1) == 0) { if (value = strpbrk(buf, SEP_EQUAL)) { value++; /* get rid of = */ if (strcmp(value, DISABLED_KEYWORD) == 0) { pent->flag_metaslot_auto_key_migrate = B_FALSE; } else if (strcmp(value, ENABLED_KEYWORD) == 0) { pent->flag_metaslot_auto_key_migrate = B_TRUE; } else { cryptoerror(LOG_ERR, "failed to parse %s.\n", _PATH_PKCS11_CONF); return (FAILURE); } return (SUCCESS); } else { cryptoerror(LOG_ERR, "failed to parse %s.\n", _PATH_PKCS11_CONF); return (FAILURE); } } else { cryptoerror(LOG_ERR, "failed to parse %s.\n", _PATH_PKCS11_CONF); return (FAILURE); } if (value = strpbrk(buf, SEP_EQUAL)) { value++; /* get rid of = */ } if ((next_token = strtok_r(value, SEP_COMMA, &lasts)) == NULL) { if (pent->flag_enabledlist) { return (SUCCESS); } else { cryptoerror(LOG_ERR, "failed to parse %s.\n", _PATH_PKCS11_CONF); return (FAILURE); } } while (next_token) { if ((pmech = create_umech(next_token)) == NULL) { cryptoerror(LOG_ERR, "parsing %s, out of memory.\n", _PATH_PKCS11_CONF); rc = FAILURE; break; } if (phead == NULL) { phead = pcur = pmech; } else { pcur->next = pmech; pcur = pcur->next; } count++; next_token = strtok_r(NULL, SEP_COMMA, &lasts); } if (rc == SUCCESS) { pent->policylist = phead; pent->count = count; } else { free_umechlist(phead); } return (rc); } /* * Create one item of type umechlist_t with the mechanism name. A NULL is * returned when the input name is NULL or the heap memory is insufficient. */ umechlist_t * create_umech(char *name) { umechlist_t *pmech = NULL; if (name == NULL) { return (NULL); } if ((pmech = malloc(sizeof (umechlist_t))) != NULL) { (void) strlcpy(pmech->name, name, sizeof (pmech->name)); pmech->next = NULL; } return (pmech); } void free_umechlist(umechlist_t *plist) { umechlist_t *pnext; while (plist != NULL) { pnext = plist->next; free(plist); plist = pnext; } } void free_uentry(uentry_t *pent) { if (pent == NULL) { return; } else { free_umechlist(pent->policylist); free(pent); } } void free_uentrylist(uentrylist_t *entrylist) { uentrylist_t *pnext; while (entrylist != NULL) { pnext = entrylist->next; free_uentry(entrylist->puent); free(entrylist); entrylist = pnext; } } /* * Duplicate an UEF mechanism list. A NULL pointer is returned if out of * memory or the input argument is NULL. */ static umechlist_t * dup_umechlist(umechlist_t *plist) { umechlist_t *pres = NULL; umechlist_t *pcur; umechlist_t *ptmp; int rc = SUCCESS; while (plist != NULL) { if (!(ptmp = create_umech(plist->name))) { rc = FAILURE; break; } if (pres == NULL) { pres = pcur = ptmp; } else { pcur->next = ptmp; pcur = pcur->next; } plist = plist->next; } if (rc != SUCCESS) { free_umechlist(pres); return (NULL); } return (pres); } /* * Duplicate an uentry. A NULL pointer is returned if out of memory * or the input argument is NULL. */ static uentry_t * dup_uentry(uentry_t *puent1) { uentry_t *puent2 = NULL; if (puent1 == NULL) { return (NULL); } if ((puent2 = malloc(sizeof (uentry_t))) == NULL) { cryptoerror(LOG_STDERR, gettext("out of memory.")); return (NULL); } else { (void) strlcpy(puent2->name, puent1->name, sizeof (puent2->name)); puent2->flag_norandom = puent1->flag_norandom; puent2->flag_enabledlist = puent1->flag_enabledlist; puent2->policylist = dup_umechlist(puent1->policylist); puent2->flag_metaslot_enabled = puent1->flag_metaslot_enabled; puent2->flag_metaslot_auto_key_migrate = puent1->flag_metaslot_auto_key_migrate; (void) memcpy(puent2->metaslot_ks_slot, puent1->metaslot_ks_slot, SLOT_DESCRIPTION_SIZE); (void) memcpy(puent2->metaslot_ks_token, puent1->metaslot_ks_token, TOKEN_LABEL_SIZE); puent2->count = puent1->count; puent2->flag_fips_enabled = puent1->flag_fips_enabled; return (puent2); } } /* * Find the entry in the "pkcs11.conf" file with "libname" as the provider * name. Return the entry if found, otherwise return NULL. */ uentry_t * getent_uef(char *libname) { uentrylist_t *pliblist = NULL; uentrylist_t *plib = NULL; uentry_t *puent = NULL; boolean_t found = B_FALSE; if (libname == NULL) { return (NULL); } if ((get_pkcs11conf_info(&pliblist)) == FAILURE) { return (NULL); } plib = pliblist; while (plib) { if (strcmp(plib->puent->name, libname) == 0) { found = B_TRUE; break; } else { plib = plib->next; } } if (found) { puent = dup_uentry(plib->puent); } free_uentrylist(pliblist); return (puent); } /* * Retrieve the metaslot information from the pkcs11.conf file. * This function returns SUCCESS if successfully done; otherwise it returns * FAILURE. If successful, the caller is responsible to free the space * allocated for objectstore_slot_info and objectstore_token_info. */ int get_metaslot_info(boolean_t *status_enabled, boolean_t *migrate_enabled, char **objectstore_slot_info, char **objectstore_token_info) { int rc = SUCCESS; uentry_t *puent; char *buf1 = NULL; char *buf2 = NULL; if ((puent = getent_uef(METASLOT_KEYWORD)) == NULL) { /* metaslot entry doesn't exist */ return (FAILURE); } *status_enabled = puent->flag_metaslot_enabled; *migrate_enabled = puent->flag_metaslot_auto_key_migrate; buf1 = malloc(SLOT_DESCRIPTION_SIZE); if (buf1 == NULL) { cryptoerror(LOG_ERR, "get_metaslot_info() - out of memory.\n"); rc = FAILURE; goto out; } (void) strcpy(buf1, (const char *) puent->metaslot_ks_slot); *objectstore_slot_info = buf1; buf2 = malloc(TOKEN_LABEL_SIZE); if (objectstore_slot_info == NULL) { cryptoerror(LOG_ERR, "get_metaslot_info() - out of memory.\n"); rc = FAILURE; goto out; } (void) strcpy(buf2, (const char *) puent->metaslot_ks_token); *objectstore_token_info = buf2; out: if (puent != NULL) { free_uentry(puent); } if (rc == FAILURE) { if (buf1 != NULL) { free(buf1); } if (buf2 != NULL) { free(buf2); } } return (rc); } static boolean_t is_fips(char *name) { if (strcmp(name, FIPS_KEYWORD) == 0) { return (B_TRUE); } else { return (B_FALSE); } } /* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License (the "License"). * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at usr/src/OPENSOLARIS.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END * * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. */ /* * Copyright 2010 Nexenta Systems, Inc. All rights reserved. * Copyright 2014, OmniTI Computer Consulting, Inc. All rights reserved. * Copyright 2018, Joyent, Inc. */ #ifndef _CRYPTOUTIL_H #define _CRYPTOUTIL_H #ifdef __cplusplus extern "C" { #endif #include #include #include #include #define LOG_STDERR -1 #define SUCCESS 0 #define FAILURE 1 #define MECH_ID_HEX_LEN 11 /* length of mechanism id in hex form */ #define _PATH_PKCS11_CONF "/etc/crypto/pkcs11.conf" #define _PATH_KCF_CONF "/etc/crypto/kcf.conf" #define _PATH_KCFD_LOCK "/var/run/kcfd.lock" /* $ISA substitution for parsing pkcs11.conf data */ #define PKCS11_ISA "/$ISA/" #if defined(_LP64) #define PKCS11_ISA_DIR "/64/" #else /* !_LP64 */ #define PKCS11_ISA_DIR "/" #endif /* keywords and delimiters for parsing configuration files */ #define SEP_COLON ":" #define SEP_SEMICOLON ";" #define SEP_EQUAL "=" #define SEP_COMMA "," #define METASLOT_KEYWORD "metaslot" #define FIPS_KEYWORD "fips-140" #define EF_DISABLED "disabledlist=" #define EF_ENABLED "enabledlist=" #define EF_NORANDOM "NO_RANDOM" #define METASLOT_TOKEN "metaslot_token=" #define METASLOT_SLOT "metaslot_slot=" #define METASLOT_STATUS "metaslot_status=" #define EF_FIPS_STATUS "fips_status=" #define METASLOT_AUTO_KEY_MIGRATE "metaslot_auto_key_migrate=" #define ENABLED_KEYWORD "enabled" #define DISABLED_KEYWORD "disabled" #define SLOT_DESCRIPTION_SIZE 64 #define TOKEN_LABEL_SIZE 32 #define TOKEN_MANUFACTURER_SIZE 32 #define TOKEN_SERIAL_SIZE 16 #define CRYPTO_FIPS_MODE_DISABLED 0 #define CRYPTO_FIPS_MODE_ENABLED 1 /* * Define the following softtoken values that are used by softtoken * library, cryptoadm and pktool command. */ #define SOFT_SLOT_DESCRIPTION \ "Sun Crypto Softtoken " \ " " #define SOFT_TOKEN_LABEL "Sun Software PKCS#11 softtoken " #define SOFT_TOKEN_SERIAL " " #define SOFT_MANUFACTURER_ID "Sun Microsystems, Inc. " #define SOFT_DEFAULT_PIN "changeme" typedef char libname_t[MAXPATHLEN]; typedef char midstr_t[MECH_ID_HEX_LEN]; typedef struct umechlist { midstr_t name; /* mechanism name in hex form */ struct umechlist *next; } umechlist_t; typedef struct uentry { libname_t name; boolean_t flag_norandom; /* TRUE if random is disabled */ boolean_t flag_enabledlist; /* TRUE if an enabledlist */ umechlist_t *policylist; /* disabledlist or enabledlist */ boolean_t flag_metaslot_enabled; /* TRUE if metaslot's enabled */ boolean_t flag_metaslot_auto_key_migrate; CK_UTF8CHAR metaslot_ks_slot[SLOT_DESCRIPTION_SIZE + 1]; CK_UTF8CHAR metaslot_ks_token[TOKEN_LABEL_SIZE + 1]; int count; boolean_t flag_fips_enabled; } uentry_t; typedef struct uentrylist { uentry_t *puent; struct uentrylist *next; } uentrylist_t; /* Return codes for pkcs11_parse_uri() */ #define PK11_URI_OK 0 #define PK11_URI_INVALID 1 #define PK11_MALLOC_ERROR 2 #define PK11_URI_VALUE_OVERFLOW 3 #define PK11_NOT_PKCS11_URI 4 /* * There is no limit for the attribute length in the spec. 256 bytes should be * enough for the object name. */ #define PK11_MAX_OBJECT_LEN 256 /* * CKA_ID is of type "byte array" which can be of arbitrary length. 256 bytes * should be sufficient though. */ #define PK11_MAX_ID_LEN 256 /* Structure for the PKCS#11 URI. */ typedef struct pkcs11_uri_t { /* CKA_LABEL attribute to the C_FindObjectsInit function. */ CK_UTF8CHAR_PTR object; /* * CKA_CLASS attribute to the C_FindObjectsInit function. The * "objecttype" URI attribute can have a value one of "private", * "public", "cert", "secretkey", and "data". The "objecttype" field can * have a value of CKO_PUBLIC_KEY, CKO_PRIVATE_KEY, CKO_CERTIFICATE, * CKO_SECRET_KEY, and CKO_DATA. This attribute cannot be empty in the * URI. */ CK_ULONG objecttype; /* CKO_DATA is 0 so we need this flag. Not part of the URI itself. */ boolean_t objecttype_present; /* * Token, manufufacturer, serial and model are of fixed size length in * the specification. We allocate memory on the fly to distinguish * between an attribute not present and an empty value. We check for * overflows. We always terminate the string with '\0' even when that is * not used in the PKCS#11's CK_TOKEN_INFO structure (fields are padded * with spaces). */ /* Token label from CK_TOKEN_INFO. */ CK_UTF8CHAR_PTR token; /* ManufacturerID from CK_TOKEN_INFO. */ CK_UTF8CHAR_PTR manuf; /* SerialNumber from CK_TOKEN_INFO. */ CK_CHAR_PTR serial; /* Model from CK_TOKEN_INFO. */ CK_UTF8CHAR_PTR model; /* This is a byte array, we need a length parameter as well. */ CK_BYTE_PTR id; int id_len; /* * Location of the file with a token PIN. Application can overload this, * eg. "/bin/askpass|" may mean to read the PIN from a command. However, * the pkcs11_parse_uri() function does not interpret this field in any * way. */ char *pinfile; } pkcs11_uri_t; extern void cryptodebug(const char *fmt, ...); extern void cryptoerror(int priority, const char *fmt, ...); extern void cryptodebug_init(const char *prefix); extern void cryptoerror_off(); extern void cryptoerror_on(); extern const char *pkcs11_mech2str(CK_MECHANISM_TYPE mech); extern CK_RV pkcs11_str2mech(char *mech_str, CK_MECHANISM_TYPE_PTR mech); extern int get_pkcs11conf_info(uentrylist_t **); extern umechlist_t *create_umech(char *); extern void free_umechlist(umechlist_t *); extern void free_uentrylist(uentrylist_t *); extern void free_uentry(uentry_t *); extern uentry_t *getent_uef(char *); extern void tohexstr(uchar_t *bytes, size_t blen, char *hexstr, size_t hexlen); extern int hexstr_to_bytes(char *hexstr, size_t hexlen, uchar_t **bytes, size_t *blen); extern CK_RV pkcs11_mech2keytype(CK_MECHANISM_TYPE mech_type, CK_KEY_TYPE *ktype); extern CK_RV pkcs11_mech2keygen(CK_MECHANISM_TYPE mech_type, CK_MECHANISM_TYPE *gen_mech); extern char *pkcs11_strerror(CK_RV rv); extern int get_metaslot_info(boolean_t *status_enabled, boolean_t *migrate_enabled, char **objectstore_slot_info, char **objectstore_token_info); extern char *get_fullpath(char *dir, char *filepath); extern int str2lifetime(char *ltimestr, uint32_t *ltime); extern char *pkcs11_default_token(void); extern int pkcs11_get_pass(char *token_name, char **pdata, size_t *psize, size_t min_psize, boolean_t with_confirmation); extern int pkcs11_seed_urandom(void *sbuf, size_t slen); extern int pkcs11_get_random(void *dbuf, size_t dlen); extern int pkcs11_get_urandom(void *dbuf, size_t dlen); extern int pkcs11_get_nzero_urandom(void *dbuf, size_t dlen); extern int pkcs11_read_data(char *filename, void **dbuf, size_t *dlen); extern int open_nointr(const char *path, int oflag, ...); extern ssize_t readn_nointr(int fd, void *dbuf, size_t dlen); extern ssize_t writen_nointr(int fd, void *dbuf, size_t dlen); extern int update_conf(char *conf_file, char *entry); extern int pkcs11_parse_uri(const char *str, pkcs11_uri_t *uri); extern void pkcs11_free_uri(pkcs11_uri_t *uri); extern CK_RV crypto2pkcs11_error_number(uint_t); #ifdef __cplusplus } #endif #endif /* _CRYPTOUTIL_H */ /* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License (the "License"). * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at usr/src/OPENSOLARIS.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END */ /* * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ #include #include #include #include #include #include #define CRYPTO_DEBUG_ENV "SUNW_CRYPTO_DEBUG" static char *_cryptodebug_prefix = NULL; static int _cryptodebug_enabled = -1; /* -1 unknown, 0 disabled, 1 enabled */ static int _cryptoerror_enabled = 1; /* 0 disabled, 1 enabled */ static boolean_t _cryptodebug_syslog = B_TRUE; /*PRINTFLIKE1*/ void cryptodebug(const char *fmt, ...) { va_list args; char fmtbuf[BUFSIZ]; char msgbuf[BUFSIZ]; if (fmt == NULL || _cryptodebug_enabled != 1) return; va_start(args, fmt); if (_cryptodebug_prefix == NULL) { (void) vsnprintf(msgbuf, sizeof (msgbuf), fmt, args); } else { (void) snprintf(fmtbuf, sizeof (fmtbuf), "%s: %s", _cryptodebug_prefix, fmt); (void) vsnprintf(msgbuf, sizeof (msgbuf), fmtbuf, args); } if (_cryptodebug_syslog) { syslog(LOG_DEBUG, msgbuf); } else { (void) fprintf(stderr, "%s\n", msgbuf); } va_end(args); } /* * cryptoerror * * This is intended to be used both by interactive commands like cryptoadm(8) * digest(1) etc, and by libraries libpkcs11, libelfsign etc. * * A library probably wants most (all?) of its errors going to syslog but * commands are usually happy for them to go to stderr. * * If a syslog priority is passed we log on that priority. Otherwise we * use LOG_STDERR to mean use stderr instead. LOG_STDERR is defined in * cryptoutil.h */ /*PRINTFLIKE2*/ void cryptoerror(int priority, const char *fmt, ...) { char fmtbuf[BUFSIZ]; char msgbuf[BUFSIZ]; va_list args; if (fmt == NULL || _cryptoerror_enabled == 0) return; va_start(args, fmt); if (_cryptodebug_prefix == NULL) { (void) vsnprintf(msgbuf, sizeof (msgbuf), fmt, args); } else { (void) snprintf(fmtbuf, sizeof (fmtbuf), "%s: %s", _cryptodebug_prefix, fmt); (void) vsnprintf(msgbuf, sizeof (msgbuf), fmtbuf, args); } if ((priority == LOG_STDERR) || (priority < 0)) { (void) fprintf(stderr, "%s\n", msgbuf); } else { syslog(priority, msgbuf); } va_end(args); } void cryptoerror_off() { _cryptoerror_enabled = 0; } void cryptoerror_on() { _cryptoerror_enabled = 1; } void cryptodebug_init(const char *prefix) { char *envval = NULL; if (prefix != NULL) { _cryptodebug_prefix = strdup(prefix); } if (_cryptodebug_enabled == -1) { envval = getenv(CRYPTO_DEBUG_ENV); /* * If unset or it isn't one of syslog or stderr * disable debug. */ if (envval == NULL || (strcmp(envval, "") == 0)) { _cryptodebug_enabled = 0; return; } else if (strcmp(envval, "stderr") == 0) { _cryptodebug_syslog = B_FALSE; _cryptodebug_enabled = 1; } else if (strcmp(envval, "syslog") == 0) { _cryptodebug_syslog = B_TRUE; _cryptodebug_enabled = 1; } } openlog(_cryptodebug_prefix, LOG_PID, LOG_USER); } #pragma fini(_cryptodebug_fini) static void _cryptodebug_fini(void) { if (_cryptodebug_prefix != NULL) free(_cryptodebug_prefix); } /* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License (the "License"). * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at usr/src/OPENSOLARIS.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END */ /* * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ #include #include #include #include #include #include #include #include /* * Read file into buffer. Used to read raw key data or initialization * vector data. Buffer must be freed by caller using free(). * * If file is a regular file, entire file is read and dlen is set * to the number of bytes read. Otherwise, dlen should first be set * to the number of bytes requested and will be reset to actual number * of bytes returned. * * Return 0 on success and errno on error. */ int pkcs11_read_data(char *filename, void **dbuf, size_t *dlen) { int fd = -1; struct stat statbuf; boolean_t plain_file; void *filebuf = NULL; size_t filesize = 0; int ret = 0; if (filename == NULL || dbuf == NULL || dlen == NULL) return (-1); if ((fd = open(filename, O_RDONLY | O_NONBLOCK)) == -1) { ret = errno; cryptoerror(LOG_STDERR, gettext("cannot open %s"), filename); goto error; } if (fstat(fd, &statbuf) == -1) { ret = errno; cryptoerror(LOG_STDERR, gettext("cannot stat %s"), filename); goto error; } if (S_ISREG(statbuf.st_mode)) { /* read the entire regular file */ filesize = statbuf.st_size; plain_file = B_TRUE; } else { /* read requested bytes from special file */ filesize = *dlen; plain_file = B_FALSE; } if (filesize == 0) { /* * for decrypt this is an error; for digest this is ok; * make it ok here but also set dbuf = NULL and dlen = 0 * to indicate there was no data to read and caller can * retranslate that to an error if it wishes. */ (void) close(fd); *dbuf = NULL; *dlen = 0; return (0); } if ((filebuf = malloc(filesize)) == NULL) { ret = errno; cryptoerror(LOG_STDERR, gettext("malloc: %s"), strerror(ret)); goto error; } if (plain_file) { /* either it got read or it didn't */ if (read(fd, filebuf, filesize) != filesize) { ret = errno; cryptoerror(LOG_STDERR, gettext("error reading file %s: %s"), filename, strerror(ret)); goto error; } } else { /* reading from special file may need some coaxing */ char *marker = (char *)filebuf; size_t left = filesize; ssize_t nread; for (/* */; left > 0; marker += nread, left -= nread) { /* keep reading it's going well */ nread = read(fd, marker, left); if (nread > 0 || (nread == 0 && errno == EINTR)) { errno = 0; continue; } /* might have to be good enough for caller */ if (nread == 0 && errno == EAGAIN) break; /* anything else is an error */ if (errno) { ret = errno; cryptoerror(LOG_STDERR, gettext("error reading file %s: %s"), filename, strerror(ret)); goto error; } } /* reset to actual number of bytes read */ filesize -= left; } (void) close(fd); *dbuf = filebuf; *dlen = filesize; return (0); error: if (fd != -1) (void) close(fd); return (ret); } # # CDDL HEADER START # # The contents of this file are subject to the terms of the # Common Development and Distribution License (the "License"). # You may not use this file except in compliance with the License. # # You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE # or http://www.opensolaris.org/os/licensing. # See the License for the specific language governing permissions # and limitations under the License. # # When distributing Covered Code, include this CDDL HEADER in each # file and include the License file at usr/src/OPENSOLARIS.LICENSE. # If applicable, add the following below this CDDL HEADER, with the # fields enclosed by brackets "[]" replaced with your own identifying # information: Portions Copyright [yyyy] [name of copyright owner] # # CDDL HEADER END # # Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved. # Copyright 2014, OmniTI Computer Consulting Inc. All rights reserved. # Copyright 2018, Joyent, Inc. # # # MAPFILE HEADER START # # WARNING: STOP NOW. DO NOT MODIFY THIS FILE. # Object versioning must comply with the rules detailed in # # usr/src/lib/README.mapfiles # # You should not be making modifications here until you've read the most current # copy of that file. If you need help, contact a gatekeeper for guidance. # # MAPFILE HEADER END # $mapfile_version 2 SYMBOL_VERSION SUNWprivate { global: create_umech; crypto2pkcs11_error_number; cryptodebug; cryptodebug_init; cryptoerror; cryptoerror_off; cryptoerror_on; free_uentry; free_uentrylist; free_umechlist; getent_uef; get_fullpath; get_metaslot_info; get_pkcs11conf_info; hexstr_to_bytes; open_nointr; pkcs11_default_token; pkcs11_free_uri; pkcs11_get_nzero_urandom; pkcs11_get_pass; pkcs11_get_random; pkcs11_get_urandom; pkcs11_mech2keytype; pkcs11_mech2keygen; pkcs11_mech2str; pkcs11_parse_uri; pkcs11_read_data; pkcs11_seed_random; pkcs11_seed_urandom; pkcs11_str2mech; pkcs11_strerror; readn_nointr; str2lifetime; tohexstr; writen_nointr; local: *; }; /* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License (the "License"). * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at usr/src/OPENSOLARIS.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END */ /* * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. * Copyright 2012 Milan Jurik. All rights reserved. * Copyright 2016 Jason King. All rights reserved. */ #include /* * Get the key generation mechanism for the given mechanism. * * All mechanisms in PKCS #11 v2.20 are listed here. */ CK_RV pkcs11_mech2keygen(CK_MECHANISM_TYPE mech_type, CK_MECHANISM_TYPE *gen_mech) { switch (mech_type) { case CKM_RSA_PKCS_KEY_PAIR_GEN: case CKM_RSA_PKCS: case CKM_RSA_9796: case CKM_RSA_X_509: case CKM_MD2_RSA_PKCS: case CKM_MD5_RSA_PKCS: case CKM_SHA1_RSA_PKCS: case CKM_SHA256_RSA_PKCS: case CKM_SHA384_RSA_PKCS: case CKM_SHA512_RSA_PKCS: case CKM_SHA256_RSA_PKCS_PSS: case CKM_SHA384_RSA_PKCS_PSS: case CKM_SHA512_RSA_PKCS_PSS: case CKM_RIPEMD128_RSA_PKCS: case CKM_RIPEMD160_RSA_PKCS: case CKM_RSA_PKCS_OAEP: case CKM_RSA_PKCS_OAEP_TPM_1_1: case CKM_RSA_PKCS_TPM_1_1: *gen_mech = CKM_RSA_PKCS_KEY_PAIR_GEN; break; case CKM_RSA_X9_31_KEY_PAIR_GEN: case CKM_RSA_X9_31: case CKM_SHA1_RSA_X9_31: *gen_mech = CKM_RSA_X9_31_KEY_PAIR_GEN; break; case CKM_RSA_PKCS_PSS: case CKM_SHA1_RSA_PKCS_PSS: *gen_mech = CKM_RSA_PKCS_KEY_PAIR_GEN; break; case CKM_DH_PKCS_PARAMETER_GEN: *gen_mech = CKM_DH_PKCS_PARAMETER_GEN; break; case CKM_DSA_KEY_PAIR_GEN: case CKM_DSA: case CKM_DSA_SHA1: case CKM_DSA_SHA224: case CKM_DSA_SHA256: case CKM_DSA_SHA384: case CKM_DSA_SHA512: *gen_mech = CKM_DSA_KEY_PAIR_GEN; break; case CKM_DSA_PARAMETER_GEN: *gen_mech = CKM_DSA_PARAMETER_GEN; break; case CKM_DSA_PROBABLISTIC_PARAMETER_GEN: *gen_mech = CKM_DSA_PROBABLISTIC_PARAMETER_GEN; break; case CKM_DSA_SHAWE_TAYLOR_PARAMETER_GEN: *gen_mech = CKM_DSA_SHAWE_TAYLOR_PARAMETER_GEN; break; case CKM_FORTEZZA_TIMESTAMP: *gen_mech = CKM_DSA_KEY_PAIR_GEN; break; case CKM_DH_PKCS_KEY_PAIR_GEN: case CKM_DH_PKCS_DERIVE: *gen_mech = CKM_DH_PKCS_KEY_PAIR_GEN; break; case CKM_ECDSA: case CKM_ECDSA_SHA1: case CKM_ECDSA_SHA224: case CKM_ECDSA_SHA256: case CKM_ECDSA_SHA384: case CKM_ECDSA_SHA512: case CKM_EC_KEY_PAIR_GEN: case CKM_ECDH1_DERIVE: case CKM_ECDH1_COFACTOR_DERIVE: case CKM_ECMQV_DERIVE: *gen_mech = CKM_EC_KEY_PAIR_GEN; break; case CKM_X9_42_DH_KEY_PAIR_GEN: case CKM_X9_42_DH_DERIVE: case CKM_X9_42_DH_HYBRID_DERIVE: case CKM_X9_42_MQV_DERIVE: *gen_mech = CKM_X9_42_DH_KEY_PAIR_GEN; break; case CKM_X9_42_DH_PARAMETER_GEN: *gen_mech = CKM_X9_42_DH_PARAMETER_GEN; break; case CKM_KEA_KEY_PAIR_GEN: case CKM_KEA_KEY_DERIVE: *gen_mech = CKM_KEA_KEY_PAIR_GEN; break; case CKM_MD2: case CKM_MD2_HMAC: case CKM_MD2_HMAC_GENERAL: case CKM_MD5: case CKM_MD5_HMAC: case CKM_MD5_HMAC_GENERAL: case CKM_SHA_1: case CKM_SHA_1_HMAC: case CKM_SHA_1_HMAC_GENERAL: case CKM_SHA256: case CKM_SHA256_HMAC: case CKM_SHA256_HMAC_GENERAL: case CKM_SHA384: case CKM_SHA384_HMAC: case CKM_SHA384_HMAC_GENERAL: case CKM_SHA512: case CKM_SHA512_HMAC: case CKM_SHA512_HMAC_GENERAL: case CKM_SHA512_224: case CKM_SHA512_224_HMAC: case CKM_SHA512_224_HMAC_GENERAL: case CKM_SHA512_224_KEY_DERIVATION: case CKM_SHA512_256: case CKM_SHA512_256_HMAC: case CKM_SHA512_256_HMAC_GENERAL: case CKM_SHA512_256_KEY_DERIVATION: case CKM_GENERIC_SECRET_KEY_GEN: case CKM_FASTHASH: case CKM_PKCS5_PBKD2: case CKM_PBA_SHA1_WITH_SHA1_HMAC: case CKM_CMS_SIG: *gen_mech = CKM_GENERIC_SECRET_KEY_GEN; break; case CKM_SSL3_MD5_MAC: case CKM_SSL3_SHA1_MAC: case CKM_SSL3_PRE_MASTER_KEY_GEN: case CKM_SSL3_MASTER_KEY_DERIVE: case CKM_SSL3_KEY_AND_MAC_DERIVE: case CKM_SSL3_MASTER_KEY_DERIVE_DH: *gen_mech = CKM_SSL3_PRE_MASTER_KEY_GEN; break; case CKM_TLS_PRE_MASTER_KEY_GEN: case CKM_TLS_MASTER_KEY_DERIVE: case CKM_TLS_KEY_AND_MAC_DERIVE: case CKM_TLS_MASTER_KEY_DERIVE_DH: case CKM_TLS_PRF: *gen_mech = CKM_TLS_PRE_MASTER_KEY_GEN; break; case CKM_WTLS_PRE_MASTER_KEY_GEN: case CKM_WTLS_MASTER_KEY_DERIVE: case CKM_WTLS_MASTER_KEY_DERIVE_DH_ECC: case CKM_WTLS_PRF: case CKM_WTLS_SERVER_KEY_AND_MAC_DERIVE: case CKM_WTLS_CLIENT_KEY_AND_MAC_DERIVE: *gen_mech = CKM_WTLS_PRE_MASTER_KEY_GEN; break; case CKM_CONCATENATE_BASE_AND_KEY: case CKM_CONCATENATE_BASE_AND_DATA: case CKM_CONCATENATE_DATA_AND_BASE: case CKM_XOR_BASE_AND_DATA: case CKM_EXTRACT_KEY_FROM_KEY: case CKM_RIPEMD128: case CKM_RIPEMD128_HMAC: case CKM_RIPEMD128_HMAC_GENERAL: case CKM_RIPEMD160: case CKM_RIPEMD160_HMAC: case CKM_RIPEMD160_HMAC_GENERAL: case CKM_SHA1_KEY_DERIVATION: case CKM_SHA256_KEY_DERIVATION: case CKM_SHA384_KEY_DERIVATION: case CKM_SHA512_KEY_DERIVATION: case CKM_MD5_KEY_DERIVATION: case CKM_MD2_KEY_DERIVATION: /* not sure the following 2 should be CKK_DES or not */ case CKM_KEY_WRAP_LYNKS: /* wrap/unwrap secret key w/ DES key */ case CKM_KEY_WRAP_SET_OAEP: /* wrap/unwarp DES key w/ RSA key */ *gen_mech = CKM_GENERIC_SECRET_KEY_GEN; break; case CKM_RC2_KEY_GEN: case CKM_RC2_ECB: case CKM_RC2_CBC: case CKM_RC2_MAC: case CKM_RC2_MAC_GENERAL: case CKM_RC2_CBC_PAD: case CKM_PBE_SHA1_RC2_128_CBC: case CKM_PBE_SHA1_RC2_40_CBC: *gen_mech = CKM_RC2_KEY_GEN; break; case CKM_RC4_KEY_GEN: case CKM_RC4: case CKM_PBE_SHA1_RC4_128: case CKM_PBE_SHA1_RC4_40: *gen_mech = CKM_RC4_KEY_GEN; break; case CKM_DES_KEY_GEN: case CKM_DES_ECB: case CKM_DES_CBC: case CKM_DES_MAC: case CKM_DES_MAC_GENERAL: case CKM_DES_CBC_PAD: case CKM_PBE_MD2_DES_CBC: case CKM_PBE_MD5_DES_CBC: case CKM_DES_OFB64: case CKM_DES_OFB8: case CKM_DES_CFB64: case CKM_DES_CFB8: case CKM_DES_ECB_ENCRYPT_DATA: case CKM_DES_CBC_ENCRYPT_DATA: *gen_mech = CKM_DES_KEY_GEN; break; case CKM_DES2_KEY_GEN: case CKM_PBE_SHA1_DES2_EDE_CBC: *gen_mech = CKM_DES2_KEY_GEN; break; case CKM_DES3_KEY_GEN: case CKM_DES3_ECB: case CKM_DES3_CBC: case CKM_DES3_MAC: case CKM_DES3_MAC_GENERAL: case CKM_DES3_CBC_PAD: case CKM_PBE_SHA1_DES3_EDE_CBC: case CKM_DES3_ECB_ENCRYPT_DATA: case CKM_DES3_CBC_ENCRYPT_DATA: case CKM_DES3_CMAC: case CKM_DES3_CMAC_GENERAL: *gen_mech = CKM_DES3_KEY_GEN; break; case CKM_ACTI: case CKM_ACTI_KEY_GEN: *gen_mech = CKM_ACTI_KEY_GEN; break; case CKM_CAST_KEY_GEN: case CKM_CAST_ECB: case CKM_CAST_CBC: case CKM_CAST_MAC: case CKM_CAST_MAC_GENERAL: case CKM_CAST_CBC_PAD: case CKM_PBE_MD5_CAST_CBC: *gen_mech = CKM_CAST_KEY_GEN; break; case CKM_CAST3_KEY_GEN: case CKM_CAST3_ECB: case CKM_CAST3_CBC: case CKM_CAST3_MAC: case CKM_CAST3_MAC_GENERAL: case CKM_CAST3_CBC_PAD: case CKM_PBE_MD5_CAST3_CBC: *gen_mech = CKM_CAST3_KEY_GEN; break; /* CAST5 and CAST128 are the same alg */ case CKM_CAST5_CBC: case CKM_CAST5_CBC_PAD: case CKM_CAST5_ECB: case CKM_CAST5_KEY_GEN: case CKM_CAST5_MAC: case CKM_CAST5_MAC_GENERAL: case CKM_PBE_MD5_CAST5_CBC: case CKM_PBE_SHA1_CAST5_CBC: *gen_mech = CKM_CAST5_KEY_GEN; break; case CKM_RC5_KEY_GEN: case CKM_RC5_ECB: case CKM_RC5_CBC: case CKM_RC5_MAC: case CKM_RC5_MAC_GENERAL: case CKM_RC5_CBC_PAD: *gen_mech = CKM_RC5_KEY_GEN; break; case CKM_IDEA_KEY_GEN: case CKM_IDEA_ECB: case CKM_IDEA_CBC: case CKM_IDEA_MAC: case CKM_IDEA_MAC_GENERAL: case CKM_IDEA_CBC_PAD: *gen_mech = CKM_IDEA_KEY_GEN; break; case CKM_SKIPJACK_KEY_GEN: case CKM_SKIPJACK_ECB64: case CKM_SKIPJACK_CBC64: case CKM_SKIPJACK_OFB64: case CKM_SKIPJACK_CFB64: case CKM_SKIPJACK_CFB32: case CKM_SKIPJACK_CFB16: case CKM_SKIPJACK_CFB8: case CKM_SKIPJACK_WRAP: case CKM_SKIPJACK_PRIVATE_WRAP: case CKM_SKIPJACK_RELAYX: *gen_mech = CKM_SKIPJACK_KEY_GEN; break; case CKM_BATON_KEY_GEN: case CKM_BATON_ECB128: case CKM_BATON_ECB96: case CKM_BATON_CBC128: case CKM_BATON_COUNTER: case CKM_BATON_SHUFFLE: case CKM_BATON_WRAP: *gen_mech = CKM_BATON_KEY_GEN; break; case CKM_JUNIPER_KEY_GEN: case CKM_JUNIPER_ECB128: case CKM_JUNIPER_CBC128: case CKM_JUNIPER_COUNTER: case CKM_JUNIPER_SHUFFLE: case CKM_JUNIPER_WRAP: *gen_mech = CKM_JUNIPER_KEY_GEN; break; case CKM_CDMF_KEY_GEN: case CKM_CDMF_ECB: case CKM_CDMF_CBC: case CKM_CDMF_MAC: case CKM_CDMF_MAC_GENERAL: case CKM_CDMF_CBC_PAD: *gen_mech = CKM_CDMF_KEY_GEN; break; case CKM_AES_KEY_GEN: case CKM_AES_ECB: case CKM_AES_CBC: case CKM_AES_MAC: case CKM_AES_MAC_GENERAL: case CKM_AES_CBC_PAD: case CKM_AES_ECB_ENCRYPT_DATA: case CKM_AES_CBC_ENCRYPT_DATA: case CKM_AES_CCM: case CKM_AES_CFB1: case CKM_AES_CFB128: case CKM_AES_CFB64: case CKM_AES_CFB8: case CKM_AES_CMAC: case CKM_AES_CMAC_GENERAL: case CKM_AES_CTR: case CKM_AES_CTS: case CKM_AES_GCM: case CKM_AES_GMAC: case CKM_AES_KEY_WRAP: case CKM_AES_KEY_WRAP_PAD: case CKM_AES_OFB: case CKM_AES_XCBC_MAC: case CKM_AES_XCBC_MAC_96: *gen_mech = CKM_AES_KEY_GEN; break; case CKM_BLOWFISH_KEY_GEN: case CKM_BLOWFISH_CBC: case CKM_BLOWFISH_CBC_PAD: *gen_mech = CKM_BLOWFISH_KEY_GEN; break; case CKM_TWOFISH_KEY_GEN: case CKM_TWOFISH_CBC: *gen_mech = CKM_TWOFISH_KEY_GEN; break; case CKM_CAMELLIA_CBC: case CKM_CAMELLIA_CBC_ENCRYPT_DATA: case CKM_CAMELLIA_CBC_PAD: case CKM_CAMELLIA_CTR: case CKM_CAMELLIA_ECB: case CKM_CAMELLIA_ECB_ENCRYPT_DATA: case CKM_CAMELLIA_KEY_GEN: case CKM_CAMELLIA_MAC: case CKM_CAMELLIA_MAC_GENERAL: *gen_mech = CKM_CAMELLIA_KEY_GEN; break; case CKM_ARIA_CBC: case CKM_ARIA_CBC_ENCRYPT_DATA: case CKM_ARIA_CBC_PAD: case CKM_ARIA_ECB: case CKM_ARIA_ECB_ENCRYPT_DATA: case CKM_ARIA_KEY_GEN: case CKM_ARIA_MAC: case CKM_ARIA_MAC_GENERAL: *gen_mech = CKM_ARIA_KEY_GEN; break; case CKM_GOST28147: case CKM_GOST28147_ECB: case CKM_GOST28147_KEY_GEN: case CKM_GOST28147_KEY_WRAP: case CKM_GOST28147_MAC: *gen_mech = CKM_GOST28147_KEY_GEN; break; case CKM_GOSTR3410: case CKM_GOSTR3410_DERIVE: case CKM_GOSTR3410_KEY_PAIR_GEN: case CKM_GOSTR3410_KEY_WRAP: case CKM_GOSTR3410_WITH_GOSTR3411: *gen_mech = CKM_GOSTR3410_KEY_PAIR_GEN; break; case CKM_HOTP: case CKM_HOTP_KEY_GEN: *gen_mech = CKM_HOTP_KEY_GEN; break; case CKM_SECURID: case CKM_SECURID_KEY_GEN: *gen_mech = CKM_SECURID_KEY_GEN; break; case CKM_SEED_CBC: case CKM_SEED_CBC_ENCRYPT_DATA: case CKM_SEED_CBC_PAD: case CKM_SEED_ECB: case CKM_SEED_ECB_ENCRYPT_DATA: case CKM_SEED_KEY_GEN: case CKM_SEED_MAC: case CKM_SEED_MAC_GENERAL: *gen_mech = CKM_SEED_KEY_GEN; break; default: return (CKR_MECHANISM_INVALID); } return (CKR_OK); } /* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License (the "License"). * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at usr/src/OPENSOLARIS.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END */ /* * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. * * Copyright 2016 Jason King. */ #include /* * Get the key type for the given mechanism * * All mechanisms in PKCS #11 v2.40 are listed here. */ CK_RV pkcs11_mech2keytype(CK_MECHANISM_TYPE mech_type, CK_KEY_TYPE *ktype) { CK_RV rv = CKR_OK; switch (mech_type) { case CKM_RSA_PKCS_KEY_PAIR_GEN: case CKM_RSA_PKCS: case CKM_RSA_9796: case CKM_RSA_X_509: case CKM_MD2_RSA_PKCS: case CKM_MD5_RSA_PKCS: case CKM_SHA1_RSA_PKCS: case CKM_SHA256_RSA_PKCS: case CKM_SHA384_RSA_PKCS: case CKM_SHA512_RSA_PKCS: case CKM_SHA256_RSA_PKCS_PSS: case CKM_SHA384_RSA_PKCS_PSS: case CKM_SHA512_RSA_PKCS_PSS: case CKM_SHA224_RSA_PKCS: case CKM_SHA224_RSA_PKCS_PSS: case CKM_RIPEMD128_RSA_PKCS: case CKM_RIPEMD160_RSA_PKCS: case CKM_RSA_PKCS_OAEP: case CKM_RSA_X9_31_KEY_PAIR_GEN: case CKM_RSA_X9_31: case CKM_SHA1_RSA_X9_31: case CKM_RSA_PKCS_PSS: case CKM_SHA1_RSA_PKCS_PSS: case CKM_RSA_PKCS_TPM_1_1: case CKM_RSA_PKCS_OAEP_TPM_1_1: *ktype = CKK_RSA; break; case CKM_DSA_KEY_PAIR_GEN: case CKM_DSA: case CKM_DSA_SHA1: case CKM_DSA_PARAMETER_GEN: case CKM_FORTEZZA_TIMESTAMP: case CKM_DSA_SHA224: case CKM_DSA_SHA256: case CKM_DSA_SHA384: case CKM_DSA_SHA512: *ktype = CKK_DSA; break; case CKM_DH_PKCS_PARAMETER_GEN: case CKM_DH_PKCS_KEY_PAIR_GEN: case CKM_DH_PKCS_DERIVE: *ktype = CKK_DH; break; case CKM_ECDSA: case CKM_ECDSA_SHA1: case CKM_EC_KEY_PAIR_GEN: case CKM_ECDH1_DERIVE: case CKM_ECDH1_COFACTOR_DERIVE: case CKM_ECMQV_DERIVE: *ktype = CKK_EC; break; case CKM_X9_42_DH_KEY_PAIR_GEN: case CKM_X9_42_DH_DERIVE: case CKM_X9_42_DH_HYBRID_DERIVE: case CKM_X9_42_MQV_DERIVE: case CKM_X9_42_DH_PARAMETER_GEN: *ktype = CKK_X9_42_DH; break; case CKM_KEA_KEY_PAIR_GEN: case CKM_KEA_KEY_DERIVE: *ktype = CKK_KEA; break; case CKM_MD2: case CKM_MD2_HMAC: case CKM_MD2_HMAC_GENERAL: case CKM_MD5: case CKM_MD5_HMAC: case CKM_MD5_HMAC_GENERAL: case CKM_SHA_1: case CKM_SHA_1_HMAC: case CKM_SHA_1_HMAC_GENERAL: case CKM_SHA256: case CKM_SHA256_HMAC: case CKM_SHA256_HMAC_GENERAL: case CKM_SHA224: case CKM_SHA224_HMAC: case CKM_SHA224_HMAC_GENERAL: case CKM_SHA384: case CKM_SHA384_HMAC: case CKM_SHA384_HMAC_GENERAL: case CKM_SHA512: case CKM_SHA512_HMAC: case CKM_SHA512_HMAC_GENERAL: case CKM_GENERIC_SECRET_KEY_GEN: case CKM_FASTHASH: case CKM_PKCS5_PBKD2: case CKM_PBA_SHA1_WITH_SHA1_HMAC: case CKM_SSL3_MD5_MAC: case CKM_SSL3_SHA1_MAC: case CKM_SSL3_PRE_MASTER_KEY_GEN: case CKM_SSL3_MASTER_KEY_DERIVE: case CKM_SSL3_KEY_AND_MAC_DERIVE: case CKM_SSL3_MASTER_KEY_DERIVE_DH: case CKM_TLS_PRE_MASTER_KEY_GEN: case CKM_TLS_MASTER_KEY_DERIVE: case CKM_TLS_KEY_AND_MAC_DERIVE: case CKM_TLS_MASTER_KEY_DERIVE_DH: case CKM_TLS_PRF: case CKM_WTLS_PRE_MASTER_KEY_GEN: case CKM_WTLS_MASTER_KEY_DERIVE: case CKM_WTLS_MASTER_KEY_DERIVE_DH_ECC: case CKM_WTLS_PRF: case CKM_WTLS_SERVER_KEY_AND_MAC_DERIVE: case CKM_WTLS_CLIENT_KEY_AND_MAC_DERIVE: case CKM_CONCATENATE_BASE_AND_KEY: case CKM_CONCATENATE_BASE_AND_DATA: case CKM_CONCATENATE_DATA_AND_BASE: case CKM_XOR_BASE_AND_DATA: case CKM_EXTRACT_KEY_FROM_KEY: case CKM_RIPEMD128: case CKM_RIPEMD128_HMAC: case CKM_RIPEMD128_HMAC_GENERAL: case CKM_RIPEMD160: case CKM_RIPEMD160_HMAC: case CKM_RIPEMD160_HMAC_GENERAL: case CKM_SHA1_KEY_DERIVATION: case CKM_SHA256_KEY_DERIVATION: case CKM_SHA384_KEY_DERIVATION: case CKM_SHA512_KEY_DERIVATION: case CKM_SHA224_KEY_DERIVATION: case CKM_MD5_KEY_DERIVATION: case CKM_MD2_KEY_DERIVATION: /* not sure the following 2 should be CKK_DES or not */ case CKM_KEY_WRAP_LYNKS: /* wrap/unwrap secret key w/ DES key */ case CKM_KEY_WRAP_SET_OAEP: /* wrap/unwarp DES key w/ RSA key */ case CKM_SHA512_224: case CKM_SHA512_224_HMAC: case CKM_SHA512_224_HMAC_GENERAL: case CKM_SHA512_224_KEY_DERIVATION: case CKM_SHA512_256: case CKM_SHA512_256_HMAC: case CKM_SHA512_256_HMAC_GENERAL: case CKM_SHA512_256_KEY_DERIVATION: case CKM_SHA512_T: case CKM_SHA512_T_HMAC: case CKM_SHA512_T_HMAC_GENERAL: case CKM_SHA512_T_KEY_DERIVATION: case CKM_TLS10_MAC_SERVER: case CKM_TLS10_MAC_CLIENT: case CKM_TLS12_MAC: case CKM_TLS12_MASTER_KEY_DERIVE: case CKM_TLS12_KEY_AND_MAC_DERIVE: case CKM_TLS12_MASTER_KEY_DERIVE_DH: case CKM_TLS12_KEY_SAFE_DERIVE: case CKM_TLS_MAC: case CKM_TLS_KDF: *ktype = CKK_GENERIC_SECRET; break; case CKM_RC2_KEY_GEN: case CKM_RC2_ECB: case CKM_RC2_CBC: case CKM_RC2_MAC: case CKM_RC2_MAC_GENERAL: case CKM_RC2_CBC_PAD: case CKM_PBE_SHA1_RC2_128_CBC: case CKM_PBE_SHA1_RC2_40_CBC: *ktype = CKK_RC2; break; case CKM_RC4_KEY_GEN: case CKM_RC4: case CKM_PBE_SHA1_RC4_128: case CKM_PBE_SHA1_RC4_40: *ktype = CKK_RC4; break; case CKM_DES_KEY_GEN: case CKM_DES_ECB: case CKM_DES_CBC: case CKM_DES_MAC: case CKM_DES_MAC_GENERAL: case CKM_DES_CBC_PAD: case CKM_PBE_MD2_DES_CBC: case CKM_PBE_MD5_DES_CBC: case CKM_DES_OFB64: case CKM_DES_OFB8: case CKM_DES_CFB64: case CKM_DES_CFB8: case CKM_DES_ECB_ENCRYPT_DATA: case CKM_DES_CBC_ENCRYPT_DATA: *ktype = CKK_DES; break; case CKM_DES2_KEY_GEN: case CKM_PBE_SHA1_DES2_EDE_CBC: *ktype = CKK_DES2; break; case CKM_DES3_KEY_GEN: case CKM_DES3_ECB: case CKM_DES3_CBC: case CKM_DES3_MAC: case CKM_DES3_MAC_GENERAL: case CKM_DES3_CBC_PAD: case CKM_PBE_SHA1_DES3_EDE_CBC: case CKM_DES3_ECB_ENCRYPT_DATA: case CKM_DES3_CBC_ENCRYPT_DATA: *ktype = CKK_DES3; break; case CKM_CAST_KEY_GEN: case CKM_CAST_ECB: case CKM_CAST_CBC: case CKM_CAST_MAC: case CKM_CAST_MAC_GENERAL: case CKM_CAST_CBC_PAD: case CKM_PBE_MD5_CAST_CBC: *ktype = CKK_CAST; break; case CKM_CAST3_KEY_GEN: case CKM_CAST3_ECB: case CKM_CAST3_CBC: case CKM_CAST3_MAC: case CKM_CAST3_MAC_GENERAL: case CKM_CAST3_CBC_PAD: case CKM_PBE_MD5_CAST3_CBC: *ktype = CKK_CAST3; break; case CKM_CAST128_KEY_GEN: case CKM_CAST128_ECB: case CKM_CAST128_CBC: case CKM_CAST128_MAC: case CKM_CAST128_MAC_GENERAL: case CKM_CAST128_CBC_PAD: case CKM_PBE_MD5_CAST128_CBC: case CKM_PBE_SHA1_CAST128_CBC: *ktype = CKK_CAST128; break; case CKM_RC5_KEY_GEN: case CKM_RC5_ECB: case CKM_RC5_CBC: case CKM_RC5_MAC: case CKM_RC5_MAC_GENERAL: case CKM_RC5_CBC_PAD: *ktype = CKK_RC5; break; case CKM_IDEA_KEY_GEN: case CKM_IDEA_ECB: case CKM_IDEA_CBC: case CKM_IDEA_MAC: case CKM_IDEA_MAC_GENERAL: case CKM_IDEA_CBC_PAD: *ktype = CKK_IDEA; break; case CKM_SKIPJACK_KEY_GEN: case CKM_SKIPJACK_ECB64: case CKM_SKIPJACK_CBC64: case CKM_SKIPJACK_OFB64: case CKM_SKIPJACK_CFB64: case CKM_SKIPJACK_CFB32: case CKM_SKIPJACK_CFB16: case CKM_SKIPJACK_CFB8: case CKM_SKIPJACK_WRAP: case CKM_SKIPJACK_PRIVATE_WRAP: case CKM_SKIPJACK_RELAYX: *ktype = CKK_SKIPJACK; break; case CKM_BATON_KEY_GEN: case CKM_BATON_ECB128: case CKM_BATON_ECB96: case CKM_BATON_CBC128: case CKM_BATON_COUNTER: case CKM_BATON_SHUFFLE: case CKM_BATON_WRAP: *ktype = CKK_BATON; break; case CKM_JUNIPER_KEY_GEN: case CKM_JUNIPER_ECB128: case CKM_JUNIPER_CBC128: case CKM_JUNIPER_COUNTER: case CKM_JUNIPER_SHUFFLE: case CKM_JUNIPER_WRAP: *ktype = CKK_JUNIPER; break; case CKM_CDMF_KEY_GEN: case CKM_CDMF_ECB: case CKM_CDMF_CBC: case CKM_CDMF_MAC: case CKM_CDMF_MAC_GENERAL: case CKM_CDMF_CBC_PAD: *ktype = CKK_CDMF; break; case CKM_AES_KEY_GEN: case CKM_AES_ECB: case CKM_AES_CBC: case CKM_AES_MAC: case CKM_AES_MAC_GENERAL: case CKM_AES_CBC_PAD: case CKM_AES_CTR: case CKM_AES_GCM: case CKM_AES_CCM: case CKM_AES_CTS: case CKM_AES_CMAC: case CKM_AES_CMAC_GENERAL: case CKM_AES_XCBC_MAC: case CKM_AES_XCBC_MAC_96: case CKM_AES_GMAC: case CKM_AES_ECB_ENCRYPT_DATA: case CKM_AES_CBC_ENCRYPT_DATA: case CKM_AES_OFB: case CKM_AES_CFB8: case CKM_AES_CFB64: case CKM_AES_CFB128: case CKM_AES_CFB1: case CKM_AES_KEY_WRAP: case CKM_AES_KEY_WRAP_PAD: *ktype = CKK_AES; break; case CKM_BLOWFISH_KEY_GEN: case CKM_BLOWFISH_CBC: case CKM_BLOWFISH_CBC_PAD: *ktype = CKK_BLOWFISH; break; case CKM_TWOFISH_KEY_GEN: case CKM_TWOFISH_CBC: case CKM_TWOFISH_CBC_PAD: *ktype = CKK_TWOFISH; break; case CKM_SECURID_KEY_GEN: case CKM_SECURID: *ktype = CKK_SECURID; break; case CKM_HOTP_KEY_GEN: case CKM_HOTP: *ktype = CKK_HOTP; break; case CKM_ACTI: case CKM_ACTI_KEY_GEN: *ktype = CKK_ACTI; break; case CKM_CAMELLIA_KEY_GEN: case CKM_CAMELLIA_ECB: case CKM_CAMELLIA_CBC: case CKM_CAMELLIA_MAC: case CKM_CAMELLIA_MAC_GENERAL: case CKM_CAMELLIA_CBC_PAD: case CKM_CAMELLIA_ECB_ENCRYPT_DATA: case CKM_CAMELLIA_CBC_ENCRYPT_DATA: case CKM_CAMELLIA_CTR: *ktype = CKK_CAMELLIA; break; case CKM_ARIA_KEY_GEN: case CKM_ARIA_ECB: case CKM_ARIA_CBC: case CKM_ARIA_MAC: case CKM_ARIA_MAC_GENERAL: case CKM_ARIA_CBC_PAD: case CKM_ARIA_ECB_ENCRYPT_DATA: case CKM_ARIA_CBC_ENCRYPT_DATA: *ktype = CKK_ARIA; break; case CKM_GOSTR3410: case CKM_GOSTR3410_WITH_GOSTR3411: case CKM_GOSTR3410_KEY_WRAP: case CKM_GOSTR3410_DERIVE: *ktype = CKK_GOSTR3410; break; case CKM_GOSTR3411: case CKM_GOSTR3411_HMAC: *ktype = CKK_GOSTR3411; break; case CKM_GOST28147_KEY_GEN: case CKM_GOST28147_ECB: case CKM_GOST28147: case CKM_GOST28147_MAC: case CKM_GOST28147_KEY_WRAP: *ktype = CKK_GOST28147; break; default: rv = CKR_MECHANISM_INVALID; break; } return (rv); } /* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License (the "License"). * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at usr/src/OPENSOLARIS.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END */ /* * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. * Copyright 2016 Jason King */ /* * Convert Algorithm names as strings to PKCS#11 Mech numbers and vice versa. */ #include #include #include #include #include #include #include /* * This table is a one-to-one mapping between mechanism names and numbers. * As such, it should not contain deprecated mechanism names (aliases). */ typedef struct { const char *str; CK_MECHANISM_TYPE mech; } pkcs11_mapping_t; /* * Note: elements in this table MUST be in numeric order, * since bsearch(3C) is used to search this table. */ static const pkcs11_mapping_t mapping[] = { { "CKM_RSA_PKCS_KEY_PAIR_GEN", CKM_RSA_PKCS_KEY_PAIR_GEN }, { "CKM_RSA_PKCS", CKM_RSA_PKCS }, { "CKM_RSA_9796", CKM_RSA_9796 }, { "CKM_RSA_X_509", CKM_RSA_X_509 }, { "CKM_MD2_RSA_PKCS", CKM_MD2_RSA_PKCS }, { "CKM_MD5_RSA_PKCS", CKM_MD5_RSA_PKCS }, { "CKM_SHA1_RSA_PKCS", CKM_SHA1_RSA_PKCS }, { "CKM_RIPEMD128_RSA_PKCS", CKM_RIPEMD128_RSA_PKCS }, { "CKM_RIPEMD160_RSA_PKCS", CKM_RIPEMD160_RSA_PKCS }, { "CKM_RSA_PKCS_OAEP", CKM_RSA_PKCS_OAEP }, { "CKM_RSA_X9_31_KEY_PAIR_GEN", CKM_RSA_X9_31_KEY_PAIR_GEN }, { "CKM_RSA_X9_31", CKM_RSA_X9_31 }, { "CKM_SHA1_RSA_X9_31", CKM_SHA1_RSA_X9_31 }, { "CKM_RSA_PKCS_PSS", CKM_RSA_PKCS_PSS }, { "CKM_SHA1_RSA_PKCS_PSS", CKM_SHA1_RSA_PKCS_PSS }, { "CKM_DSA_KEY_PAIR_GEN", CKM_DSA_KEY_PAIR_GEN }, { "CKM_DSA", CKM_DSA }, { "CKM_DSA_SHA1", CKM_DSA_SHA1 }, { "CKM_DSA_SHA224", CKM_DSA_SHA224 }, { "CKM_DSA_SHA256", CKM_DSA_SHA256 }, { "CKM_DSA_SHA384", CKM_DSA_SHA384 }, { "CKM_DSA_SHA512", CKM_DSA_SHA512 }, { "CKM_DH_PKCS_KEY_PAIR_GEN", CKM_DH_PKCS_KEY_PAIR_GEN }, { "CKM_DH_PKCS_DERIVE", CKM_DH_PKCS_DERIVE }, { "CKM_X9_42_DH_KEY_PAIR_GEN", CKM_X9_42_DH_KEY_PAIR_GEN }, { "CKM_X9_42_DH_DERIVE", CKM_X9_42_DH_DERIVE }, { "CKM_X9_42_DH_HYBRID_DERIVE", CKM_X9_42_DH_HYBRID_DERIVE }, { "CKM_X9_42_MQV_DERIVE", CKM_X9_42_MQV_DERIVE }, { "CKM_SHA256_RSA_PKCS", CKM_SHA256_RSA_PKCS }, { "CKM_SHA384_RSA_PKCS", CKM_SHA384_RSA_PKCS }, { "CKM_SHA512_RSA_PKCS", CKM_SHA512_RSA_PKCS }, { "CKM_SHA256_RSA_PKCS_PSS", CKM_SHA256_RSA_PKCS_PSS }, { "CKM_SHA384_RSA_PKCS_PSS", CKM_SHA384_RSA_PKCS_PSS }, { "CKM_SHA512_RSA_PKCS_PSS", CKM_SHA512_RSA_PKCS_PSS }, { "CKM_SHA224_RSA_PKCS", CKM_SHA224_RSA_PKCS }, { "CKM_SHA224_RSA_PKCS_PSS", CKM_SHA224_RSA_PKCS_PSS }, { "CKM_SHA512_224", CKM_SHA512_224 }, { "CKM_SHA512_224_HMAC", CKM_SHA512_224_HMAC }, { "CKM_SHA512_224_HMAC_GENERAL", CKM_SHA512_224_HMAC_GENERAL }, { "CKM_SHA512_224_KEY_DERIVATION", CKM_SHA512_224_KEY_DERIVATION }, { "CKM_SHA512_256", CKM_SHA512_256 }, { "CKM_SHA512_256_HMAC", CKM_SHA512_256_HMAC }, { "CKM_SHA512_256_HMAC_GENERAL", CKM_SHA512_256_HMAC_GENERAL }, { "CKM_SHA512_256_KEY_DERIVATION", CKM_SHA512_256_KEY_DERIVATION }, { "CKM_SHA512_T", CKM_SHA512_T }, { "CKM_SHA512_T_HMAC", CKM_SHA512_T_HMAC }, { "CKM_SHA512_T_HMAC_GENERAL", CKM_SHA512_T_HMAC_GENERAL }, { "CKM_SHA512_T_KEY_DERIVATION", CKM_SHA512_T_KEY_DERIVATION }, { "CKM_RC2_KEY_GEN", CKM_RC2_KEY_GEN }, { "CKM_RC2_ECB", CKM_RC2_ECB }, { "CKM_RC2_CBC", CKM_RC2_CBC }, { "CKM_RC2_MAC", CKM_RC2_MAC }, { "CKM_RC2_MAC_GENERAL", CKM_RC2_MAC_GENERAL }, { "CKM_RC2_CBC_PAD", CKM_RC2_CBC_PAD }, { "CKM_RC4_KEY_GEN", CKM_RC4_KEY_GEN }, { "CKM_RC4", CKM_RC4 }, { "CKM_DES_KEY_GEN", CKM_DES_KEY_GEN }, { "CKM_DES_ECB", CKM_DES_ECB }, { "CKM_DES_CBC", CKM_DES_CBC }, { "CKM_DES_MAC", CKM_DES_MAC }, { "CKM_DES_MAC_GENERAL", CKM_DES_MAC_GENERAL }, { "CKM_DES_CBC_PAD", CKM_DES_CBC_PAD }, { "CKM_DES2_KEY_GEN", CKM_DES2_KEY_GEN }, { "CKM_DES3_KEY_GEN", CKM_DES3_KEY_GEN }, { "CKM_DES3_ECB", CKM_DES3_ECB }, { "CKM_DES3_CBC", CKM_DES3_CBC }, { "CKM_DES3_MAC", CKM_DES3_MAC }, { "CKM_DES3_MAC_GENERAL", CKM_DES3_MAC_GENERAL }, { "CKM_DES3_CBC_PAD", CKM_DES3_CBC_PAD }, { "CKM_DES3_CMAC_GENERAL", CKM_DES3_CMAC_GENERAL }, { "CKM_DES3_CMAC", CKM_DES3_CMAC }, { "CKM_CDMF_KEY_GEN", CKM_CDMF_KEY_GEN }, { "CKM_CDMF_ECB", CKM_CDMF_ECB }, { "CKM_CDMF_CBC", CKM_CDMF_CBC }, { "CKM_CDMF_MAC", CKM_CDMF_MAC }, { "CKM_CDMF_MAC_GENERAL", CKM_CDMF_MAC_GENERAL }, { "CKM_CDMF_CBC_PAD", CKM_CDMF_CBC_PAD }, { "CKM_DES_OFB64", CKM_DES_OFB64 }, { "CKM_DES_OFB8", CKM_DES_OFB8 }, { "CKM_DES_CFB64", CKM_DES_CFB64 }, { "CKM_DES_CFB8", CKM_DES_CFB8 }, { "CKM_MD2", CKM_MD2 }, { "CKM_MD2_HMAC", CKM_MD2_HMAC }, { "CKM_MD2_HMAC_GENERAL", CKM_MD2_HMAC_GENERAL }, { "CKM_MD5", CKM_MD5 }, { "CKM_MD5_HMAC", CKM_MD5_HMAC }, { "CKM_MD5_HMAC_GENERAL", CKM_MD5_HMAC_GENERAL }, { "CKM_SHA_1", CKM_SHA_1 }, { "CKM_SHA_1_HMAC", CKM_SHA_1_HMAC }, { "CKM_SHA_1_HMAC_GENERAL", CKM_SHA_1_HMAC_GENERAL }, { "CKM_RIPEMD128", CKM_RIPEMD128 }, { "CKM_RIPEMD128_HMAC", CKM_RIPEMD128_HMAC }, { "CKM_RIPEMD128_HMAC_GENERAL", CKM_RIPEMD128_HMAC_GENERAL }, { "CKM_RIPEMD160", CKM_RIPEMD160 }, { "CKM_RIPEMD160_HMAC", CKM_RIPEMD160_HMAC }, { "CKM_RIPEMD160_HMAC_GENERAL", CKM_RIPEMD160_HMAC_GENERAL }, { "CKM_SHA256", CKM_SHA256 }, { "CKM_SHA256_HMAC", CKM_SHA256_HMAC }, { "CKM_SHA256_HMAC_GENERAL", CKM_SHA256_HMAC_GENERAL }, { "CKM_SHA224", CKM_SHA224 }, { "CKM_SHA224_HMAC", CKM_SHA224_HMAC }, { "CKM_SHA224_HMAC_GENERAL", CKM_SHA224_HMAC_GENERAL }, { "CKM_SHA384", CKM_SHA384 }, { "CKM_SHA384_HMAC", CKM_SHA384_HMAC }, { "CKM_SHA384_HMAC_GENERAL", CKM_SHA384_HMAC_GENERAL }, { "CKM_SHA512", CKM_SHA512 }, { "CKM_SHA512_HMAC", CKM_SHA512_HMAC }, { "CKM_SHA512_HMAC_GENERAL", CKM_SHA512_HMAC_GENERAL }, { "CKM_SECURID_KEY_GEN", CKM_SECURID_KEY_GEN }, { "CKM_SECURID", CKM_SECURID }, { "CKM_HOTP_KEY_GEN", CKM_HOTP_KEY_GEN }, { "CKM_HOTP", CKM_HOTP }, { "CKM_ACTI", CKM_ACTI }, { "CKM_ACTI_KEY_GEN", CKM_ACTI_KEY_GEN }, { "CKM_CAST_KEY_GEN", CKM_CAST_KEY_GEN }, { "CKM_CAST_ECB", CKM_CAST_ECB }, { "CKM_CAST_CBC", CKM_CAST_CBC }, { "CKM_CAST_MAC", CKM_CAST_MAC }, { "CKM_CAST_MAC_GENERAL", CKM_CAST_MAC_GENERAL }, { "CKM_CAST_CBC_PAD", CKM_CAST_CBC_PAD }, { "CKM_CAST3_KEY_GEN", CKM_CAST3_KEY_GEN }, { "CKM_CAST3_ECB", CKM_CAST3_ECB }, { "CKM_CAST3_CBC", CKM_CAST3_CBC }, { "CKM_CAST3_MAC", CKM_CAST3_MAC }, { "CKM_CAST3_MAC_GENERAL", CKM_CAST3_MAC_GENERAL }, { "CKM_CAST3_CBC_PAD", CKM_CAST3_CBC_PAD }, { "CKM_CAST5_KEY_GEN", CKM_CAST5_KEY_GEN }, { "CKM_CAST128_KEY_GEN", CKM_CAST128_KEY_GEN }, { "CKM_CAST5_ECB", CKM_CAST5_ECB }, { "CKM_CAST128_ECB", CKM_CAST128_ECB }, { "CKM_CAST5_CBC", CKM_CAST5_CBC }, { "CKM_CAST128_CBC", CKM_CAST128_CBC }, { "CKM_CAST5_MAC", CKM_CAST5_MAC }, { "CKM_CAST128_MAC", CKM_CAST128_MAC }, { "CKM_CAST5_MAC_GENERAL", CKM_CAST5_MAC_GENERAL }, { "CKM_CAST128_MAC_GENERAL", CKM_CAST128_MAC_GENERAL }, { "CKM_CAST5_CBC_PAD", CKM_CAST5_CBC_PAD }, { "CKM_CAST128_CBC_PAD", CKM_CAST128_CBC_PAD }, { "CKM_RC5_KEY_GEN", CKM_RC5_KEY_GEN }, { "CKM_RC5_ECB", CKM_RC5_ECB }, { "CKM_RC5_CBC", CKM_RC5_CBC }, { "CKM_RC5_MAC", CKM_RC5_MAC }, { "CKM_RC5_MAC_GENERAL", CKM_RC5_MAC_GENERAL }, { "CKM_RC5_CBC_PAD", CKM_RC5_CBC_PAD }, { "CKM_IDEA_KEY_GEN", CKM_IDEA_KEY_GEN }, { "CKM_IDEA_ECB", CKM_IDEA_ECB }, { "CKM_IDEA_CBC", CKM_IDEA_CBC }, { "CKM_IDEA_MAC", CKM_IDEA_MAC }, { "CKM_IDEA_MAC_GENERAL", CKM_IDEA_MAC_GENERAL }, { "CKM_IDEA_CBC_PAD", CKM_IDEA_CBC_PAD }, { "CKM_GENERIC_SECRET_KEY_GEN", CKM_GENERIC_SECRET_KEY_GEN }, { "CKM_CONCATENATE_BASE_AND_KEY", CKM_CONCATENATE_BASE_AND_KEY }, { "CKM_CONCATENATE_BASE_AND_DATA", CKM_CONCATENATE_BASE_AND_DATA }, { "CKM_CONCATENATE_DATA_AND_BASE", CKM_CONCATENATE_DATA_AND_BASE }, { "CKM_XOR_BASE_AND_DATA", CKM_XOR_BASE_AND_DATA }, { "CKM_EXTRACT_KEY_FROM_KEY", CKM_EXTRACT_KEY_FROM_KEY }, { "CKM_SSL3_PRE_MASTER_KEY_GEN", CKM_SSL3_PRE_MASTER_KEY_GEN }, { "CKM_SSL3_MASTER_KEY_DERIVE", CKM_SSL3_MASTER_KEY_DERIVE }, { "CKM_SSL3_KEY_AND_MAC_DERIVE", CKM_SSL3_KEY_AND_MAC_DERIVE }, { "CKM_SSL3_MASTER_KEY_DERIVE_DH", CKM_SSL3_MASTER_KEY_DERIVE_DH }, { "CKM_TLS_PRE_MASTER_KEY_GEN", CKM_TLS_PRE_MASTER_KEY_GEN }, { "CKM_TLS_MASTER_KEY_DERIVE", CKM_TLS_MASTER_KEY_DERIVE }, { "CKM_TLS_KEY_AND_MAC_DERIVE", CKM_TLS_KEY_AND_MAC_DERIVE }, { "CKM_TLS_MASTER_KEY_DERIVE_DH", CKM_TLS_MASTER_KEY_DERIVE_DH }, { "CKM_TLS_PRF", CKM_TLS_PRF }, { "CKM_SSL3_MD5_MAC", CKM_SSL3_MD5_MAC }, { "CKM_SSL3_SHA1_MAC", CKM_SSL3_SHA1_MAC }, { "CKM_MD5_KEY_DERIVATION", CKM_MD5_KEY_DERIVATION }, { "CKM_MD2_KEY_DERIVATION", CKM_MD2_KEY_DERIVATION }, { "CKM_SHA1_KEY_DERIVATION", CKM_SHA1_KEY_DERIVATION }, { "CKM_SHA256_KEY_DERIVATION", CKM_SHA256_KEY_DERIVATION }, { "CKM_SHA384_KEY_DERIVATION", CKM_SHA384_KEY_DERIVATION }, { "CKM_SHA512_KEY_DERIVATION", CKM_SHA512_KEY_DERIVATION }, { "CKM_SHA224_KEY_DERIVATION", CKM_SHA224_KEY_DERIVATION }, { "CKM_PBE_MD2_DES_CBC", CKM_PBE_MD2_DES_CBC }, { "CKM_PBE_MD5_DES_CBC", CKM_PBE_MD5_DES_CBC }, { "CKM_PBE_MD5_CAST_CBC", CKM_PBE_MD5_CAST_CBC }, { "CKM_PBE_MD5_CAST3_CBC", CKM_PBE_MD5_CAST3_CBC }, { "CKM_PBE_MD5_CAST5_CBC", CKM_PBE_MD5_CAST5_CBC }, { "CKM_PBE_MD5_CAST128_CBC", CKM_PBE_MD5_CAST128_CBC }, { "CKM_PBE_SHA1_CAST5_CBC", CKM_PBE_SHA1_CAST5_CBC }, { "CKM_PBE_SHA1_CAST128_CBC", CKM_PBE_SHA1_CAST128_CBC }, { "CKM_PBE_SHA1_RC4_128", CKM_PBE_SHA1_RC4_128 }, { "CKM_PBE_SHA1_RC4_40", CKM_PBE_SHA1_RC4_40 }, { "CKM_PBE_SHA1_DES3_EDE_CBC", CKM_PBE_SHA1_DES3_EDE_CBC }, { "CKM_PBE_SHA1_DES2_EDE_CBC", CKM_PBE_SHA1_DES2_EDE_CBC }, { "CKM_PBE_SHA1_RC2_128_CBC", CKM_PBE_SHA1_RC2_128_CBC }, { "CKM_PBE_SHA1_RC2_40_CBC", CKM_PBE_SHA1_RC2_40_CBC }, { "CKM_PKCS5_PBKD2", CKM_PKCS5_PBKD2 }, { "CKM_PBA_SHA1_WITH_SHA1_HMAC", CKM_PBA_SHA1_WITH_SHA1_HMAC }, { "CKM_WTLS_PRE_MASTER_KEY_GEN", CKM_WTLS_PRE_MASTER_KEY_GEN }, { "CKM_WTLS_MASTER_KEY_DERIVE", CKM_WTLS_MASTER_KEY_DERIVE }, { "CKM_WTLS_MASTER_KEY_DERIVE_DH_ECC", CKM_WTLS_MASTER_KEY_DERIVE_DH_ECC }, { "CKM_WTLS_PRF", CKM_WTLS_PRF }, { "CKM_WTLS_SERVER_KEY_AND_MAC_DERIVE", CKM_WTLS_SERVER_KEY_AND_MAC_DERIVE }, { "CKM_WTLS_CLIENT_KEY_AND_MAC_DERIVE", CKM_WTLS_CLIENT_KEY_AND_MAC_DERIVE }, { "CKM_TLS10_MAC_SERVER", CKM_TLS10_MAC_SERVER }, { "CKM_TLS10_MAC_CLIENT", CKM_TLS10_MAC_CLIENT }, { "CKM_TLS12_MAC", CKM_TLS12_MAC }, { "CKM_TLS12_KDF", CKM_TLS12_KDF }, { "CKM_TLS12_MASTER_KEY_DERIVE", CKM_TLS12_MASTER_KEY_DERIVE }, { "CKM_TLS12_KEY_AND_MAC_DERIVE", CKM_TLS12_KEY_AND_MAC_DERIVE }, { "CKM_TLS12_MASTER_KEY_DERIVE_DH", CKM_TLS12_MASTER_KEY_DERIVE_DH }, { "CKM_TLS12_KEY_SAFE_DERIVE", CKM_TLS12_KEY_SAFE_DERIVE }, { "CKM_TLS_MAC", CKM_TLS_MAC }, { "CKM_TLS_KDF", CKM_TLS_KDF }, { "CKM_KEY_WRAP_LYNKS", CKM_KEY_WRAP_LYNKS }, { "CKM_KEY_WRAP_SET_OAEP", CKM_KEY_WRAP_SET_OAEP }, { "CKM_CMS_SIG", CKM_CMS_SIG }, { "CKM_KIP_DERIVE", CKM_KIP_DERIVE }, { "CKM_KIP_WRAP", CKM_KIP_WRAP }, { "CKM_KIP_MAC", CKM_KIP_MAC }, { "CKM_CAMELLIA_KEY_GEN", CKM_CAMELLIA_KEY_GEN }, { "CKM_CAMELLIA_ECB", CKM_CAMELLIA_ECB }, { "CKM_CAMELLIA_CBC", CKM_CAMELLIA_CBC }, { "CKM_CAMELLIA_MAC", CKM_CAMELLIA_MAC }, { "CKM_CAMELLIA_MAC_GENERAL", CKM_CAMELLIA_MAC_GENERAL }, { "CKM_CAMELLIA_CBC_PAD", CKM_CAMELLIA_CBC_PAD }, { "CKM_CAMELLIA_ECB_ENCRYPT_DATA", CKM_CAMELLIA_ECB_ENCRYPT_DATA }, { "CKM_CAMELLIA_CBC_ENCRYPT_DATA", CKM_CAMELLIA_CBC_ENCRYPT_DATA }, { "CKM_CAMELLIA_CTR", CKM_CAMELLIA_CTR }, { "CKM_ARIA_KEY_GEN", CKM_ARIA_KEY_GEN }, { "CKM_ARIA_ECB", CKM_ARIA_ECB }, { "CKM_ARIA_CBC", CKM_ARIA_CBC }, { "CKM_ARIA_MAC", CKM_ARIA_MAC }, { "CKM_ARIA_MAC_GENERAL", CKM_ARIA_MAC_GENERAL }, { "CKM_ARIA_CBC_PAD", CKM_ARIA_CBC_PAD }, { "CKM_ARIA_ECB_ENCRYPT_DATA", CKM_ARIA_ECB_ENCRYPT_DATA }, { "CKM_ARIA_CBC_ENCRYPT_DATA", CKM_ARIA_CBC_ENCRYPT_DATA }, { "CKM_SEED_KEY_GEN", CKM_SEED_KEY_GEN }, { "CKM_SEED_ECB", CKM_SEED_ECB }, { "CKM_SEED_CBC", CKM_SEED_CBC }, { "CKM_SEED_MAC", CKM_SEED_MAC }, { "CKM_SEED_MAC_GENERAL", CKM_SEED_MAC_GENERAL }, { "CKM_SEED_CBC_PAD", CKM_SEED_CBC_PAD }, { "CKM_SEED_ECB_ENCRYPT_DATA", CKM_SEED_ECB_ENCRYPT_DATA }, { "CKM_SEED_CBC_ENCRYPT_DATA", CKM_SEED_CBC_ENCRYPT_DATA }, { "CKM_SKIPJACK_KEY_GEN", CKM_SKIPJACK_KEY_GEN }, { "CKM_SKIPJACK_ECB64", CKM_SKIPJACK_ECB64 }, { "CKM_SKIPJACK_CBC64", CKM_SKIPJACK_CBC64 }, { "CKM_SKIPJACK_OFB64", CKM_SKIPJACK_OFB64 }, { "CKM_SKIPJACK_CFB64", CKM_SKIPJACK_CFB64 }, { "CKM_SKIPJACK_CFB32", CKM_SKIPJACK_CFB32 }, { "CKM_SKIPJACK_CFB16", CKM_SKIPJACK_CFB16 }, { "CKM_SKIPJACK_CFB8", CKM_SKIPJACK_CFB8 }, { "CKM_SKIPJACK_WRAP", CKM_SKIPJACK_WRAP }, { "CKM_SKIPJACK_PRIVATE_WRAP", CKM_SKIPJACK_PRIVATE_WRAP }, { "CKM_SKIPJACK_RELAYX", CKM_SKIPJACK_RELAYX }, { "CKM_KEA_KEY_PAIR_GEN", CKM_KEA_KEY_PAIR_GEN }, { "CKM_KEA_KEY_DERIVE", CKM_KEA_KEY_DERIVE }, { "CKM_KEA_DERIVE", CKM_KEA_DERIVE }, { "CKM_FORTEZZA_TIMESTAMP", CKM_FORTEZZA_TIMESTAMP }, { "CKM_BATON_KEY_GEN", CKM_BATON_KEY_GEN }, { "CKM_BATON_ECB128", CKM_BATON_ECB128 }, { "CKM_BATON_ECB96", CKM_BATON_ECB96 }, { "CKM_BATON_CBC128", CKM_BATON_CBC128 }, { "CKM_BATON_COUNTER", CKM_BATON_COUNTER }, { "CKM_BATON_SHUFFLE", CKM_BATON_SHUFFLE }, { "CKM_BATON_WRAP", CKM_BATON_WRAP }, { "CKM_ECDSA_KEY_PAIR_GEN", CKM_ECDSA_KEY_PAIR_GEN }, { "CKM_EC_KEY_PAIR_GEN", CKM_EC_KEY_PAIR_GEN }, { "CKM_ECDSA", CKM_ECDSA }, { "CKM_ECDSA_SHA1", CKM_ECDSA_SHA1 }, { "CKM_ECDSA_SHA224", CKM_ECDSA_SHA224 }, { "CKM_ECDSA_SHA256", CKM_ECDSA_SHA256 }, { "CKM_ECDSA_SHA384", CKM_ECDSA_SHA384 }, { "CKM_ECDSA_SHA512", CKM_ECDSA_SHA512 }, { "CKM_ECDH1_DERIVE", CKM_ECDH1_DERIVE }, { "CKM_ECDH1_COFACTOR_DERIVE", CKM_ECDH1_COFACTOR_DERIVE }, { "CKM_ECMQV_DERIVE", CKM_ECMQV_DERIVE }, { "CKM_ECDH_AES_KEY_WRAP", CKM_ECDH_AES_KEY_WRAP }, { "CKM_RSA_AES_KEY_WRAP", CKM_RSA_AES_KEY_WRAP }, { "CKM_JUNIPER_KEY_GEN", CKM_JUNIPER_KEY_GEN }, { "CKM_JUNIPER_ECB128", CKM_JUNIPER_ECB128 }, { "CKM_JUNIPER_CBC128", CKM_JUNIPER_CBC128 }, { "CKM_JUNIPER_COUNTER", CKM_JUNIPER_COUNTER }, { "CKM_JUNIPER_SHUFFLE", CKM_JUNIPER_SHUFFLE }, { "CKM_JUNIPER_WRAP", CKM_JUNIPER_WRAP }, { "CKM_FASTHASH", CKM_FASTHASH }, { "CKM_AES_KEY_GEN", CKM_AES_KEY_GEN }, { "CKM_AES_ECB", CKM_AES_ECB }, { "CKM_AES_CBC", CKM_AES_CBC }, { "CKM_AES_MAC", CKM_AES_MAC }, { "CKM_AES_MAC_GENERAL", CKM_AES_MAC_GENERAL }, { "CKM_AES_CBC_PAD", CKM_AES_CBC_PAD }, { "CKM_AES_CTR", CKM_AES_CTR }, { "CKM_AES_GCM", CKM_AES_GCM }, { "CKM_AES_CCM", CKM_AES_CCM }, { "CKM_AES_CTS", CKM_AES_CTS }, { "CKM_AES_CMAC", CKM_AES_CMAC }, { "CKM_AES_CMAC_GENERAL", CKM_AES_CMAC_GENERAL }, { "CKM_AES_XCBC_MAC", CKM_AES_XCBC_MAC }, { "CKM_AES_XCBC_MAC_96", CKM_AES_XCBC_MAC_96 }, { "CKM_AES_GMAC", CKM_AES_GMAC }, { "CKM_BLOWFISH_KEY_GEN", CKM_BLOWFISH_KEY_GEN }, { "CKM_BLOWFISH_CBC", CKM_BLOWFISH_CBC }, { "CKM_TWOFISH_KEY_GEN", CKM_TWOFISH_KEY_GEN }, { "CKM_TWOFISH_CBC", CKM_TWOFISH_CBC }, { "CKM_BLOWFISH_CBC_PAD", CKM_BLOWFISH_CBC_PAD }, { "CKM_TWOFISH_CBC_PAD", CKM_TWOFISH_CBC_PAD }, { "CKM_DES_ECB_ENCRYPT_DATA", CKM_DES_ECB_ENCRYPT_DATA }, { "CKM_DES_CBC_ENCRYPT_DATA", CKM_DES_CBC_ENCRYPT_DATA }, { "CKM_DES3_ECB_ENCRYPT_DATA", CKM_DES3_ECB_ENCRYPT_DATA }, { "CKM_DES3_CBC_ENCRYPT_DATA", CKM_DES3_CBC_ENCRYPT_DATA }, { "CKM_AES_ECB_ENCRYPT_DATA", CKM_AES_ECB_ENCRYPT_DATA }, { "CKM_AES_CBC_ENCRYPT_DATA", CKM_AES_CBC_ENCRYPT_DATA }, { "CKM_GOSTR3410_KEY_PAIR_GEN", CKM_GOSTR3410_KEY_PAIR_GEN }, { "CKM_GOSTR3410", CKM_GOSTR3410 }, { "CKM_GOSTR3410_WITH_GOSTR3411", CKM_GOSTR3410_WITH_GOSTR3411 }, { "CKM_GOSTR3410_KEY_WRAP", CKM_GOSTR3410_KEY_WRAP }, { "CKM_GOSTR3410_DERIVE", CKM_GOSTR3410_DERIVE }, { "CKM_GOSTR3411", CKM_GOSTR3411 }, { "CKM_GOSTR3411_HMAC", CKM_GOSTR3411_HMAC }, { "CKM_GOST28147_KEY_GEN", CKM_GOST28147_KEY_GEN }, { "CKM_GOST28147_ECB", CKM_GOST28147_ECB }, { "CKM_GOST28147", CKM_GOST28147 }, { "CKM_GOST28147_MAC", CKM_GOST28147_MAC }, { "CKM_GOST28147_KEY_WRAP", CKM_GOST28147_KEY_WRAP }, { "CKM_DSA_PARAMETER_GEN", CKM_DSA_PARAMETER_GEN }, { "CKM_DH_PKCS_PARAMETER_GEN", CKM_DH_PKCS_PARAMETER_GEN }, { "CKM_X9_42_DH_PARAMETER_GEN", CKM_X9_42_DH_PARAMETER_GEN }, { "CKM_DSA_PROBABLISTIC_PARAMETER_GEN", CKM_DSA_PROBABLISTIC_PARAMETER_GEN }, { "CKM_DSA_SHAWE_TAYLOR_PARAMETER_GEN", CKM_DSA_SHAWE_TAYLOR_PARAMETER_GEN }, { "CKM_AES_OFB", CKM_AES_OFB }, { "CKM_AES_CFB64", CKM_AES_CFB64 }, { "CKM_AES_CFB8", CKM_AES_CFB8 }, { "CKM_AES_CFB128", CKM_AES_CFB128 }, { "CKM_AES_CFB1", CKM_AES_CFB1 }, { "CKM_AES_KEY_WRAP", CKM_AES_KEY_WRAP }, { "CKM_AES_KEY_WRAP_PAD", CKM_AES_KEY_WRAP_PAD }, { "CKM_RSA_PKCS_TPM_1_1", CKM_RSA_PKCS_TPM_1_1 }, { "CKM_RSA_PKCS_OAEP_TPM_1_1", CKM_RSA_PKCS_OAEP_TPM_1_1 }, /* * Values >= 0x8000000 (CKM_VENDOR_DEFINED) are represented * as strings with hexadecimal numbers (e.g., "0x8123456"). */ { NULL, 0 } }; /* * pkcs11_mech_comp - compare two pkcs11_mapping_t structures * * Return a strcmp-like result (positive, zero, or negative). * For use with bsearch(3C) in pkcs11_mech2str(). */ static int pkcs11_mech_comp(const void *mapping1, const void *mapping2) { return (((pkcs11_mapping_t *)mapping1)->mech - ((pkcs11_mapping_t *)mapping2)->mech); } /* * pkcs11_mech2str - convert PKCS#11 mech to a string * * Anything below CKM_VENDOR_DEFINED that wasn't in the mapping table * at build time causes NULL to be returned. Anything above it also * returns NULL since we have no way to know its real name. */ const char *pkcs11_mech2str(CK_MECHANISM_TYPE mech) { pkcs11_mapping_t target; pkcs11_mapping_t *result = NULL; if (mech >= CKM_VENDOR_DEFINED) { return (NULL); } /* Search for the mechanism number using bsearch(3C) */ target.mech = mech; target.str = NULL; result = (pkcs11_mapping_t *)bsearch((void *)&target, (void *)mapping, (sizeof (mapping) / sizeof (pkcs11_mapping_t)) - 1, sizeof (pkcs11_mapping_t), pkcs11_mech_comp); if (result != NULL) { return (result->str); } return (NULL); } /* * pkcs11_str2mech - convert a string into a PKCS#11 mech number. * * Since there isn't a reserved value for an invalid mech we return * CKR_MECHANISM_INVALID for anything we don't recognise. * The value in mech isn't meaningful in these cases. */ CK_RV pkcs11_str2mech(char *mech_str, CK_MECHANISM_TYPE_PTR mech) { int i; int compare_off = 0; if (mech_str == NULL) return (CKR_MECHANISM_INVALID); if (strncasecmp(mech_str, "0x", 2) == 0) { long long llnum; cryptodebug("pkcs11_str2mech: hex string passed in: %s", mech_str); llnum = strtoll(mech_str, NULL, 16); if ((llnum >= CKM_VENDOR_DEFINED) && (llnum <= UINT_MAX)) { *mech = llnum; return (CKR_OK); } else { return (CKR_MECHANISM_INVALID); } } /* If there's no CKM_ prefix, then ignore it in comparisons */ if (strncasecmp(mech_str, "CKM_", 4) != 0) { cryptodebug("pkcs11_str2mech: no CKM_ prefix: %s", mech_str); cryptodebug("pkcs11_str2mech: with prefix: CKM_%s", mech_str); compare_off = 4; } /* Linear search for a matching string */ for (i = 0; mapping[i].str; i++) { if (strcasecmp(&mapping[i].str[compare_off], mech_str) == 0) { *mech = mapping[i].mech; return (CKR_OK); } } return (CKR_MECHANISM_INVALID); } /* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License (the "License"). * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at usr/src/OPENSOLARIS.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END */ /* * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ #include #include #include #include #include #define MAX_PASS_TRIES 5 /* maximum tries to get passphrase */ #define DEFAULT_TOKEN_PROMPT gettext("Enter PIN for %s: ") #define DEFAULT_TOKEN_REPROMPT gettext("Re-enter PIN for %s: ") #define DEFAULT_TOKEN_MINSIZE gettext("PIN must be at least %d characters.\n") #define DEFAULT_USER_PROMPT gettext("Enter passphrase: ") #define DEFAULT_USER_REPROMPT gettext("Re-enter passphrase: ") #define DEFAULT_USER_MINSIZE \ gettext("Passphrase must be at least %d characters.\n") #define DEFAULT_PK11TOKEN SOFT_TOKEN_LABEL /* * Default token name */ char * pkcs11_default_token(void) { return (DEFAULT_PK11TOKEN); } /* * Prompt user for a passphrase or the PIN for a token. * * An optional minimum length can be enforced. Caller can optionally also * reprompt for the passphrase/PIN to confirm it was entered correctly. * The caller must free the buffer containing the passphrase/PIN with free(). * 0 returned for success, -1 for failure with the first passphrase/PIN, * -2 for failure with the optional second passphrase/PIN used to confirm. */ int pkcs11_get_pass(char *token_name, char **pdata, size_t *psize, size_t min_psize, boolean_t with_confirmation) { char prompt[1024]; char *tmpbuf = NULL; char *databuf = NULL; int tries; if (token_name != NULL) (void) snprintf(prompt, sizeof (prompt), DEFAULT_TOKEN_PROMPT, token_name); else (void) snprintf(prompt, sizeof (prompt), DEFAULT_USER_PROMPT); for (tries = MAX_PASS_TRIES; tries > 0; tries--) { tmpbuf = getpassphrase(prompt); if (tmpbuf == NULL) return (-1); if (strnlen(tmpbuf, min_psize) >= min_psize) break; if (token_name != NULL) (void) printf(DEFAULT_TOKEN_MINSIZE, min_psize); else (void) printf(DEFAULT_USER_MINSIZE, min_psize); } if (tries == 0) { (void) printf(gettext("Exceeded number of attempts.\n")); return (-1); } databuf = strdup(tmpbuf); (void) memset(tmpbuf, 0, strlen(tmpbuf)); /* clean up */ if (databuf == NULL) return (-1); if (with_confirmation) { if (token_name != NULL) (void) snprintf(prompt, sizeof (prompt), DEFAULT_TOKEN_REPROMPT, token_name); else (void) snprintf(prompt, sizeof (prompt), DEFAULT_USER_REPROMPT); tmpbuf = getpassphrase(prompt); if (tmpbuf == NULL) { /* clean up */ (void) memset(databuf, 0, strlen(databuf)); free(databuf); return (-2); } if (strcmp(databuf, tmpbuf) != 0) { /* clean up */ (void) memset(tmpbuf, 0, strlen(tmpbuf)); (void) memset(databuf, 0, strlen(databuf)); free(databuf); return (-2); } } *pdata = databuf; *psize = strlen(databuf); return (0); } /* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License (the "License"). * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at usr/src/OPENSOLARIS.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END * * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. */ #include #include #include #include #include #include #include #include #include #include #include #include /* PKCS#11 URI prefix and attributes. */ #define PK11_URI_PREFIX "pkcs11:" #define PK11_TOKEN "token" #define PK11_MANUF "manufacturer" #define PK11_SERIAL "serial" #define PK11_MODEL "model" #define PK11_OBJECT "object" #define PK11_OBJECTTYPE "objecttype" #define PK11_ID "id" #define PK11_PINFILE "pinfile" /* * Gets a hexadecimal string of the xx:xx:xx-like format and fills the output * buffer with bytes represeting each of the hexadecimal numbers. Returns 0 on * error (missing ':', not a hexadecimal character (eg. 'z'), output buffer * overflow, etc.), or the number of hexadecimal numbers processed. * * Returns: * 0 * on failure * >0 * number of bytes returned via the output parameter */ static int read_id(char *str, unsigned char *output, int out_len) { int i, len, n; unsigned int x1, x2; len = strlen(str); (void) memset(output, 0, out_len); /* Counter of the processed bytes. */ i = 0; /* Counter for the used output bytes. */ n = 0; while (i < len) { /* We require at least one hexadecimal character. */ if (sscanf(str + i, "%1x", &x1) != 1) return (0); ++i; /* And we accept the 2nd one if it is there. */ if (sscanf(str + i, "%1x", &x2) == 1) { x1 = x1 * 16 + x2; ++i; } /* Output buffer overflow? */ if ((n + 1) > out_len) return (0); output[n] = (unsigned char)x1; /* Still some bytes to process? */ if (i < len) { /* ':' is the only acceptable delimiter. */ if (str[i] != ':') return (0); /* Skip ':' */ ++i; } ++n; } return (n); } /* * Process the PKCS#11 URI. The function expects an allocated URI structure. The * caller is later expected to call pkcs11_free_uri() when the parsed URI is no * longer needed. * * Returns: * PK11_URI_OK * success * PK11_URI_INVALID * invalid PKCS#11 URI (one that has the "pkcs11:" prefix but is * otherwise incorrectly specified) * PK11_MALLOC_ERROR * malloc(3C) failed when allocating one of the internal buffers * PK11_URI_VALUE_OVERFLOW * some attributes in the URI are of the fixed length accroding to * the spec. If any of those attributes overflows we report an * error * PK11_NOT_PKCS11_URI * the URI supplied is not the PKCS#11 URI at all (does not have * the "pkcs11:" prefix) */ int pkcs11_parse_uri(const char *str, pkcs11_uri_t *uri) { char *str2, *l1, *l2, *tok, *name; /* Initialize the structure. */ (void) memset(uri, 0, sizeof (pkcs11_uri_t)); /* Be really safe. */ uri->objecttype_present = B_FALSE; /* Check that we have the correct PKCS#11 URI prefix. */ if (strncmp(str, PK11_URI_PREFIX, strlen(PK11_URI_PREFIX)) != 0) return (PK11_NOT_PKCS11_URI); /* Dup the string and skip over the prefix then. */ if ((str2 = strdup(str + strlen(PK11_URI_PREFIX))) == NULL) return (PK11_MALLOC_ERROR); /* * Using strtok_r() would silently skip over multiple semicolons. We * must check such situation before moving on. We must also avoid ';' as * the first and the last character of the URI. */ if (strstr(str2, ";;") != NULL || str2[0] == ';' || (strlen(str2) > 0 && str2[strlen(str2) - 1] == ';')) goto bad_uri; /* Now parse the URI. */ tok = strtok_r(str2, ";", &l1); for (; tok != NULL; tok = strtok_r(NULL, ";", &l1)) { /* "tok" is not empty so there will be something in "name". */ name = strtok_r(tok, "=", &l2); /* Check whether there is '=' at all. */ if (l2 == NULL) goto bad_uri; /* * Fill out the URI structure. We do not accept duplicate * attributes. */ if (strcmp(name, PK11_TOKEN) == 0) { /* Check for duplicity. */ if (uri->token != NULL) goto bad_uri; if (strlen(l2) > 32) goto value_overflow; if ((uri->token = (unsigned char *)strdup(l2)) == NULL) goto malloc_failed; } else if (strcmp(name, PK11_MANUF) == 0) { /* Check for duplicity. */ if (uri->manuf != NULL) goto bad_uri; if (strlen(l2) > 32) goto value_overflow; if ((uri->manuf = (unsigned char *)strdup(l2)) == NULL) goto malloc_failed; } else if (strcmp(name, PK11_SERIAL) == 0) { /* Check for duplicity. */ if (uri->serial != NULL) goto bad_uri; if (strlen(l2) > 16) goto value_overflow; if ((uri->serial = (unsigned char *)strdup(l2)) == NULL) goto malloc_failed; } else if (strcmp(name, PK11_MODEL) == 0) { /* Check for duplicity. */ if (uri->model != NULL) goto bad_uri; if (strlen(l2) > 16) goto value_overflow; if ((uri->model = (unsigned char *)strdup(l2)) == NULL) goto malloc_failed; } else if (strcmp(name, PK11_ID) == 0) { /* Check for duplicity. */ if (uri->id_len != 0) goto bad_uri; /* * We can have maximum of PK11_MAX_ID_LEN 2-byte * numbers separated by ':'s, like * 01:02:0A:FF:... */ if (strlen(l2) > PK11_MAX_ID_LEN * 2 + PK11_MAX_ID_LEN - 1) { goto value_overflow; } if ((uri->id = malloc(PK11_MAX_ID_LEN)) == NULL) goto malloc_failed; uri->id_len = read_id(l2, uri->id, PK11_MAX_ID_LEN); if (uri->id_len == 0) goto bad_uri; } else if (strcmp(name, PK11_OBJECT) == 0) { /* Check for duplicity. */ if (uri->object != NULL) goto bad_uri; if (strlen(l2) > PK11_MAX_OBJECT_LEN) goto value_overflow; if ((uri->object = (unsigned char *)strdup(l2)) == NULL) goto malloc_failed; } else if (strcmp(name, PK11_OBJECTTYPE) == 0) { /* * Check for duplicity. objecttype can not be empty, it * would not make sense. */ if (uri->objecttype_present == CK_TRUE) goto bad_uri; if (strcmp(l2, "public") == 0) uri->objecttype = CKO_PUBLIC_KEY; else if (strcmp(l2, "private") == 0) uri->objecttype = CKO_PRIVATE_KEY; else if (strcmp(l2, "cert") == 0) uri->objecttype = CKO_CERTIFICATE; else if (strcmp(l2, "secretkey") == 0) uri->objecttype = CKO_SECRET_KEY; else if (strcmp(l2, "data") == 0) uri->objecttype = CKO_DATA; else goto bad_uri; uri->objecttype_present = CK_TRUE; } else if (strcmp(name, PK11_PINFILE) == 0) /* Check for duplicity. */ if (uri->pinfile == NULL) { if (strlen(l2) > MAXPATHLEN) goto value_overflow; if ((uri->pinfile = strdup(l2)) == NULL) goto malloc_failed; /* Empty pinfile makes no sense. */ if (uri->pinfile[0] == '\0') goto bad_uri; } else goto bad_uri; else /* Unknown attribute name. */ goto bad_uri; } free(str2); return (PK11_URI_OK); malloc_failed: free(str2); pkcs11_free_uri(uri); return (PK11_MALLOC_ERROR); bad_uri: free(str2); pkcs11_free_uri(uri); return (PK11_URI_INVALID); value_overflow: free(str2); pkcs11_free_uri(uri); return (PK11_URI_VALUE_OVERFLOW); } /* * Free the PKCS#11 URI structure attributes but do not free the structure * itself. */ void pkcs11_free_uri(pkcs11_uri_t *uri) { if (uri->object != NULL) free(uri->object); if (uri->token != NULL) free(uri->token); if (uri->manuf != NULL) free(uri->manuf); if (uri->serial != NULL) free(uri->serial); if (uri->model != NULL) free(uri->model); if (uri->id != NULL) free(uri->id); if (uri->pinfile != NULL) free(uri->pinfile); } /* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License, Version 1.0 only * (the "License"). You may not use this file except in compliance * with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at usr/src/OPENSOLARIS.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END */ /* * Copyright 2004 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. * Copyright 2012 Milan Jurik. All rights reserved. * Copyright 2015 Jason King. */ /* * Block comment which describes the contents of this file. */ #include #include /* * pkcs11_strerror: returns a string representation of the given return code. * The string returned is static pointer. It doesn't need to be free'd * by the caller. */ char * pkcs11_strerror(CK_RV rv) { static char errstr[128]; switch (rv) { case CKR_OK: return ("CKR_OK"); case CKR_CANCEL: return ("CKR_CANCEL"); case CKR_HOST_MEMORY: return ("CKR_HOST_MEMORY"); case CKR_SLOT_ID_INVALID: return ("CKR_SLOT_ID_INVALID"); case CKR_GENERAL_ERROR: return ("CKR_GENERAL_ERROR"); case CKR_FUNCTION_FAILED: return ("CKR_FUNCTION_FAILED"); case CKR_ARGUMENTS_BAD: return ("CKR_ARGUMENTS_BAD"); case CKR_NO_EVENT: return ("CKR_NO_EVENT"); case CKR_NEED_TO_CREATE_THREADS: return ("CKR_NEED_TO_CREATE_THREADS"); case CKR_CANT_LOCK: return ("CKR_CANT_LOCK"); case CKR_ATTRIBUTE_READ_ONLY: return ("CKR_ATTRIBUTE_READ_ONLY"); case CKR_ATTRIBUTE_SENSITIVE: return ("CKR_ATTRIBUTE_SENSITIVE"); case CKR_ATTRIBUTE_TYPE_INVALID: return ("CKR_ATTRIBUTE_TYPE_INVALID"); case CKR_ATTRIBUTE_VALUE_INVALID: return ("CKR_ATTRIBUTE_VALUE_INVALID"); case CKR_ACTION_PROHIBITED: return ("CKR_ACTION_PROHIBITED"); case CKR_DATA_INVALID: return ("CKR_DATA_INVALID"); case CKR_DATA_LEN_RANGE: return ("CKR_DATA_LEN_RANGE"); case CKR_DEVICE_ERROR: return ("CKR_DEVICE_ERROR"); case CKR_DEVICE_MEMORY: return ("CKR_DEVICE_MEMORY"); case CKR_DEVICE_REMOVED: return ("CKR_DEVICE_REMOVED"); case CKR_ENCRYPTED_DATA_INVALID: return ("CKR_ENCRYPTED_DATA_INVALID"); case CKR_ENCRYPTED_DATA_LEN_RANGE: return ("CKR_ENCRYPTED_DATA_LEN_RANGE"); case CKR_FUNCTION_CANCELED: return ("CKR_FUNCTION_CANCELED"); case CKR_FUNCTION_NOT_PARALLEL: return ("CKR_FUNCTION_NOT_PARALLEL"); case CKR_FUNCTION_NOT_SUPPORTED: return ("CKR_FUNCTION_NOT_SUPPORTED"); case CKR_KEY_HANDLE_INVALID: return ("CKR_KEY_HANDLE_INVALID"); case CKR_KEY_SIZE_RANGE: return ("CKR_KEY_SIZE_RANGE"); case CKR_KEY_TYPE_INCONSISTENT: return ("CKR_KEY_TYPE_INCONSISTENT"); case CKR_KEY_NOT_NEEDED: return ("CKR_KEY_NOT_NEEDED"); case CKR_KEY_CHANGED: return ("CKR_KEY_CHANGED"); case CKR_KEY_NEEDED: return ("CKR_KEY_NEEDED"); case CKR_KEY_INDIGESTIBLE: return ("CKR_KEY_INDIGESTIBLE"); case CKR_KEY_FUNCTION_NOT_PERMITTED: return ("CKR_KEY_FUNCTION_NOT_PERMITTED"); case CKR_KEY_NOT_WRAPPABLE: return ("CKR_KEY_NOT_WRAPPABLE"); case CKR_KEY_UNEXTRACTABLE: return ("CKR_KEY_UNEXTRACTABLE"); case CKR_MECHANISM_INVALID: return ("CKR_MECHANISM_INVALID"); case CKR_MECHANISM_PARAM_INVALID: return ("CKR_MECHANISM_PARAM_INVALID"); case CKR_OBJECT_HANDLE_INVALID: return ("CKR_OBJECT_HANDLE_INVALID"); case CKR_OPERATION_ACTIVE: return ("CKR_OPERATION_ACTIVE"); case CKR_OPERATION_NOT_INITIALIZED: return ("CKR_OPERATION_NOT_INITIALIZED"); case CKR_PIN_INCORRECT: return ("CKR_PIN_INCORRECT"); case CKR_PIN_INVALID: return ("CKR_PIN_INVALID"); case CKR_PIN_LEN_RANGE: return ("CKR_PIN_LEN_RANGE"); case CKR_PIN_EXPIRED: return ("CKR_PIN_EXPIRED"); case CKR_PIN_LOCKED: return ("CKR_PIN_LOCKED"); case CKR_SESSION_CLOSED: return ("CKR_SESSION_CLOSED"); case CKR_SESSION_COUNT: return ("CKR_SESSION_COUNT"); case CKR_SESSION_HANDLE_INVALID: return ("CKR_SESSION_HANDLE_INVALID"); case CKR_SESSION_PARALLEL_NOT_SUPPORTED: return ("CKR_SESSION_PARALLEL_NOT_SUPPORTED"); case CKR_SESSION_READ_ONLY: return ("CKR_SESSION_READ_ONLY"); case CKR_SESSION_EXISTS: return ("CKR_SESSION_EXISTS"); case CKR_SESSION_READ_ONLY_EXISTS: return ("CKR_SESSION_READ_ONLY_EXISTS"); case CKR_SESSION_READ_WRITE_SO_EXISTS: return ("CKR_SESSION_READ_WRITE_SO_EXISTS"); case CKR_SIGNATURE_INVALID: return ("CKR_SIGNATURE_INVALID"); case CKR_SIGNATURE_LEN_RANGE: return ("CKR_SIGNATURE_LEN_RANGE"); case CKR_TEMPLATE_INCOMPLETE: return ("CKR_TEMPLATE_INCOMPLETE"); case CKR_TEMPLATE_INCONSISTENT: return ("CKR_TEMPLATE_INCONSISTENT"); case CKR_TOKEN_NOT_PRESENT: return ("CKR_TOKEN_NOT_PRESENT"); case CKR_TOKEN_NOT_RECOGNIZED: return ("CKR_TOKEN_NOT_RECOGNIZED"); case CKR_TOKEN_WRITE_PROTECTED: return ("CKR_TOKEN_WRITE_PROTECTED"); case CKR_UNWRAPPING_KEY_HANDLE_INVALID: return ("CKR_UNWRAPPING_KEY_HANDLE_INVALID"); case CKR_UNWRAPPING_KEY_SIZE_RANGE: return ("CKR_UNWRAPPING_KEY_SIZE_RANGE"); case CKR_UNWRAPPING_KEY_TYPE_INCONSISTENT: return ("CKR_UNWRAPPING_KEY_TYPE_INCONSISTENT"); case CKR_USER_ALREADY_LOGGED_IN: return ("CKR_USER_ALREADY_LOGGED_IN"); case CKR_USER_NOT_LOGGED_IN: return ("CKR_USER_NOT_LOGGED_IN"); case CKR_USER_PIN_NOT_INITIALIZED: return ("CKR_USER_PIN_NOT_INITIALIZED"); case CKR_USER_TYPE_INVALID: return ("CKR_USER_TYPE_INVALID"); case CKR_USER_ANOTHER_ALREADY_LOGGED_IN: return ("CKR_USER_ANOTHER_ALREADY_LOGGED_IN"); case CKR_USER_TOO_MANY_TYPES: return ("CKR_USER_TOO_MANY_TYPES"); case CKR_WRAPPED_KEY_INVALID: return ("CKR_WRAPPED_KEY_INVALID"); case CKR_WRAPPED_KEY_LEN_RANGE: return ("CKR_WRAPPED_KEY_LEN_RANGE"); case CKR_WRAPPING_KEY_HANDLE_INVALID: return ("CKR_WRAPPING_KEY_HANDLE_INVALID"); case CKR_WRAPPING_KEY_SIZE_RANGE: return ("CKR_WRAPPING_KEY_SIZE_RANGE"); case CKR_WRAPPING_KEY_TYPE_INCONSISTENT: return ("CKR_WRAPPING_KEY_TYPE_INCONSISTENT"); case CKR_RANDOM_SEED_NOT_SUPPORTED: return ("CKR_RANDOM_SEED_NOT_SUPPORTED"); case CKR_RANDOM_NO_RNG: return ("CKR_RANDOM_NO_RNG"); case CKR_DOMAIN_PARAMS_INVALID: return ("CKR_DOMAIN_PARAMS_INVALID"); case CKR_CURVE_NOT_SUPPORTED: return ("CLR_CURVE_NOT_SUPPORTED"); case CKR_BUFFER_TOO_SMALL: return ("CKR_BUFFER_TOO_SMALL"); case CKR_SAVED_STATE_INVALID: return ("CKR_SAVED_STATE_INVALID"); case CKR_INFORMATION_SENSITIVE: return ("CKR_INFORMATION_SENSITIVE"); case CKR_STATE_UNSAVEABLE: return ("CKR_STATE_UNSAVEABLE"); case CKR_CRYPTOKI_NOT_INITIALIZED: return ("CKR_CRYPTOKI_NOT_INITIALIZED"); case CKR_CRYPTOKI_ALREADY_INITIALIZED: return ("CKR_CRYPTOKI_ALREADY_INITIALIZED"); case CKR_MUTEX_BAD: return ("CKR_MUTEX_BAD"); case CKR_MUTEX_NOT_LOCKED: return ("CKR_MUTEX_NOT_LOCKED"); case CKR_NEW_PIN_MODE: return ("CKR_NEW_PIN_MODE"); case CKR_NEXT_OTP: return ("CKR_NEXT_OTP"); case CKR_EXCEEDED_MAX_ITERATIONS: return ("CKR_EXCEEDED_MAX_ITERATIONS"); case CKR_FIPS_SELF_TEST_FAILED: return ("CKR_FIPS_SELF_TEST_FAILED"); case CKR_LIBRARY_LOAD_FAILED: return ("CKR_LIBRARY_LOAD_FAILED"); case CKR_PIN_TOO_WEAK: return ("CKR_PIN_TOO_WEAK"); case CKR_PUBLIC_KEY_INVALID: return ("CKR_PUBLIC_KEY_INVALID"); case CKR_FUNCTION_REJECTED: return ("CKR_FUNCTION_REJECTED"); case CKR_VENDOR_DEFINED: return ("CKR_VENDOR_DEFINED"); default: /* rv not found */ (void) snprintf(errstr, sizeof (errstr), "Unknown return code: 0x%lx", rv); return (errstr); } } /* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License (the "License"). * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at usr/src/OPENSOLARIS.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END */ /* * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved. * Copyright 2014, OmniTI Computer Consulting, Inc. All rights reserved. */ #include #include #include #include #include #include #include #include #include #pragma init(pkcs11_random_init) static pthread_mutex_t random_mutex = PTHREAD_MUTEX_INITIALIZER; static pthread_mutex_t urandom_mutex = PTHREAD_MUTEX_INITIALIZER; static pthread_mutex_t random_seed_mutex = PTHREAD_MUTEX_INITIALIZER; static pthread_mutex_t urandom_seed_mutex = PTHREAD_MUTEX_INITIALIZER; #define RANDOM_DEVICE "/dev/random" /* random device name */ #define URANDOM_DEVICE "/dev/urandom" /* urandom device name */ static int random_fd = -1; static int urandom_fd = -1; static int random_seed_fd = -1; static int urandom_seed_fd = -1; /* * Equivalent of open(2) insulated from EINTR. * Also sets close-on-exec. */ int open_nointr(const char *path, int oflag, ...) { int fd; mode_t pmode; va_list alist; va_start(alist, oflag); pmode = va_arg(alist, mode_t); va_end(alist); do { if ((fd = open(path, oflag, pmode)) >= 0) { (void) fcntl(fd, F_SETFD, FD_CLOEXEC); break; } /* errno definitely set by failed open() */ } while (errno == EINTR); return (fd); } /* * Equivalent of read(2) insulated from EINTR. */ ssize_t readn_nointr(int fd, void *dbuf, size_t dlen) { char *marker = dbuf; size_t left = dlen; ssize_t nread = 0, err; for (err = 0; left > 0 && nread != -1; marker += nread, left -= nread) { if ((nread = read(fd, marker, left)) < 0) { if (errno == EINTR) { /* keep trying */ nread = 0; continue; } err = nread; /* hard error */ break; } else if (nread == 0) { break; } } return (err != 0 ? err : dlen - left); } /* * Equivalent of write(2) insulated from EINTR. */ ssize_t writen_nointr(int fd, void *dbuf, size_t dlen) { char *marker = dbuf; size_t left = dlen; ssize_t nwrite = 0, err; for (err = 0; left > 0 && nwrite != -1; marker += nwrite, left -= nwrite) { if ((nwrite = write(fd, marker, left)) < 0) { if (errno == EINTR) { /* keep trying */ nwrite = 0; continue; } err = nwrite; /* hard error */ break; } else if (nwrite == 0) { break; } } return (err != 0 ? err : dlen - left); } /* * Opens the random number generator devices if not already open. * Always returns the opened fd of the device, or error. */ static int pkcs11_open_common(int *fd, pthread_mutex_t *mtx, const char *dev, int oflag) { (void) pthread_mutex_lock(mtx); if (*fd < 0) *fd = open_nointr(dev, oflag); (void) pthread_mutex_unlock(mtx); return (*fd); } static int pkcs11_open_random(void) { return (pkcs11_open_common(&random_fd, &random_mutex, RANDOM_DEVICE, O_RDONLY)); } static int pkcs11_open_urandom(void) { return (pkcs11_open_common(&urandom_fd, &urandom_mutex, URANDOM_DEVICE, O_RDONLY)); } static int pkcs11_open_random_seed(void) { return (pkcs11_open_common(&random_seed_fd, &random_seed_mutex, RANDOM_DEVICE, O_WRONLY)); } static int pkcs11_open_urandom_seed(void) { return (pkcs11_open_common(&urandom_seed_fd, &urandom_seed_mutex, URANDOM_DEVICE, O_WRONLY)); } /* * Close the random number generator devices if already open. */ static void pkcs11_close_common(int *fd, pthread_mutex_t *mtx) { (void) pthread_mutex_lock(mtx); (void) close(*fd); *fd = -1; (void) pthread_mutex_unlock(mtx); } static void pkcs11_close_random(void) { pkcs11_close_common(&random_fd, &random_mutex); } static void pkcs11_close_urandom(void) { pkcs11_close_common(&urandom_fd, &urandom_mutex); } static void pkcs11_close_random_seed(void) { pkcs11_close_common(&random_seed_fd, &random_seed_mutex); } static void pkcs11_close_urandom_seed(void) { pkcs11_close_common(&urandom_seed_fd, &urandom_seed_mutex); } /* * Read from the random number generator devices. */ static size_t pkcs11_read_common(int *fd, pthread_mutex_t *mtx, void *dbuf, size_t dlen) { size_t n; (void) pthread_mutex_lock(mtx); n = readn_nointr(*fd, dbuf, dlen); (void) pthread_mutex_unlock(mtx); return (n); } static size_t pkcs11_read_random(void *dbuf, size_t dlen) { return (pkcs11_read_common(&random_fd, &random_mutex, dbuf, dlen)); } static size_t pkcs11_read_urandom(void *dbuf, size_t dlen) { return (pkcs11_read_common(&urandom_fd, &urandom_mutex, dbuf, dlen)); } /* * Write to the random number generator devices. */ static size_t pkcs11_write_common(int *fd, pthread_mutex_t *mtx, void *dbuf, size_t dlen) { size_t n; (void) pthread_mutex_lock(mtx); n = writen_nointr(*fd, dbuf, dlen); (void) pthread_mutex_unlock(mtx); return (n); } static size_t pkcs11_write_random_seed(void *dbuf, size_t dlen) { return (pkcs11_write_common(&random_seed_fd, &random_seed_mutex, dbuf, dlen)); } static size_t pkcs11_write_urandom_seed(void *dbuf, size_t dlen) { return (pkcs11_write_common(&urandom_seed_fd, &urandom_seed_mutex, dbuf, dlen)); } /* * Seed /dev/random with the data in the buffer. */ int pkcs11_seed_random(void *sbuf, size_t slen) { int rv; if (sbuf == NULL || slen == 0) return (0); /* Seeding error could mean it's not supported (errno = EACCES) */ if (pkcs11_open_random_seed() < 0) return (-1); rv = -1; if (pkcs11_write_random_seed(sbuf, slen) == slen) rv = 0; pkcs11_close_random_seed(); return (rv); } /* * Seed /dev/urandom with the data in the buffer. */ int pkcs11_seed_urandom(void *sbuf, size_t slen) { int rv; if (sbuf == NULL || slen == 0) return (0); /* Seeding error could mean it's not supported (errno = EACCES) */ if (pkcs11_open_urandom_seed() < 0) return (-1); rv = -1; if (pkcs11_write_urandom_seed(sbuf, slen) == slen) rv = 0; pkcs11_close_urandom_seed(); return (rv); } /* * Put the requested amount of random data into a preallocated buffer. * Good for token key data, persistent objects. */ int pkcs11_get_random(void *dbuf, size_t dlen) { if (dbuf == NULL || dlen == 0) return (0); /* Read random data directly from /dev/random */ if (pkcs11_open_random() < 0) return (-1); if (pkcs11_read_random(dbuf, dlen) == dlen) return (0); return (-1); } /* * Put the requested amount of random data into a preallocated buffer. * Good for passphrase salts, initialization vectors. */ int pkcs11_get_urandom(void *dbuf, size_t dlen) { if (dbuf == NULL || dlen == 0) return (0); /* Read random data directly from /dev/urandom */ if (pkcs11_open_urandom() < 0) return (-1); if (pkcs11_read_urandom(dbuf, dlen) == dlen) return (0); return (-1); } /* * Same as pkcs11_get_urandom but ensures non zero data. */ int pkcs11_get_nzero_urandom(void *dbuf, size_t dlen) { char extrarand[32]; size_t bytesleft = 0; size_t i = 0; /* Start with some random data */ if (pkcs11_get_urandom(dbuf, dlen) < 0) return (-1); /* Walk through data replacing any 0 bytes with more random data */ while (i < dlen) { if (((char *)dbuf)[i] != 0) { i++; continue; } if (bytesleft == 0) { bytesleft = sizeof (extrarand); if (pkcs11_get_urandom(extrarand, bytesleft) < 0) return (-1); } bytesleft--; ((char *)dbuf)[i] = extrarand[bytesleft]; } return (0); } static void pkcs11_random_prepare(void) { /* * NOTE - None of these are acquired more than one at a time. * I can therefore acquire all four without fear of deadlock. */ (void) pthread_mutex_lock(&random_mutex); (void) pthread_mutex_lock(&urandom_mutex); (void) pthread_mutex_lock(&random_seed_mutex); (void) pthread_mutex_lock(&urandom_seed_mutex); } static void pkcs11_random_parent_post(void) { /* Drop the mutexes and get back to work! */ (void) pthread_mutex_unlock(&urandom_seed_mutex); (void) pthread_mutex_unlock(&random_seed_mutex); (void) pthread_mutex_unlock(&urandom_mutex); (void) pthread_mutex_unlock(&random_mutex); } static void pkcs11_random_child_post(void) { pkcs11_random_parent_post(); /* Also, close the FDs, just in case. */ pkcs11_close_random(); pkcs11_close_urandom(); pkcs11_close_random_seed(); pkcs11_close_urandom_seed(); } static void pkcs11_random_init(void) { (void) pthread_atfork(pkcs11_random_prepare, pkcs11_random_parent_post, pkcs11_random_child_post); } /* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License (the "License"). * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at usr/src/OPENSOLARIS.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END */ /* * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ #include #include #include #include /* * tohexstr * IN bytes * blen * hexlen should be 2 * blen + 1 * OUT * hexstr */ void tohexstr(uchar_t *bytes, size_t blen, char *hexstr, size_t hexlen) { size_t i; char hexlist[] = "0123456789abcdef"; for (i = 0; i < blen; i++) { if (hexlen < (2 * i + 1)) break; hexstr[2 * i] = hexlist[(bytes[i] >> 4) & 0xf]; hexstr[2 * i + 1] = hexlist[bytes[i] & 0xf]; } hexstr[2 * blen] = '\0'; } /* * This function takes a char[] and length of hexadecimal values and * returns a malloc'ed byte array with the length of that new byte array. * The caller needs to provide a pointer to where this new malloc'ed byte array * will be passed back; as well as, a pointer for the length of the new * byte array. * * The caller is responsible for freeing the malloc'ed array when done * * The return code is 0 if successful, otherwise the errno value is returned. */ int hexstr_to_bytes(char *hexstr, size_t hexlen, uchar_t **bytes, size_t *blen) { int i, ret = 0; unsigned char ch; uchar_t *b = NULL; *bytes = NULL; *blen = 0; if (hexstr == NULL || (hexlen % 2 == 1)) return (EINVAL); if (hexstr[0] == '0' && ((hexstr[1] == 'x') || (hexstr[1] == 'X'))) { hexstr += 2; hexlen -= 2; } *blen = (hexlen / 2); b = malloc(*blen); if (b == NULL) { *blen = 0; return (errno); } for (i = 0; i < hexlen; i++) { ch = (unsigned char) *hexstr; if (!isxdigit(ch)) { ret = EINVAL; goto out; } hexstr++; if ((ch >= '0') && (ch <= '9')) ch -= '0'; else if ((ch >= 'A') && (ch <= 'F')) ch = ch - 'A' + 10; else if ((ch >= 'a') && (ch <= 'f')) ch = ch - 'a' + 10; if (i & 1) b[i/2] |= ch; else b[i/2] = (ch << 4); } out: if (b != NULL && ret != 0) { free(b); *blen = 0; } else *bytes = b; return (ret); } /* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License (the "License"). * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at usr/src/OPENSOLARIS.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END */ /* * Copyright 2006 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. * Copyright 2018, Joyent, Inc. */ #include #include #include #include #include /* * In order to fit everything on one line, the 'CRYPTO_' prefix * has been dropped from the KCF #defines, e.g. * CRYPTO_SUCCESS becomes SUCCESS. */ static CK_RV error_number_table[CRYPTO_LAST_ERROR + 1] = { CKR_OK, /* SUCCESS */ CKR_CANCEL, /* CANCEL */ CKR_HOST_MEMORY, /* HOST_MEMORY */ CKR_GENERAL_ERROR, /* GENERAL_ERROR */ CKR_FUNCTION_FAILED, /* FAILED */ CKR_ARGUMENTS_BAD, /* ARGUMENTS_BAD */ CKR_ATTRIBUTE_READ_ONLY, /* ATTRIBUTE_READ_ONLY */ CKR_ATTRIBUTE_SENSITIVE, /* ATTRIBUTE_SENSITIVE */ CKR_ATTRIBUTE_TYPE_INVALID, /* ATTRIBUTE_TYPE_INVALID */ CKR_ATTRIBUTE_VALUE_INVALID, /* ATTRIBUTE_VALUE_INVALID */ CKR_FUNCTION_FAILED, /* CANCELED */ CKR_DATA_INVALID, /* DATA_INVALID */ CKR_DATA_LEN_RANGE, /* DATA_LEN_RANGE */ CKR_DEVICE_ERROR, /* DEVICE_ERROR */ CKR_DEVICE_MEMORY, /* DEVICE_MEMORY */ CKR_DEVICE_REMOVED, /* DEVICE_REMOVED */ CKR_ENCRYPTED_DATA_INVALID, /* ENCRYPTED_DATA_INVALID */ CKR_ENCRYPTED_DATA_LEN_RANGE, /* ENCRYPTED_DATA_LEN_RANGE */ CKR_KEY_HANDLE_INVALID, /* KEY_HANDLE_INVALID */ CKR_KEY_SIZE_RANGE, /* KEY_SIZE_RANGE */ CKR_KEY_TYPE_INCONSISTENT, /* KEY_TYPE_INCONSISTENT */ CKR_KEY_NOT_NEEDED, /* KEY_NOT_NEEDED */ CKR_KEY_CHANGED, /* KEY_CHANGED */ CKR_KEY_NEEDED, /* KEY_NEEDED */ CKR_KEY_INDIGESTIBLE, /* KEY_INDIGESTIBLE */ CKR_KEY_FUNCTION_NOT_PERMITTED, /* KEY_FUNCTION_NOT_PERMITTED */ CKR_KEY_NOT_WRAPPABLE, /* KEY_NOT_WRAPPABLE */ CKR_KEY_UNEXTRACTABLE, /* KEY_UNEXTRACTABLE */ CKR_MECHANISM_INVALID, /* MECHANISM_INVALID */ CKR_MECHANISM_PARAM_INVALID, /* MECHANISM_PARAM_INVALID */ CKR_OBJECT_HANDLE_INVALID, /* OBJECT_HANDLE_INVALID */ CKR_OPERATION_ACTIVE, /* OPERATION_ACTIVE */ CKR_OPERATION_NOT_INITIALIZED, /* OPERATION_NOT_INITIALIZED */ CKR_PIN_INCORRECT, /* PIN_INCORRECT */ CKR_PIN_INVALID, /* PIN_INVALID */ CKR_PIN_LEN_RANGE, /* PIN_LEN_RANGE */ CKR_PIN_EXPIRED, /* PIN_EXPIRED */ CKR_PIN_LOCKED, /* PIN_LOCKED */ CKR_SESSION_CLOSED, /* SESSION_CLOSED */ CKR_SESSION_COUNT, /* SESSION_COUNT */ CKR_SESSION_HANDLE_INVALID, /* SESSION_HANDLE_INVALID */ CKR_SESSION_READ_ONLY, /* SESSION_READ_ONLY */ CKR_SESSION_EXISTS, /* SESSION_EXISTS */ CKR_SESSION_READ_ONLY_EXISTS, /* SESSION_READ_ONLY_EXISTS */ CKR_SESSION_READ_WRITE_SO_EXISTS, /* SESSION_READ_WRITE_SO_EXISTS */ CKR_SIGNATURE_INVALID, /* SIGNATURE_INVALID */ CKR_SIGNATURE_LEN_RANGE, /* SIGNATURE_LEN_RANGE */ CKR_TEMPLATE_INCOMPLETE, /* TEMPLATE_INCOMPLETE */ CKR_TEMPLATE_INCONSISTENT, /* TEMPLATE_INCONSISTENT */ CKR_UNWRAPPING_KEY_HANDLE_INVALID, /* UNWRAPPING_KEY_HANDLE_INVALID */ CKR_UNWRAPPING_KEY_SIZE_RANGE, /* UNWRAPPING_KEY_SIZE_RANGE */ CKR_UNWRAPPING_KEY_TYPE_INCONSISTENT, /* UNWRAPPING_KEY_TYPE_INCONSISTENT */ CKR_USER_ALREADY_LOGGED_IN, /* USER_ALREADY_LOGGED_IN */ CKR_USER_NOT_LOGGED_IN, /* USER_NOT_LOGGED_IN */ CKR_USER_PIN_NOT_INITIALIZED, /* USER_PIN_NOT_INITIALIZED */ CKR_USER_TYPE_INVALID, /* USER_TYPE_INVALID */ CKR_USER_ANOTHER_ALREADY_LOGGED_IN, /* USER_ANOTHER_ALREADY_LOGGED_IN */ CKR_USER_TOO_MANY_TYPES, /* USER_TOO_MANY_TYPES */ CKR_WRAPPED_KEY_INVALID, /* WRAPPED_KEY_INVALID */ CKR_WRAPPED_KEY_LEN_RANGE, /* WRAPPED_KEY_LEN_RANGE */ CKR_WRAPPING_KEY_HANDLE_INVALID, /* WRAPPING_KEY_HANDLE_INVALID */ CKR_WRAPPING_KEY_SIZE_RANGE, /* WRAPPING_KEY_SIZE_RANGE */ CKR_WRAPPING_KEY_TYPE_INCONSISTENT, /* WRAPPING_KEY_TYPE_INCONSISTENT */ CKR_RANDOM_SEED_NOT_SUPPORTED, /* RANDOM_SEED_NOT_SUPPORTED */ CKR_RANDOM_NO_RNG, /* RANDOM_NO_RNG */ CKR_DOMAIN_PARAMS_INVALID, /* DOMAIN_PARAMS_INVALID */ CKR_BUFFER_TOO_SMALL, /* BUFFER_TOO_SMALL */ CKR_INFORMATION_SENSITIVE, /* INFORMATION_SENSITIVE */ CKR_FUNCTION_NOT_SUPPORTED, /* NOT_SUPPORTED */ CKR_GENERAL_ERROR, /* QUEUED */ CKR_GENERAL_ERROR, /* BUFFER_TOO_BIG */ CKR_OPERATION_NOT_INITIALIZED, /* INVALID_CONTEXT */ CKR_GENERAL_ERROR, /* INVALID_MAC */ CKR_GENERAL_ERROR, /* MECH_NOT_SUPPORTED */ CKR_GENERAL_ERROR, /* INCONSISTENT_ATTRIBUTE */ CKR_GENERAL_ERROR, /* NO_PERMISSION */ CKR_SLOT_ID_INVALID, /* INVALID_PROVIDER_ID */ CKR_GENERAL_ERROR, /* VERSION_MISMATCH */ CKR_GENERAL_ERROR, /* BUSY */ CKR_GENERAL_ERROR, /* UNKNOWN_PROVIDER */ CKR_GENERAL_ERROR, /* MODVERIFICATION_FAILED */ CKR_GENERAL_ERROR, /* OLD_CTX_TEMPLATE */ CKR_GENERAL_ERROR, /* WEAK_KEY */ CKR_GENERAL_ERROR /* FIPS140_ERROR */ }; #if CRYPTO_LAST_ERROR != CRYPTO_FIPS140_ERROR #error "Crypto to PKCS11 error mapping table needs to be updated!" #endif /* * This function returns a fullpath based on the "dir" and "filepath" input * arugments. * - If the filepath specified does not start with a "/" and the directory * is also given, prepend the directory to the filename. * - If only dir or filepath is given, this function returns a copy of the * given argument. * - If the filepath is fully qualified already and the "dir" is also * given, return NULL to indicate an error. */ char * get_fullpath(char *dir, char *filepath) { char *fullpath = NULL; int pathlen = 0; int dirlen = 0; if (filepath != NULL) pathlen = strlen(filepath); if (dir != NULL) dirlen = strlen(dir); if (pathlen > 0 && dirlen > 0) { if (filepath[0] != '/') { int len = pathlen + dirlen + 2; fullpath = (char *)malloc(len); if (fullpath != NULL) (void) snprintf(fullpath, len, "%s/%s", dir, filepath); } else { return (NULL); } } else if (pathlen > 0) { fullpath = (char *)strdup(filepath); } else if (dirlen > 0) { fullpath = (char *)strdup(dir); } return (fullpath); } /* * This function converts the input string to the value of time * in seconds. * - If the input string is NULL, return zero second. * - The input string needs to be in the form of: * number-second(s), number-minute(s), number-hour(s) or * number-day(s). */ int str2lifetime(char *ltimestr, uint32_t *ltime) { int num; char timetok[10]; if (ltimestr == NULL || !strlen(ltimestr)) { *ltime = 0; return (0); } (void) memset(timetok, 0, sizeof (timetok)); if (sscanf(ltimestr, "%d-%08s", &num, timetok) != 2) return (-1); if (!strcasecmp(timetok, "second") || !strcasecmp(timetok, "seconds")) { *ltime = num; } else if (!strcasecmp(timetok, "minute") || !strcasecmp(timetok, "minutes")) { *ltime = num * SECSPERMIN; } else if (!strcasecmp(timetok, "day") || !strcasecmp(timetok, "days")) { *ltime = num * SECSPERDAY; } else if (!strcasecmp(timetok, "hour") || !strcasecmp(timetok, "hours")) { *ltime = num * SECSPERHOUR; } else { *ltime = 0; return (-1); } return (0); } /* * Map KCF error codes into PKCS11 error codes. */ CK_RV crypto2pkcs11_error_number(uint_t n) { if (n >= sizeof (error_number_table) / sizeof (error_number_table[0])) return (CKR_GENERAL_ERROR); return (error_number_table[n]); }