199ebb4caSwyllys /*
2e65e5c2dSWyllys Ingersoll * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
39a767088Shaimay * Use is subject to license terms.
499ebb4caSwyllys */
599ebb4caSwyllys /*
699ebb4caSwyllys * Copyright (c) 1995-2000 Intel Corporation. All rights reserved.
799ebb4caSwyllys */
899ebb4caSwyllys
999ebb4caSwyllys #include <kmfapiP.h>
109b37d296Swyllys #include <sha1.h>
1199ebb4caSwyllys #include <security/cryptoki.h>
1299ebb4caSwyllys
1399ebb4caSwyllys #include <ber_der.h>
1499ebb4caSwyllys
1599ebb4caSwyllys #define MAX_PUBLIC_KEY_TEMPLATES (20)
1699ebb4caSwyllys #define MAX_PRIVATE_KEY_TEMPLATES (24)
1799ebb4caSwyllys #define MAX_SECRET_KEY_TEMPLATES (24)
1899ebb4caSwyllys
19e65e5c2dSWyllys Ingersoll typedef struct
20e65e5c2dSWyllys Ingersoll {
21e65e5c2dSWyllys Ingersoll KMF_ALGORITHM_INDEX kmfAlgorithmId;
22e65e5c2dSWyllys Ingersoll CK_KEY_TYPE ckKeyType;
23e65e5c2dSWyllys Ingersoll CK_MECHANISM_TYPE signmech;
24e65e5c2dSWyllys Ingersoll CK_MECHANISM_TYPE vfymech;
25e65e5c2dSWyllys Ingersoll CK_MECHANISM_TYPE hashmech;
26e65e5c2dSWyllys Ingersoll } ALG_INFO;
27e65e5c2dSWyllys Ingersoll
28e65e5c2dSWyllys Ingersoll static const ALG_INFO alg_info_map[] = {
29*f810c7e5SToomas Soome { KMF_ALGID_RSA, CKK_RSA, CKM_RSA_PKCS, CKM_RSA_PKCS, 0},
30e65e5c2dSWyllys Ingersoll { KMF_ALGID_DSA, CKK_DSA, CKM_DSA, CKM_DSA, CKM_SHA_1 },
31e65e5c2dSWyllys Ingersoll { KMF_ALGID_ECDSA, CKK_EC, CKM_ECDSA, CKM_ECDSA, CKM_SHA_1 },
32e65e5c2dSWyllys Ingersoll { KMF_ALGID_SHA1WithDSA, CKK_DSA, CKM_DSA, CKM_DSA, CKM_SHA_1 },
33e65e5c2dSWyllys Ingersoll { KMF_ALGID_SHA256WithDSA, CKK_DSA, CKM_DSA, CKM_DSA, CKM_SHA256 },
34e65e5c2dSWyllys Ingersoll
35e65e5c2dSWyllys Ingersoll /*
36e65e5c2dSWyllys Ingersoll * For RSA, the verify can be done using a single mechanism,
37e65e5c2dSWyllys Ingersoll * but signing must be done separately because not all hardware
38e65e5c2dSWyllys Ingersoll * tokens support the combined hash+key operations.
39e65e5c2dSWyllys Ingersoll */
40e65e5c2dSWyllys Ingersoll { KMF_ALGID_MD5WithRSA, CKK_RSA, CKM_RSA_PKCS,
41e65e5c2dSWyllys Ingersoll CKM_MD5_RSA_PKCS, CKM_MD5},
42e65e5c2dSWyllys Ingersoll { KMF_ALGID_SHA1WithRSA, CKK_RSA, CKM_RSA_PKCS,
43e65e5c2dSWyllys Ingersoll CKM_SHA1_RSA_PKCS, CKM_SHA_1},
44e65e5c2dSWyllys Ingersoll { KMF_ALGID_SHA256WithRSA, CKK_RSA, CKM_RSA_PKCS,
45e65e5c2dSWyllys Ingersoll CKM_SHA256_RSA_PKCS, CKM_SHA256},
46e65e5c2dSWyllys Ingersoll { KMF_ALGID_SHA384WithRSA, CKK_RSA, CKM_RSA_PKCS,
47e65e5c2dSWyllys Ingersoll CKM_SHA384_RSA_PKCS, CKM_SHA384},
48e65e5c2dSWyllys Ingersoll { KMF_ALGID_SHA512WithRSA, CKK_RSA, CKM_RSA_PKCS,
49e65e5c2dSWyllys Ingersoll CKM_SHA512_RSA_PKCS, CKM_SHA512},
50e65e5c2dSWyllys Ingersoll { KMF_ALGID_SHA1WithECDSA, CKK_EC, CKM_ECDSA,
51e65e5c2dSWyllys Ingersoll CKM_ECDSA, CKM_SHA_1},
52e65e5c2dSWyllys Ingersoll { KMF_ALGID_SHA256WithECDSA, CKK_EC, CKM_ECDSA,
53e65e5c2dSWyllys Ingersoll CKM_ECDSA, CKM_SHA256},
54e65e5c2dSWyllys Ingersoll { KMF_ALGID_SHA384WithECDSA, CKK_EC, CKM_ECDSA,
55e65e5c2dSWyllys Ingersoll CKM_ECDSA, CKM_SHA384},
56e65e5c2dSWyllys Ingersoll { KMF_ALGID_SHA512WithECDSA, CKK_EC, CKM_ECDSA,
57e65e5c2dSWyllys Ingersoll CKM_ECDSA, CKM_SHA512}
58e65e5c2dSWyllys Ingersoll };
59e65e5c2dSWyllys Ingersoll
60e65e5c2dSWyllys Ingersoll KMF_RETURN
get_pk11_data(KMF_ALGORITHM_INDEX AlgId,CK_KEY_TYPE * keytype,CK_MECHANISM_TYPE * signmech,CK_MECHANISM_TYPE * hashmech,boolean_t vfy)61e65e5c2dSWyllys Ingersoll get_pk11_data(KMF_ALGORITHM_INDEX AlgId,
62e65e5c2dSWyllys Ingersoll CK_KEY_TYPE *keytype, CK_MECHANISM_TYPE *signmech,
63e65e5c2dSWyllys Ingersoll CK_MECHANISM_TYPE *hashmech, boolean_t vfy)
64e65e5c2dSWyllys Ingersoll {
65e65e5c2dSWyllys Ingersoll uint32_t uIndex;
66e65e5c2dSWyllys Ingersoll uint32_t uMapSize =
67e65e5c2dSWyllys Ingersoll sizeof (alg_info_map) / sizeof (ALG_INFO);
68e65e5c2dSWyllys Ingersoll
69e65e5c2dSWyllys Ingersoll for (uIndex = 0; uIndex < uMapSize; uIndex++) {
70e65e5c2dSWyllys Ingersoll if (alg_info_map[uIndex].kmfAlgorithmId == AlgId) {
71e65e5c2dSWyllys Ingersoll if (keytype)
72e65e5c2dSWyllys Ingersoll *keytype = alg_info_map[uIndex].ckKeyType;
73e65e5c2dSWyllys Ingersoll if (hashmech)
74e65e5c2dSWyllys Ingersoll *hashmech = alg_info_map[uIndex].hashmech;
75e65e5c2dSWyllys Ingersoll if (signmech)
76e65e5c2dSWyllys Ingersoll *signmech =
77e65e5c2dSWyllys Ingersoll (vfy ? alg_info_map[uIndex].vfymech :
78e65e5c2dSWyllys Ingersoll alg_info_map[uIndex].signmech);
79e65e5c2dSWyllys Ingersoll return (KMF_OK);
80e65e5c2dSWyllys Ingersoll }
81e65e5c2dSWyllys Ingersoll }
82e65e5c2dSWyllys Ingersoll /* no match */
83e65e5c2dSWyllys Ingersoll return (KMF_ERR_BAD_ALGORITHM);
84e65e5c2dSWyllys Ingersoll }
85e65e5c2dSWyllys Ingersoll
86e65e5c2dSWyllys Ingersoll KMF_RETURN
kmf_create_pk11_session(CK_SESSION_HANDLE * sessionp,CK_MECHANISM_TYPE wanted_mech,CK_FLAGS wanted_flags)87e65e5c2dSWyllys Ingersoll kmf_create_pk11_session(CK_SESSION_HANDLE *sessionp,
88e65e5c2dSWyllys Ingersoll CK_MECHANISM_TYPE wanted_mech,
8999ebb4caSwyllys CK_FLAGS wanted_flags)
9099ebb4caSwyllys {
9199ebb4caSwyllys CK_RV rv;
929b37d296Swyllys KMF_RETURN ret;
9399ebb4caSwyllys KMF_RETURN kmf_rv = KMF_OK;
9499ebb4caSwyllys CK_SLOT_ID_PTR pSlotList;
9599ebb4caSwyllys CK_ULONG pulCount;
9699ebb4caSwyllys CK_MECHANISM_INFO info;
9799ebb4caSwyllys int i;
9899ebb4caSwyllys
999b37d296Swyllys ret = init_pk11();
1009b37d296Swyllys
1019b37d296Swyllys if (ret != KMF_OK)
1029b37d296Swyllys return (ret);
10399ebb4caSwyllys
10499ebb4caSwyllys rv = C_GetSlotList(0, NULL, &pulCount);
10599ebb4caSwyllys if (rv != CKR_OK) {
10699ebb4caSwyllys kmf_rv = KMF_ERR_UNINITIALIZED;
10799ebb4caSwyllys goto out;
10899ebb4caSwyllys }
10999ebb4caSwyllys
11099ebb4caSwyllys pSlotList = (CK_SLOT_ID_PTR) malloc(pulCount * sizeof (CK_SLOT_ID));
11199ebb4caSwyllys if (pSlotList == NULL) {
11299ebb4caSwyllys kmf_rv = KMF_ERR_MEMORY;
11399ebb4caSwyllys goto out;
11499ebb4caSwyllys }
11599ebb4caSwyllys
11699ebb4caSwyllys rv = C_GetSlotList(0, pSlotList, &pulCount);
11799ebb4caSwyllys if (rv != CKR_OK) {
11899ebb4caSwyllys kmf_rv = KMF_ERR_UNINITIALIZED;
11999ebb4caSwyllys goto out;
12099ebb4caSwyllys }
12199ebb4caSwyllys
12299ebb4caSwyllys for (i = 0; i < pulCount; i++) {
12399ebb4caSwyllys rv = C_GetMechanismInfo(pSlotList[i], wanted_mech, &info);
124e65e5c2dSWyllys Ingersoll if (rv == CKR_OK &&
125e65e5c2dSWyllys Ingersoll (info.flags & wanted_flags) == wanted_flags)
12699ebb4caSwyllys break;
12799ebb4caSwyllys }
12899ebb4caSwyllys if (i < pulCount) {
12999ebb4caSwyllys rv = C_OpenSession(pSlotList[i], CKF_SERIAL_SESSION,
13030a5e8faSwyllys NULL, NULL, sessionp);
13199ebb4caSwyllys
13299ebb4caSwyllys if (rv != CKR_OK) {
13399ebb4caSwyllys kmf_rv = KMF_ERR_UNINITIALIZED;
13499ebb4caSwyllys }
13599ebb4caSwyllys } else {
13699ebb4caSwyllys kmf_rv = KMF_ERR_UNINITIALIZED;
13799ebb4caSwyllys }
13899ebb4caSwyllys
13999ebb4caSwyllys out:
14099ebb4caSwyllys if (pSlotList != NULL)
14199ebb4caSwyllys free(pSlotList);
14299ebb4caSwyllys return (kmf_rv);
14399ebb4caSwyllys
14499ebb4caSwyllys }
14599ebb4caSwyllys
14699ebb4caSwyllys /*
14799ebb4caSwyllys * Name: PKCS_AddTemplate
14899ebb4caSwyllys *
14999ebb4caSwyllys * Description:
15099ebb4caSwyllys * Adds a CK_ATTRIBUTE value to an existing array of CK_ATTRIBUTES. Will
15199ebb4caSwyllys * not expand the array beyond the maximum specified size.
15299ebb4caSwyllys *
15399ebb4caSwyllys * Returns:
15499ebb4caSwyllys * TRUE - Attribute value succesfully added.
15599ebb4caSwyllys * FALSE - Maximum array size would be exceded.
15699ebb4caSwyllys */
15799ebb4caSwyllys static int
PKCS_AddTemplate(CK_ATTRIBUTE * pTemplate,CK_ULONG * ckNumTemplates,CK_ULONG ckMaxTemplates,CK_ATTRIBUTE_TYPE ckAttribCode,CK_BYTE * pckBuffer,CK_ULONG ckBufferLen)15899ebb4caSwyllys PKCS_AddTemplate(CK_ATTRIBUTE *pTemplate,
15999ebb4caSwyllys CK_ULONG *ckNumTemplates,
16099ebb4caSwyllys CK_ULONG ckMaxTemplates,
16199ebb4caSwyllys CK_ATTRIBUTE_TYPE ckAttribCode,
16299ebb4caSwyllys CK_BYTE * pckBuffer,
16399ebb4caSwyllys CK_ULONG ckBufferLen)
16499ebb4caSwyllys {
16599ebb4caSwyllys if (*ckNumTemplates >= ckMaxTemplates) {
16699ebb4caSwyllys return (FALSE);
16799ebb4caSwyllys }
16899ebb4caSwyllys
16999ebb4caSwyllys pTemplate[*ckNumTemplates].type = ckAttribCode;
17099ebb4caSwyllys pTemplate[*ckNumTemplates].pValue = pckBuffer;
17199ebb4caSwyllys pTemplate[*ckNumTemplates].ulValueLen = ckBufferLen;
17299ebb4caSwyllys (*ckNumTemplates)++;
17399ebb4caSwyllys
17499ebb4caSwyllys return (TRUE);
17599ebb4caSwyllys }
17699ebb4caSwyllys
17799ebb4caSwyllys /*
17899ebb4caSwyllys * Convert an SPKI data record to PKCS#11
17999ebb4caSwyllys * public key object.
18099ebb4caSwyllys */
18199ebb4caSwyllys static KMF_RETURN
PKCS_CreatePublicKey(const KMF_X509_SPKI * pKey,CK_SESSION_HANDLE ckSession,CK_OBJECT_HANDLE * pckPublicKey)18299ebb4caSwyllys PKCS_CreatePublicKey(
18399ebb4caSwyllys const KMF_X509_SPKI *pKey,
18499ebb4caSwyllys CK_SESSION_HANDLE ckSession,
18599ebb4caSwyllys CK_OBJECT_HANDLE *pckPublicKey)
18699ebb4caSwyllys {
18799ebb4caSwyllys KMF_RETURN mrReturn = KMF_OK;
18899ebb4caSwyllys CK_RV ckRv;
18999ebb4caSwyllys
19099ebb4caSwyllys CK_ATTRIBUTE ckTemplate[MAX_PUBLIC_KEY_TEMPLATES];
19199ebb4caSwyllys CK_ULONG ckNumTemplates = 0;
19299ebb4caSwyllys
19399ebb4caSwyllys /* Common object attributes */
19499ebb4caSwyllys CK_OBJECT_CLASS ckObjClass = CKO_PUBLIC_KEY;
19599ebb4caSwyllys CK_BBOOL ckToken = 0;
19699ebb4caSwyllys CK_BBOOL ckPrivate = 0;
19799ebb4caSwyllys
19899ebb4caSwyllys /* Common key attributes */
19999ebb4caSwyllys CK_KEY_TYPE ckKeyType;
20099ebb4caSwyllys CK_BBOOL ckDerive = CK_FALSE;
20199ebb4caSwyllys
20299ebb4caSwyllys /* Common public key attributes */
20399ebb4caSwyllys CK_BBOOL ckEncrypt = 1;
20499ebb4caSwyllys CK_BBOOL ckVerify = 1;
20599ebb4caSwyllys
20699ebb4caSwyllys CK_BBOOL ckVerifyRecover = CK_FALSE;
20799ebb4caSwyllys CK_BBOOL ckWrap = CK_FALSE;
20899ebb4caSwyllys
20999ebb4caSwyllys /* Key part array */
21099ebb4caSwyllys KMF_DATA KeyParts[KMF_MAX_PUBLIC_KEY_PARTS];
21199ebb4caSwyllys uint32_t i, uNumKeyParts = KMF_MAX_PUBLIC_KEY_PARTS;
21299ebb4caSwyllys KMF_ALGORITHM_INDEX AlgorithmId;
21399ebb4caSwyllys
21499ebb4caSwyllys /* Parse the keyblob */
21599ebb4caSwyllys (void) memset(KeyParts, 0, sizeof (KeyParts));
21699ebb4caSwyllys
21730a5e8faSwyllys AlgorithmId = x509_algoid_to_algid(
21830a5e8faSwyllys (KMF_OID *)&pKey->algorithm.algorithm);
21930a5e8faSwyllys if (AlgorithmId == KMF_ALGID_NONE)
22030a5e8faSwyllys return (KMF_ERR_BAD_ALGORITHM);
22199ebb4caSwyllys
22299ebb4caSwyllys mrReturn = ExtractSPKIData(pKey, AlgorithmId, KeyParts, &uNumKeyParts);
22399ebb4caSwyllys
22499ebb4caSwyllys if (mrReturn != KMF_OK)
22599ebb4caSwyllys return (mrReturn);
22699ebb4caSwyllys
22799ebb4caSwyllys /* Fill in the common object attributes */
22830a5e8faSwyllys if (!PKCS_AddTemplate(ckTemplate, &ckNumTemplates,
22930a5e8faSwyllys MAX_PUBLIC_KEY_TEMPLATES, CKA_CLASS, (CK_BYTE *)&ckObjClass,
23030a5e8faSwyllys sizeof (ckObjClass)) ||
23130a5e8faSwyllys !PKCS_AddTemplate(ckTemplate, &ckNumTemplates,
23230a5e8faSwyllys MAX_PUBLIC_KEY_TEMPLATES, CKA_TOKEN, (CK_BYTE *)&ckToken,
23330a5e8faSwyllys sizeof (ckToken)) ||
23430a5e8faSwyllys !PKCS_AddTemplate(ckTemplate, &ckNumTemplates,
23530a5e8faSwyllys MAX_PUBLIC_KEY_TEMPLATES, CKA_PRIVATE, (CK_BYTE *)&ckPrivate,
23630a5e8faSwyllys sizeof (ckPrivate))) {
23799ebb4caSwyllys mrReturn = KMF_ERR_INTERNAL;
23899ebb4caSwyllys goto cleanup;
23999ebb4caSwyllys }
24099ebb4caSwyllys
24199ebb4caSwyllys /* Fill in the common key attributes */
242e65e5c2dSWyllys Ingersoll if (get_pk11_data(AlgorithmId, &ckKeyType, NULL, NULL, 0)) {
24399ebb4caSwyllys goto cleanup;
24499ebb4caSwyllys }
24530a5e8faSwyllys if (!PKCS_AddTemplate(ckTemplate, &ckNumTemplates,
24630a5e8faSwyllys MAX_PUBLIC_KEY_TEMPLATES, CKA_KEY_TYPE, (CK_BYTE *)&ckKeyType,
24730a5e8faSwyllys sizeof (ckKeyType)) ||
24830a5e8faSwyllys !PKCS_AddTemplate(ckTemplate, &ckNumTemplates,
24930a5e8faSwyllys MAX_PUBLIC_KEY_TEMPLATES, CKA_DERIVE, (CK_BYTE *)&ckDerive,
25030a5e8faSwyllys sizeof (ckDerive))) {
25199ebb4caSwyllys mrReturn = KMF_ERR_INTERNAL;
25299ebb4caSwyllys goto cleanup;
25399ebb4caSwyllys }
25499ebb4caSwyllys
25599ebb4caSwyllys /* Add common public key attributes */
25630a5e8faSwyllys if (!PKCS_AddTemplate(ckTemplate, &ckNumTemplates,
25730a5e8faSwyllys MAX_PUBLIC_KEY_TEMPLATES, CKA_ENCRYPT, (CK_BYTE *)&ckEncrypt,
25830a5e8faSwyllys sizeof (ckEncrypt)) ||
25930a5e8faSwyllys !PKCS_AddTemplate(ckTemplate, &ckNumTemplates,
26030a5e8faSwyllys MAX_PUBLIC_KEY_TEMPLATES, CKA_VERIFY, (CK_BYTE *)&ckVerify,
26130a5e8faSwyllys sizeof (ckVerify)) ||
26230a5e8faSwyllys !PKCS_AddTemplate(ckTemplate, &ckNumTemplates,
26330a5e8faSwyllys MAX_PUBLIC_KEY_TEMPLATES, CKA_VERIFY_RECOVER,
26430a5e8faSwyllys (CK_BYTE *)&ckVerifyRecover, sizeof (ckVerifyRecover)) ||
26530a5e8faSwyllys !PKCS_AddTemplate(ckTemplate, &ckNumTemplates,
26630a5e8faSwyllys MAX_PUBLIC_KEY_TEMPLATES, CKA_WRAP, (CK_BYTE *)&ckWrap,
26730a5e8faSwyllys sizeof (ckWrap))) {
26899ebb4caSwyllys mrReturn = KMF_ERR_INTERNAL;
26999ebb4caSwyllys goto cleanup;
27099ebb4caSwyllys }
27199ebb4caSwyllys
27299ebb4caSwyllys /* Add algorithm specific attributes */
27399ebb4caSwyllys switch (ckKeyType) {
27499ebb4caSwyllys case CKK_RSA:
27530a5e8faSwyllys if (!PKCS_AddTemplate(ckTemplate, &ckNumTemplates,
27630a5e8faSwyllys MAX_PUBLIC_KEY_TEMPLATES, CKA_MODULUS,
27730a5e8faSwyllys (CK_BYTE *)KeyParts[KMF_RSA_MODULUS].Data,
27830a5e8faSwyllys (CK_ULONG)KeyParts[KMF_RSA_MODULUS].Length) ||
279e65e5c2dSWyllys Ingersoll
28030a5e8faSwyllys !PKCS_AddTemplate(ckTemplate, &ckNumTemplates,
28130a5e8faSwyllys MAX_PUBLIC_KEY_TEMPLATES, CKA_PUBLIC_EXPONENT,
28230a5e8faSwyllys (CK_BYTE *)KeyParts[KMF_RSA_PUBLIC_EXPONENT].Data,
28330a5e8faSwyllys (CK_ULONG)KeyParts[KMF_RSA_PUBLIC_EXPONENT].Length)) {
28430a5e8faSwyllys mrReturn = KMF_ERR_INTERNAL;
28530a5e8faSwyllys goto cleanup;
28699ebb4caSwyllys }
28799ebb4caSwyllys break;
28899ebb4caSwyllys case CKK_DSA:
28930a5e8faSwyllys if (!PKCS_AddTemplate(ckTemplate, &ckNumTemplates,
29030a5e8faSwyllys MAX_PUBLIC_KEY_TEMPLATES, CKA_PRIME,
29130a5e8faSwyllys (CK_BYTE *)KeyParts[KMF_DSA_PRIME].Data,
29230a5e8faSwyllys (CK_ULONG)KeyParts[KMF_DSA_PRIME].Length) ||
29330a5e8faSwyllys !PKCS_AddTemplate(ckTemplate, &ckNumTemplates,
29430a5e8faSwyllys MAX_PUBLIC_KEY_TEMPLATES, CKA_SUBPRIME,
29530a5e8faSwyllys (CK_BYTE *)KeyParts[KMF_DSA_SUB_PRIME].Data,
29630a5e8faSwyllys (CK_ULONG)KeyParts[KMF_DSA_SUB_PRIME].Length) ||
29730a5e8faSwyllys !PKCS_AddTemplate(ckTemplate, &ckNumTemplates,
29830a5e8faSwyllys MAX_PUBLIC_KEY_TEMPLATES, CKA_BASE,
29930a5e8faSwyllys (CK_BYTE *)KeyParts[KMF_DSA_BASE].Data,
30030a5e8faSwyllys (CK_ULONG)KeyParts[KMF_DSA_BASE].Length) ||
30130a5e8faSwyllys !PKCS_AddTemplate(ckTemplate, &ckNumTemplates,
30230a5e8faSwyllys MAX_PUBLIC_KEY_TEMPLATES, CKA_VALUE,
30330a5e8faSwyllys (CK_BYTE *)KeyParts[KMF_DSA_PUBLIC_VALUE].Data,
30430a5e8faSwyllys (CK_ULONG)KeyParts[KMF_DSA_PUBLIC_VALUE].Length)) {
30599ebb4caSwyllys mrReturn = KMF_ERR_INTERNAL;
30699ebb4caSwyllys goto cleanup;
30799ebb4caSwyllys }
30899ebb4caSwyllys break;
309e65e5c2dSWyllys Ingersoll case CKK_EC:
310e65e5c2dSWyllys Ingersoll if (!PKCS_AddTemplate(ckTemplate, &ckNumTemplates,
311e65e5c2dSWyllys Ingersoll MAX_PUBLIC_KEY_TEMPLATES, CKA_EC_POINT,
312e65e5c2dSWyllys Ingersoll (CK_BYTE *)KeyParts[KMF_ECDSA_POINT].Data,
313e65e5c2dSWyllys Ingersoll (CK_ULONG)KeyParts[KMF_ECDSA_POINT].Length) ||
314e65e5c2dSWyllys Ingersoll
315e65e5c2dSWyllys Ingersoll !PKCS_AddTemplate(ckTemplate, &ckNumTemplates,
316e65e5c2dSWyllys Ingersoll MAX_PUBLIC_KEY_TEMPLATES, CKA_EC_PARAMS,
317e65e5c2dSWyllys Ingersoll (CK_BYTE *)KeyParts[KMF_ECDSA_PARAMS].Data,
318e65e5c2dSWyllys Ingersoll (CK_ULONG)KeyParts[KMF_ECDSA_PARAMS].Length)) {
319e65e5c2dSWyllys Ingersoll mrReturn = KMF_ERR_INTERNAL;
320e65e5c2dSWyllys Ingersoll goto cleanup;
321e65e5c2dSWyllys Ingersoll }
322e65e5c2dSWyllys Ingersoll break;
32399ebb4caSwyllys default:
32499ebb4caSwyllys mrReturn = KMF_ERR_BAD_PARAMETER;
32599ebb4caSwyllys }
32699ebb4caSwyllys
32799ebb4caSwyllys if (mrReturn == KMF_OK) {
32899ebb4caSwyllys /* Instantiate the object */
32930a5e8faSwyllys ckRv = C_CreateObject(ckSession, ckTemplate,
33030a5e8faSwyllys ckNumTemplates, pckPublicKey);
33199ebb4caSwyllys if (ckRv != CKR_OK)
33299ebb4caSwyllys mrReturn = KMF_ERR_INTERNAL;
33399ebb4caSwyllys }
33499ebb4caSwyllys
33599ebb4caSwyllys cleanup:
33699ebb4caSwyllys for (i = 0; i < uNumKeyParts; i++) {
33730a5e8faSwyllys kmf_free_data(&KeyParts[i]);
33899ebb4caSwyllys }
33999ebb4caSwyllys
34099ebb4caSwyllys return (mrReturn);
34199ebb4caSwyllys }
34299ebb4caSwyllys
34399ebb4caSwyllys /*
34499ebb4caSwyllys * PKCS_AcquirePublicKeyHandle
34599ebb4caSwyllys *
34699ebb4caSwyllys * Given an assymetric key keyblob, attempts to find the appropriate
34799ebb4caSwyllys * public key.
34899ebb4caSwyllys *
34999ebb4caSwyllys * Methods of finding the public key:
35099ebb4caSwyllys * - Public Key with data present:
35199ebb4caSwyllys * Parses the key and creates a temporary session object.
35299ebb4caSwyllys * - Public Key with handle:
35399ebb4caSwyllys * The handle is type converted and returned. Validity of the handle is
35499ebb4caSwyllys * not checked.
35599ebb4caSwyllys * - Public Key with label:
35699ebb4caSwyllys * Attempts to find a public key with the corresponding label.
35799ebb4caSwyllys */
358e65e5c2dSWyllys Ingersoll static KMF_RETURN
PKCS_AcquirePublicKeyHandle(CK_SESSION_HANDLE ckSession,const KMF_X509_SPKI * pKey,CK_KEY_TYPE ckRequestedKeyType,CK_OBJECT_HANDLE * pckKeyHandle)35999ebb4caSwyllys PKCS_AcquirePublicKeyHandle(CK_SESSION_HANDLE ckSession,
36099ebb4caSwyllys const KMF_X509_SPKI *pKey,
36199ebb4caSwyllys CK_KEY_TYPE ckRequestedKeyType,
362e65e5c2dSWyllys Ingersoll CK_OBJECT_HANDLE *pckKeyHandle)
36399ebb4caSwyllys {
36499ebb4caSwyllys KMF_RETURN mrReturn = KMF_OK;
36599ebb4caSwyllys
36699ebb4caSwyllys /* Key searching variables */
367e65e5c2dSWyllys Ingersoll CK_OBJECT_HANDLE ckKeyHandle = 0;
36899ebb4caSwyllys CK_OBJECT_CLASS ckObjClass;
36999ebb4caSwyllys CK_KEY_TYPE ckKeyType;
37099ebb4caSwyllys CK_ATTRIBUTE ckTemplate[3];
37199ebb4caSwyllys CK_ULONG ckNumTemplates;
37299ebb4caSwyllys static const CK_ULONG ckMaxTemplates = (sizeof (ckTemplate) /
37330a5e8faSwyllys sizeof (CK_ATTRIBUTE));
37499ebb4caSwyllys CK_RV ckRv;
37599ebb4caSwyllys
37699ebb4caSwyllys /* Extract the data from the SPKI into individual fields */
37799ebb4caSwyllys mrReturn = PKCS_CreatePublicKey(pKey, ckSession, &ckKeyHandle);
37899ebb4caSwyllys if (mrReturn != KMF_OK)
37999ebb4caSwyllys return (mrReturn);
38099ebb4caSwyllys
38199ebb4caSwyllys /* Fetch the key class and algorithm from the object */
38299ebb4caSwyllys ckNumTemplates = 0;
38330a5e8faSwyllys if (!PKCS_AddTemplate(ckTemplate, &ckNumTemplates,
38430a5e8faSwyllys ckMaxTemplates, CKA_CLASS, (CK_BYTE *)&ckObjClass,
38530a5e8faSwyllys sizeof (ckObjClass)) ||
38630a5e8faSwyllys !PKCS_AddTemplate(ckTemplate, &ckNumTemplates,
38730a5e8faSwyllys ckMaxTemplates, CKA_KEY_TYPE, (CK_BYTE *)&ckKeyType,
38830a5e8faSwyllys sizeof (ckKeyType))) {
389e65e5c2dSWyllys Ingersoll (void) C_DestroyObject(ckSession, ckKeyHandle);
39099ebb4caSwyllys return (KMF_ERR_INTERNAL);
39199ebb4caSwyllys }
39230a5e8faSwyllys ckRv = C_GetAttributeValue(ckSession, ckKeyHandle,
39330a5e8faSwyllys ckTemplate, ckNumTemplates);
39499ebb4caSwyllys if (ckRv != CKR_OK) {
395e65e5c2dSWyllys Ingersoll (void) C_DestroyObject(ckSession, ckKeyHandle);
39699ebb4caSwyllys return (ckRv);
39799ebb4caSwyllys }
39899ebb4caSwyllys
39999ebb4caSwyllys /* Make sure the results match the expected values */
40099ebb4caSwyllys if ((ckKeyType != ckRequestedKeyType) ||
40130a5e8faSwyllys (ckObjClass != CKO_PUBLIC_KEY)) {
402e65e5c2dSWyllys Ingersoll (void) C_DestroyObject(ckSession, ckKeyHandle);
40399ebb4caSwyllys return (KMF_ERR_BAD_KEY_FORMAT);
40499ebb4caSwyllys }
40599ebb4caSwyllys
40699ebb4caSwyllys /* Set the return values */
40799ebb4caSwyllys *pckKeyHandle = ckKeyHandle;
40899ebb4caSwyllys
40999ebb4caSwyllys return (KMF_OK);
41099ebb4caSwyllys }
41199ebb4caSwyllys
412e65e5c2dSWyllys Ingersoll /*
413e65e5c2dSWyllys Ingersoll * Utility routine for verifying generic data using
414e65e5c2dSWyllys Ingersoll * the cryptographic framework (PKCS#11).
415e65e5c2dSWyllys Ingersoll * There are situations where we want to force this
416e65e5c2dSWyllys Ingersoll * operation to happen in a specific keystore.
417e65e5c2dSWyllys Ingersoll * For example:
418e65e5c2dSWyllys Ingersoll * libelfsign.so.1 verifies signatures on crypto libraries.
419e65e5c2dSWyllys Ingersoll * We must use pkcs11 functions to verify the pkcs11
420e65e5c2dSWyllys Ingersoll * plugins in order to keep the validation within the
421e65e5c2dSWyllys Ingersoll * Cryptographic Framework's FIPS-140 boundary. To avoid
422e65e5c2dSWyllys Ingersoll * a circular dependency, pksc11_softtoken.so.1 is
423e65e5c2dSWyllys Ingersoll * interposed by libkcfd.so.1 via kcfd, which prevents
424e65e5c2dSWyllys Ingersoll * libpkcs11.so.1's interfaces from being used when libkmf.so.1
425e65e5c2dSWyllys Ingersoll * is called from kcfd.
426e65e5c2dSWyllys Ingersoll *
427e65e5c2dSWyllys Ingersoll * This also saves code and time because verify operations
428e65e5c2dSWyllys Ingersoll * only use public keys and do not need acccess to any
429e65e5c2dSWyllys Ingersoll * keystore specific functions.
430e65e5c2dSWyllys Ingersoll */
43199ebb4caSwyllys KMF_RETURN
PKCS_VerifyData(KMF_HANDLE_T handle,KMF_ALGORITHM_INDEX AlgorithmId,KMF_X509_SPKI * keyp,KMF_DATA * data,KMF_DATA * signature)432e65e5c2dSWyllys Ingersoll PKCS_VerifyData(KMF_HANDLE_T handle,
43399ebb4caSwyllys KMF_ALGORITHM_INDEX AlgorithmId,
43499ebb4caSwyllys KMF_X509_SPKI *keyp,
43599ebb4caSwyllys KMF_DATA *data,
436e65e5c2dSWyllys Ingersoll KMF_DATA *signature)
43799ebb4caSwyllys {
438e65e5c2dSWyllys Ingersoll KMF_RETURN rv = KMF_OK;
439e65e5c2dSWyllys Ingersoll CK_RV ckRv;
440e65e5c2dSWyllys Ingersoll KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
441e65e5c2dSWyllys Ingersoll CK_MECHANISM ckMechanism;
442e65e5c2dSWyllys Ingersoll CK_MECHANISM_TYPE mechtype, hashmech;
443e65e5c2dSWyllys Ingersoll CK_OBJECT_HANDLE ckKeyHandle = 0;
444e65e5c2dSWyllys Ingersoll CK_KEY_TYPE pk11keytype;
44599ebb4caSwyllys CK_SESSION_HANDLE ckSession = 0;
446e65e5c2dSWyllys Ingersoll CK_ATTRIBUTE subprime = { CKA_SUBPRIME, NULL, 0 };
447e65e5c2dSWyllys Ingersoll CK_BYTE *dataptr;
448e65e5c2dSWyllys Ingersoll CK_ULONG datalen;
4496b35cb3cSRichard PALO KMF_DATA hashData = { 0, NULL };
450e65e5c2dSWyllys Ingersoll uchar_t digest[1024];
45199ebb4caSwyllys
45299ebb4caSwyllys if (AlgorithmId == KMF_ALGID_NONE)
45399ebb4caSwyllys return (KMF_ERR_BAD_ALGORITHM);
45499ebb4caSwyllys
455e65e5c2dSWyllys Ingersoll if (get_pk11_data(AlgorithmId, &pk11keytype, &mechtype, &hashmech, 1))
45699ebb4caSwyllys return (KMF_ERR_BAD_ALGORITHM);
45799ebb4caSwyllys
458e65e5c2dSWyllys Ingersoll /*
459e65e5c2dSWyllys Ingersoll * Verify in metaslot/softtoken since only the public key is needed
460e65e5c2dSWyllys Ingersoll * and not all hardware tokens support the combined [hash]-RSA/DSA/EC
461e65e5c2dSWyllys Ingersoll * mechanisms.
462e65e5c2dSWyllys Ingersoll */
463e65e5c2dSWyllys Ingersoll rv = kmf_create_pk11_session(&ckSession, mechtype, 0);
46499ebb4caSwyllys if (rv != KMF_OK)
46599ebb4caSwyllys return (rv);
46699ebb4caSwyllys
46799ebb4caSwyllys /* Fetch the verifying key */
46899ebb4caSwyllys rv = PKCS_AcquirePublicKeyHandle(ckSession, keyp,
469e65e5c2dSWyllys Ingersoll pk11keytype, &ckKeyHandle);
47099ebb4caSwyllys
47199ebb4caSwyllys if (rv != KMF_OK) {
47299ebb4caSwyllys (void) C_CloseSession(ckSession);
47399ebb4caSwyllys return (rv);
47499ebb4caSwyllys }
475e65e5c2dSWyllys Ingersoll dataptr = data->Data;
476e65e5c2dSWyllys Ingersoll datalen = data->Length;
477e65e5c2dSWyllys Ingersoll /*
478e65e5c2dSWyllys Ingersoll * For some mechanisms, we must compute the hash separately
479e65e5c2dSWyllys Ingersoll * and then do the verify.
480e65e5c2dSWyllys Ingersoll */
481e65e5c2dSWyllys Ingersoll if (hashmech != 0 &&
482e65e5c2dSWyllys Ingersoll (mechtype == CKM_ECDSA ||
483e65e5c2dSWyllys Ingersoll mechtype == CKM_DSA ||
484e65e5c2dSWyllys Ingersoll mechtype == CKM_RSA_PKCS)) {
485e65e5c2dSWyllys Ingersoll hashData.Data = digest;
486e65e5c2dSWyllys Ingersoll hashData.Length = sizeof (digest);
487e65e5c2dSWyllys Ingersoll
488e65e5c2dSWyllys Ingersoll rv = PKCS_DigestData(handle, ckSession,
489e65e5c2dSWyllys Ingersoll hashmech, data, &hashData,
490e65e5c2dSWyllys Ingersoll (mechtype == CKM_RSA_PKCS));
491e65e5c2dSWyllys Ingersoll if (rv)
492e65e5c2dSWyllys Ingersoll goto cleanup;
49399ebb4caSwyllys
494e65e5c2dSWyllys Ingersoll dataptr = hashData.Data;
495e65e5c2dSWyllys Ingersoll datalen = hashData.Length;
496e65e5c2dSWyllys Ingersoll }
497e65e5c2dSWyllys Ingersoll if (mechtype == CKM_DSA &&
498e65e5c2dSWyllys Ingersoll hashmech == CKM_SHA256) {
499e65e5c2dSWyllys Ingersoll /*
500e65e5c2dSWyllys Ingersoll * FIPS 186-3 says that when using DSA
501e65e5c2dSWyllys Ingersoll * the hash must be truncated to the size of the
502e65e5c2dSWyllys Ingersoll * subprime.
503e65e5c2dSWyllys Ingersoll */
504e65e5c2dSWyllys Ingersoll ckRv = C_GetAttributeValue(ckSession,
505e65e5c2dSWyllys Ingersoll ckKeyHandle, &subprime, 1);
506e65e5c2dSWyllys Ingersoll if (ckRv != CKR_OK) {
507e65e5c2dSWyllys Ingersoll kmfh->lasterr.kstype = KMF_KEYSTORE_PK11TOKEN;
508e65e5c2dSWyllys Ingersoll kmfh->lasterr.errcode = ckRv;
509e65e5c2dSWyllys Ingersoll rv = KMF_ERR_INTERNAL;
510e65e5c2dSWyllys Ingersoll goto cleanup;
511e65e5c2dSWyllys Ingersoll }
512e65e5c2dSWyllys Ingersoll datalen = subprime.ulValueLen;
513e65e5c2dSWyllys Ingersoll }
514e65e5c2dSWyllys Ingersoll
515e65e5c2dSWyllys Ingersoll ckMechanism.mechanism = mechtype;
51699ebb4caSwyllys ckMechanism.pParameter = NULL;
51799ebb4caSwyllys ckMechanism.ulParameterLen = 0;
51899ebb4caSwyllys
51999ebb4caSwyllys ckRv = C_VerifyInit(ckSession, &ckMechanism, ckKeyHandle);
52099ebb4caSwyllys if (ckRv != CKR_OK) {
52199ebb4caSwyllys kmfh->lasterr.kstype = KMF_KEYSTORE_PK11TOKEN;
52299ebb4caSwyllys kmfh->lasterr.errcode = ckRv;
523e65e5c2dSWyllys Ingersoll rv = KMF_ERR_INTERNAL;
524e65e5c2dSWyllys Ingersoll goto cleanup;
52599ebb4caSwyllys }
526e65e5c2dSWyllys Ingersoll ckRv = C_Verify(ckSession,
527e65e5c2dSWyllys Ingersoll dataptr, datalen,
528e65e5c2dSWyllys Ingersoll (CK_BYTE *)signature->Data,
529e65e5c2dSWyllys Ingersoll (CK_ULONG)signature->Length);
53099ebb4caSwyllys
53199ebb4caSwyllys if (ckRv != CKR_OK) {
53299ebb4caSwyllys kmfh->lasterr.kstype = KMF_KEYSTORE_PK11TOKEN;
53399ebb4caSwyllys kmfh->lasterr.errcode = ckRv;
53499ebb4caSwyllys rv = KMF_ERR_INTERNAL;
53599ebb4caSwyllys }
53699ebb4caSwyllys
537e65e5c2dSWyllys Ingersoll cleanup:
538e65e5c2dSWyllys Ingersoll if (ckKeyHandle != 0)
539e65e5c2dSWyllys Ingersoll (void) C_DestroyObject(ckSession, ckKeyHandle);
54099ebb4caSwyllys (void) C_CloseSession(ckSession);
54199ebb4caSwyllys return (rv);
54299ebb4caSwyllys }
54399ebb4caSwyllys
54499ebb4caSwyllys KMF_RETURN
PKCS_EncryptData(KMF_HANDLE_T kmfh,KMF_ALGORITHM_INDEX AlgorithmId,KMF_X509_SPKI * keyp,KMF_DATA * plaintext,KMF_DATA * ciphertext)54599ebb4caSwyllys PKCS_EncryptData(KMF_HANDLE_T kmfh,
54699ebb4caSwyllys KMF_ALGORITHM_INDEX AlgorithmId,
54799ebb4caSwyllys KMF_X509_SPKI *keyp,
54899ebb4caSwyllys KMF_DATA *plaintext,
54999ebb4caSwyllys KMF_DATA *ciphertext)
55099ebb4caSwyllys {
55199ebb4caSwyllys KMF_RETURN rv = KMF_OK;
55299ebb4caSwyllys CK_RV ckRv;
55399ebb4caSwyllys CK_MECHANISM ckMechanism;
554e65e5c2dSWyllys Ingersoll CK_MECHANISM_TYPE mechtype;
555e65e5c2dSWyllys Ingersoll CK_KEY_TYPE keytype;
556e65e5c2dSWyllys Ingersoll CK_OBJECT_HANDLE ckKeyHandle = 0;
557*f810c7e5SToomas Soome CK_SESSION_HANDLE ckSession = 0;
55899ebb4caSwyllys CK_ULONG out_len = 0, in_len = 0, total_encrypted = 0;
55999ebb4caSwyllys uint8_t *in_data, *out_data;
56099ebb4caSwyllys int i, blocks, block_size;
56199ebb4caSwyllys CK_ATTRIBUTE ckTemplate[2];
56299ebb4caSwyllys CK_ULONG ckNumTemplates;
56399ebb4caSwyllys CK_ULONG ckMaxTemplates = (sizeof (ckTemplate) /
56430a5e8faSwyllys sizeof (CK_ATTRIBUTE));
56599ebb4caSwyllys
566e65e5c2dSWyllys Ingersoll if (get_pk11_data(AlgorithmId, &keytype, &mechtype, NULL, 0))
56799ebb4caSwyllys return (KMF_ERR_BAD_ALGORITHM);
56899ebb4caSwyllys
569e65e5c2dSWyllys Ingersoll rv = kmf_create_pk11_session(&ckSession, mechtype, CKF_ENCRYPT);
57099ebb4caSwyllys if (rv != KMF_OK)
57199ebb4caSwyllys return (rv);
57299ebb4caSwyllys
57399ebb4caSwyllys /* Get the public key used in encryption */
57499ebb4caSwyllys rv = PKCS_AcquirePublicKeyHandle(ckSession, keyp,
575e65e5c2dSWyllys Ingersoll keytype, &ckKeyHandle);
57699ebb4caSwyllys
57799ebb4caSwyllys if (rv != KMF_OK) {
57899ebb4caSwyllys (void) C_CloseSession(ckSession);
57999ebb4caSwyllys return (rv);
58099ebb4caSwyllys }
58199ebb4caSwyllys
58299ebb4caSwyllys /* Get the modulus length */
58399ebb4caSwyllys ckNumTemplates = 0;
58430a5e8faSwyllys if (!PKCS_AddTemplate(ckTemplate, &ckNumTemplates, ckMaxTemplates,
58530a5e8faSwyllys CKA_MODULUS, (CK_BYTE *)NULL, sizeof (CK_ULONG))) {
586e65e5c2dSWyllys Ingersoll if (ckKeyHandle != 0)
58799ebb4caSwyllys (void) C_DestroyObject(ckSession, ckKeyHandle);
58899ebb4caSwyllys (void) C_CloseSession(ckSession);
58999ebb4caSwyllys return (KMF_ERR_INTERNAL);
59099ebb4caSwyllys }
59199ebb4caSwyllys
59230a5e8faSwyllys ckRv = C_GetAttributeValue(ckSession, ckKeyHandle,
59330a5e8faSwyllys ckTemplate, ckNumTemplates);
59499ebb4caSwyllys
59599ebb4caSwyllys if (ckRv != CKR_OK) {
596e65e5c2dSWyllys Ingersoll if (ckKeyHandle != 0)
59799ebb4caSwyllys (void) C_DestroyObject(ckSession, ckKeyHandle);
59899ebb4caSwyllys kmfh->lasterr.kstype = KMF_KEYSTORE_PK11TOKEN;
59999ebb4caSwyllys kmfh->lasterr.errcode = ckRv;
60099ebb4caSwyllys (void) C_CloseSession(ckSession);
60199ebb4caSwyllys return (KMF_ERR_INTERNAL);
60299ebb4caSwyllys }
60399ebb4caSwyllys out_len = ckTemplate[0].ulValueLen;
60499ebb4caSwyllys
60599ebb4caSwyllys if (out_len > ciphertext->Length) {
606e65e5c2dSWyllys Ingersoll if (ckKeyHandle != 0)
60799ebb4caSwyllys (void) C_DestroyObject(ckSession, ckKeyHandle);
60899ebb4caSwyllys (void) C_CloseSession(ckSession);
60999ebb4caSwyllys return (KMF_ERR_BUFFER_SIZE);
61099ebb4caSwyllys }
61199ebb4caSwyllys
612e65e5c2dSWyllys Ingersoll ckMechanism.mechanism = mechtype;
61399ebb4caSwyllys ckMechanism.pParameter = NULL_PTR;
61499ebb4caSwyllys ckMechanism.ulParameterLen = 0;
61599ebb4caSwyllys
61699ebb4caSwyllys /* Compute the fixed input data length for single-part encryption */
61799ebb4caSwyllys block_size = out_len - 11;
61899ebb4caSwyllys
61999ebb4caSwyllys in_data = plaintext->Data;
62099ebb4caSwyllys out_data = ciphertext->Data;
62199ebb4caSwyllys
62299ebb4caSwyllys blocks = plaintext->Length/block_size;
62399ebb4caSwyllys
62499ebb4caSwyllys for (i = 0; i < blocks; i++) {
62599ebb4caSwyllys ckRv = C_EncryptInit(ckSession, &ckMechanism, ckKeyHandle);
62699ebb4caSwyllys if (ckRv != CKR_OK) {
627e65e5c2dSWyllys Ingersoll if (ckKeyHandle != 0)
62899ebb4caSwyllys (void) C_DestroyObject(ckSession, ckKeyHandle);
62999ebb4caSwyllys kmfh->lasterr.kstype = KMF_KEYSTORE_PK11TOKEN;
63099ebb4caSwyllys kmfh->lasterr.errcode = ckRv;
63199ebb4caSwyllys (void) C_CloseSession(ckSession);
63299ebb4caSwyllys return (KMF_ERR_INTERNAL);
63399ebb4caSwyllys }
63499ebb4caSwyllys ckRv = C_Encrypt(ckSession, (CK_BYTE_PTR)in_data, block_size,
63599ebb4caSwyllys (CK_BYTE_PTR)out_data, &out_len);
63699ebb4caSwyllys
63799ebb4caSwyllys if (ckRv != CKR_OK) {
638e65e5c2dSWyllys Ingersoll if (ckKeyHandle != 0)
63999ebb4caSwyllys (void) C_DestroyObject(ckSession, ckKeyHandle);
64099ebb4caSwyllys kmfh->lasterr.kstype = KMF_KEYSTORE_PK11TOKEN;
64199ebb4caSwyllys kmfh->lasterr.errcode = ckRv;
64299ebb4caSwyllys (void) C_CloseSession(ckSession);
64399ebb4caSwyllys return (KMF_ERR_INTERNAL);
64499ebb4caSwyllys }
64599ebb4caSwyllys
64699ebb4caSwyllys out_data += out_len;
64799ebb4caSwyllys total_encrypted += out_len;
64899ebb4caSwyllys in_data += block_size;
64999ebb4caSwyllys }
65099ebb4caSwyllys
65199ebb4caSwyllys if (plaintext->Length % block_size) {
65299ebb4caSwyllys /* Encrypt the remaining data */
65399ebb4caSwyllys ckRv = C_EncryptInit(ckSession, &ckMechanism, ckKeyHandle);
65499ebb4caSwyllys if (ckRv != CKR_OK) {
655e65e5c2dSWyllys Ingersoll if (ckKeyHandle != 0)
65699ebb4caSwyllys (void) C_DestroyObject(ckSession, ckKeyHandle);
65799ebb4caSwyllys kmfh->lasterr.kstype = KMF_KEYSTORE_PK11TOKEN;
65899ebb4caSwyllys kmfh->lasterr.errcode = ckRv;
65999ebb4caSwyllys (void) C_CloseSession(ckSession);
66099ebb4caSwyllys return (KMF_ERR_INTERNAL);
66199ebb4caSwyllys }
66299ebb4caSwyllys
66399ebb4caSwyllys in_len = plaintext->Length % block_size;
66499ebb4caSwyllys ckRv = C_Encrypt(ckSession, (CK_BYTE_PTR)in_data, in_len,
66599ebb4caSwyllys (CK_BYTE_PTR)out_data, &out_len);
66699ebb4caSwyllys
66799ebb4caSwyllys if (ckRv != CKR_OK) {
668e65e5c2dSWyllys Ingersoll if (ckKeyHandle != 0)
66999ebb4caSwyllys (void) C_DestroyObject(ckSession, ckKeyHandle);
67099ebb4caSwyllys kmfh->lasterr.kstype = KMF_KEYSTORE_PK11TOKEN;
67199ebb4caSwyllys kmfh->lasterr.errcode = ckRv;
67299ebb4caSwyllys (void) C_CloseSession(ckSession);
67399ebb4caSwyllys return (KMF_ERR_INTERNAL);
67499ebb4caSwyllys }
67599ebb4caSwyllys
67699ebb4caSwyllys out_data += out_len;
67799ebb4caSwyllys total_encrypted += out_len;
67899ebb4caSwyllys in_data += in_len;
67999ebb4caSwyllys }
68099ebb4caSwyllys
68199ebb4caSwyllys ciphertext->Length = total_encrypted;
68299ebb4caSwyllys
683e65e5c2dSWyllys Ingersoll if (ckKeyHandle != 0)
68499ebb4caSwyllys (void) C_DestroyObject(ckSession, ckKeyHandle);
68599ebb4caSwyllys
68699ebb4caSwyllys (void) C_CloseSession(ckSession);
68799ebb4caSwyllys return (rv);
68899ebb4caSwyllys
68999ebb4caSwyllys }
69099ebb4caSwyllys
6919b37d296Swyllys static void
create_id_hash(KMF_DATA * IDInput,KMF_DATA * IDOutput)692e65e5c2dSWyllys Ingersoll create_id_hash(KMF_DATA *IDInput, KMF_DATA *IDOutput)
69399ebb4caSwyllys {
6949b37d296Swyllys SHA1_CTX ctx;
69599ebb4caSwyllys
6969b37d296Swyllys SHA1Init(&ctx);
6979b37d296Swyllys SHA1Update(&ctx, IDInput->Data, IDInput->Length);
6989b37d296Swyllys SHA1Final(IDOutput->Data, &ctx);
69999ebb4caSwyllys
7009b37d296Swyllys IDOutput->Length = SHA1_DIGEST_LENGTH;
70199ebb4caSwyllys }
70299ebb4caSwyllys
70399ebb4caSwyllys KMF_RETURN
GetIDFromSPKI(KMF_X509_SPKI * spki,KMF_DATA * ID)7049b37d296Swyllys GetIDFromSPKI(KMF_X509_SPKI *spki, KMF_DATA *ID)
70599ebb4caSwyllys {
70699ebb4caSwyllys KMF_RETURN rv = KMF_OK;
70799ebb4caSwyllys KMF_DATA KeyParts[KMF_MAX_PUBLIC_KEY_PARTS];
70899ebb4caSwyllys uint32_t uNumKeyParts = KMF_MAX_PUBLIC_KEY_PARTS;
70999ebb4caSwyllys KMF_ALGORITHM_INDEX algId;
71099ebb4caSwyllys int i;
71199ebb4caSwyllys
71299ebb4caSwyllys if (ID == NULL || spki == NULL)
71399ebb4caSwyllys return (KMF_ERR_BAD_PARAMETER);
71499ebb4caSwyllys
71599ebb4caSwyllys ID->Data = (uchar_t *)malloc(SHA1_HASH_LENGTH);
71699ebb4caSwyllys if (ID->Data == NULL)
71799ebb4caSwyllys return (KMF_ERR_MEMORY);
71899ebb4caSwyllys
71999ebb4caSwyllys ID->Length = SHA1_HASH_LENGTH;
72099ebb4caSwyllys
72130a5e8faSwyllys algId = x509_algoid_to_algid(&spki->algorithm.algorithm);
72230a5e8faSwyllys if (algId == KMF_ALGID_NONE)
72330a5e8faSwyllys return (KMF_ERR_BAD_ALGORITHM);
72499ebb4caSwyllys
72599ebb4caSwyllys rv = ExtractSPKIData(spki, algId, KeyParts, &uNumKeyParts);
72699ebb4caSwyllys if (rv != KMF_OK)
72799ebb4caSwyllys return (rv);
72899ebb4caSwyllys
72999ebb4caSwyllys /* Check the KEY algorithm */
73099ebb4caSwyllys if (algId == KMF_ALGID_RSA) {
731e65e5c2dSWyllys Ingersoll create_id_hash(&KeyParts[KMF_RSA_MODULUS], ID);
73299ebb4caSwyllys } else if (algId == KMF_ALGID_DSA) {
733e65e5c2dSWyllys Ingersoll create_id_hash(&KeyParts[KMF_DSA_PUBLIC_VALUE], ID);
734e65e5c2dSWyllys Ingersoll } else if (algId == KMF_ALGID_SHA1WithECDSA ||
735e65e5c2dSWyllys Ingersoll algId == KMF_ALGID_ECDSA) {
736e65e5c2dSWyllys Ingersoll create_id_hash(&KeyParts[KMF_ECDSA_POINT], ID);
73799ebb4caSwyllys } else {
73899ebb4caSwyllys /* We only support RSA and DSA keys for now */
73999ebb4caSwyllys rv = KMF_ERR_BAD_ALGORITHM;
74099ebb4caSwyllys }
74199ebb4caSwyllys
74299ebb4caSwyllys for (i = 0; i < uNumKeyParts; i++) {
74399ebb4caSwyllys if (KeyParts[i].Data != NULL)
74499ebb4caSwyllys free(KeyParts[i].Data);
74599ebb4caSwyllys }
74699ebb4caSwyllys
74799ebb4caSwyllys if (rv != KMF_OK && ID->Data != NULL) {
74899ebb4caSwyllys free(ID->Data);
74999ebb4caSwyllys ID->Data = NULL;
75099ebb4caSwyllys ID->Length = 0;
75199ebb4caSwyllys }
75299ebb4caSwyllys
75399ebb4caSwyllys return (rv);
75499ebb4caSwyllys }
755e65e5c2dSWyllys Ingersoll
756e65e5c2dSWyllys Ingersoll /*
757e65e5c2dSWyllys Ingersoll * For PKCS1 encoding (necessary for RSA signatures), we
758e65e5c2dSWyllys Ingersoll * must prepend the following prefixes before computing
759e65e5c2dSWyllys Ingersoll * the digest.
760e65e5c2dSWyllys Ingersoll */
761e65e5c2dSWyllys Ingersoll static uchar_t SHA1_DER_PREFIX[] = {
762e65e5c2dSWyllys Ingersoll 0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e,
763e65e5c2dSWyllys Ingersoll 0x03, 0x02, 0x1a, 0x05, 0x00, 0x04, 0x14
764e65e5c2dSWyllys Ingersoll };
765e65e5c2dSWyllys Ingersoll static uchar_t MD5_DER_PREFIX[] = {
766e65e5c2dSWyllys Ingersoll 0x30, 0x20, 0x30, 0x0c, 0x06, 0x08, 0x2a, 0x86,
767e65e5c2dSWyllys Ingersoll 0x48, 0x86, 0xf7, 0x0d, 0x02, 0x05, 0x05, 0x00,
768e65e5c2dSWyllys Ingersoll 0x04, 0x10
769e65e5c2dSWyllys Ingersoll };
770e65e5c2dSWyllys Ingersoll static uchar_t SHA256_DER_PREFIX[] = {0x30, 0x31, 0x30, 0x0d,
771e65e5c2dSWyllys Ingersoll 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05,
772e65e5c2dSWyllys Ingersoll 0x00, 0x04, 0x20};
773e65e5c2dSWyllys Ingersoll
774e65e5c2dSWyllys Ingersoll static uchar_t SHA384_DER_PREFIX[] = {0x30, 0x41, 0x30, 0x0d,
775e65e5c2dSWyllys Ingersoll 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x02, 0x05,
776e65e5c2dSWyllys Ingersoll 0x00, 0x04, 0x30};
777e65e5c2dSWyllys Ingersoll
778e65e5c2dSWyllys Ingersoll static uchar_t SHA512_DER_PREFIX[] = {0x30, 0x51, 0x30, 0x0d,
779e65e5c2dSWyllys Ingersoll 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03, 0x05,
780e65e5c2dSWyllys Ingersoll 0x00, 0x04, 0x40};
781e65e5c2dSWyllys Ingersoll
782e65e5c2dSWyllys Ingersoll #define MAX_SHA2_DIGEST_LENGTH 64
783e65e5c2dSWyllys Ingersoll /*
784e65e5c2dSWyllys Ingersoll * Compute hashes using metaslot (or softtoken).
785e65e5c2dSWyllys Ingersoll * Not all hardware tokens support the combined HASH + RSA/EC
786e65e5c2dSWyllys Ingersoll * Signing operations so it is safer to separate the hashing
787e65e5c2dSWyllys Ingersoll * from the signing. This function generates a hash using a
788e65e5c2dSWyllys Ingersoll * separate session. The resulting digest can be signed later.
789e65e5c2dSWyllys Ingersoll */
790e65e5c2dSWyllys Ingersoll 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)791e65e5c2dSWyllys Ingersoll PKCS_DigestData(KMF_HANDLE_T handle,
792e65e5c2dSWyllys Ingersoll CK_SESSION_HANDLE hSession,
793e65e5c2dSWyllys Ingersoll CK_MECHANISM_TYPE mechtype,
794e65e5c2dSWyllys Ingersoll KMF_DATA *tobesigned, KMF_DATA *output,
795e65e5c2dSWyllys Ingersoll boolean_t pkcs1_encoding)
796e65e5c2dSWyllys Ingersoll {
797e65e5c2dSWyllys Ingersoll KMF_RETURN rv = KMF_OK;
798e65e5c2dSWyllys Ingersoll CK_RV ckrv;
799e65e5c2dSWyllys Ingersoll CK_MECHANISM mechanism;
800e65e5c2dSWyllys Ingersoll KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
801e65e5c2dSWyllys Ingersoll CK_BYTE outbuf[MAX_SHA2_DIGEST_LENGTH +
802e65e5c2dSWyllys Ingersoll sizeof (SHA512_DER_PREFIX)];
803e65e5c2dSWyllys Ingersoll CK_ULONG outlen = sizeof (outbuf);
804e65e5c2dSWyllys Ingersoll
805e65e5c2dSWyllys Ingersoll mechanism.mechanism = mechtype;
806e65e5c2dSWyllys Ingersoll mechanism.pParameter = NULL;
807e65e5c2dSWyllys Ingersoll mechanism.ulParameterLen = 0;
808e65e5c2dSWyllys Ingersoll
809e65e5c2dSWyllys Ingersoll ckrv = C_DigestInit(hSession, &mechanism);
810e65e5c2dSWyllys Ingersoll if (ckrv != CKR_OK) {
811e65e5c2dSWyllys Ingersoll kmfh->lasterr.kstype = KMF_KEYSTORE_PK11TOKEN;
812e65e5c2dSWyllys Ingersoll kmfh->lasterr.errcode = ckrv;
813e65e5c2dSWyllys Ingersoll rv = KMF_ERR_INTERNAL;
814e65e5c2dSWyllys Ingersoll goto end;
815e65e5c2dSWyllys Ingersoll }
816e65e5c2dSWyllys Ingersoll
817e65e5c2dSWyllys Ingersoll ckrv = C_Digest(hSession, tobesigned->Data,
818e65e5c2dSWyllys Ingersoll tobesigned->Length, outbuf, &outlen);
819e65e5c2dSWyllys Ingersoll if (ckrv != CKR_OK) {
820e65e5c2dSWyllys Ingersoll kmfh->lasterr.kstype = KMF_KEYSTORE_PK11TOKEN;
821e65e5c2dSWyllys Ingersoll kmfh->lasterr.errcode = ckrv;
822e65e5c2dSWyllys Ingersoll rv = KMF_ERR_INTERNAL;
823e65e5c2dSWyllys Ingersoll }
824e65e5c2dSWyllys Ingersoll
825e65e5c2dSWyllys Ingersoll if (pkcs1_encoding) {
826e65e5c2dSWyllys Ingersoll uchar_t *pfx;
827e65e5c2dSWyllys Ingersoll int pfxlen;
828e65e5c2dSWyllys Ingersoll switch (mechtype) {
829e65e5c2dSWyllys Ingersoll case CKM_MD5:
830e65e5c2dSWyllys Ingersoll pfx = MD5_DER_PREFIX;
831e65e5c2dSWyllys Ingersoll pfxlen = sizeof (MD5_DER_PREFIX);
832e65e5c2dSWyllys Ingersoll break;
833e65e5c2dSWyllys Ingersoll case CKM_SHA_1:
834e65e5c2dSWyllys Ingersoll pfx = SHA1_DER_PREFIX;
835e65e5c2dSWyllys Ingersoll pfxlen = sizeof (SHA1_DER_PREFIX);
836e65e5c2dSWyllys Ingersoll break;
837e65e5c2dSWyllys Ingersoll case CKM_SHA256:
838e65e5c2dSWyllys Ingersoll pfx = SHA256_DER_PREFIX;
839e65e5c2dSWyllys Ingersoll pfxlen = sizeof (SHA256_DER_PREFIX);
840e65e5c2dSWyllys Ingersoll break;
841e65e5c2dSWyllys Ingersoll case CKM_SHA384:
842e65e5c2dSWyllys Ingersoll pfx = SHA384_DER_PREFIX;
843e65e5c2dSWyllys Ingersoll pfxlen = sizeof (SHA384_DER_PREFIX);
844e65e5c2dSWyllys Ingersoll break;
845e65e5c2dSWyllys Ingersoll case CKM_SHA512:
846e65e5c2dSWyllys Ingersoll pfx = SHA512_DER_PREFIX;
847e65e5c2dSWyllys Ingersoll pfxlen = sizeof (SHA512_DER_PREFIX);
848e65e5c2dSWyllys Ingersoll break;
849e65e5c2dSWyllys Ingersoll default:
850e65e5c2dSWyllys Ingersoll rv = KMF_ERR_BAD_ALGORITHM;
851e65e5c2dSWyllys Ingersoll goto end;
852e65e5c2dSWyllys Ingersoll }
853e65e5c2dSWyllys Ingersoll (void) memcpy(output->Data, pfx, pfxlen);
854e65e5c2dSWyllys Ingersoll (void) memcpy(output->Data + pfxlen, outbuf, outlen);
855e65e5c2dSWyllys Ingersoll output->Length = outlen + pfxlen;
856e65e5c2dSWyllys Ingersoll } else {
857e65e5c2dSWyllys Ingersoll (void) memcpy(output->Data, outbuf, outlen);
858e65e5c2dSWyllys Ingersoll output->Length = outlen;
859e65e5c2dSWyllys Ingersoll }
860e65e5c2dSWyllys Ingersoll
861e65e5c2dSWyllys Ingersoll end:
862e65e5c2dSWyllys Ingersoll return (rv);
863e65e5c2dSWyllys Ingersoll }
864