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 2009 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
24 * Copyright 2018, Joyent, Inc.
25 */
26
27 #include <pthread.h>
28 #include <stdlib.h>
29 #include <errno.h>
30 #include <sys/crypto/ioctl.h>
31 #include <security/cryptoki.h>
32 #include "kernelGlobal.h"
33 #include "kernelSession.h"
34 #include "kernelObject.h"
35
36
37 CK_RV
C_EncryptInit(CK_SESSION_HANDLE hSession,CK_MECHANISM_PTR pMechanism,CK_OBJECT_HANDLE hKey)38 C_EncryptInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism,
39 CK_OBJECT_HANDLE hKey)
40 {
41
42 CK_RV rv;
43 kernel_session_t *session_p;
44 kernel_object_t *key_p;
45 boolean_t ses_lock_held = B_FALSE;
46 crypto_encrypt_init_t encrypt_init;
47 crypto_mech_type_t k_mech_type;
48 int r;
49 CK_AES_CCM_PARAMS ccm_params = { 0 };
50
51 if (!kernel_initialized)
52 return (CKR_CRYPTOKI_NOT_INITIALIZED);
53
54 if (pMechanism == NULL) {
55 return (CKR_ARGUMENTS_BAD);
56 }
57
58 /* Get the kernel's internal mechanism number. */
59 rv = kernel_mech(pMechanism->mechanism, &k_mech_type);
60 if (rv != CKR_OK)
61 return (rv);
62
63 /* Obtain the session pointer. */
64 rv = handle2session(hSession, &session_p);
65 if (rv != CKR_OK)
66 return (rv);
67
68 /* Obtain the object pointer. */
69 HANDLE2OBJECT(hKey, key_p, rv);
70 if (rv != CKR_OK) {
71 REFRELE(session_p, ses_lock_held);
72 return (rv);
73 }
74
75 /* Check to see if key object allows for encryption. */
76 if (key_p->is_lib_obj && !(key_p->bool_attr_mask & ENCRYPT_BOOL_ON)) {
77 rv = CKR_KEY_TYPE_INCONSISTENT;
78 goto clean_exit;
79 }
80
81 (void) pthread_mutex_lock(&session_p->session_mutex);
82 ses_lock_held = B_TRUE;
83
84 /*
85 * This active flag will remain ON until application calls either
86 * C_Encrypt or C_EncryptFinal to actually obtain the final piece
87 * of ciphertext.
88 */
89 session_p->encrypt.flags = CRYPTO_OPERATION_ACTIVE;
90
91 /* set up key data */
92 if (!key_p->is_lib_obj) {
93 encrypt_init.ei_key.ck_format = CRYPTO_KEY_REFERENCE;
94 encrypt_init.ei_key.ck_obj_id = key_p->k_handle;
95 } else {
96 if (key_p->class == CKO_SECRET_KEY) {
97 encrypt_init.ei_key.ck_format = CRYPTO_KEY_RAW;
98 encrypt_init.ei_key.ck_data =
99 get_symmetric_key_value(key_p);
100 if (encrypt_init.ei_key.ck_data == NULL) {
101 rv = CKR_HOST_MEMORY;
102 goto clean_exit;
103 }
104 encrypt_init.ei_key.ck_length =
105 OBJ_SEC(key_p)->sk_value_len << 3;
106
107 } else if (key_p->key_type == CKK_RSA) {
108 if (get_rsa_public_key(key_p, &encrypt_init.ei_key) !=
109 CKR_OK) {
110 rv = CKR_HOST_MEMORY;
111 goto clean_exit;
112 }
113 } else {
114 rv = CKR_KEY_TYPE_INCONSISTENT;
115 goto clean_exit;
116 }
117 }
118
119 encrypt_init.ei_session = session_p->k_session;
120 session_p->encrypt.mech = *pMechanism;
121
122 /* Cache this capability value for efficiency */
123 if (INPLACE_MECHANISM(session_p->encrypt.mech.mechanism)) {
124 session_p->encrypt.flags |= CRYPTO_OPERATION_INPLACE_OK;
125 }
126 (void) pthread_mutex_unlock(&session_p->session_mutex);
127
128 ses_lock_held = B_FALSE;
129 encrypt_init.ei_mech.cm_type = k_mech_type;
130 encrypt_init.ei_mech.cm_param = pMechanism->pParameter;
131 encrypt_init.ei_mech.cm_param_len = pMechanism->ulParameterLen;
132
133 /*
134 * PKCS#11 uses CK_CCM_PARAMS as its mechanism parameter, while the
135 * kernel uses CK_AES_CCM_PARAMS. Unlike
136 * CK_GCM_PARAMS / CK_AES_GCM_PARAMS, the two definitions are not
137 * equivalent -- the fields are defined in different orders, so
138 * we much translate.
139 */
140 if (session_p->encrypt.mech.mechanism == CKM_AES_CCM) {
141 if (pMechanism->ulParameterLen != sizeof (CK_CCM_PARAMS)) {
142 rv = CKR_MECHANISM_PARAM_INVALID;
143 goto clean_exit;
144 }
145 p11_to_kernel_ccm_params(pMechanism->pParameter, &ccm_params);
146 encrypt_init.ei_mech.cm_param = (caddr_t)&ccm_params;
147 encrypt_init.ei_mech.cm_param_len = sizeof (ccm_params);
148 }
149
150 while ((r = ioctl(kernel_fd, CRYPTO_ENCRYPT_INIT, &encrypt_init)) < 0) {
151 if (errno != EINTR)
152 break;
153 }
154 if (r < 0) {
155 rv = CKR_FUNCTION_FAILED;
156 } else {
157 if (encrypt_init.ei_return_value != CRYPTO_SUCCESS) {
158 rv = crypto2pkcs11_error_number(
159 encrypt_init.ei_return_value);
160 }
161 }
162
163 /* Free memory allocated for decrypt_init.di_key */
164 if (key_p->is_lib_obj) {
165 if (key_p->class == CKO_SECRET_KEY) {
166 free(encrypt_init.ei_key.ck_data);
167 } else if (key_p->key_type == CKK_RSA) {
168 free_key_attributes(&encrypt_init.ei_key);
169 }
170 }
171
172 if (rv != CKR_OK) {
173 (void) pthread_mutex_lock(&session_p->session_mutex);
174 session_p->encrypt.flags &= ~CRYPTO_OPERATION_ACTIVE;
175 ses_lock_held = B_TRUE;
176 }
177
178 clean_exit:
179 /*
180 * ccm_params does not contain any key material -- just lengths and
181 * pointers, therefore it does not need to be zeroed on exit.
182 */
183 OBJ_REFRELE(key_p);
184 REFRELE(session_p, ses_lock_held);
185 return (rv);
186 }
187
188
189 CK_RV
C_Encrypt(CK_SESSION_HANDLE hSession,CK_BYTE_PTR pData,CK_ULONG ulDataLen,CK_BYTE_PTR pEncryptedData,CK_ULONG_PTR pulEncryptedDataLen)190 C_Encrypt(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData, CK_ULONG ulDataLen,
191 CK_BYTE_PTR pEncryptedData, CK_ULONG_PTR pulEncryptedDataLen)
192 {
193
194 CK_RV rv;
195 kernel_session_t *session_p;
196 boolean_t ses_lock_held = B_FALSE;
197 boolean_t inplace;
198 crypto_encrypt_t encrypt;
199 int r;
200
201 if (!kernel_initialized)
202 return (CKR_CRYPTOKI_NOT_INITIALIZED);
203
204 /* Obtain the session pointer. */
205 rv = handle2session(hSession, &session_p);
206 if (rv != CKR_OK)
207 return (rv);
208
209 /*
210 * Only check if pulEncryptedDataLen is NULL.
211 * No need to check if pEncryptedData is NULL because
212 * application might just ask for the length of buffer to hold
213 * the ciphertext.
214 */
215 if (pulEncryptedDataLen == NULL) {
216 rv = CKR_ARGUMENTS_BAD;
217 goto clean_exit;
218 }
219
220 /*
221 * Some encryption algs (often combined mode ciphers such as AES-GCM)
222 * allow 0-byte inputs to encrypt.
223 */
224 if (pData == NULL && ulDataLen != 0) {
225 rv = CKR_ARGUMENTS_BAD;
226 goto clean_exit;
227 }
228
229 (void) pthread_mutex_lock(&session_p->session_mutex);
230 ses_lock_held = B_TRUE;
231
232 /* Application must call C_EncryptInit before calling C_Encrypt. */
233 if (!(session_p->encrypt.flags & CRYPTO_OPERATION_ACTIVE)) {
234 REFRELE(session_p, ses_lock_held);
235 return (CKR_OPERATION_NOT_INITIALIZED);
236 }
237
238 /*
239 * C_Encrypt must be called without intervening C_EncryptUpdate
240 * calls.
241 */
242 if (session_p->encrypt.flags & CRYPTO_OPERATION_UPDATE) {
243 /*
244 * C_Encrypt can not be used to terminate a multi-part
245 * operation, so we'll leave the active encrypt operation
246 * flag on and let the application continue with the
247 * encrypt update operation.
248 */
249 REFRELE(session_p, ses_lock_held);
250 return (CKR_FUNCTION_FAILED);
251 }
252
253 encrypt.ce_session = session_p->k_session;
254
255 /*
256 * Certain mechanisms, where the length of the ciphertext is
257 * same as the transformed plaintext, can be optimized
258 * by the kernel into an in-place operation. Unfortunately,
259 * some applications use a ciphertext buffer that is larger
260 * than it needs to be. We fix that here.
261 */
262 inplace = (session_p->encrypt.flags & CRYPTO_OPERATION_INPLACE_OK) != 0;
263 if (ulDataLen < *pulEncryptedDataLen && inplace) {
264 encrypt.ce_encrlen = ulDataLen;
265 } else {
266 encrypt.ce_encrlen = *pulEncryptedDataLen;
267 }
268 (void) pthread_mutex_unlock(&session_p->session_mutex);
269 ses_lock_held = B_FALSE;
270
271 encrypt.ce_datalen = ulDataLen;
272 encrypt.ce_databuf = (char *)pData;
273 encrypt.ce_encrbuf = (char *)pEncryptedData;
274 encrypt.ce_flags =
275 ((inplace && (pEncryptedData != NULL)) ||
276 (pData == pEncryptedData)) &&
277 (encrypt.ce_encrlen == encrypt.ce_datalen) ?
278 CRYPTO_INPLACE_OPERATION : 0;
279
280 while ((r = ioctl(kernel_fd, CRYPTO_ENCRYPT, &encrypt)) < 0) {
281 if (errno != EINTR)
282 break;
283 }
284 if (r < 0) {
285 rv = CKR_FUNCTION_FAILED;
286 } else {
287 rv = crypto2pkcs11_error_number(encrypt.ce_return_value);
288 }
289
290 if (rv == CKR_OK || rv == CKR_BUFFER_TOO_SMALL)
291 *pulEncryptedDataLen = encrypt.ce_encrlen;
292
293 if ((rv == CKR_BUFFER_TOO_SMALL) ||
294 (rv == CKR_OK && pEncryptedData == NULL)) {
295 /*
296 * We will not terminate the active encrypt operation flag,
297 * when the application-supplied buffer is too small, or
298 * the application asks for the length of buffer to hold
299 * the ciphertext.
300 */
301 REFRELE(session_p, ses_lock_held);
302 return (rv);
303 }
304
305 clean_exit:
306 /*
307 * Terminates the active encrypt operation.
308 * Application needs to call C_EncryptInit again for next
309 * encrypt operation.
310 */
311 (void) pthread_mutex_lock(&session_p->session_mutex);
312 session_p->encrypt.flags = 0;
313 ses_lock_held = B_TRUE;
314 REFRELE(session_p, ses_lock_held);
315
316 return (rv);
317 }
318
319
320 CK_RV
C_EncryptUpdate(CK_SESSION_HANDLE hSession,CK_BYTE_PTR pPart,CK_ULONG ulPartLen,CK_BYTE_PTR pEncryptedPart,CK_ULONG_PTR pulEncryptedPartLen)321 C_EncryptUpdate(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pPart,
322 CK_ULONG ulPartLen, CK_BYTE_PTR pEncryptedPart,
323 CK_ULONG_PTR pulEncryptedPartLen)
324 {
325
326 CK_RV rv;
327 kernel_session_t *session_p;
328 boolean_t ses_lock_held = B_FALSE;
329 boolean_t inplace;
330 crypto_encrypt_update_t encrypt_update;
331 int r;
332
333 if (!kernel_initialized)
334 return (CKR_CRYPTOKI_NOT_INITIALIZED);
335
336 /* Obtain the session pointer. */
337 rv = handle2session(hSession, &session_p);
338 if (rv != CKR_OK)
339 return (rv);
340
341 if (pPart == NULL) {
342 rv = CKR_ARGUMENTS_BAD;
343 goto clean_exit;
344 }
345
346 /*
347 * Only check if pulEncryptedPartLen is NULL.
348 * No need to check if pEncryptedPart is NULL because
349 * application might just ask for the length of buffer to hold
350 * the ciphertext.
351 */
352 if (pulEncryptedPartLen == NULL) {
353 rv = CKR_ARGUMENTS_BAD;
354 goto clean_exit;
355 }
356
357 (void) pthread_mutex_lock(&session_p->session_mutex);
358 ses_lock_held = B_TRUE;
359
360 /*
361 * Application must call C_EncryptInit before calling
362 * C_EncryptUpdate.
363 */
364 if (!(session_p->encrypt.flags & CRYPTO_OPERATION_ACTIVE)) {
365 REFRELE(session_p, ses_lock_held);
366 return (CKR_OPERATION_NOT_INITIALIZED);
367 }
368
369 session_p->encrypt.flags |= CRYPTO_OPERATION_UPDATE;
370
371 encrypt_update.eu_session = session_p->k_session;
372 (void) pthread_mutex_unlock(&session_p->session_mutex);
373 ses_lock_held = B_FALSE;
374
375 encrypt_update.eu_datalen = ulPartLen;
376 encrypt_update.eu_databuf = (char *)pPart;
377 encrypt_update.eu_encrlen = *pulEncryptedPartLen;
378 encrypt_update.eu_encrbuf = (char *)pEncryptedPart;
379
380 inplace = (session_p->encrypt.flags & CRYPTO_OPERATION_INPLACE_OK) != 0;
381 encrypt_update.eu_flags =
382 ((inplace && (pEncryptedPart != NULL)) ||
383 (pPart == pEncryptedPart)) &&
384 (encrypt_update.eu_encrlen == encrypt_update.eu_datalen) ?
385 CRYPTO_INPLACE_OPERATION : 0;
386
387 while ((r = ioctl(kernel_fd, CRYPTO_ENCRYPT_UPDATE,
388 &encrypt_update)) < 0) {
389 if (errno != EINTR)
390 break;
391 }
392 if (r < 0) {
393 rv = CKR_FUNCTION_FAILED;
394 } else {
395 rv = crypto2pkcs11_error_number(
396 encrypt_update.eu_return_value);
397 }
398
399 /*
400 * If CKR_OK or CKR_BUFFER_TOO_SMALL, set the output length.
401 * We don't terminate the current encryption operation.
402 */
403 if (rv == CKR_OK || rv == CKR_BUFFER_TOO_SMALL) {
404 *pulEncryptedPartLen = encrypt_update.eu_encrlen;
405 REFRELE(session_p, ses_lock_held);
406 return (rv);
407 }
408
409 clean_exit:
410 /*
411 * After an error occurred, terminate the current encrypt
412 * operation by resetting the active and update flags.
413 */
414 (void) pthread_mutex_lock(&session_p->session_mutex);
415 session_p->encrypt.flags = 0;
416 ses_lock_held = B_TRUE;
417 REFRELE(session_p, ses_lock_held);
418
419 return (rv);
420 }
421
422
423 CK_RV
C_EncryptFinal(CK_SESSION_HANDLE hSession,CK_BYTE_PTR pLastEncryptedPart,CK_ULONG_PTR pulLastEncryptedPartLen)424 C_EncryptFinal(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pLastEncryptedPart,
425 CK_ULONG_PTR pulLastEncryptedPartLen)
426 {
427
428 CK_RV rv;
429 kernel_session_t *session_p;
430 boolean_t ses_lock_held = B_FALSE;
431 crypto_encrypt_final_t encrypt_final;
432 int r;
433
434 if (!kernel_initialized)
435 return (CKR_CRYPTOKI_NOT_INITIALIZED);
436
437 /* Obtain the session pointer. */
438 rv = handle2session(hSession, &session_p);
439 if (rv != CKR_OK)
440 return (rv);
441
442 if (pulLastEncryptedPartLen == NULL) {
443 rv = CKR_ARGUMENTS_BAD;
444 goto clean_exit;
445 }
446
447 (void) pthread_mutex_lock(&session_p->session_mutex);
448 ses_lock_held = B_TRUE;
449
450 /*
451 * Application must call C_EncryptInit before calling
452 * C_EncryptFinal.
453 */
454 if (!(session_p->encrypt.flags & CRYPTO_OPERATION_ACTIVE)) {
455 REFRELE(session_p, ses_lock_held);
456 return (CKR_OPERATION_NOT_INITIALIZED);
457 }
458
459 encrypt_final.ef_session = session_p->k_session;
460 (void) pthread_mutex_unlock(&session_p->session_mutex);
461 ses_lock_held = B_FALSE;
462
463 encrypt_final.ef_encrlen = *pulLastEncryptedPartLen;
464 encrypt_final.ef_encrbuf = (char *)pLastEncryptedPart;
465
466 while ((r = ioctl(kernel_fd, CRYPTO_ENCRYPT_FINAL,
467 &encrypt_final)) < 0) {
468 if (errno != EINTR)
469 break;
470 }
471 if (r < 0) {
472 rv = CKR_FUNCTION_FAILED;
473 } else {
474 rv = crypto2pkcs11_error_number(encrypt_final.ef_return_value);
475 }
476
477 if (rv == CKR_OK || rv == CKR_BUFFER_TOO_SMALL)
478 *pulLastEncryptedPartLen = encrypt_final.ef_encrlen;
479
480 if ((rv == CKR_BUFFER_TOO_SMALL) ||
481 (rv == CKR_OK && pLastEncryptedPart == NULL)) {
482 /*
483 * We will not terminate the active encrypt operation flag,
484 * when the application-supplied buffer is too small, or
485 * the application asks for the length of buffer to hold
486 * the ciphertext.
487 */
488 REFRELE(session_p, ses_lock_held);
489 return (rv);
490 }
491
492 clean_exit:
493 /* Terminates the active encrypt operation. */
494 (void) pthread_mutex_lock(&session_p->session_mutex);
495 session_p->encrypt.flags = 0;
496 ses_lock_held = B_TRUE;
497 REFRELE(session_p, ses_lock_held);
498
499 return (rv);
500 }
501