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