1 /*
2 * Copyright 2010 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 #include <kmfapiP.h>
10 #include <sha1.h>
11 #include <security/cryptoki.h>
12
13 #include <ber_der.h>
14
15 #define MAX_PUBLIC_KEY_TEMPLATES (20)
16 #define MAX_PRIVATE_KEY_TEMPLATES (24)
17 #define MAX_SECRET_KEY_TEMPLATES (24)
18
19 typedef struct
20 {
21 KMF_ALGORITHM_INDEX kmfAlgorithmId;
22 CK_KEY_TYPE ckKeyType;
23 CK_MECHANISM_TYPE signmech;
24 CK_MECHANISM_TYPE vfymech;
25 CK_MECHANISM_TYPE hashmech;
26 } ALG_INFO;
27
28 static const ALG_INFO alg_info_map[] = {
29 { KMF_ALGID_RSA, CKK_RSA, CKM_RSA_PKCS, CKM_RSA_PKCS, NULL},
30 { KMF_ALGID_DSA, CKK_DSA, CKM_DSA, CKM_DSA, CKM_SHA_1 },
31 { KMF_ALGID_ECDSA, CKK_EC, CKM_ECDSA, CKM_ECDSA, CKM_SHA_1 },
32 { KMF_ALGID_SHA1WithDSA, CKK_DSA, CKM_DSA, CKM_DSA, CKM_SHA_1 },
33 { KMF_ALGID_SHA256WithDSA, CKK_DSA, CKM_DSA, CKM_DSA, CKM_SHA256 },
34
35 /*
36 * For RSA, the verify can be done using a single mechanism,
37 * but signing must be done separately because not all hardware
38 * tokens support the combined hash+key operations.
39 */
40 { KMF_ALGID_MD5WithRSA, CKK_RSA, CKM_RSA_PKCS,
41 CKM_MD5_RSA_PKCS, CKM_MD5},
42 { KMF_ALGID_SHA1WithRSA, CKK_RSA, CKM_RSA_PKCS,
43 CKM_SHA1_RSA_PKCS, CKM_SHA_1},
44 { KMF_ALGID_SHA256WithRSA, CKK_RSA, CKM_RSA_PKCS,
45 CKM_SHA256_RSA_PKCS, CKM_SHA256},
46 { KMF_ALGID_SHA384WithRSA, CKK_RSA, CKM_RSA_PKCS,
47 CKM_SHA384_RSA_PKCS, CKM_SHA384},
48 { KMF_ALGID_SHA512WithRSA, CKK_RSA, CKM_RSA_PKCS,
49 CKM_SHA512_RSA_PKCS, CKM_SHA512},
50 { KMF_ALGID_SHA1WithECDSA, CKK_EC, CKM_ECDSA,
51 CKM_ECDSA, CKM_SHA_1},
52 { KMF_ALGID_SHA256WithECDSA, CKK_EC, CKM_ECDSA,
53 CKM_ECDSA, CKM_SHA256},
54 { KMF_ALGID_SHA384WithECDSA, CKK_EC, CKM_ECDSA,
55 CKM_ECDSA, CKM_SHA384},
56 { KMF_ALGID_SHA512WithECDSA, CKK_EC, CKM_ECDSA,
57 CKM_ECDSA, CKM_SHA512}
58 };
59
60 KMF_RETURN
get_pk11_data(KMF_ALGORITHM_INDEX AlgId,CK_KEY_TYPE * keytype,CK_MECHANISM_TYPE * signmech,CK_MECHANISM_TYPE * hashmech,boolean_t vfy)61 get_pk11_data(KMF_ALGORITHM_INDEX AlgId,
62 CK_KEY_TYPE *keytype, CK_MECHANISM_TYPE *signmech,
63 CK_MECHANISM_TYPE *hashmech, boolean_t vfy)
64 {
65 uint32_t uIndex;
66 uint32_t uMapSize =
67 sizeof (alg_info_map) / sizeof (ALG_INFO);
68
69 for (uIndex = 0; uIndex < uMapSize; uIndex++) {
70 if (alg_info_map[uIndex].kmfAlgorithmId == AlgId) {
71 if (keytype)
72 *keytype = alg_info_map[uIndex].ckKeyType;
73 if (hashmech)
74 *hashmech = alg_info_map[uIndex].hashmech;
75 if (signmech)
76 *signmech =
77 (vfy ? alg_info_map[uIndex].vfymech :
78 alg_info_map[uIndex].signmech);
79 return (KMF_OK);
80 }
81 }
82 /* no match */
83 return (KMF_ERR_BAD_ALGORITHM);
84 }
85
86 KMF_RETURN
kmf_create_pk11_session(CK_SESSION_HANDLE * sessionp,CK_MECHANISM_TYPE wanted_mech,CK_FLAGS wanted_flags)87 kmf_create_pk11_session(CK_SESSION_HANDLE *sessionp,
88 CK_MECHANISM_TYPE wanted_mech,
89 CK_FLAGS wanted_flags)
90 {
91 CK_RV rv;
92 KMF_RETURN ret;
93 KMF_RETURN kmf_rv = KMF_OK;
94 CK_SLOT_ID_PTR pSlotList;
95 CK_ULONG pulCount;
96 CK_MECHANISM_INFO info;
97 int i;
98
99 ret = init_pk11();
100
101 if (ret != KMF_OK)
102 return (ret);
103
104 rv = C_GetSlotList(0, NULL, &pulCount);
105 if (rv != CKR_OK) {
106 kmf_rv = KMF_ERR_UNINITIALIZED;
107 goto out;
108 }
109
110 pSlotList = (CK_SLOT_ID_PTR) malloc(pulCount * sizeof (CK_SLOT_ID));
111 if (pSlotList == NULL) {
112 kmf_rv = KMF_ERR_MEMORY;
113 goto out;
114 }
115
116 rv = C_GetSlotList(0, pSlotList, &pulCount);
117 if (rv != CKR_OK) {
118 kmf_rv = KMF_ERR_UNINITIALIZED;
119 goto out;
120 }
121
122 for (i = 0; i < pulCount; i++) {
123 rv = C_GetMechanismInfo(pSlotList[i], wanted_mech, &info);
124 if (rv == CKR_OK &&
125 (info.flags & wanted_flags) == wanted_flags)
126 break;
127 }
128 if (i < pulCount) {
129 rv = C_OpenSession(pSlotList[i], CKF_SERIAL_SESSION,
130 NULL, NULL, sessionp);
131
132 if (rv != CKR_OK) {
133 kmf_rv = KMF_ERR_UNINITIALIZED;
134 }
135 } else {
136 kmf_rv = KMF_ERR_UNINITIALIZED;
137 }
138
139 out:
140 if (pSlotList != NULL)
141 free(pSlotList);
142 return (kmf_rv);
143
144 }
145
146 /*
147 * Name: PKCS_AddTemplate
148 *
149 * Description:
150 * Adds a CK_ATTRIBUTE value to an existing array of CK_ATTRIBUTES. Will
151 * not expand the array beyond the maximum specified size.
152 *
153 * Returns:
154 * TRUE - Attribute value succesfully added.
155 * FALSE - Maximum array size would be exceded.
156 */
157 static int
PKCS_AddTemplate(CK_ATTRIBUTE * pTemplate,CK_ULONG * ckNumTemplates,CK_ULONG ckMaxTemplates,CK_ATTRIBUTE_TYPE ckAttribCode,CK_BYTE * pckBuffer,CK_ULONG ckBufferLen)158 PKCS_AddTemplate(CK_ATTRIBUTE *pTemplate,
159 CK_ULONG *ckNumTemplates,
160 CK_ULONG ckMaxTemplates,
161 CK_ATTRIBUTE_TYPE ckAttribCode,
162 CK_BYTE * pckBuffer,
163 CK_ULONG ckBufferLen)
164 {
165 if (*ckNumTemplates >= ckMaxTemplates) {
166 return (FALSE);
167 }
168
169 pTemplate[*ckNumTemplates].type = ckAttribCode;
170 pTemplate[*ckNumTemplates].pValue = pckBuffer;
171 pTemplate[*ckNumTemplates].ulValueLen = ckBufferLen;
172 (*ckNumTemplates)++;
173
174 return (TRUE);
175 }
176
177 /*
178 * Convert an SPKI data record to PKCS#11
179 * public key object.
180 */
181 static KMF_RETURN
PKCS_CreatePublicKey(const KMF_X509_SPKI * pKey,CK_SESSION_HANDLE ckSession,CK_OBJECT_HANDLE * pckPublicKey)182 PKCS_CreatePublicKey(
183 const KMF_X509_SPKI *pKey,
184 CK_SESSION_HANDLE ckSession,
185 CK_OBJECT_HANDLE *pckPublicKey)
186 {
187 KMF_RETURN mrReturn = KMF_OK;
188 CK_RV ckRv;
189
190 CK_ATTRIBUTE ckTemplate[MAX_PUBLIC_KEY_TEMPLATES];
191 CK_ULONG ckNumTemplates = 0;
192
193 /* Common object attributes */
194 CK_OBJECT_CLASS ckObjClass = CKO_PUBLIC_KEY;
195 CK_BBOOL ckToken = 0;
196 CK_BBOOL ckPrivate = 0;
197
198 /* Common key attributes */
199 CK_KEY_TYPE ckKeyType;
200 CK_BBOOL ckDerive = CK_FALSE;
201
202 /* Common public key attributes */
203 CK_BBOOL ckEncrypt = 1;
204 CK_BBOOL ckVerify = 1;
205
206 CK_BBOOL ckVerifyRecover = CK_FALSE;
207 CK_BBOOL ckWrap = CK_FALSE;
208
209 /* Key part array */
210 KMF_DATA KeyParts[KMF_MAX_PUBLIC_KEY_PARTS];
211 uint32_t i, uNumKeyParts = KMF_MAX_PUBLIC_KEY_PARTS;
212 KMF_ALGORITHM_INDEX AlgorithmId;
213
214 /* Parse the keyblob */
215 (void) memset(KeyParts, 0, sizeof (KeyParts));
216
217 AlgorithmId = x509_algoid_to_algid(
218 (KMF_OID *)&pKey->algorithm.algorithm);
219 if (AlgorithmId == KMF_ALGID_NONE)
220 return (KMF_ERR_BAD_ALGORITHM);
221
222 mrReturn = ExtractSPKIData(pKey, AlgorithmId, KeyParts, &uNumKeyParts);
223
224 if (mrReturn != KMF_OK)
225 return (mrReturn);
226
227 /* Fill in the common object attributes */
228 if (!PKCS_AddTemplate(ckTemplate, &ckNumTemplates,
229 MAX_PUBLIC_KEY_TEMPLATES, CKA_CLASS, (CK_BYTE *)&ckObjClass,
230 sizeof (ckObjClass)) ||
231 !PKCS_AddTemplate(ckTemplate, &ckNumTemplates,
232 MAX_PUBLIC_KEY_TEMPLATES, CKA_TOKEN, (CK_BYTE *)&ckToken,
233 sizeof (ckToken)) ||
234 !PKCS_AddTemplate(ckTemplate, &ckNumTemplates,
235 MAX_PUBLIC_KEY_TEMPLATES, CKA_PRIVATE, (CK_BYTE *)&ckPrivate,
236 sizeof (ckPrivate))) {
237 mrReturn = KMF_ERR_INTERNAL;
238 goto cleanup;
239 }
240
241 /* Fill in the common key attributes */
242 if (get_pk11_data(AlgorithmId, &ckKeyType, NULL, NULL, 0)) {
243 goto cleanup;
244 }
245 if (!PKCS_AddTemplate(ckTemplate, &ckNumTemplates,
246 MAX_PUBLIC_KEY_TEMPLATES, CKA_KEY_TYPE, (CK_BYTE *)&ckKeyType,
247 sizeof (ckKeyType)) ||
248 !PKCS_AddTemplate(ckTemplate, &ckNumTemplates,
249 MAX_PUBLIC_KEY_TEMPLATES, CKA_DERIVE, (CK_BYTE *)&ckDerive,
250 sizeof (ckDerive))) {
251 mrReturn = KMF_ERR_INTERNAL;
252 goto cleanup;
253 }
254
255 /* Add common public key attributes */
256 if (!PKCS_AddTemplate(ckTemplate, &ckNumTemplates,
257 MAX_PUBLIC_KEY_TEMPLATES, CKA_ENCRYPT, (CK_BYTE *)&ckEncrypt,
258 sizeof (ckEncrypt)) ||
259 !PKCS_AddTemplate(ckTemplate, &ckNumTemplates,
260 MAX_PUBLIC_KEY_TEMPLATES, CKA_VERIFY, (CK_BYTE *)&ckVerify,
261 sizeof (ckVerify)) ||
262 !PKCS_AddTemplate(ckTemplate, &ckNumTemplates,
263 MAX_PUBLIC_KEY_TEMPLATES, CKA_VERIFY_RECOVER,
264 (CK_BYTE *)&ckVerifyRecover, sizeof (ckVerifyRecover)) ||
265 !PKCS_AddTemplate(ckTemplate, &ckNumTemplates,
266 MAX_PUBLIC_KEY_TEMPLATES, CKA_WRAP, (CK_BYTE *)&ckWrap,
267 sizeof (ckWrap))) {
268 mrReturn = KMF_ERR_INTERNAL;
269 goto cleanup;
270 }
271
272 /* Add algorithm specific attributes */
273 switch (ckKeyType) {
274 case CKK_RSA:
275 if (!PKCS_AddTemplate(ckTemplate, &ckNumTemplates,
276 MAX_PUBLIC_KEY_TEMPLATES, CKA_MODULUS,
277 (CK_BYTE *)KeyParts[KMF_RSA_MODULUS].Data,
278 (CK_ULONG)KeyParts[KMF_RSA_MODULUS].Length) ||
279
280 !PKCS_AddTemplate(ckTemplate, &ckNumTemplates,
281 MAX_PUBLIC_KEY_TEMPLATES, CKA_PUBLIC_EXPONENT,
282 (CK_BYTE *)KeyParts[KMF_RSA_PUBLIC_EXPONENT].Data,
283 (CK_ULONG)KeyParts[KMF_RSA_PUBLIC_EXPONENT].Length)) {
284 mrReturn = KMF_ERR_INTERNAL;
285 goto cleanup;
286 }
287 break;
288 case CKK_DSA:
289 if (!PKCS_AddTemplate(ckTemplate, &ckNumTemplates,
290 MAX_PUBLIC_KEY_TEMPLATES, CKA_PRIME,
291 (CK_BYTE *)KeyParts[KMF_DSA_PRIME].Data,
292 (CK_ULONG)KeyParts[KMF_DSA_PRIME].Length) ||
293 !PKCS_AddTemplate(ckTemplate, &ckNumTemplates,
294 MAX_PUBLIC_KEY_TEMPLATES, CKA_SUBPRIME,
295 (CK_BYTE *)KeyParts[KMF_DSA_SUB_PRIME].Data,
296 (CK_ULONG)KeyParts[KMF_DSA_SUB_PRIME].Length) ||
297 !PKCS_AddTemplate(ckTemplate, &ckNumTemplates,
298 MAX_PUBLIC_KEY_TEMPLATES, CKA_BASE,
299 (CK_BYTE *)KeyParts[KMF_DSA_BASE].Data,
300 (CK_ULONG)KeyParts[KMF_DSA_BASE].Length) ||
301 !PKCS_AddTemplate(ckTemplate, &ckNumTemplates,
302 MAX_PUBLIC_KEY_TEMPLATES, CKA_VALUE,
303 (CK_BYTE *)KeyParts[KMF_DSA_PUBLIC_VALUE].Data,
304 (CK_ULONG)KeyParts[KMF_DSA_PUBLIC_VALUE].Length)) {
305 mrReturn = KMF_ERR_INTERNAL;
306 goto cleanup;
307 }
308 break;
309 case CKK_EC:
310 if (!PKCS_AddTemplate(ckTemplate, &ckNumTemplates,
311 MAX_PUBLIC_KEY_TEMPLATES, CKA_EC_POINT,
312 (CK_BYTE *)KeyParts[KMF_ECDSA_POINT].Data,
313 (CK_ULONG)KeyParts[KMF_ECDSA_POINT].Length) ||
314
315 !PKCS_AddTemplate(ckTemplate, &ckNumTemplates,
316 MAX_PUBLIC_KEY_TEMPLATES, CKA_EC_PARAMS,
317 (CK_BYTE *)KeyParts[KMF_ECDSA_PARAMS].Data,
318 (CK_ULONG)KeyParts[KMF_ECDSA_PARAMS].Length)) {
319 mrReturn = KMF_ERR_INTERNAL;
320 goto cleanup;
321 }
322 break;
323 default:
324 mrReturn = KMF_ERR_BAD_PARAMETER;
325 }
326
327 if (mrReturn == KMF_OK) {
328 /* Instantiate the object */
329 ckRv = C_CreateObject(ckSession, ckTemplate,
330 ckNumTemplates, pckPublicKey);
331 if (ckRv != CKR_OK)
332 mrReturn = KMF_ERR_INTERNAL;
333 }
334
335 cleanup:
336 for (i = 0; i < uNumKeyParts; i++) {
337 kmf_free_data(&KeyParts[i]);
338 }
339
340 return (mrReturn);
341 }
342
343 /*
344 * PKCS_AcquirePublicKeyHandle
345 *
346 * Given an assymetric key keyblob, attempts to find the appropriate
347 * public key.
348 *
349 * Methods of finding the public key:
350 * - Public Key with data present:
351 * Parses the key and creates a temporary session object.
352 * - Public Key with handle:
353 * The handle is type converted and returned. Validity of the handle is
354 * not checked.
355 * - Public Key with label:
356 * Attempts to find a public key with the corresponding label.
357 */
358 static KMF_RETURN
PKCS_AcquirePublicKeyHandle(CK_SESSION_HANDLE ckSession,const KMF_X509_SPKI * pKey,CK_KEY_TYPE ckRequestedKeyType,CK_OBJECT_HANDLE * pckKeyHandle)359 PKCS_AcquirePublicKeyHandle(CK_SESSION_HANDLE ckSession,
360 const KMF_X509_SPKI *pKey,
361 CK_KEY_TYPE ckRequestedKeyType,
362 CK_OBJECT_HANDLE *pckKeyHandle)
363 {
364 KMF_RETURN mrReturn = KMF_OK;
365
366 /* Key searching variables */
367 CK_OBJECT_HANDLE ckKeyHandle = 0;
368 CK_OBJECT_CLASS ckObjClass;
369 CK_KEY_TYPE ckKeyType;
370 CK_ATTRIBUTE ckTemplate[3];
371 CK_ULONG ckNumTemplates;
372 static const CK_ULONG ckMaxTemplates = (sizeof (ckTemplate) /
373 sizeof (CK_ATTRIBUTE));
374 CK_RV ckRv;
375
376 /* Extract the data from the SPKI into individual fields */
377 mrReturn = PKCS_CreatePublicKey(pKey, ckSession, &ckKeyHandle);
378 if (mrReturn != KMF_OK)
379 return (mrReturn);
380
381 /* Fetch the key class and algorithm from the object */
382 ckNumTemplates = 0;
383 if (!PKCS_AddTemplate(ckTemplate, &ckNumTemplates,
384 ckMaxTemplates, CKA_CLASS, (CK_BYTE *)&ckObjClass,
385 sizeof (ckObjClass)) ||
386 !PKCS_AddTemplate(ckTemplate, &ckNumTemplates,
387 ckMaxTemplates, CKA_KEY_TYPE, (CK_BYTE *)&ckKeyType,
388 sizeof (ckKeyType))) {
389 (void) C_DestroyObject(ckSession, ckKeyHandle);
390 return (KMF_ERR_INTERNAL);
391 }
392 ckRv = C_GetAttributeValue(ckSession, ckKeyHandle,
393 ckTemplate, ckNumTemplates);
394 if (ckRv != CKR_OK) {
395 (void) C_DestroyObject(ckSession, ckKeyHandle);
396 return (ckRv);
397 }
398
399 /* Make sure the results match the expected values */
400 if ((ckKeyType != ckRequestedKeyType) ||
401 (ckObjClass != CKO_PUBLIC_KEY)) {
402 (void) C_DestroyObject(ckSession, ckKeyHandle);
403 return (KMF_ERR_BAD_KEY_FORMAT);
404 }
405
406 /* Set the return values */
407 *pckKeyHandle = ckKeyHandle;
408
409 return (KMF_OK);
410 }
411
412 /*
413 * Utility routine for verifying generic data using
414 * the cryptographic framework (PKCS#11).
415 * There are situations where we want to force this
416 * operation to happen in a specific keystore.
417 * For example:
418 * libelfsign.so.1 verifies signatures on crypto libraries.
419 * We must use pkcs11 functions to verify the pkcs11
420 * plugins in order to keep the validation within the
421 * Cryptographic Framework's FIPS-140 boundary. To avoid
422 * a circular dependency, pksc11_softtoken.so.1 is
423 * interposed by libkcfd.so.1 via kcfd, which prevents
424 * libpkcs11.so.1's interfaces from being used when libkmf.so.1
425 * is called from kcfd.
426 *
427 * This also saves code and time because verify operations
428 * only use public keys and do not need acccess to any
429 * keystore specific functions.
430 */
431 KMF_RETURN
PKCS_VerifyData(KMF_HANDLE_T handle,KMF_ALGORITHM_INDEX AlgorithmId,KMF_X509_SPKI * keyp,KMF_DATA * data,KMF_DATA * signature)432 PKCS_VerifyData(KMF_HANDLE_T handle,
433 KMF_ALGORITHM_INDEX AlgorithmId,
434 KMF_X509_SPKI *keyp,
435 KMF_DATA *data,
436 KMF_DATA *signature)
437 {
438 KMF_RETURN rv = KMF_OK;
439 CK_RV ckRv;
440 KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
441 CK_MECHANISM ckMechanism;
442 CK_MECHANISM_TYPE mechtype, hashmech;
443 CK_OBJECT_HANDLE ckKeyHandle = 0;
444 CK_KEY_TYPE pk11keytype;
445 CK_SESSION_HANDLE ckSession = 0;
446 CK_ATTRIBUTE subprime = { CKA_SUBPRIME, NULL, 0 };
447 CK_BYTE *dataptr;
448 CK_ULONG datalen;
449 KMF_DATA hashData = { 0, NULL };
450 uchar_t digest[1024];
451
452 if (AlgorithmId == KMF_ALGID_NONE)
453 return (KMF_ERR_BAD_ALGORITHM);
454
455 if (get_pk11_data(AlgorithmId, &pk11keytype, &mechtype, &hashmech, 1))
456 return (KMF_ERR_BAD_ALGORITHM);
457
458 /*
459 * Verify in metaslot/softtoken since only the public key is needed
460 * and not all hardware tokens support the combined [hash]-RSA/DSA/EC
461 * mechanisms.
462 */
463 rv = kmf_create_pk11_session(&ckSession, mechtype, 0);
464 if (rv != KMF_OK)
465 return (rv);
466
467 /* Fetch the verifying key */
468 rv = PKCS_AcquirePublicKeyHandle(ckSession, keyp,
469 pk11keytype, &ckKeyHandle);
470
471 if (rv != KMF_OK) {
472 (void) C_CloseSession(ckSession);
473 return (rv);
474 }
475 dataptr = data->Data;
476 datalen = data->Length;
477 /*
478 * For some mechanisms, we must compute the hash separately
479 * and then do the verify.
480 */
481 if (hashmech != 0 &&
482 (mechtype == CKM_ECDSA ||
483 mechtype == CKM_DSA ||
484 mechtype == CKM_RSA_PKCS)) {
485 hashData.Data = digest;
486 hashData.Length = sizeof (digest);
487
488 rv = PKCS_DigestData(handle, ckSession,
489 hashmech, data, &hashData,
490 (mechtype == CKM_RSA_PKCS));
491 if (rv)
492 goto cleanup;
493
494 dataptr = hashData.Data;
495 datalen = hashData.Length;
496 }
497 if (mechtype == CKM_DSA &&
498 hashmech == CKM_SHA256) {
499 /*
500 * FIPS 186-3 says that when using DSA
501 * the hash must be truncated to the size of the
502 * subprime.
503 */
504 ckRv = C_GetAttributeValue(ckSession,
505 ckKeyHandle, &subprime, 1);
506 if (ckRv != CKR_OK) {
507 kmfh->lasterr.kstype = KMF_KEYSTORE_PK11TOKEN;
508 kmfh->lasterr.errcode = ckRv;
509 rv = KMF_ERR_INTERNAL;
510 goto cleanup;
511 }
512 datalen = subprime.ulValueLen;
513 }
514
515 ckMechanism.mechanism = mechtype;
516 ckMechanism.pParameter = NULL;
517 ckMechanism.ulParameterLen = 0;
518
519 ckRv = C_VerifyInit(ckSession, &ckMechanism, ckKeyHandle);
520 if (ckRv != CKR_OK) {
521 kmfh->lasterr.kstype = KMF_KEYSTORE_PK11TOKEN;
522 kmfh->lasterr.errcode = ckRv;
523 rv = KMF_ERR_INTERNAL;
524 goto cleanup;
525 }
526 ckRv = C_Verify(ckSession,
527 dataptr, datalen,
528 (CK_BYTE *)signature->Data,
529 (CK_ULONG)signature->Length);
530
531 if (ckRv != CKR_OK) {
532 kmfh->lasterr.kstype = KMF_KEYSTORE_PK11TOKEN;
533 kmfh->lasterr.errcode = ckRv;
534 rv = KMF_ERR_INTERNAL;
535 }
536
537 cleanup:
538 if (ckKeyHandle != 0)
539 (void) C_DestroyObject(ckSession, ckKeyHandle);
540 (void) C_CloseSession(ckSession);
541 return (rv);
542 }
543
544 KMF_RETURN
PKCS_EncryptData(KMF_HANDLE_T kmfh,KMF_ALGORITHM_INDEX AlgorithmId,KMF_X509_SPKI * keyp,KMF_DATA * plaintext,KMF_DATA * ciphertext)545 PKCS_EncryptData(KMF_HANDLE_T kmfh,
546 KMF_ALGORITHM_INDEX AlgorithmId,
547 KMF_X509_SPKI *keyp,
548 KMF_DATA *plaintext,
549 KMF_DATA *ciphertext)
550 {
551 KMF_RETURN rv = KMF_OK;
552 CK_RV ckRv;
553 CK_MECHANISM ckMechanism;
554 CK_MECHANISM_TYPE mechtype;
555 CK_KEY_TYPE keytype;
556 CK_OBJECT_HANDLE ckKeyHandle = 0;
557 CK_SESSION_HANDLE ckSession = NULL;
558 CK_ULONG out_len = 0, in_len = 0, total_encrypted = 0;
559 uint8_t *in_data, *out_data;
560 int i, blocks, block_size;
561 CK_ATTRIBUTE ckTemplate[2];
562 CK_ULONG ckNumTemplates;
563 CK_ULONG ckMaxTemplates = (sizeof (ckTemplate) /
564 sizeof (CK_ATTRIBUTE));
565
566 if (get_pk11_data(AlgorithmId, &keytype, &mechtype, NULL, 0))
567 return (KMF_ERR_BAD_ALGORITHM);
568
569 rv = kmf_create_pk11_session(&ckSession, mechtype, CKF_ENCRYPT);
570 if (rv != KMF_OK)
571 return (rv);
572
573 /* Get the public key used in encryption */
574 rv = PKCS_AcquirePublicKeyHandle(ckSession, keyp,
575 keytype, &ckKeyHandle);
576
577 if (rv != KMF_OK) {
578 (void) C_CloseSession(ckSession);
579 return (rv);
580 }
581
582 /* Get the modulus length */
583 ckNumTemplates = 0;
584 if (!PKCS_AddTemplate(ckTemplate, &ckNumTemplates, ckMaxTemplates,
585 CKA_MODULUS, (CK_BYTE *)NULL, sizeof (CK_ULONG))) {
586 if (ckKeyHandle != 0)
587 (void) C_DestroyObject(ckSession, ckKeyHandle);
588 (void) C_CloseSession(ckSession);
589 return (KMF_ERR_INTERNAL);
590 }
591
592 ckRv = C_GetAttributeValue(ckSession, ckKeyHandle,
593 ckTemplate, ckNumTemplates);
594
595 if (ckRv != CKR_OK) {
596 if (ckKeyHandle != 0)
597 (void) C_DestroyObject(ckSession, ckKeyHandle);
598 kmfh->lasterr.kstype = KMF_KEYSTORE_PK11TOKEN;
599 kmfh->lasterr.errcode = ckRv;
600 (void) C_CloseSession(ckSession);
601 return (KMF_ERR_INTERNAL);
602 }
603 out_len = ckTemplate[0].ulValueLen;
604
605 if (out_len > ciphertext->Length) {
606 if (ckKeyHandle != 0)
607 (void) C_DestroyObject(ckSession, ckKeyHandle);
608 (void) C_CloseSession(ckSession);
609 return (KMF_ERR_BUFFER_SIZE);
610 }
611
612 ckMechanism.mechanism = mechtype;
613 ckMechanism.pParameter = NULL_PTR;
614 ckMechanism.ulParameterLen = 0;
615
616 /* Compute the fixed input data length for single-part encryption */
617 block_size = out_len - 11;
618
619 in_data = plaintext->Data;
620 out_data = ciphertext->Data;
621
622 blocks = plaintext->Length/block_size;
623
624 for (i = 0; i < blocks; i++) {
625 ckRv = C_EncryptInit(ckSession, &ckMechanism, ckKeyHandle);
626 if (ckRv != CKR_OK) {
627 if (ckKeyHandle != 0)
628 (void) C_DestroyObject(ckSession, ckKeyHandle);
629 kmfh->lasterr.kstype = KMF_KEYSTORE_PK11TOKEN;
630 kmfh->lasterr.errcode = ckRv;
631 (void) C_CloseSession(ckSession);
632 return (KMF_ERR_INTERNAL);
633 }
634 ckRv = C_Encrypt(ckSession, (CK_BYTE_PTR)in_data, block_size,
635 (CK_BYTE_PTR)out_data, &out_len);
636
637 if (ckRv != CKR_OK) {
638 if (ckKeyHandle != 0)
639 (void) C_DestroyObject(ckSession, ckKeyHandle);
640 kmfh->lasterr.kstype = KMF_KEYSTORE_PK11TOKEN;
641 kmfh->lasterr.errcode = ckRv;
642 (void) C_CloseSession(ckSession);
643 return (KMF_ERR_INTERNAL);
644 }
645
646 out_data += out_len;
647 total_encrypted += out_len;
648 in_data += block_size;
649 }
650
651 if (plaintext->Length % block_size) {
652 /* Encrypt the remaining data */
653 ckRv = C_EncryptInit(ckSession, &ckMechanism, ckKeyHandle);
654 if (ckRv != CKR_OK) {
655 if (ckKeyHandle != 0)
656 (void) C_DestroyObject(ckSession, ckKeyHandle);
657 kmfh->lasterr.kstype = KMF_KEYSTORE_PK11TOKEN;
658 kmfh->lasterr.errcode = ckRv;
659 (void) C_CloseSession(ckSession);
660 return (KMF_ERR_INTERNAL);
661 }
662
663 in_len = plaintext->Length % block_size;
664 ckRv = C_Encrypt(ckSession, (CK_BYTE_PTR)in_data, in_len,
665 (CK_BYTE_PTR)out_data, &out_len);
666
667 if (ckRv != CKR_OK) {
668 if (ckKeyHandle != 0)
669 (void) C_DestroyObject(ckSession, ckKeyHandle);
670 kmfh->lasterr.kstype = KMF_KEYSTORE_PK11TOKEN;
671 kmfh->lasterr.errcode = ckRv;
672 (void) C_CloseSession(ckSession);
673 return (KMF_ERR_INTERNAL);
674 }
675
676 out_data += out_len;
677 total_encrypted += out_len;
678 in_data += in_len;
679 }
680
681 ciphertext->Length = total_encrypted;
682
683 if (ckKeyHandle != 0)
684 (void) C_DestroyObject(ckSession, ckKeyHandle);
685
686 (void) C_CloseSession(ckSession);
687 return (rv);
688
689 }
690
691 static void
create_id_hash(KMF_DATA * IDInput,KMF_DATA * IDOutput)692 create_id_hash(KMF_DATA *IDInput, KMF_DATA *IDOutput)
693 {
694 SHA1_CTX ctx;
695
696 SHA1Init(&ctx);
697 SHA1Update(&ctx, IDInput->Data, IDInput->Length);
698 SHA1Final(IDOutput->Data, &ctx);
699
700 IDOutput->Length = SHA1_DIGEST_LENGTH;
701 }
702
703 KMF_RETURN
GetIDFromSPKI(KMF_X509_SPKI * spki,KMF_DATA * ID)704 GetIDFromSPKI(KMF_X509_SPKI *spki, KMF_DATA *ID)
705 {
706 KMF_RETURN rv = KMF_OK;
707 KMF_DATA KeyParts[KMF_MAX_PUBLIC_KEY_PARTS];
708 uint32_t uNumKeyParts = KMF_MAX_PUBLIC_KEY_PARTS;
709 KMF_ALGORITHM_INDEX algId;
710 int i;
711
712 if (ID == NULL || spki == NULL)
713 return (KMF_ERR_BAD_PARAMETER);
714
715 ID->Data = (uchar_t *)malloc(SHA1_HASH_LENGTH);
716 if (ID->Data == NULL)
717 return (KMF_ERR_MEMORY);
718
719 ID->Length = SHA1_HASH_LENGTH;
720
721 algId = x509_algoid_to_algid(&spki->algorithm.algorithm);
722 if (algId == KMF_ALGID_NONE)
723 return (KMF_ERR_BAD_ALGORITHM);
724
725 rv = ExtractSPKIData(spki, algId, KeyParts, &uNumKeyParts);
726 if (rv != KMF_OK)
727 return (rv);
728
729 /* Check the KEY algorithm */
730 if (algId == KMF_ALGID_RSA) {
731 create_id_hash(&KeyParts[KMF_RSA_MODULUS], ID);
732 } else if (algId == KMF_ALGID_DSA) {
733 create_id_hash(&KeyParts[KMF_DSA_PUBLIC_VALUE], ID);
734 } else if (algId == KMF_ALGID_SHA1WithECDSA ||
735 algId == KMF_ALGID_ECDSA) {
736 create_id_hash(&KeyParts[KMF_ECDSA_POINT], ID);
737 } else {
738 /* We only support RSA and DSA keys for now */
739 rv = KMF_ERR_BAD_ALGORITHM;
740 }
741
742 for (i = 0; i < uNumKeyParts; i++) {
743 if (KeyParts[i].Data != NULL)
744 free(KeyParts[i].Data);
745 }
746
747 if (rv != KMF_OK && ID->Data != NULL) {
748 free(ID->Data);
749 ID->Data = NULL;
750 ID->Length = 0;
751 }
752
753 return (rv);
754 }
755
756 /*
757 * For PKCS1 encoding (necessary for RSA signatures), we
758 * must prepend the following prefixes before computing
759 * the digest.
760 */
761 static uchar_t SHA1_DER_PREFIX[] = {
762 0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e,
763 0x03, 0x02, 0x1a, 0x05, 0x00, 0x04, 0x14
764 };
765 static uchar_t MD5_DER_PREFIX[] = {
766 0x30, 0x20, 0x30, 0x0c, 0x06, 0x08, 0x2a, 0x86,
767 0x48, 0x86, 0xf7, 0x0d, 0x02, 0x05, 0x05, 0x00,
768 0x04, 0x10
769 };
770 static uchar_t SHA256_DER_PREFIX[] = {0x30, 0x31, 0x30, 0x0d,
771 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05,
772 0x00, 0x04, 0x20};
773
774 static uchar_t SHA384_DER_PREFIX[] = {0x30, 0x41, 0x30, 0x0d,
775 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x02, 0x05,
776 0x00, 0x04, 0x30};
777
778 static uchar_t SHA512_DER_PREFIX[] = {0x30, 0x51, 0x30, 0x0d,
779 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03, 0x05,
780 0x00, 0x04, 0x40};
781
782 #define MAX_SHA2_DIGEST_LENGTH 64
783 /*
784 * Compute hashes using metaslot (or softtoken).
785 * Not all hardware tokens support the combined HASH + RSA/EC
786 * Signing operations so it is safer to separate the hashing
787 * from the signing. This function generates a hash using a
788 * separate session. The resulting digest can be signed later.
789 */
790 KMF_RETURN
PKCS_DigestData(KMF_HANDLE_T handle,CK_SESSION_HANDLE hSession,CK_MECHANISM_TYPE mechtype,KMF_DATA * tobesigned,KMF_DATA * output,boolean_t pkcs1_encoding)791 PKCS_DigestData(KMF_HANDLE_T handle,
792 CK_SESSION_HANDLE hSession,
793 CK_MECHANISM_TYPE mechtype,
794 KMF_DATA *tobesigned, KMF_DATA *output,
795 boolean_t pkcs1_encoding)
796 {
797 KMF_RETURN rv = KMF_OK;
798 CK_RV ckrv;
799 CK_MECHANISM mechanism;
800 KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
801 CK_BYTE outbuf[MAX_SHA2_DIGEST_LENGTH +
802 sizeof (SHA512_DER_PREFIX)];
803 CK_ULONG outlen = sizeof (outbuf);
804
805 mechanism.mechanism = mechtype;
806 mechanism.pParameter = NULL;
807 mechanism.ulParameterLen = 0;
808
809 ckrv = C_DigestInit(hSession, &mechanism);
810 if (ckrv != CKR_OK) {
811 kmfh->lasterr.kstype = KMF_KEYSTORE_PK11TOKEN;
812 kmfh->lasterr.errcode = ckrv;
813 rv = KMF_ERR_INTERNAL;
814 goto end;
815 }
816
817 ckrv = C_Digest(hSession, tobesigned->Data,
818 tobesigned->Length, outbuf, &outlen);
819 if (ckrv != CKR_OK) {
820 kmfh->lasterr.kstype = KMF_KEYSTORE_PK11TOKEN;
821 kmfh->lasterr.errcode = ckrv;
822 rv = KMF_ERR_INTERNAL;
823 }
824
825 if (pkcs1_encoding) {
826 uchar_t *pfx;
827 int pfxlen;
828 switch (mechtype) {
829 case CKM_MD5:
830 pfx = MD5_DER_PREFIX;
831 pfxlen = sizeof (MD5_DER_PREFIX);
832 break;
833 case CKM_SHA_1:
834 pfx = SHA1_DER_PREFIX;
835 pfxlen = sizeof (SHA1_DER_PREFIX);
836 break;
837 case CKM_SHA256:
838 pfx = SHA256_DER_PREFIX;
839 pfxlen = sizeof (SHA256_DER_PREFIX);
840 break;
841 case CKM_SHA384:
842 pfx = SHA384_DER_PREFIX;
843 pfxlen = sizeof (SHA384_DER_PREFIX);
844 break;
845 case CKM_SHA512:
846 pfx = SHA512_DER_PREFIX;
847 pfxlen = sizeof (SHA512_DER_PREFIX);
848 break;
849 default:
850 rv = KMF_ERR_BAD_ALGORITHM;
851 goto end;
852 }
853 (void) memcpy(output->Data, pfx, pfxlen);
854 (void) memcpy(output->Data + pfxlen, outbuf, outlen);
855 output->Length = outlen + pfxlen;
856 } else {
857 (void) memcpy(output->Data, outbuf, outlen);
858 output->Length = outlen;
859 }
860
861 end:
862 return (rv);
863 }
864