xref: /illumos-gate/usr/src/lib/libkmf/libkmf/common/pk11keys.c (revision b07ce584f4e28873b8927d7f83d9d3275a0f3ed2)
1 /*
2  * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
3  * Use is subject to license terms.
4  */
5 /*
6  * Copyright (c) 1995-2000 Intel Corporation. All rights reserved.
7  */
8 
9 #pragma ident	"%Z%%M%	%I%	%E% SMI"
10 
11 #include <kmfapiP.h>
12 #include <sha1.h>
13 #include <security/cryptoki.h>
14 
15 #include <algorithm.h>
16 #include <ber_der.h>
17 
18 #define	MAX_PUBLIC_KEY_TEMPLATES    (20)
19 #define	MAX_PRIVATE_KEY_TEMPLATES   (24)
20 #define	MAX_SECRET_KEY_TEMPLATES    (24)
21 
22 static KMF_RETURN
23 create_pk11_session(CK_SESSION_HANDLE *sessionp, CK_MECHANISM_TYPE wanted_mech,
24 	CK_FLAGS wanted_flags)
25 {
26 	CK_RV rv;
27 	KMF_RETURN ret;
28 	KMF_RETURN kmf_rv = KMF_OK;
29 	CK_SLOT_ID_PTR pSlotList;
30 	CK_ULONG pulCount;
31 	CK_MECHANISM_INFO info;
32 	int i;
33 
34 	ret = init_pk11();
35 
36 	if (ret != KMF_OK)
37 		return (ret);
38 
39 	rv = C_GetSlotList(0, NULL, &pulCount);
40 	if (rv != CKR_OK) {
41 		kmf_rv = KMF_ERR_UNINITIALIZED;
42 		goto out;
43 	}
44 
45 	pSlotList = (CK_SLOT_ID_PTR) malloc(pulCount * sizeof (CK_SLOT_ID));
46 	if (pSlotList == NULL) {
47 		kmf_rv = KMF_ERR_MEMORY;
48 		goto out;
49 	}
50 
51 	rv = C_GetSlotList(0, pSlotList, &pulCount);
52 	if (rv != CKR_OK) {
53 		kmf_rv = KMF_ERR_UNINITIALIZED;
54 		goto out;
55 	}
56 
57 	for (i = 0; i < pulCount; i++) {
58 		rv = C_GetMechanismInfo(pSlotList[i], wanted_mech, &info);
59 		if (rv == CKR_OK && (info.flags & wanted_flags))
60 			break;
61 	}
62 	if (i < pulCount) {
63 		rv = C_OpenSession(pSlotList[i], CKF_SERIAL_SESSION,
64 		    NULL, NULL, sessionp);
65 
66 		if (rv != CKR_OK) {
67 			kmf_rv = KMF_ERR_UNINITIALIZED;
68 		}
69 	} else {
70 		kmf_rv = KMF_ERR_UNINITIALIZED;
71 	}
72 
73 out:
74 	if (pSlotList != NULL)
75 		free(pSlotList);
76 	return (kmf_rv);
77 
78 }
79 
80 /*
81  * Name: PKCS_AddTemplate
82  *
83  * Description:
84  *  Adds a CK_ATTRIBUTE value to an existing array of CK_ATTRIBUTES. Will
85  *  not expand the array beyond the maximum specified size.
86  *
87  * Returns:
88  *  TRUE - Attribute value succesfully added.
89  *  FALSE - Maximum array size would be exceded.
90  */
91 static int
92 PKCS_AddTemplate(CK_ATTRIBUTE *pTemplate,
93 	CK_ULONG *ckNumTemplates,
94 	CK_ULONG ckMaxTemplates,
95 	CK_ATTRIBUTE_TYPE ckAttribCode,
96 	CK_BYTE * pckBuffer,
97 	CK_ULONG ckBufferLen)
98 {
99 	if (*ckNumTemplates >= ckMaxTemplates) {
100 		return (FALSE);
101 	}
102 
103 	pTemplate[*ckNumTemplates].type = ckAttribCode;
104 	pTemplate[*ckNumTemplates].pValue = pckBuffer;
105 	pTemplate[*ckNumTemplates].ulValueLen = ckBufferLen;
106 	(*ckNumTemplates)++;
107 
108 	return (TRUE);
109 }
110 
111 /*
112  * Convert an SPKI data record to PKCS#11
113  * public key object.
114  */
115 static KMF_RETURN
116 PKCS_CreatePublicKey(
117 	const KMF_X509_SPKI *pKey,
118 	CK_SESSION_HANDLE ckSession,
119 	CK_OBJECT_HANDLE *pckPublicKey)
120 {
121 	KMF_RETURN mrReturn = KMF_OK;
122 	CK_RV ckRv;
123 
124 	CK_ATTRIBUTE ckTemplate[MAX_PUBLIC_KEY_TEMPLATES];
125 	CK_ULONG ckNumTemplates = 0;
126 
127 	/* Common object attributes */
128 	CK_OBJECT_CLASS ckObjClass = CKO_PUBLIC_KEY;
129 	CK_BBOOL ckToken = 0;
130 	CK_BBOOL ckPrivate = 0;
131 
132 	/* Common key attributes */
133 	CK_KEY_TYPE ckKeyType;
134 	CK_BBOOL ckDerive = CK_FALSE;
135 
136 	/* Common public key attributes */
137 	CK_BBOOL ckEncrypt = 1;
138 	CK_BBOOL ckVerify = 1;
139 
140 	CK_BBOOL ckVerifyRecover = CK_FALSE;
141 	CK_BBOOL ckWrap = CK_FALSE;
142 
143 	/* Key part array */
144 	KMF_DATA KeyParts[KMF_MAX_PUBLIC_KEY_PARTS];
145 	uint32_t i, uNumKeyParts = KMF_MAX_PUBLIC_KEY_PARTS;
146 	KMF_ALGORITHM_INDEX AlgorithmId;
147 
148 	/* Parse the keyblob */
149 	(void) memset(KeyParts, 0, sizeof (KeyParts));
150 
151 	AlgorithmId = x509_algoid_to_algid(
152 	    (KMF_OID *)&pKey->algorithm.algorithm);
153 	if (AlgorithmId == KMF_ALGID_NONE)
154 		return (KMF_ERR_BAD_ALGORITHM);
155 
156 	mrReturn = ExtractSPKIData(pKey, AlgorithmId, KeyParts, &uNumKeyParts);
157 
158 	if (mrReturn != KMF_OK)
159 		return (mrReturn);
160 
161 	/* Fill in the common object attributes */
162 	if (!PKCS_AddTemplate(ckTemplate, &ckNumTemplates,
163 	    MAX_PUBLIC_KEY_TEMPLATES, CKA_CLASS, (CK_BYTE *)&ckObjClass,
164 	    sizeof (ckObjClass)) ||
165 	    !PKCS_AddTemplate(ckTemplate, &ckNumTemplates,
166 	    MAX_PUBLIC_KEY_TEMPLATES, CKA_TOKEN, (CK_BYTE *)&ckToken,
167 	    sizeof (ckToken)) ||
168 	    !PKCS_AddTemplate(ckTemplate, &ckNumTemplates,
169 	    MAX_PUBLIC_KEY_TEMPLATES, CKA_PRIVATE, (CK_BYTE *)&ckPrivate,
170 	    sizeof (ckPrivate))) {
171 		mrReturn = KMF_ERR_INTERNAL;
172 		goto cleanup;
173 	}
174 
175 	/* Fill in the common key attributes */
176 	if (!pkcs_algid_to_keytype(AlgorithmId,	&ckKeyType)) {
177 		goto cleanup;
178 	}
179 	if (!PKCS_AddTemplate(ckTemplate, &ckNumTemplates,
180 	    MAX_PUBLIC_KEY_TEMPLATES, CKA_KEY_TYPE, (CK_BYTE *)&ckKeyType,
181 	    sizeof (ckKeyType)) ||
182 	    !PKCS_AddTemplate(ckTemplate, &ckNumTemplates,
183 	    MAX_PUBLIC_KEY_TEMPLATES, CKA_DERIVE, (CK_BYTE *)&ckDerive,
184 	    sizeof (ckDerive))) {
185 		mrReturn = KMF_ERR_INTERNAL;
186 		goto cleanup;
187 	}
188 
189 	/* Add common public key attributes */
190 	if (!PKCS_AddTemplate(ckTemplate, &ckNumTemplates,
191 	    MAX_PUBLIC_KEY_TEMPLATES, CKA_ENCRYPT, (CK_BYTE *)&ckEncrypt,
192 	    sizeof (ckEncrypt)) ||
193 	    !PKCS_AddTemplate(ckTemplate, &ckNumTemplates,
194 	    MAX_PUBLIC_KEY_TEMPLATES, CKA_VERIFY, (CK_BYTE *)&ckVerify,
195 	    sizeof (ckVerify)) ||
196 	    !PKCS_AddTemplate(ckTemplate, &ckNumTemplates,
197 	    MAX_PUBLIC_KEY_TEMPLATES, CKA_VERIFY_RECOVER,
198 	    (CK_BYTE *)&ckVerifyRecover, sizeof (ckVerifyRecover)) ||
199 	    !PKCS_AddTemplate(ckTemplate, &ckNumTemplates,
200 	    MAX_PUBLIC_KEY_TEMPLATES, CKA_WRAP, (CK_BYTE *)&ckWrap,
201 	    sizeof (ckWrap))) {
202 		mrReturn = KMF_ERR_INTERNAL;
203 		goto cleanup;
204 	}
205 
206 	/* Add algorithm specific attributes */
207 	switch (ckKeyType) {
208 	case CKK_RSA:
209 		if (!PKCS_AddTemplate(ckTemplate, &ckNumTemplates,
210 		    MAX_PUBLIC_KEY_TEMPLATES, CKA_MODULUS,
211 		    (CK_BYTE *)KeyParts[KMF_RSA_MODULUS].Data,
212 		    (CK_ULONG)KeyParts[KMF_RSA_MODULUS].Length) ||
213 		    !PKCS_AddTemplate(ckTemplate, &ckNumTemplates,
214 		    MAX_PUBLIC_KEY_TEMPLATES, CKA_PUBLIC_EXPONENT,
215 		    (CK_BYTE *)KeyParts[KMF_RSA_PUBLIC_EXPONENT].Data,
216 		    (CK_ULONG)KeyParts[KMF_RSA_PUBLIC_EXPONENT].Length)) {
217 			mrReturn = KMF_ERR_INTERNAL;
218 			goto cleanup;
219 		}
220 		break;
221 	case CKK_DSA:
222 		if (!PKCS_AddTemplate(ckTemplate, &ckNumTemplates,
223 		    MAX_PUBLIC_KEY_TEMPLATES, CKA_PRIME,
224 		    (CK_BYTE *)KeyParts[KMF_DSA_PRIME].Data,
225 		    (CK_ULONG)KeyParts[KMF_DSA_PRIME].Length) ||
226 		    !PKCS_AddTemplate(ckTemplate, &ckNumTemplates,
227 		    MAX_PUBLIC_KEY_TEMPLATES, CKA_SUBPRIME,
228 		    (CK_BYTE *)KeyParts[KMF_DSA_SUB_PRIME].Data,
229 		    (CK_ULONG)KeyParts[KMF_DSA_SUB_PRIME].Length) ||
230 		    !PKCS_AddTemplate(ckTemplate, &ckNumTemplates,
231 		    MAX_PUBLIC_KEY_TEMPLATES, CKA_BASE,
232 		    (CK_BYTE *)KeyParts[KMF_DSA_BASE].Data,
233 		    (CK_ULONG)KeyParts[KMF_DSA_BASE].Length) ||
234 		    !PKCS_AddTemplate(ckTemplate, &ckNumTemplates,
235 		    MAX_PUBLIC_KEY_TEMPLATES, CKA_VALUE,
236 		    (CK_BYTE *)KeyParts[KMF_DSA_PUBLIC_VALUE].Data,
237 		    (CK_ULONG)KeyParts[KMF_DSA_PUBLIC_VALUE].Length)) {
238 		mrReturn = KMF_ERR_INTERNAL;
239 		goto cleanup;
240 		}
241 		break;
242 	default:
243 		mrReturn = KMF_ERR_BAD_PARAMETER;
244 	}
245 
246 	if (mrReturn == KMF_OK) {
247 		/* Instantiate the object */
248 		ckRv = C_CreateObject(ckSession, ckTemplate,
249 		    ckNumTemplates, pckPublicKey);
250 		if (ckRv != CKR_OK)
251 			mrReturn = KMF_ERR_INTERNAL;
252 	}
253 
254 cleanup:
255 	for (i = 0; i < uNumKeyParts; i++) {
256 		kmf_free_data(&KeyParts[i]);
257 	}
258 
259 	return (mrReturn);
260 }
261 
262 /*
263  * PKCS_AcquirePublicKeyHandle
264  *
265  *   Given an assymetric key keyblob, attempts to find the appropriate
266  *    public key.
267  *
268  *  Methods of finding the public key:
269  *  - Public Key with data present:
270  *    Parses the key and creates a temporary session object.
271  *  - Public Key with handle:
272  *    The handle is type converted and returned. Validity of the handle is
273  *    not checked.
274  *  - Public Key with label:
275  *    Attempts to find a public key with the corresponding label.
276  */
277 KMF_RETURN
278 PKCS_AcquirePublicKeyHandle(CK_SESSION_HANDLE ckSession,
279 	const KMF_X509_SPKI *pKey,
280 	CK_KEY_TYPE ckRequestedKeyType,
281 	CK_OBJECT_HANDLE *pckKeyHandle,
282 	KMF_BOOL *pbTemporary)
283 {
284 	KMF_RETURN mrReturn = KMF_OK;
285 
286 
287 	/* Key searching variables */
288 	CK_OBJECT_HANDLE ckKeyHandle;
289 	CK_OBJECT_CLASS ckObjClass;
290 	CK_KEY_TYPE ckKeyType;
291 	CK_ATTRIBUTE ckTemplate[3];
292 	CK_ULONG ckNumTemplates;
293 	static const CK_ULONG ckMaxTemplates = (sizeof (ckTemplate) /
294 	    sizeof (CK_ATTRIBUTE));
295 	CK_RV ckRv;
296 
297 	/* Extract the data from the SPKI into individual fields */
298 	mrReturn = PKCS_CreatePublicKey(pKey, ckSession, &ckKeyHandle);
299 	if (mrReturn != KMF_OK)
300 		return (mrReturn);
301 
302 	*pbTemporary = KMF_TRUE;
303 
304 	/* Fetch the key class and algorithm from the object */
305 	ckNumTemplates = 0;
306 	if (!PKCS_AddTemplate(ckTemplate, &ckNumTemplates,
307 	    ckMaxTemplates, CKA_CLASS, (CK_BYTE *)&ckObjClass,
308 	    sizeof (ckObjClass)) ||
309 	    !PKCS_AddTemplate(ckTemplate, &ckNumTemplates,
310 	    ckMaxTemplates, CKA_KEY_TYPE, (CK_BYTE *)&ckKeyType,
311 	    sizeof (ckKeyType))) {
312 		return (KMF_ERR_INTERNAL);
313 	}
314 	ckRv = C_GetAttributeValue(ckSession, ckKeyHandle,
315 	    ckTemplate,	ckNumTemplates);
316 	if (ckRv != CKR_OK) {
317 		return (ckRv);
318 	}
319 
320 	/* Make sure the results match the expected values */
321 	if ((ckKeyType != ckRequestedKeyType) ||
322 	    (ckObjClass != CKO_PUBLIC_KEY)) {
323 		if (*pbTemporary == KMF_TRUE) {
324 			(void) C_DestroyObject(ckSession, ckKeyHandle);
325 		}
326 
327 		return (KMF_ERR_BAD_KEY_FORMAT);
328 	}
329 
330 	/* Set the return values */
331 	*pckKeyHandle = ckKeyHandle;
332 
333 	return (KMF_OK);
334 }
335 
336 KMF_SIGNATURE_MODE
337 PKCS_GetDefaultSignatureMode(KMF_ALGORITHM_INDEX AlgId)
338 {
339 	KMF_SIGNATURE_MODE AlgMode;
340 
341 	switch (AlgId) {
342 		case KMF_ALGID_RSA:
343 		case KMF_ALGID_MD5WithRSA:
344 		case KMF_ALGID_MD2WithRSA:
345 		case KMF_ALGID_SHA1WithRSA:
346 			AlgMode = KMF_ALGMODE_PKCS1_EMSA_V15;
347 			break;
348 		default:
349 			AlgMode = KMF_ALGMODE_NONE;
350 			break;
351 	}
352 
353 	return (AlgMode);
354 }
355 
356 KMF_RETURN
357 PKCS_VerifyData(KMF_HANDLE_T kmfh,
358 		KMF_ALGORITHM_INDEX AlgorithmId,
359 		KMF_X509_SPKI *keyp,
360 		KMF_DATA *data,
361 		KMF_DATA *signed_data)
362 {
363 	KMF_RETURN rv = KMF_OK;
364 	PKCS_ALGORITHM_MAP *pAlgMap = NULL;
365 	CK_RV ckRv;
366 	CK_MECHANISM ckMechanism;
367 	CK_OBJECT_HANDLE ckKeyHandle;
368 	KMF_BOOL	bTempKey;
369 	CK_SESSION_HANDLE ckSession = 0;
370 
371 	if (AlgorithmId == KMF_ALGID_NONE)
372 		return (KMF_ERR_BAD_ALGORITHM);
373 
374 	pAlgMap = pkcs_get_alg_map(KMF_ALGCLASS_SIGNATURE,
375 	    AlgorithmId, PKCS_GetDefaultSignatureMode(AlgorithmId));
376 
377 	if (!pAlgMap)
378 		return (KMF_ERR_BAD_ALGORITHM);
379 
380 	rv = create_pk11_session(&ckSession, pAlgMap->pkcs_mechanism,
381 	    CKF_VERIFY);
382 
383 	if (rv != KMF_OK)
384 		return (rv);
385 
386 	/* Fetch the verifying key */
387 	rv = PKCS_AcquirePublicKeyHandle(ckSession, keyp,
388 	    pAlgMap->key_type, &ckKeyHandle, &bTempKey);
389 
390 	if (rv != KMF_OK) {
391 		(void) C_CloseSession(ckSession);
392 		return (rv);
393 	}
394 
395 	ckMechanism.mechanism = pAlgMap->pkcs_mechanism;
396 	ckMechanism.pParameter = NULL;
397 	ckMechanism.ulParameterLen = 0;
398 
399 	ckRv = C_VerifyInit(ckSession, &ckMechanism, ckKeyHandle);
400 	if (ckRv != CKR_OK) {
401 		if (bTempKey)
402 			(void) C_DestroyObject(ckSession, ckKeyHandle);
403 		kmfh->lasterr.kstype = KMF_KEYSTORE_PK11TOKEN;
404 		kmfh->lasterr.errcode = ckRv;
405 		(void) C_CloseSession(ckSession);
406 		return (KMF_ERR_INTERNAL);
407 	}
408 
409 	ckRv = C_Verify(ckSession, (CK_BYTE *)data->Data,
410 	    (CK_ULONG)data->Length,
411 	    (CK_BYTE *)signed_data->Data,
412 	    (CK_ULONG)signed_data->Length);
413 
414 	if (ckRv != CKR_OK) {
415 		kmfh->lasterr.kstype = KMF_KEYSTORE_PK11TOKEN;
416 		kmfh->lasterr.errcode = ckRv;
417 		rv = KMF_ERR_INTERNAL;
418 	}
419 	if (bTempKey)
420 		(void) C_DestroyObject(ckSession, ckKeyHandle);
421 
422 	(void) C_CloseSession(ckSession);
423 	return (rv);
424 
425 }
426 
427 KMF_RETURN
428 PKCS_EncryptData(KMF_HANDLE_T kmfh,
429 		KMF_ALGORITHM_INDEX AlgorithmId,
430 		KMF_X509_SPKI *keyp,
431 		KMF_DATA *plaintext,
432 		KMF_DATA *ciphertext)
433 {
434 	KMF_RETURN rv = KMF_OK;
435 	PKCS_ALGORITHM_MAP *pAlgMap = NULL;
436 	CK_RV ckRv;
437 	CK_MECHANISM ckMechanism;
438 	CK_OBJECT_HANDLE ckKeyHandle;
439 	KMF_BOOL bTempKey;
440 	CK_SESSION_HANDLE ckSession = NULL;
441 	CK_ULONG out_len = 0, in_len = 0, total_encrypted = 0;
442 	uint8_t *in_data, *out_data;
443 	int i, blocks, block_size;
444 	CK_ATTRIBUTE ckTemplate[2];
445 	CK_ULONG ckNumTemplates;
446 	CK_ULONG ckMaxTemplates = (sizeof (ckTemplate) /
447 	    sizeof (CK_ATTRIBUTE));
448 
449 	pAlgMap = pkcs_get_alg_map(KMF_ALGCLASS_SIGNATURE,
450 	    AlgorithmId, PKCS_GetDefaultSignatureMode(AlgorithmId));
451 
452 	if (!pAlgMap)
453 		return (KMF_ERR_BAD_ALGORITHM);
454 
455 	rv = create_pk11_session(&ckSession, pAlgMap->pkcs_mechanism,
456 	    CKF_ENCRYPT);
457 
458 	if (rv != KMF_OK)
459 		return (rv);
460 
461 	/* Get the public key used in encryption */
462 	rv = PKCS_AcquirePublicKeyHandle(ckSession, keyp,
463 	    pAlgMap->key_type, &ckKeyHandle, &bTempKey);
464 
465 	if (rv != KMF_OK) {
466 		(void) C_CloseSession(ckSession);
467 		return (rv);
468 	}
469 
470 	/* Get the modulus length */
471 	ckNumTemplates = 0;
472 	if (!PKCS_AddTemplate(ckTemplate, &ckNumTemplates, ckMaxTemplates,
473 	    CKA_MODULUS, (CK_BYTE *)NULL, sizeof (CK_ULONG))) {
474 		if (bTempKey)
475 			(void) C_DestroyObject(ckSession, ckKeyHandle);
476 		(void) C_CloseSession(ckSession);
477 		return (KMF_ERR_INTERNAL);
478 	}
479 
480 	ckRv = C_GetAttributeValue(ckSession, ckKeyHandle,
481 	    ckTemplate, ckNumTemplates);
482 
483 	if (ckRv != CKR_OK) {
484 		if (bTempKey)
485 			(void) C_DestroyObject(ckSession, ckKeyHandle);
486 		kmfh->lasterr.kstype = KMF_KEYSTORE_PK11TOKEN;
487 		kmfh->lasterr.errcode = ckRv;
488 		(void) C_CloseSession(ckSession);
489 		return (KMF_ERR_INTERNAL);
490 	}
491 	out_len = ckTemplate[0].ulValueLen;
492 
493 	if (out_len > ciphertext->Length) {
494 		if (bTempKey)
495 			(void) C_DestroyObject(ckSession, ckKeyHandle);
496 		(void) C_CloseSession(ckSession);
497 		return (KMF_ERR_BUFFER_SIZE);
498 	}
499 
500 	ckMechanism.mechanism = pAlgMap->pkcs_mechanism;
501 	ckMechanism.pParameter = NULL_PTR;
502 	ckMechanism.ulParameterLen = 0;
503 
504 	/* Compute the fixed input data length for single-part encryption */
505 	block_size = out_len - 11;
506 
507 	in_data = plaintext->Data;
508 	out_data = ciphertext->Data;
509 
510 	blocks = plaintext->Length/block_size;
511 
512 	for (i = 0; i < blocks; i++) {
513 		ckRv = C_EncryptInit(ckSession, &ckMechanism, ckKeyHandle);
514 		if (ckRv != CKR_OK) {
515 			if (bTempKey)
516 				(void) C_DestroyObject(ckSession, ckKeyHandle);
517 			kmfh->lasterr.kstype = KMF_KEYSTORE_PK11TOKEN;
518 			kmfh->lasterr.errcode = ckRv;
519 			(void) C_CloseSession(ckSession);
520 			return (KMF_ERR_INTERNAL);
521 		}
522 		ckRv = C_Encrypt(ckSession, (CK_BYTE_PTR)in_data, block_size,
523 		    (CK_BYTE_PTR)out_data, &out_len);
524 
525 		if (ckRv != CKR_OK) {
526 			if (bTempKey)
527 				(void) C_DestroyObject(ckSession, ckKeyHandle);
528 			kmfh->lasterr.kstype = KMF_KEYSTORE_PK11TOKEN;
529 			kmfh->lasterr.errcode = ckRv;
530 			(void) C_CloseSession(ckSession);
531 			return (KMF_ERR_INTERNAL);
532 		}
533 
534 		out_data += out_len;
535 		total_encrypted += out_len;
536 		in_data += block_size;
537 	}
538 
539 	if (plaintext->Length % block_size) {
540 		/* Encrypt the remaining data */
541 		ckRv = C_EncryptInit(ckSession, &ckMechanism, ckKeyHandle);
542 		if (ckRv != CKR_OK) {
543 			if (bTempKey)
544 				(void) C_DestroyObject(ckSession, ckKeyHandle);
545 			kmfh->lasterr.kstype = KMF_KEYSTORE_PK11TOKEN;
546 			kmfh->lasterr.errcode = ckRv;
547 			(void) C_CloseSession(ckSession);
548 			return (KMF_ERR_INTERNAL);
549 		}
550 
551 		in_len = plaintext->Length % block_size;
552 		ckRv = C_Encrypt(ckSession, (CK_BYTE_PTR)in_data, in_len,
553 		    (CK_BYTE_PTR)out_data, &out_len);
554 
555 		if (ckRv != CKR_OK) {
556 			if (bTempKey)
557 				(void) C_DestroyObject(ckSession, ckKeyHandle);
558 			kmfh->lasterr.kstype = KMF_KEYSTORE_PK11TOKEN;
559 			kmfh->lasterr.errcode = ckRv;
560 			(void) C_CloseSession(ckSession);
561 			return (KMF_ERR_INTERNAL);
562 		}
563 
564 		out_data += out_len;
565 		total_encrypted += out_len;
566 		in_data += in_len;
567 	}
568 
569 	ciphertext->Length = total_encrypted;
570 
571 	if (bTempKey)
572 		(void) C_DestroyObject(ckSession, ckKeyHandle);
573 
574 	(void) C_CloseSession(ckSession);
575 	return (rv);
576 
577 }
578 
579 static void
580 DigestData(KMF_DATA *IDInput, KMF_DATA *IDOutput)
581 {
582 	SHA1_CTX ctx;
583 
584 	SHA1Init(&ctx);
585 	SHA1Update(&ctx, IDInput->Data, IDInput->Length);
586 	SHA1Final(IDOutput->Data, &ctx);
587 
588 	IDOutput->Length = SHA1_DIGEST_LENGTH;
589 }
590 
591 KMF_RETURN
592 GetIDFromSPKI(KMF_X509_SPKI *spki, KMF_DATA *ID)
593 {
594 	KMF_RETURN rv = KMF_OK;
595 	KMF_DATA KeyParts[KMF_MAX_PUBLIC_KEY_PARTS];
596 	uint32_t uNumKeyParts = KMF_MAX_PUBLIC_KEY_PARTS;
597 	KMF_ALGORITHM_INDEX algId;
598 	int i;
599 
600 	if (ID == NULL || spki == NULL)
601 		return (KMF_ERR_BAD_PARAMETER);
602 
603 	ID->Data = (uchar_t *)malloc(SHA1_HASH_LENGTH);
604 	if (ID->Data == NULL)
605 		return (KMF_ERR_MEMORY);
606 
607 	ID->Length = SHA1_HASH_LENGTH;
608 
609 	algId = x509_algoid_to_algid(&spki->algorithm.algorithm);
610 	if (algId == KMF_ALGID_NONE)
611 		return (KMF_ERR_BAD_ALGORITHM);
612 
613 	rv = ExtractSPKIData(spki, algId, KeyParts, &uNumKeyParts);
614 	if (rv != KMF_OK)
615 		return (rv);
616 
617 	/* Check the KEY algorithm */
618 	if (algId == KMF_ALGID_RSA) {
619 		DigestData(&KeyParts[KMF_RSA_MODULUS], ID);
620 	} else if (algId == KMF_ALGID_DSA) {
621 		DigestData(&KeyParts[KMF_DSA_PUBLIC_VALUE], ID);
622 	} else {
623 		/* We only support RSA and DSA keys for now */
624 		rv = KMF_ERR_BAD_ALGORITHM;
625 	}
626 
627 	for (i = 0; i < uNumKeyParts; i++) {
628 		if (KeyParts[i].Data != NULL)
629 			free(KeyParts[i].Data);
630 	}
631 
632 	if (rv != KMF_OK && ID->Data != NULL) {
633 		free(ID->Data);
634 		ID->Data = NULL;
635 		ID->Length = 0;
636 	}
637 
638 	return (rv);
639 }
640