pk11keys.c revision 9a7670889e9c36ec355371e6b02f2d9084f040dc
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw/*
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Use is subject to license terms.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw/*
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Copyright (c) 1995-2000 Intel Corporation. All rights reserved.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw#pragma ident "%Z%%M% %I% %E% SMI"
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw#include <kmfapiP.h>
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw#include <security/cryptoki.h>
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw#include <algorithm.h>
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw#include <ber_der.h>
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw#define MAX_PUBLIC_KEY_TEMPLATES (20)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw#define MAX_PRIVATE_KEY_TEMPLATES (24)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw#define MAX_SECRET_KEY_TEMPLATES (24)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwstatic KMF_RETURN
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwcreate_pk11_session(CK_SESSION_HANDLE *sessionp, CK_MECHANISM_TYPE wanted_mech,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw CK_FLAGS wanted_flags)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw{
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw CK_RV rv;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw KMF_RETURN kmf_rv = KMF_OK;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw CK_SLOT_ID_PTR pSlotList;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw CK_ULONG pulCount;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw CK_MECHANISM_INFO info;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw int i;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (!is_pk11_ready()) {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw rv = C_Initialize(NULL);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if ((rv != CKR_OK) &&
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw (rv != CKR_CRYPTOKI_ALREADY_INITIALIZED)) {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw kmf_rv = KMF_ERR_UNINITIALIZED;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw goto out;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw rv = C_GetSlotList(0, NULL, &pulCount);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (rv != CKR_OK) {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw kmf_rv = KMF_ERR_UNINITIALIZED;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw goto out;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw pSlotList = (CK_SLOT_ID_PTR) malloc(pulCount * sizeof (CK_SLOT_ID));
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (pSlotList == NULL) {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw kmf_rv = KMF_ERR_MEMORY;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw goto out;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw rv = C_GetSlotList(0, pSlotList, &pulCount);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (rv != CKR_OK) {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw kmf_rv = KMF_ERR_UNINITIALIZED;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw goto out;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw for (i = 0; i < pulCount; i++) {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw rv = C_GetMechanismInfo(pSlotList[i], wanted_mech, &info);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (rv == CKR_OK && (info.flags & wanted_flags))
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw break;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (i < pulCount) {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw rv = C_OpenSession(pSlotList[i], CKF_SERIAL_SESSION,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw NULL, NULL, sessionp);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (rv != CKR_OK) {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw kmf_rv = KMF_ERR_UNINITIALIZED;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw } else {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw kmf_rv = KMF_ERR_UNINITIALIZED;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwout:
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (pSlotList != NULL)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw free(pSlotList);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return (kmf_rv);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw}
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw/*
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Name: PKCS_AddTemplate
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw *
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Description:
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Adds a CK_ATTRIBUTE value to an existing array of CK_ATTRIBUTES. Will
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * not expand the array beyond the maximum specified size.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw *
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Returns:
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * TRUE - Attribute value succesfully added.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * FALSE - Maximum array size would be exceded.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwstatic int
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwPKCS_AddTemplate(CK_ATTRIBUTE *pTemplate,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw CK_ULONG *ckNumTemplates,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw CK_ULONG ckMaxTemplates,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw CK_ATTRIBUTE_TYPE ckAttribCode,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw CK_BYTE * pckBuffer,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw CK_ULONG ckBufferLen)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw{
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (*ckNumTemplates >= ckMaxTemplates) {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return (FALSE);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw pTemplate[*ckNumTemplates].type = ckAttribCode;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw pTemplate[*ckNumTemplates].pValue = pckBuffer;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw pTemplate[*ckNumTemplates].ulValueLen = ckBufferLen;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw (*ckNumTemplates)++;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return (TRUE);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw}
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw/*
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Convert an SPKI data record to PKCS#11
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * public key object.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwstatic KMF_RETURN
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwPKCS_CreatePublicKey(
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw const KMF_X509_SPKI *pKey,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw CK_SESSION_HANDLE ckSession,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw CK_OBJECT_HANDLE *pckPublicKey)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw{
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw KMF_RETURN mrReturn = KMF_OK;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw CK_RV ckRv;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw CK_ATTRIBUTE ckTemplate[MAX_PUBLIC_KEY_TEMPLATES];
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw CK_ULONG ckNumTemplates = 0;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw /* Common object attributes */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw CK_OBJECT_CLASS ckObjClass = CKO_PUBLIC_KEY;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw CK_BBOOL ckToken = 0;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw CK_BBOOL ckPrivate = 0;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw /* Common key attributes */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw CK_KEY_TYPE ckKeyType;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw CK_BBOOL ckDerive = CK_FALSE;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw /* Common public key attributes */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw CK_BBOOL ckEncrypt = 1;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw CK_BBOOL ckVerify = 1;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw CK_BBOOL ckVerifyRecover = CK_FALSE;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw CK_BBOOL ckWrap = CK_FALSE;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw /* Key part array */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw KMF_DATA KeyParts[KMF_MAX_PUBLIC_KEY_PARTS];
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw uint32_t i, uNumKeyParts = KMF_MAX_PUBLIC_KEY_PARTS;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw KMF_ALGORITHM_INDEX AlgorithmId;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw /* Parse the keyblob */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw (void) memset(KeyParts, 0, sizeof (KeyParts));
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw AlgorithmId = X509_AlgorithmOidToAlgId((KMF_OID *)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw &pKey->algorithm.algorithm);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw mrReturn = ExtractSPKIData(pKey, AlgorithmId, KeyParts, &uNumKeyParts);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (mrReturn != KMF_OK)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return (mrReturn);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw /* Fill in the common object attributes */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (!PKCS_AddTemplate(ckTemplate,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw &ckNumTemplates,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw MAX_PUBLIC_KEY_TEMPLATES,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw CKA_CLASS,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw (CK_BYTE *)&ckObjClass,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw sizeof (ckObjClass)) ||
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw !PKCS_AddTemplate(ckTemplate,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw &ckNumTemplates,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw MAX_PUBLIC_KEY_TEMPLATES,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw CKA_TOKEN,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw (CK_BYTE *)&ckToken,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw sizeof (ckToken)) ||
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw !PKCS_AddTemplate(ckTemplate,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw &ckNumTemplates,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw MAX_PUBLIC_KEY_TEMPLATES,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw CKA_PRIVATE,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw (CK_BYTE *)&ckPrivate,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw sizeof (ckPrivate))) {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw mrReturn = KMF_ERR_INTERNAL;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw goto cleanup;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw /* Fill in the common key attributes */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (!PKCS_ConvertAlgorithmId2PKCSKeyType(AlgorithmId,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw &ckKeyType)) {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw goto cleanup;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (!PKCS_AddTemplate(ckTemplate,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw &ckNumTemplates,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw MAX_PUBLIC_KEY_TEMPLATES,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw CKA_KEY_TYPE,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw (CK_BYTE *)&ckKeyType,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw sizeof (ckKeyType)) ||
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw !PKCS_AddTemplate(ckTemplate,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw &ckNumTemplates,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw MAX_PUBLIC_KEY_TEMPLATES,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw CKA_DERIVE,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw (CK_BYTE *)&ckDerive,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw sizeof (ckDerive))) {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw mrReturn = KMF_ERR_INTERNAL;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw goto cleanup;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw /* Add common public key attributes */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (!PKCS_AddTemplate(ckTemplate,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw &ckNumTemplates,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw MAX_PUBLIC_KEY_TEMPLATES,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw CKA_ENCRYPT,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw (CK_BYTE *)&ckEncrypt,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw sizeof (ckEncrypt)) ||
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw !PKCS_AddTemplate(ckTemplate,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw &ckNumTemplates,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw MAX_PUBLIC_KEY_TEMPLATES,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw CKA_VERIFY,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw (CK_BYTE *)&ckVerify,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw sizeof (ckVerify)) ||
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw !PKCS_AddTemplate(ckTemplate,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw &ckNumTemplates,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw MAX_PUBLIC_KEY_TEMPLATES,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw CKA_VERIFY_RECOVER,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw (CK_BYTE *)&ckVerifyRecover,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw sizeof (ckVerifyRecover)) ||
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw !PKCS_AddTemplate(ckTemplate,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw &ckNumTemplates,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw MAX_PUBLIC_KEY_TEMPLATES,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw CKA_WRAP,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw (CK_BYTE *)&ckWrap,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw sizeof (ckWrap))) {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw mrReturn = KMF_ERR_INTERNAL;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw 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);
}