summaryrefslogtreecommitdiff
path: root/usr/src/lib/libkmf/libkmf/common/pk11keys.c
diff options
context:
space:
mode:
Diffstat (limited to 'usr/src/lib/libkmf/libkmf/common/pk11keys.c')
-rw-r--r--usr/src/lib/libkmf/libkmf/common/pk11keys.c735
1 files changed, 735 insertions, 0 deletions
diff --git a/usr/src/lib/libkmf/libkmf/common/pk11keys.c b/usr/src/lib/libkmf/libkmf/common/pk11keys.c
new file mode 100644
index 0000000000..adbcf64224
--- /dev/null
+++ b/usr/src/lib/libkmf/libkmf/common/pk11keys.c
@@ -0,0 +1,735 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ *
+ * File: KEYS.C
+ *
+ * Copyright (c) 1995-2000 Intel Corporation. All rights reserved.
+ *
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include <kmfapiP.h>
+#include <security/cryptoki.h>
+
+#include <algorithm.h>
+#include <ber_der.h>
+
+#define MAX_PUBLIC_KEY_TEMPLATES (20)
+#define MAX_PRIVATE_KEY_TEMPLATES (24)
+#define MAX_SECRET_KEY_TEMPLATES (24)
+
+static KMF_RETURN
+create_pk11_session(CK_SESSION_HANDLE *sessionp, CK_MECHANISM_TYPE wanted_mech,
+ CK_FLAGS wanted_flags)
+{
+ CK_RV rv;
+ KMF_RETURN kmf_rv = KMF_OK;
+ CK_SLOT_ID_PTR pSlotList;
+ CK_ULONG pulCount;
+ CK_MECHANISM_INFO info;
+ int i;
+
+ if (!is_pk11_ready()) {
+ rv = C_Initialize(NULL);
+ if ((rv != CKR_OK) &&
+ (rv != CKR_CRYPTOKI_ALREADY_INITIALIZED)) {
+ kmf_rv = KMF_ERR_UNINITIALIZED;
+ goto out;
+ }
+ }
+
+ rv = C_GetSlotList(0, NULL, &pulCount);
+ if (rv != CKR_OK) {
+ kmf_rv = KMF_ERR_UNINITIALIZED;
+ goto out;
+ }
+
+ pSlotList = (CK_SLOT_ID_PTR) malloc(pulCount * sizeof (CK_SLOT_ID));
+ if (pSlotList == NULL) {
+ kmf_rv = KMF_ERR_MEMORY;
+ goto out;
+ }
+
+ rv = C_GetSlotList(0, pSlotList, &pulCount);
+ if (rv != CKR_OK) {
+ kmf_rv = KMF_ERR_UNINITIALIZED;
+ goto out;
+ }
+
+ for (i = 0; i < pulCount; i++) {
+ rv = C_GetMechanismInfo(pSlotList[i], wanted_mech, &info);
+ if (rv == CKR_OK && (info.flags & wanted_flags))
+ break;
+ }
+ if (i < pulCount) {
+ rv = C_OpenSession(pSlotList[i], CKF_SERIAL_SESSION,
+ NULL, NULL, sessionp);
+
+ if (rv != CKR_OK) {
+ kmf_rv = KMF_ERR_UNINITIALIZED;
+ }
+ } else {
+ kmf_rv = KMF_ERR_UNINITIALIZED;
+ }
+
+out:
+ if (pSlotList != NULL)
+ free(pSlotList);
+ return (kmf_rv);
+
+}
+
+/*
+ * Name: PKCS_AddTemplate
+ *
+ * Description:
+ * Adds a CK_ATTRIBUTE value to an existing array of CK_ATTRIBUTES. Will
+ * not expand the array beyond the maximum specified size.
+ *
+ * Returns:
+ * TRUE - Attribute value succesfully added.
+ * FALSE - Maximum array size would be exceded.
+ */
+static int
+PKCS_AddTemplate(CK_ATTRIBUTE *pTemplate,
+ CK_ULONG *ckNumTemplates,
+ CK_ULONG ckMaxTemplates,
+ CK_ATTRIBUTE_TYPE ckAttribCode,
+ CK_BYTE * pckBuffer,
+ CK_ULONG ckBufferLen)
+{
+ if (*ckNumTemplates >= ckMaxTemplates) {
+ return (FALSE);
+ }
+
+ pTemplate[*ckNumTemplates].type = ckAttribCode;
+ pTemplate[*ckNumTemplates].pValue = pckBuffer;
+ pTemplate[*ckNumTemplates].ulValueLen = ckBufferLen;
+ (*ckNumTemplates)++;
+
+ return (TRUE);
+}
+
+/*
+ * Convert an SPKI data record to PKCS#11
+ * public key object.
+ */
+static KMF_RETURN
+PKCS_CreatePublicKey(
+ const KMF_X509_SPKI *pKey,
+ CK_SESSION_HANDLE ckSession,
+ CK_OBJECT_HANDLE *pckPublicKey)
+{
+ KMF_RETURN mrReturn = KMF_OK;
+ CK_RV ckRv;
+
+ CK_ATTRIBUTE ckTemplate[MAX_PUBLIC_KEY_TEMPLATES];
+ CK_ULONG ckNumTemplates = 0;
+
+ /* Common object attributes */
+ CK_OBJECT_CLASS ckObjClass = CKO_PUBLIC_KEY;
+ CK_BBOOL ckToken = 0;
+ CK_BBOOL ckPrivate = 0;
+
+ /* Common key attributes */
+ CK_KEY_TYPE ckKeyType;
+ CK_BBOOL ckDerive = CK_FALSE;
+
+ /* Common public key attributes */
+ CK_BBOOL ckEncrypt = 1;
+ CK_BBOOL ckVerify = 1;
+
+ CK_BBOOL ckVerifyRecover = CK_FALSE;
+ CK_BBOOL ckWrap = CK_FALSE;
+
+ /* Key part array */
+ KMF_DATA KeyParts[KMF_MAX_PUBLIC_KEY_PARTS];
+ uint32_t i, uNumKeyParts = KMF_MAX_PUBLIC_KEY_PARTS;
+ KMF_ALGORITHM_INDEX AlgorithmId;
+
+ /* Parse the keyblob */
+ (void) memset(KeyParts, 0, sizeof (KeyParts));
+
+ AlgorithmId = X509_AlgorithmOidToAlgId((KMF_OID *)
+ &pKey->algorithm.algorithm);
+
+ mrReturn = ExtractSPKIData(pKey, AlgorithmId, KeyParts, &uNumKeyParts);
+
+ if (mrReturn != KMF_OK)
+ return (mrReturn);
+
+ /* Fill in the common object attributes */
+ if (!PKCS_AddTemplate(ckTemplate,
+ &ckNumTemplates,
+ MAX_PUBLIC_KEY_TEMPLATES,
+ CKA_CLASS,
+ (CK_BYTE *)&ckObjClass,
+ sizeof (ckObjClass)) ||
+ !PKCS_AddTemplate(ckTemplate,
+ &ckNumTemplates,
+ MAX_PUBLIC_KEY_TEMPLATES,
+ CKA_TOKEN,
+ (CK_BYTE *)&ckToken,
+ sizeof (ckToken)) ||
+ !PKCS_AddTemplate(ckTemplate,
+ &ckNumTemplates,
+ MAX_PUBLIC_KEY_TEMPLATES,
+ CKA_PRIVATE,
+ (CK_BYTE *)&ckPrivate,
+ sizeof (ckPrivate))) {
+ mrReturn = KMF_ERR_INTERNAL;
+ goto cleanup;
+ }
+
+ /* Fill in the common key attributes */
+ if (!PKCS_ConvertAlgorithmId2PKCSKeyType(AlgorithmId,
+ &ckKeyType)) {
+ goto cleanup;
+ }
+ if (!PKCS_AddTemplate(ckTemplate,
+ &ckNumTemplates,
+ MAX_PUBLIC_KEY_TEMPLATES,
+ CKA_KEY_TYPE,
+ (CK_BYTE *)&ckKeyType,
+ sizeof (ckKeyType)) ||
+ !PKCS_AddTemplate(ckTemplate,
+ &ckNumTemplates,
+ MAX_PUBLIC_KEY_TEMPLATES,
+ CKA_DERIVE,
+ (CK_BYTE *)&ckDerive,
+ sizeof (ckDerive))) {
+ mrReturn = KMF_ERR_INTERNAL;
+ goto cleanup;
+ }
+
+ /* Add common public key attributes */
+ if (!PKCS_AddTemplate(ckTemplate,
+ &ckNumTemplates,
+ MAX_PUBLIC_KEY_TEMPLATES,
+ CKA_ENCRYPT,
+ (CK_BYTE *)&ckEncrypt,
+ sizeof (ckEncrypt)) ||
+ !PKCS_AddTemplate(ckTemplate,
+ &ckNumTemplates,
+ MAX_PUBLIC_KEY_TEMPLATES,
+ CKA_VERIFY,
+ (CK_BYTE *)&ckVerify,
+ sizeof (ckVerify)) ||
+ !PKCS_AddTemplate(ckTemplate,
+ &ckNumTemplates,
+ MAX_PUBLIC_KEY_TEMPLATES,
+ CKA_VERIFY_RECOVER,
+ (CK_BYTE *)&ckVerifyRecover,
+ sizeof (ckVerifyRecover)) ||
+ !PKCS_AddTemplate(ckTemplate,
+ &ckNumTemplates,
+ MAX_PUBLIC_KEY_TEMPLATES,
+ CKA_WRAP,
+ (CK_BYTE *)&ckWrap,
+ sizeof (ckWrap))) {
+ mrReturn = KMF_ERR_INTERNAL;
+ goto cleanup;
+ }
+
+ /* Add algorithm specific attributes */
+ switch (ckKeyType) {
+ case CKK_RSA:
+ if (!PKCS_AddTemplate(ckTemplate,
+ &ckNumTemplates,
+ MAX_PUBLIC_KEY_TEMPLATES,
+ CKA_MODULUS,
+ (CK_BYTE *)KeyParts[KMF_RSA_MODULUS].Data,
+ (CK_ULONG)KeyParts[KMF_RSA_MODULUS].Length) ||
+ !PKCS_AddTemplate(ckTemplate,
+ &ckNumTemplates,
+ MAX_PUBLIC_KEY_TEMPLATES,
+ CKA_PUBLIC_EXPONENT,
+ (CK_BYTE *)KeyParts[KMF_RSA_PUBLIC_EXPONENT].Data,
+ (CK_ULONG)KeyParts[KMF_RSA_PUBLIC_EXPONENT].Length)) {
+ mrReturn = KMF_ERR_INTERNAL;
+ goto cleanup;
+ }
+ break;
+ case CKK_DSA:
+ if (!PKCS_AddTemplate(ckTemplate,
+ &ckNumTemplates,
+ MAX_PUBLIC_KEY_TEMPLATES,
+ CKA_PRIME,
+ (CK_BYTE *)KeyParts[KMF_DSA_PRIME].Data,
+ (CK_ULONG)KeyParts[KMF_DSA_PRIME].Length) ||
+ !PKCS_AddTemplate(ckTemplate,
+ &ckNumTemplates,
+ MAX_PUBLIC_KEY_TEMPLATES,
+ CKA_SUBPRIME,
+ (CK_BYTE *)KeyParts[KMF_DSA_SUB_PRIME].Data,
+ (CK_ULONG)KeyParts[KMF_DSA_SUB_PRIME].Length) ||
+ !PKCS_AddTemplate(ckTemplate,
+ &ckNumTemplates,
+ MAX_PUBLIC_KEY_TEMPLATES,
+ CKA_BASE,
+ (CK_BYTE *)KeyParts[KMF_DSA_BASE].Data,
+ (CK_ULONG)KeyParts[KMF_DSA_BASE].Length) ||
+ !PKCS_AddTemplate(ckTemplate,
+ &ckNumTemplates,
+ MAX_PUBLIC_KEY_TEMPLATES,
+ CKA_VALUE,
+ (CK_BYTE *)KeyParts[KMF_DSA_PUBLIC_VALUE].Data,
+ (CK_ULONG)KeyParts[KMF_DSA_PUBLIC_VALUE].Length)) {
+ mrReturn = KMF_ERR_INTERNAL;
+ goto cleanup;
+ }
+ break;
+ default:
+ mrReturn = KMF_ERR_BAD_PARAMETER;
+ }
+
+ if (mrReturn == KMF_OK) {
+ /* Instantiate the object */
+ ckRv = C_CreateObject(ckSession,
+ ckTemplate,
+ ckNumTemplates,
+ pckPublicKey);
+ if (ckRv != CKR_OK)
+ mrReturn = KMF_ERR_INTERNAL;
+ }
+
+cleanup:
+ for (i = 0; i < uNumKeyParts; i++) {
+ KMF_FreeData(&KeyParts[i]);
+ }
+
+ return (mrReturn);
+}
+
+/*
+ * PKCS_AcquirePublicKeyHandle
+ *
+ * Given an assymetric key keyblob, attempts to find the appropriate
+ * public key.
+ *
+ * Methods of finding the public key:
+ * - Public Key with data present:
+ * Parses the key and creates a temporary session object.
+ * - Public Key with handle:
+ * The handle is type converted and returned. Validity of the handle is
+ * not checked.
+ * - Public Key with label:
+ * Attempts to find a public key with the corresponding label.
+ */
+static KMF_RETURN
+PKCS_AcquirePublicKeyHandle(CK_SESSION_HANDLE ckSession,
+ const KMF_X509_SPKI *pKey,
+ CK_KEY_TYPE ckRequestedKeyType,
+ CK_OBJECT_HANDLE *pckKeyHandle,
+ KMF_BOOL *pbTemporary)
+{
+ KMF_RETURN mrReturn = KMF_OK;
+
+
+ /* Key searching variables */
+ CK_OBJECT_HANDLE ckKeyHandle;
+ CK_OBJECT_CLASS ckObjClass;
+ CK_KEY_TYPE ckKeyType;
+ CK_ATTRIBUTE ckTemplate[3];
+ CK_ULONG ckNumTemplates;
+ static const CK_ULONG ckMaxTemplates = (sizeof (ckTemplate) /
+ sizeof (CK_ATTRIBUTE));
+ CK_RV ckRv;
+
+ /* Extract the data from the SPKI into individual fields */
+ mrReturn = PKCS_CreatePublicKey(pKey, ckSession, &ckKeyHandle);
+ if (mrReturn != KMF_OK)
+ return (mrReturn);
+
+ *pbTemporary = KMF_TRUE;
+
+ /* Fetch the key class and algorithm from the object */
+ ckNumTemplates = 0;
+ if (!PKCS_AddTemplate(ckTemplate,
+ &ckNumTemplates,
+ ckMaxTemplates,
+ CKA_CLASS,
+ (CK_BYTE *)&ckObjClass,
+ sizeof (ckObjClass)) ||
+ !PKCS_AddTemplate(ckTemplate,
+ &ckNumTemplates,
+ ckMaxTemplates,
+ CKA_KEY_TYPE,
+ (CK_BYTE *)&ckKeyType,
+ sizeof (ckKeyType))) {
+ return (KMF_ERR_INTERNAL);
+ }
+ ckRv = C_GetAttributeValue(ckSession,
+ ckKeyHandle,
+ ckTemplate,
+ ckNumTemplates);
+ if (ckRv != CKR_OK) {
+ return (ckRv);
+ }
+
+ /* Make sure the results match the expected values */
+ if ((ckKeyType != ckRequestedKeyType) ||
+ (ckObjClass != CKO_PUBLIC_KEY)) {
+ if (*pbTemporary == KMF_TRUE) {
+ (void) C_DestroyObject(ckSession, ckKeyHandle);
+ }
+
+ return (KMF_ERR_BAD_KEY_FORMAT);
+ }
+
+ /* Set the return values */
+ *pckKeyHandle = ckKeyHandle;
+
+ return (KMF_OK);
+}
+
+KMF_SIGNATURE_MODE
+PKCS_GetDefaultSignatureMode(KMF_ALGORITHM_INDEX AlgId)
+{
+ KMF_SIGNATURE_MODE AlgMode;
+
+ switch (AlgId) {
+ case KMF_ALGID_RSA:
+ case KMF_ALGID_MD5WithRSA:
+ case KMF_ALGID_MD2WithRSA:
+ case KMF_ALGID_SHA1WithRSA:
+ AlgMode = KMF_ALGMODE_PKCS1_EMSA_V15;
+ break;
+ default:
+ AlgMode = KMF_ALGMODE_NONE;
+ break;
+ }
+
+ return (AlgMode);
+}
+
+KMF_RETURN
+PKCS_VerifyData(KMF_HANDLE_T kmfh,
+ KMF_ALGORITHM_INDEX AlgorithmId,
+ KMF_X509_SPKI *keyp,
+ KMF_DATA *data,
+ KMF_DATA *signed_data)
+{
+ KMF_RETURN rv = KMF_OK;
+ PKCS_ALGORITHM_MAP *pAlgMap = NULL;
+ CK_RV ckRv;
+ CK_MECHANISM ckMechanism;
+ CK_OBJECT_HANDLE ckKeyHandle;
+ KMF_BOOL bTempKey;
+ CK_SESSION_HANDLE ckSession = 0;
+
+ if (AlgorithmId == KMF_ALGID_NONE)
+ return (KMF_ERR_BAD_ALGORITHM);
+
+ pAlgMap = PKCS_GetAlgorithmMap(KMF_ALGCLASS_SIGNATURE,
+ AlgorithmId, PKCS_GetDefaultSignatureMode(AlgorithmId));
+
+ if (!pAlgMap)
+ return (KMF_ERR_BAD_ALGORITHM);
+
+ rv = create_pk11_session(&ckSession, pAlgMap->pkcs_mechanism,
+ CKF_VERIFY);
+
+ if (rv != KMF_OK)
+ return (rv);
+
+ /* Fetch the verifying key */
+ rv = PKCS_AcquirePublicKeyHandle(ckSession, keyp,
+ pAlgMap->key_type, &ckKeyHandle, &bTempKey);
+
+ if (rv != KMF_OK) {
+ (void) C_CloseSession(ckSession);
+ return (rv);
+ }
+
+ ckMechanism.mechanism = pAlgMap->pkcs_mechanism;
+ ckMechanism.pParameter = NULL;
+ ckMechanism.ulParameterLen = 0;
+
+ ckRv = C_VerifyInit(ckSession, &ckMechanism, ckKeyHandle);
+ if (ckRv != CKR_OK) {
+ if (bTempKey)
+ (void) C_DestroyObject(ckSession, ckKeyHandle);
+ kmfh->lasterr.kstype = KMF_KEYSTORE_PK11TOKEN;
+ kmfh->lasterr.errcode = ckRv;
+ (void) C_CloseSession(ckSession);
+ return (KMF_ERR_INTERNAL);
+ }
+
+ ckRv = C_Verify(ckSession,
+ (CK_BYTE *)data->Data,
+ (CK_ULONG)data->Length,
+ (CK_BYTE *)signed_data->Data,
+ (CK_ULONG)signed_data->Length);
+
+ if (ckRv != CKR_OK) {
+ kmfh->lasterr.kstype = KMF_KEYSTORE_PK11TOKEN;
+ kmfh->lasterr.errcode = ckRv;
+ rv = KMF_ERR_INTERNAL;
+ }
+ if (bTempKey)
+ (void) C_DestroyObject(ckSession, ckKeyHandle);
+
+ (void) C_CloseSession(ckSession);
+ return (rv);
+
+}
+
+KMF_RETURN
+PKCS_EncryptData(KMF_HANDLE_T kmfh,
+ KMF_ALGORITHM_INDEX AlgorithmId,
+ KMF_X509_SPKI *keyp,
+ KMF_DATA *plaintext,
+ KMF_DATA *ciphertext)
+{
+ KMF_RETURN rv = KMF_OK;
+ PKCS_ALGORITHM_MAP *pAlgMap = NULL;
+ CK_RV ckRv;
+ CK_MECHANISM ckMechanism;
+ CK_OBJECT_HANDLE ckKeyHandle;
+ KMF_BOOL bTempKey;
+ CK_SESSION_HANDLE ckSession = NULL;
+ CK_ULONG out_len = 0, in_len = 0, total_encrypted = 0;
+ uint8_t *in_data, *out_data;
+ int i, blocks, block_size;
+ CK_ATTRIBUTE ckTemplate[2];
+ CK_ULONG ckNumTemplates;
+ CK_ULONG ckMaxTemplates = (sizeof (ckTemplate) /
+ sizeof (CK_ATTRIBUTE));
+
+ pAlgMap = PKCS_GetAlgorithmMap(KMF_ALGCLASS_SIGNATURE,
+ AlgorithmId, PKCS_GetDefaultSignatureMode(AlgorithmId));
+
+ if (!pAlgMap)
+ return (KMF_ERR_BAD_ALGORITHM);
+
+ rv = create_pk11_session(&ckSession, pAlgMap->pkcs_mechanism,
+ CKF_ENCRYPT);
+
+ if (rv != KMF_OK)
+ return (rv);
+
+ /* Get the public key used in encryption */
+ rv = PKCS_AcquirePublicKeyHandle(ckSession, keyp,
+ pAlgMap->key_type, &ckKeyHandle, &bTempKey);
+
+ if (rv != KMF_OK) {
+ (void) C_CloseSession(ckSession);
+ return (rv);
+ }
+
+ /* Get the modulus length */
+ ckNumTemplates = 0;
+ if (!PKCS_AddTemplate(ckTemplate,
+ &ckNumTemplates,
+ ckMaxTemplates,
+ CKA_MODULUS,
+ (CK_BYTE *)NULL,
+ sizeof (CK_ULONG))) {
+ if (bTempKey)
+ (void) C_DestroyObject(ckSession, ckKeyHandle);
+ (void) C_CloseSession(ckSession);
+ return (KMF_ERR_INTERNAL);
+ }
+
+ ckRv = C_GetAttributeValue(ckSession,
+ ckKeyHandle,
+ ckTemplate,
+ ckNumTemplates);
+
+ if (ckRv != CKR_OK) {
+ if (bTempKey)
+ (void) C_DestroyObject(ckSession, ckKeyHandle);
+ kmfh->lasterr.kstype = KMF_KEYSTORE_PK11TOKEN;
+ kmfh->lasterr.errcode = ckRv;
+ (void) C_CloseSession(ckSession);
+ return (KMF_ERR_INTERNAL);
+ }
+ out_len = ckTemplate[0].ulValueLen;
+
+ if (out_len > ciphertext->Length) {
+ if (bTempKey)
+ (void) C_DestroyObject(ckSession, ckKeyHandle);
+ (void) C_CloseSession(ckSession);
+ return (KMF_ERR_BUFFER_SIZE);
+ }
+
+ ckMechanism.mechanism = pAlgMap->pkcs_mechanism;
+ ckMechanism.pParameter = NULL_PTR;
+ ckMechanism.ulParameterLen = 0;
+
+ /* Compute the fixed input data length for single-part encryption */
+ block_size = out_len - 11;
+
+ in_data = plaintext->Data;
+ out_data = ciphertext->Data;
+
+ blocks = plaintext->Length/block_size;
+
+ for (i = 0; i < blocks; i++) {
+ ckRv = C_EncryptInit(ckSession, &ckMechanism, ckKeyHandle);
+ if (ckRv != CKR_OK) {
+ if (bTempKey)
+ (void) C_DestroyObject(ckSession, ckKeyHandle);
+ kmfh->lasterr.kstype = KMF_KEYSTORE_PK11TOKEN;
+ kmfh->lasterr.errcode = ckRv;
+ (void) C_CloseSession(ckSession);
+ return (KMF_ERR_INTERNAL);
+ }
+ ckRv = C_Encrypt(ckSession, (CK_BYTE_PTR)in_data, block_size,
+ (CK_BYTE_PTR)out_data, &out_len);
+
+ if (ckRv != CKR_OK) {
+ if (bTempKey)
+ (void) C_DestroyObject(ckSession, ckKeyHandle);
+ kmfh->lasterr.kstype = KMF_KEYSTORE_PK11TOKEN;
+ kmfh->lasterr.errcode = ckRv;
+ (void) C_CloseSession(ckSession);
+ return (KMF_ERR_INTERNAL);
+ }
+
+ out_data += out_len;
+ total_encrypted += out_len;
+ in_data += block_size;
+ }
+
+ if (plaintext->Length % block_size) {
+ /* Encrypt the remaining data */
+ ckRv = C_EncryptInit(ckSession, &ckMechanism, ckKeyHandle);
+ if (ckRv != CKR_OK) {
+ if (bTempKey)
+ (void) C_DestroyObject(ckSession, ckKeyHandle);
+ kmfh->lasterr.kstype = KMF_KEYSTORE_PK11TOKEN;
+ kmfh->lasterr.errcode = ckRv;
+ (void) C_CloseSession(ckSession);
+ return (KMF_ERR_INTERNAL);
+ }
+
+ in_len = plaintext->Length % block_size;
+ ckRv = C_Encrypt(ckSession, (CK_BYTE_PTR)in_data, in_len,
+ (CK_BYTE_PTR)out_data, &out_len);
+
+ if (ckRv != CKR_OK) {
+ if (bTempKey)
+ (void) C_DestroyObject(ckSession, ckKeyHandle);
+ kmfh->lasterr.kstype = KMF_KEYSTORE_PK11TOKEN;
+ kmfh->lasterr.errcode = ckRv;
+ (void) C_CloseSession(ckSession);
+ return (KMF_ERR_INTERNAL);
+ }
+
+ out_data += out_len;
+ total_encrypted += out_len;
+ in_data += in_len;
+ }
+
+ ciphertext->Length = total_encrypted;
+
+ if (bTempKey)
+ (void) C_DestroyObject(ckSession, ckKeyHandle);
+
+ (void) C_CloseSession(ckSession);
+ return (rv);
+
+}
+
+CK_RV
+DigestData(CK_SESSION_HANDLE hSession,
+ KMF_DATA *IDInput, KMF_DATA *IDOutput)
+{
+ CK_RV rv = KMF_OK;
+ CK_MECHANISM mechanism = {CKM_SHA_1, NULL, 0};
+
+ rv = C_DigestInit(hSession, &mechanism);
+ if (rv != CKR_OK)
+ return (rv);
+
+ rv = C_Digest(hSession,
+ IDInput->Data, IDInput->Length,
+ IDOutput->Data, (CK_ULONG *)&IDOutput->Length);
+
+ return (rv);
+}
+
+KMF_RETURN
+GetIDFromSPKI(KMF_X509_SPKI *spki,
+ KMF_DATA *ID)
+{
+ KMF_RETURN rv = KMF_OK;
+ KMF_DATA KeyParts[KMF_MAX_PUBLIC_KEY_PARTS];
+ uint32_t uNumKeyParts = KMF_MAX_PUBLIC_KEY_PARTS;
+ KMF_ALGORITHM_INDEX algId;
+ CK_SESSION_HANDLE hSession = NULL;
+ int i;
+
+ if (ID == NULL || spki == NULL)
+ return (KMF_ERR_BAD_PARAMETER);
+
+ ID->Data = (uchar_t *)malloc(SHA1_HASH_LENGTH);
+ if (ID->Data == NULL)
+ return (KMF_ERR_MEMORY);
+
+ ID->Length = SHA1_HASH_LENGTH;
+
+ algId = X509_AlgorithmOidToAlgId(&spki->algorithm.algorithm);
+
+ rv = ExtractSPKIData(spki, algId, KeyParts, &uNumKeyParts);
+ if (rv != KMF_OK)
+ return (rv);
+
+ rv = create_pk11_session(&hSession, CKM_SHA_1, CKF_DIGEST);
+
+ if (rv != KMF_OK)
+ return (rv);
+
+ /* Check the KEY algorithm */
+ if (algId == KMF_ALGID_RSA) {
+ rv = DigestData(hSession,
+ &KeyParts[KMF_RSA_MODULUS],
+ ID);
+ } else if (algId == KMF_ALGID_DSA) {
+ rv = DigestData(hSession,
+ &KeyParts[KMF_DSA_PUBLIC_VALUE],
+ ID);
+ } else {
+ /* We only support RSA and DSA keys for now */
+ rv = KMF_ERR_BAD_ALGORITHM;
+ }
+
+
+ for (i = 0; i < uNumKeyParts; i++) {
+ if (KeyParts[i].Data != NULL)
+ free(KeyParts[i].Data);
+ }
+
+ if (rv != KMF_OK && ID->Data != NULL) {
+ free(ID->Data);
+ ID->Data = NULL;
+ ID->Length = 0;
+ }
+
+ (void) C_CloseSession(hSession);
+ return (rv);
+}