Print this page
9642 PKCS#11 softtoken should use explicit_bzero
Reviewed by: Dan McDonald <danmcd@joyent.com>
Reviewed by: Alex Wilson <alex.wilson@joyent.com>
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/lib/pkcs11/pkcs11_softtoken/common/softBlowfishCrypt.c
+++ new/usr/src/lib/pkcs11/pkcs11_softtoken/common/softBlowfishCrypt.c
1 1 /*
2 2 * CDDL HEADER START
3 3 *
4 4 * The contents of this file are subject to the terms of the
5 5 * Common Development and Distribution License (the "License").
6 6 * You may not use this file except in compliance with the License.
7 7 *
8 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 9 * or http://www.opensolaris.org/os/licensing.
10 10 * See the License for the specific language governing permissions
11 11 * and limitations under the License.
12 12 *
13 13 * When distributing Covered Code, include this CDDL HEADER in each
↓ open down ↓ |
13 lines elided |
↑ open up ↑ |
14 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 15 * If applicable, add the following below this CDDL HEADER, with the
16 16 * fields enclosed by brackets "[]" replaced with your own identifying
17 17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 18 *
19 19 * CDDL HEADER END
20 20 */
21 21 /*
22 22 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
23 23 * Use is subject to license terms.
24 + * Copyright (c) 2018, Joyent, Inc.
24 25 */
25 26
26 27 #include <pthread.h>
27 28 #include <stdlib.h>
28 29 #include <string.h>
29 30 #include <strings.h>
30 31 #include <sys/types.h>
31 32 #include <security/cryptoki.h>
32 33 #include "softSession.h"
33 34 #include "softObject.h"
34 35 #include "softCrypt.h"
35 36 #include <blowfish_impl.h>
36 37
37 38 CK_RV
38 39 soft_blowfish_crypt_init_common(soft_session_t *session_p,
39 40 CK_MECHANISM_PTR pMechanism, soft_object_t *key_p, boolean_t encrypt) {
40 41
41 42 size_t size;
42 43 soft_blowfish_ctx_t *soft_blowfish_ctx;
43 44
44 45 soft_blowfish_ctx = calloc(1, sizeof (soft_blowfish_ctx_t));
45 46 if (soft_blowfish_ctx == NULL) {
46 47 return (CKR_HOST_MEMORY);
47 48 }
48 49
49 50 soft_blowfish_ctx->key_sched = blowfish_alloc_keysched(&size, 0);
50 51
51 52 if (soft_blowfish_ctx->key_sched == NULL) {
52 53 free(soft_blowfish_ctx);
53 54 return (CKR_HOST_MEMORY);
54 55 }
55 56
56 57 soft_blowfish_ctx->keysched_len = size;
57 58
58 59 (void) pthread_mutex_lock(&session_p->session_mutex);
59 60 if (encrypt) {
60 61 /* Called by C_EncryptInit */
61 62 session_p->encrypt.context = soft_blowfish_ctx;
62 63 session_p->encrypt.mech.mechanism = pMechanism->mechanism;
63 64 } else {
64 65 /* Called by C_DecryptInit */
65 66 session_p->decrypt.context = soft_blowfish_ctx;
66 67 session_p->decrypt.mech.mechanism = pMechanism->mechanism;
67 68 }
68 69 (void) pthread_mutex_unlock(&session_p->session_mutex);
69 70
70 71 /*
71 72 * If this is a non-sensitive key and it does NOT have
72 73 * a key schedule yet, then allocate one and expand it.
73 74 * Otherwise, if it's a non-sensitive key, and it DOES have
74 75 * a key schedule already attached to it, just copy the
75 76 * pre-expanded schedule to the context and avoid the
76 77 * extra key schedule expansion operation.
77 78 */
78 79 if (!(key_p->bool_attr_mask & SENSITIVE_BOOL_ON)) {
79 80 if (OBJ_KEY_SCHED(key_p) == NULL) {
80 81 void *ks;
81 82
82 83 (void) pthread_mutex_lock(&key_p->object_mutex);
83 84 if (OBJ_KEY_SCHED(key_p) == NULL) {
84 85 ks = blowfish_alloc_keysched(&size, 0);
85 86 if (ks == NULL) {
86 87 (void) pthread_mutex_unlock(
87 88 &key_p->object_mutex);
88 89 free(soft_blowfish_ctx);
89 90 return (CKR_HOST_MEMORY);
90 91 }
91 92
92 93 blowfish_init_keysched(OBJ_SEC_VALUE(key_p),
93 94 (OBJ_SEC_VALUE_LEN(key_p) * 8), ks);
94 95
95 96 OBJ_KEY_SCHED_LEN(key_p) = size;
96 97 OBJ_KEY_SCHED(key_p) = ks;
97 98 }
98 99 (void) pthread_mutex_unlock(&key_p->object_mutex);
99 100 }
100 101 (void) memcpy(soft_blowfish_ctx->key_sched,
101 102 OBJ_KEY_SCHED(key_p), OBJ_KEY_SCHED_LEN(key_p));
102 103 soft_blowfish_ctx->keysched_len = OBJ_KEY_SCHED_LEN(key_p);
103 104
104 105 } else {
105 106 /*
106 107 * Initialize key schedule for Blowfish.
107 108 * blowfish_init_keysched() requires key length in bits.
108 109 */
109 110 blowfish_init_keysched(OBJ_SEC_VALUE(key_p),
110 111 (OBJ_SEC_VALUE_LEN(key_p) * 8),
111 112 soft_blowfish_ctx->key_sched);
112 113 }
113 114 return (CKR_OK);
114 115 }
115 116
116 117
117 118 /*
118 119 * soft_blowfish_encrypt_common()
119 120 *
120 121 * Arguments:
121 122 * session_p: pointer to soft_session_t struct
122 123 * pData: pointer to the input data to be encrypted
123 124 * ulDataLen: length of the input data
124 125 * pEncrypted: pointer to the output data after encryption
125 126 * pulEncryptedLen: pointer to the length of the output data
126 127 * update: boolean flag indicates caller is soft_encrypt
127 128 * or soft_encrypt_update
128 129 *
129 130 * Description:
130 131 * This function calls the corresponding encrypt routine based
131 132 * on the mechanism.
132 133 *
133 134 * Returns:
134 135 * CKR_OK: success
135 136 * CKR_BUFFER_TOO_SMALL: the output buffer provided by application
136 137 * is too small
137 138 * CKR_FUNCTION_FAILED: encrypt function failed
138 139 * CKR_DATA_LEN_RANGE: the input data is not a multiple of blocksize
139 140 */
140 141 CK_RV
141 142 soft_blowfish_encrypt_common(soft_session_t *session_p, CK_BYTE_PTR pData,
142 143 CK_ULONG ulDataLen, CK_BYTE_PTR pEncrypted, CK_ULONG_PTR pulEncryptedLen,
143 144 boolean_t update) {
144 145
145 146 int rc = 0;
146 147 CK_RV rv = CKR_OK;
147 148 soft_blowfish_ctx_t *soft_blowfish_ctx =
148 149 (soft_blowfish_ctx_t *)session_p->encrypt.context;
149 150 blowfish_ctx_t *blowfish_ctx;
150 151 CK_BYTE *in_buf = NULL;
151 152 CK_BYTE *out_buf = NULL;
152 153 CK_ULONG out_len;
153 154 CK_ULONG total_len;
154 155 CK_ULONG remain;
155 156 crypto_data_t out;
156 157
157 158 /*
158 159 * Blowfish only takes input length that is a multiple of blocksize
159 160 * for C_Encrypt function with the mechanism CKM_BLOWFISH_CBC.
160 161 *
161 162 */
162 163 if (!update) {
163 164 if ((ulDataLen % BLOWFISH_BLOCK_LEN) != 0) {
164 165 rv = CKR_DATA_LEN_RANGE;
165 166 goto cleanup;
166 167 }
167 168
168 169 out_len = ulDataLen;
169 170 /*
170 171 * If application asks for the length of the output buffer
171 172 * to hold the ciphertext?
172 173 */
173 174 if (pEncrypted == NULL) {
174 175 *pulEncryptedLen = out_len;
175 176 return (CKR_OK);
176 177 }
177 178
178 179 /* Is the application-supplied buffer large enough? */
179 180 if (*pulEncryptedLen < out_len) {
180 181 *pulEncryptedLen = out_len;
181 182 return (CKR_BUFFER_TOO_SMALL);
182 183 }
183 184
184 185 in_buf = pData;
185 186 out_buf = pEncrypted;
186 187 } else {
187 188 /*
188 189 * Called by C_EncryptUpdate
189 190 *
190 191 * Add the lengths of last remaining data and current
191 192 * plaintext together to get the total input length.
192 193 */
193 194 total_len = soft_blowfish_ctx->remain_len + ulDataLen;
194 195
195 196 /*
196 197 * If the total input length is less than one blocksize,
197 198 * we will need to delay encryption until when more data
198 199 * comes in next C_EncryptUpdate or when C_EncryptFinal
199 200 * is called.
200 201 */
201 202 if (total_len < BLOWFISH_BLOCK_LEN) {
202 203 if (pEncrypted != NULL) {
203 204 /*
204 205 * Save input data and its length in
205 206 * the remaining buffer of BLOWFISH context.
206 207 */
207 208 (void) memcpy(soft_blowfish_ctx->data +
208 209 soft_blowfish_ctx->remain_len, pData,
209 210 ulDataLen);
210 211 soft_blowfish_ctx->remain_len += ulDataLen;
211 212 }
212 213
213 214 /* Set encrypted data length to 0. */
214 215 *pulEncryptedLen = 0;
215 216 return (CKR_OK);
216 217 }
217 218
218 219 /* Compute the length of remaing data. */
219 220 remain = total_len % BLOWFISH_BLOCK_LEN;
220 221
221 222 /*
222 223 * Make sure that the output length is a multiple of
223 224 * blocksize.
224 225 */
225 226 out_len = total_len - remain;
226 227
227 228 /*
228 229 * If application asks for the length of the output buffer
229 230 * to hold the ciphertext?
230 231 */
231 232 if (pEncrypted == NULL) {
232 233 *pulEncryptedLen = out_len;
233 234 return (CKR_OK);
234 235 }
235 236
236 237 /* Is the application-supplied buffer large enough? */
237 238 if (*pulEncryptedLen < out_len) {
238 239 *pulEncryptedLen = out_len;
239 240 return (CKR_BUFFER_TOO_SMALL);
240 241 }
241 242
242 243 if (soft_blowfish_ctx->remain_len != 0) {
243 244 /*
244 245 * Copy last remaining data and current input data
245 246 * to the output buffer.
246 247 */
247 248 (void) memmove(pEncrypted +
248 249 soft_blowfish_ctx->remain_len,
249 250 pData, out_len - soft_blowfish_ctx->remain_len);
250 251 (void) memcpy(pEncrypted, soft_blowfish_ctx->data,
251 252 soft_blowfish_ctx->remain_len);
252 253 bzero(soft_blowfish_ctx->data,
253 254 soft_blowfish_ctx->remain_len);
254 255
255 256 in_buf = pEncrypted;
256 257 } else {
257 258 in_buf = pData;
258 259 }
259 260 out_buf = pEncrypted;
260 261 }
261 262
262 263 /*
263 264 * Begin Encryption now.
264 265 */
265 266
266 267 out.cd_format = CRYPTO_DATA_RAW;
267 268 out.cd_offset = 0;
268 269 out.cd_length = out_len;
269 270 out.cd_raw.iov_base = (char *)out_buf;
270 271 out.cd_raw.iov_len = out_len;
271 272
272 273 /* Encrypt multiple blocks of data. */
273 274 rc = blowfish_encrypt_contiguous_blocks(
274 275 (blowfish_ctx_t *)soft_blowfish_ctx->blowfish_cbc,
275 276 (char *)in_buf, out_len, &out);
276 277
277 278 if (rc == 0) {
278 279 *pulEncryptedLen = out_len;
279 280 if (update) {
280 281 /*
281 282 * For encrypt update, if there is remaining data,
282 283 * save it and it's length in the context.
283 284 */
284 285 if (remain != 0)
285 286 (void) memcpy(soft_blowfish_ctx->data, pData +
286 287 (ulDataLen - remain), remain);
287 288
288 289 soft_blowfish_ctx->remain_len = remain;
289 290 return (CKR_OK);
↓ open down ↓ |
256 lines elided |
↑ open up ↑ |
290 291 }
291 292
292 293 } else {
293 294 *pulEncryptedLen = 0;
294 295 rv = CKR_FUNCTION_FAILED;
295 296 }
296 297
297 298 cleanup:
298 299 (void) pthread_mutex_lock(&session_p->session_mutex);
299 300 blowfish_ctx = (blowfish_ctx_t *)soft_blowfish_ctx->blowfish_cbc;
300 - if (blowfish_ctx != NULL) {
301 - bzero(blowfish_ctx->bc_keysched,
302 - blowfish_ctx->bc_keysched_len);
303 - free(soft_blowfish_ctx->blowfish_cbc);
304 - }
305 -
306 - bzero(soft_blowfish_ctx->key_sched, soft_blowfish_ctx->keysched_len);
307 - free(soft_blowfish_ctx->key_sched);
308 - free(session_p->encrypt.context);
301 + freezero(blowfish_ctx, sizeof (cbc_ctx_t));
302 + freezero(soft_blowfish_ctx->key_sched,
303 + soft_blowfish_ctx->keysched_len);
304 + freezero(session_p->encrypt.context,
305 + sizeof (soft_blowfish_ctx_t));
309 306 session_p->encrypt.context = NULL;
310 307 (void) pthread_mutex_unlock(&session_p->session_mutex);
311 308
312 309 return (rv);
313 310 }
314 311
315 312
316 313 CK_RV
317 314 soft_blowfish_decrypt_common(soft_session_t *session_p, CK_BYTE_PTR pEncrypted,
318 315 CK_ULONG ulEncryptedLen, CK_BYTE_PTR pData, CK_ULONG_PTR pulDataLen,
319 316 boolean_t update) {
320 317
321 318 int rc = 0;
322 319 CK_RV rv = CKR_OK;
323 320 soft_blowfish_ctx_t *soft_blowfish_ctx =
324 321 (soft_blowfish_ctx_t *)session_p->decrypt.context;
325 322 blowfish_ctx_t *blowfish_ctx;
326 323 CK_BYTE *in_buf = NULL;
327 324 CK_BYTE *out_buf = NULL;
328 325 CK_ULONG out_len;
329 326 CK_ULONG total_len;
330 327 CK_ULONG remain;
331 328 crypto_data_t out;
332 329
333 330 /*
334 331 * Blowfish only takes input length that is a multiple of 16 bytes
335 332 * for C_Decrypt function using CKM_BLOWFISH_CBC.
336 333 */
337 334
338 335 if (!update) {
339 336 /* Called by C_Decrypt */
340 337 if ((ulEncryptedLen % BLOWFISH_BLOCK_LEN) != 0) {
341 338 rv = CKR_ENCRYPTED_DATA_LEN_RANGE;
342 339 goto cleanup;
343 340 }
344 341
345 342 /*
346 343 * If application asks for the length of the output buffer
347 344 * to hold the plaintext?
348 345 */
349 346 if (pData == NULL) {
350 347 *pulDataLen = ulEncryptedLen;
351 348 return (CKR_OK);
352 349 }
353 350
354 351 /* Is the application-supplied buffer large enough? */
355 352 if (*pulDataLen < ulEncryptedLen) {
356 353 *pulDataLen = ulEncryptedLen;
357 354 return (CKR_BUFFER_TOO_SMALL);
358 355 }
359 356 out_len = ulEncryptedLen;
360 357 in_buf = pEncrypted;
361 358 out_buf = pData;
362 359 } else {
363 360 /*
364 361 * Called by C_DecryptUpdate
365 362 *
366 363 * Add the lengths of last remaining data and current
367 364 * input data together to get the total input length.
368 365 */
369 366 total_len = soft_blowfish_ctx->remain_len + ulEncryptedLen;
370 367
371 368 if (total_len < BLOWFISH_BLOCK_LEN) {
372 369 if (pData != NULL) {
373 370 (void) memcpy(soft_blowfish_ctx->data +
374 371 soft_blowfish_ctx->remain_len,
375 372 pEncrypted, ulEncryptedLen);
376 373
377 374 soft_blowfish_ctx->remain_len += ulEncryptedLen;
378 375 }
379 376
380 377 /* Set output data length to 0. */
381 378 *pulDataLen = 0;
382 379 return (CKR_OK);
383 380 }
384 381
385 382 /* Compute the length of remaining data. */
386 383 remain = total_len % BLOWFISH_BLOCK_LEN;
387 384
388 385 /*
389 386 * Make sure that the output length is a multiple of
390 387 * blocksize.
391 388 */
392 389 out_len = total_len - remain;
393 390
394 391 /*
395 392 * if application asks for the length of the output buffer
396 393 * to hold the plaintext?
397 394 */
398 395 if (pData == NULL) {
399 396 *pulDataLen = out_len;
400 397 return (CKR_OK);
401 398 }
402 399
403 400 /*
404 401 * Is the application-supplied buffer large enough?
405 402 */
406 403 if (*pulDataLen < out_len) {
407 404 *pulDataLen = out_len;
408 405 return (CKR_BUFFER_TOO_SMALL);
409 406 }
410 407
411 408 if (soft_blowfish_ctx->remain_len != 0) {
412 409 /*
413 410 * Copy last remaining data and current input data
414 411 * to the output buffer.
415 412 */
416 413 (void) memmove(pData + soft_blowfish_ctx->remain_len,
417 414 pEncrypted,
418 415 out_len - soft_blowfish_ctx->remain_len);
419 416 (void) memcpy(pData, soft_blowfish_ctx->data,
420 417 soft_blowfish_ctx->remain_len);
421 418 bzero(soft_blowfish_ctx->data,
422 419 soft_blowfish_ctx->remain_len);
423 420
424 421
425 422 in_buf = pData;
426 423 } else {
427 424 in_buf = pEncrypted;
428 425 }
429 426
430 427 out_buf = pData;
431 428 }
432 429
433 430 out.cd_format = CRYPTO_DATA_RAW;
434 431 out.cd_offset = 0;
435 432 out.cd_length = out_len;
436 433 out.cd_raw.iov_base = (char *)out_buf;
437 434 out.cd_raw.iov_len = out_len;
438 435
439 436 /* Decrypt multiple blocks of data. */
440 437 rc = blowfish_decrypt_contiguous_blocks(
441 438 (blowfish_ctx_t *)soft_blowfish_ctx->blowfish_cbc,
442 439 (char *)in_buf, out_len, &out);
443 440
444 441 if (rc == 0) {
445 442 *pulDataLen = out_len;
446 443 if (update) {
447 444 /*
448 445 * For decrypt update, if there is remaining data,
449 446 * save it and its length in the context.
450 447 */
451 448 if (remain != 0)
452 449 (void) memcpy(soft_blowfish_ctx->data,
453 450 pEncrypted + (ulEncryptedLen - remain),
454 451 remain);
455 452 soft_blowfish_ctx->remain_len = remain;
456 453 return (CKR_OK);
457 454 }
↓ open down ↓ |
139 lines elided |
↑ open up ↑ |
458 455
459 456
460 457 } else {
461 458 *pulDataLen = 0;
462 459 rv = CKR_FUNCTION_FAILED;
463 460 }
464 461
465 462 cleanup:
466 463 (void) pthread_mutex_lock(&session_p->session_mutex);
467 464 blowfish_ctx = (blowfish_ctx_t *)soft_blowfish_ctx->blowfish_cbc;
468 - if (blowfish_ctx != NULL) {
469 - bzero(blowfish_ctx->bc_keysched,
470 - blowfish_ctx->bc_keysched_len);
471 - free(soft_blowfish_ctx->blowfish_cbc);
472 - }
473 -
474 - bzero(soft_blowfish_ctx->key_sched, soft_blowfish_ctx->keysched_len);
475 - free(soft_blowfish_ctx->key_sched);
476 - free(session_p->decrypt.context);
465 + free(blowfish_ctx);
466 + freezero(soft_blowfish_ctx->key_sched,
467 + soft_blowfish_ctx->keysched_len);
468 + freezero(session_p->decrypt.context,
469 + sizeof (soft_blowfish_ctx_t));
477 470 session_p->decrypt.context = NULL;
478 471 (void) pthread_mutex_unlock(&session_p->session_mutex);
479 472
480 473 return (rv);
481 474 }
482 475
483 476 /*
484 477 * Allocate and initialize a context for BLOWFISH CBC mode of operation.
485 478 */
486 479
487 480 void *
488 481 blowfish_cbc_ctx_init(void *key_sched, size_t size, uint8_t *ivec)
489 482 {
490 483
491 484 cbc_ctx_t *cbc_ctx;
492 485
493 486 if ((cbc_ctx = calloc(1, sizeof (cbc_ctx_t))) == NULL)
494 487 return (NULL);
495 488
496 489 cbc_ctx->cbc_keysched = key_sched;
497 490
498 491 (void) memcpy(&cbc_ctx->cbc_iv[0], ivec, BLOWFISH_BLOCK_LEN);
499 492
500 493 cbc_ctx->cbc_lastp = (uint8_t *)&(cbc_ctx->cbc_iv);
501 494 cbc_ctx->cbc_keysched_len = size;
502 495 cbc_ctx->cbc_flags |= CBC_MODE;
503 496
504 497 return (cbc_ctx);
505 498 }
↓ open down ↓ |
19 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX