xref: /illumos-gate/usr/src/lib/libcryptoutil/common/util.c (revision 66582b606a8194f7f3ba5b3a3a6dca5b0d346361)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 /*
22  * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
23  * Use is subject to license terms.
24  * Copyright 2018, Joyent, Inc.
25  */
26 
27 #include <cryptoutil.h>
28 #include <strings.h>
29 #include <stdio.h>
30 #include <tzfile.h>
31 #include <sys/crypto/common.h>
32 
33 /*
34  * In order to fit everything on one line, the 'CRYPTO_' prefix
35  * has been dropped from the KCF #defines, e.g.
36  * CRYPTO_SUCCESS becomes SUCCESS.
37  */
38 
39 static CK_RV error_number_table[CRYPTO_LAST_ERROR + 1] = {
40 CKR_OK,					/* SUCCESS */
41 CKR_CANCEL,				/* CANCEL */
42 CKR_HOST_MEMORY,			/* HOST_MEMORY */
43 CKR_GENERAL_ERROR,			/* GENERAL_ERROR */
44 CKR_FUNCTION_FAILED,			/* FAILED */
45 CKR_ARGUMENTS_BAD,			/* ARGUMENTS_BAD */
46 CKR_ATTRIBUTE_READ_ONLY,		/* ATTRIBUTE_READ_ONLY */
47 CKR_ATTRIBUTE_SENSITIVE,		/* ATTRIBUTE_SENSITIVE */
48 CKR_ATTRIBUTE_TYPE_INVALID,		/* ATTRIBUTE_TYPE_INVALID */
49 CKR_ATTRIBUTE_VALUE_INVALID,		/* ATTRIBUTE_VALUE_INVALID */
50 CKR_FUNCTION_FAILED,			/* CANCELED */
51 CKR_DATA_INVALID,			/* DATA_INVALID */
52 CKR_DATA_LEN_RANGE,			/* DATA_LEN_RANGE */
53 CKR_DEVICE_ERROR,			/* DEVICE_ERROR */
54 CKR_DEVICE_MEMORY,			/* DEVICE_MEMORY */
55 CKR_DEVICE_REMOVED,			/* DEVICE_REMOVED */
56 CKR_ENCRYPTED_DATA_INVALID,		/* ENCRYPTED_DATA_INVALID */
57 CKR_ENCRYPTED_DATA_LEN_RANGE,		/* ENCRYPTED_DATA_LEN_RANGE */
58 CKR_KEY_HANDLE_INVALID,			/* KEY_HANDLE_INVALID */
59 CKR_KEY_SIZE_RANGE,			/* KEY_SIZE_RANGE */
60 CKR_KEY_TYPE_INCONSISTENT,		/* KEY_TYPE_INCONSISTENT */
61 CKR_KEY_NOT_NEEDED,			/* KEY_NOT_NEEDED */
62 CKR_KEY_CHANGED,			/* KEY_CHANGED */
63 CKR_KEY_NEEDED,				/* KEY_NEEDED */
64 CKR_KEY_INDIGESTIBLE,			/* KEY_INDIGESTIBLE */
65 CKR_KEY_FUNCTION_NOT_PERMITTED,		/* KEY_FUNCTION_NOT_PERMITTED */
66 CKR_KEY_NOT_WRAPPABLE,			/* KEY_NOT_WRAPPABLE */
67 CKR_KEY_UNEXTRACTABLE,			/* KEY_UNEXTRACTABLE */
68 CKR_MECHANISM_INVALID,			/* MECHANISM_INVALID */
69 CKR_MECHANISM_PARAM_INVALID,		/* MECHANISM_PARAM_INVALID */
70 CKR_OBJECT_HANDLE_INVALID,		/* OBJECT_HANDLE_INVALID */
71 CKR_OPERATION_ACTIVE,			/* OPERATION_ACTIVE */
72 CKR_OPERATION_NOT_INITIALIZED,		/* OPERATION_NOT_INITIALIZED */
73 CKR_PIN_INCORRECT,			/* PIN_INCORRECT */
74 CKR_PIN_INVALID,			/* PIN_INVALID */
75 CKR_PIN_LEN_RANGE,			/* PIN_LEN_RANGE */
76 CKR_PIN_EXPIRED,			/* PIN_EXPIRED */
77 CKR_PIN_LOCKED,				/* PIN_LOCKED */
78 CKR_SESSION_CLOSED,			/* SESSION_CLOSED */
79 CKR_SESSION_COUNT,			/* SESSION_COUNT */
80 CKR_SESSION_HANDLE_INVALID,		/* SESSION_HANDLE_INVALID */
81 CKR_SESSION_READ_ONLY,			/* SESSION_READ_ONLY */
82 CKR_SESSION_EXISTS,			/* SESSION_EXISTS */
83 CKR_SESSION_READ_ONLY_EXISTS,		/* SESSION_READ_ONLY_EXISTS */
84 CKR_SESSION_READ_WRITE_SO_EXISTS,	/* SESSION_READ_WRITE_SO_EXISTS */
85 CKR_SIGNATURE_INVALID,			/* SIGNATURE_INVALID */
86 CKR_SIGNATURE_LEN_RANGE,		/* SIGNATURE_LEN_RANGE */
87 CKR_TEMPLATE_INCOMPLETE,		/* TEMPLATE_INCOMPLETE */
88 CKR_TEMPLATE_INCONSISTENT,		/* TEMPLATE_INCONSISTENT */
89 CKR_UNWRAPPING_KEY_HANDLE_INVALID,	/* UNWRAPPING_KEY_HANDLE_INVALID */
90 CKR_UNWRAPPING_KEY_SIZE_RANGE,		/* UNWRAPPING_KEY_SIZE_RANGE */
91 CKR_UNWRAPPING_KEY_TYPE_INCONSISTENT,	/* UNWRAPPING_KEY_TYPE_INCONSISTENT */
92 CKR_USER_ALREADY_LOGGED_IN,		/* USER_ALREADY_LOGGED_IN */
93 CKR_USER_NOT_LOGGED_IN,			/* USER_NOT_LOGGED_IN */
94 CKR_USER_PIN_NOT_INITIALIZED,		/* USER_PIN_NOT_INITIALIZED */
95 CKR_USER_TYPE_INVALID,			/* USER_TYPE_INVALID */
96 CKR_USER_ANOTHER_ALREADY_LOGGED_IN,	/* USER_ANOTHER_ALREADY_LOGGED_IN */
97 CKR_USER_TOO_MANY_TYPES,		/* USER_TOO_MANY_TYPES */
98 CKR_WRAPPED_KEY_INVALID,		/* WRAPPED_KEY_INVALID */
99 CKR_WRAPPED_KEY_LEN_RANGE,		/* WRAPPED_KEY_LEN_RANGE */
100 CKR_WRAPPING_KEY_HANDLE_INVALID,	/* WRAPPING_KEY_HANDLE_INVALID */
101 CKR_WRAPPING_KEY_SIZE_RANGE,		/* WRAPPING_KEY_SIZE_RANGE */
102 CKR_WRAPPING_KEY_TYPE_INCONSISTENT,	/* WRAPPING_KEY_TYPE_INCONSISTENT */
103 CKR_RANDOM_SEED_NOT_SUPPORTED,		/* RANDOM_SEED_NOT_SUPPORTED */
104 CKR_RANDOM_NO_RNG,			/* RANDOM_NO_RNG */
105 CKR_DOMAIN_PARAMS_INVALID,		/* DOMAIN_PARAMS_INVALID */
106 CKR_BUFFER_TOO_SMALL,			/* BUFFER_TOO_SMALL */
107 CKR_INFORMATION_SENSITIVE,		/* INFORMATION_SENSITIVE */
108 CKR_FUNCTION_NOT_SUPPORTED,		/* NOT_SUPPORTED */
109 CKR_GENERAL_ERROR,			/* QUEUED */
110 CKR_GENERAL_ERROR,			/* BUFFER_TOO_BIG */
111 CKR_OPERATION_NOT_INITIALIZED,		/* INVALID_CONTEXT */
112 CKR_GENERAL_ERROR,			/* INVALID_MAC */
113 CKR_GENERAL_ERROR,			/* MECH_NOT_SUPPORTED */
114 CKR_GENERAL_ERROR,			/* INCONSISTENT_ATTRIBUTE */
115 CKR_GENERAL_ERROR,			/* NO_PERMISSION */
116 CKR_SLOT_ID_INVALID,			/* INVALID_PROVIDER_ID */
117 CKR_GENERAL_ERROR,			/* VERSION_MISMATCH */
118 CKR_GENERAL_ERROR,			/* BUSY */
119 CKR_GENERAL_ERROR,			/* UNKNOWN_PROVIDER */
120 CKR_GENERAL_ERROR,			/* MODVERIFICATION_FAILED */
121 CKR_GENERAL_ERROR,			/* OLD_CTX_TEMPLATE */
122 CKR_GENERAL_ERROR,			/* WEAK_KEY */
123 CKR_GENERAL_ERROR			/* FIPS140_ERROR */
124 };
125 
126 #if CRYPTO_LAST_ERROR != CRYPTO_FIPS140_ERROR
127 #error "Crypto to PKCS11 error mapping table needs to be updated!"
128 #endif
129 
130 /*
131  * This function returns a fullpath based on the "dir" and "filepath" input
132  * arugments.
133  * - If the filepath specified does not start with a "/" and the directory
134  *   is also given, prepend the directory to the filename.
135  * - If only dir or filepath is given, this function returns a copy of the
136  *   given argument.
137  * - If the filepath is fully qualified already and the "dir" is also
138  *   given, return NULL to indicate an error.
139  */
140 char *
141 get_fullpath(char *dir, char *filepath)
142 {
143 	char *fullpath = NULL;
144 	int pathlen = 0;
145 	int dirlen = 0;
146 
147 	if (filepath != NULL)
148 		pathlen = strlen(filepath);
149 
150 	if (dir != NULL)
151 		dirlen = strlen(dir);
152 
153 	if (pathlen > 0 && dirlen > 0) {
154 		if (filepath[0] != '/') {
155 			int len = pathlen + dirlen + 2;
156 			fullpath = (char *)malloc(len);
157 			if (fullpath != NULL)
158 				(void) snprintf(fullpath, len, "%s/%s",
159 				    dir, filepath);
160 		} else {
161 			return (NULL);
162 		}
163 	} else if (pathlen > 0) {
164 		fullpath = (char *)strdup(filepath);
165 	} else if (dirlen > 0) {
166 		fullpath = (char *)strdup(dir);
167 	}
168 
169 	return (fullpath);
170 }
171 
172 /*
173  * This function converts the input string to the value of time
174  * in seconds.
175  * - If the input string is NULL, return zero second.
176  * - The input string needs to be in the form of:
177  *   number-second(s), number-minute(s), number-hour(s) or
178  *   number-day(s).
179  */
180 int
181 str2lifetime(char *ltimestr, uint32_t *ltime)
182 {
183 	int num;
184 	char timetok[10];
185 
186 	if (ltimestr == NULL || !strlen(ltimestr)) {
187 		*ltime = 0;
188 		return (0);
189 	}
190 
191 	(void) memset(timetok, 0, sizeof (timetok));
192 	if (sscanf(ltimestr, "%d-%08s", &num, timetok) != 2)
193 		return (-1);
194 
195 	if (!strcasecmp(timetok, "second") ||
196 	    !strcasecmp(timetok, "seconds")) {
197 		*ltime = num;
198 	} else if (!strcasecmp(timetok, "minute") ||
199 	    !strcasecmp(timetok, "minutes")) {
200 		*ltime = num * SECSPERMIN;
201 	} else if (!strcasecmp(timetok, "day") ||
202 	    !strcasecmp(timetok, "days")) {
203 		*ltime = num * SECSPERDAY;
204 	} else if (!strcasecmp(timetok, "hour") ||
205 	    !strcasecmp(timetok, "hours")) {
206 		*ltime = num * SECSPERHOUR;
207 	} else {
208 		*ltime = 0;
209 		return (-1);
210 	}
211 
212 	return (0);
213 }
214 
215 /*
216  * Map KCF error codes into PKCS11 error codes.
217  */
218 CK_RV
219 crypto2pkcs11_error_number(uint_t n)
220 {
221 	if (n >= sizeof (error_number_table) / sizeof (error_number_table[0]))
222 		return (CKR_GENERAL_ERROR);
223 
224 	return (error_number_table[n]);
225 }
226