pkcs11.c (207574B)
1 /* This Source Code Form is subject to the terms of the Mozilla Public 2 * License, v. 2.0. If a copy of the MPL was not distributed with this 3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 /* 5 * This file implements PKCS 11 on top of our existing security modules 6 * 7 * For more information about PKCS 11 See PKCS 11 Token Inteface Standard. 8 * This implementation has two slots: 9 * slot 1 is our generic crypto support. It does not require login. 10 * It supports Public Key ops, and all they bulk ciphers and hashes. 11 * It can also support Private Key ops for imported Private keys. It does 12 * not have any token storage. 13 * slot 2 is our private key support. It requires a login before use. It 14 * can store Private Keys and Certs as token objects. Currently only private 15 * keys and their associated Certificates are saved on the token. 16 * 17 * In this implementation, session objects are only visible to the session 18 * that created or generated them. 19 */ 20 #include "seccomon.h" 21 #include "secitem.h" 22 /* we need to use the deprecated mechanisms values for backward compatibility */ 23 #include "pkcs11.h" 24 #include "pkcs11i.h" 25 #include "softoken.h" 26 #include "lowkeyi.h" 27 #include "blapi.h" 28 #include "secder.h" 29 #include "secport.h" 30 #include "secrng.h" 31 #include "prtypes.h" 32 #include "nspr.h" 33 #include "softkver.h" 34 #include "secoid.h" 35 #include "sftkdb.h" 36 #include "utilpars.h" 37 #include "ec.h" 38 #include "secasn1.h" 39 #include "secerr.h" 40 #include "lgglue.h" 41 #include "kem.h" 42 43 PRBool parentForkedAfterC_Initialize; 44 45 #ifndef NO_FORK_CHECK 46 47 PRBool sftkForkCheckDisabled; 48 49 #if defined(CHECK_FORK_PTHREAD) || defined(CHECK_FORK_MIXED) 50 PRBool forked = PR_FALSE; 51 #endif 52 53 #if defined(CHECK_FORK_GETPID) || defined(CHECK_FORK_MIXED) 54 #include <unistd.h> 55 pid_t myPid; 56 #endif 57 58 #ifdef CHECK_FORK_MIXED 59 #include <sys/systeminfo.h> 60 PRBool usePthread_atfork; 61 #endif 62 63 #endif 64 65 #ifdef XP_UNIX 66 #define LIB_PARAM_DEFAULT_FILE_LOCATION "/etc/nss/params.config" 67 #endif 68 69 #define LIB_PARAM_DEFAULT " configdir='' certPrefix='' keyPrefix='' secmod='' flags=noCertDB,noModDB " 70 /* 71 * ******************** Static data ******************************* 72 */ 73 74 /* The next three strings must be exactly 32 characters long */ 75 static char *manufacturerID = "Mozilla Foundation "; 76 static char manufacturerID_space[33]; 77 static char *libraryDescription = "NSS Internal Crypto Services "; 78 static char libraryDescription_space[33]; 79 80 /* 81 * In FIPS mode, we disallow login attempts for 1 second after a login 82 * failure so that there are at most 60 login attempts per minute. 83 */ 84 static PRIntervalTime loginWaitTime; 85 86 #undef __PASTE 87 #define __PASTE(x, y) x##y 88 89 /* 90 * we renamed all our internal functions, get the correct 91 * definitions for them... 92 */ 93 #undef CK_PKCS11_FUNCTION_INFO 94 #undef CK_NEED_ARG_LIST 95 96 #define CK_PKCS11_3_2 1 97 #define CK_PKCS11_3_0 1 98 #define CK_EXTERN extern 99 #define CK_PKCS11_FUNCTION_INFO(func) \ 100 CK_RV __PASTE(NS, func) 101 #define CK_NEED_ARG_LIST 1 102 103 #include "pkcs11f.h" 104 105 #ifndef NSS_FIPS_DISABLE 106 /* ------------- forward declare all the FIPS functions ------------- */ 107 #undef CK_NEED_ARG_LIST 108 #undef CK_PKCS11_FUNCTION_INFO 109 110 #define CK_PKCS11_FUNCTION_INFO(name) CK_RV __PASTE(F, name) 111 #define CK_NEED_ARG_LIST 1 112 113 #include "pkcs11f.h" 114 #endif 115 116 /* build the crypto module table */ 117 static CK_FUNCTION_LIST_3_2 sftk_funcList_v32 = { 118 { 3, 2 }, 119 120 #undef CK_PKCS11_FUNCTION_INFO 121 #undef CK_NEED_ARG_LIST 122 123 #define CK_PKCS11_3_2_ONLY 1 124 #define CK_PKCS11_FUNCTION_INFO(func) \ 125 __PASTE(NS, func) \ 126 , 127 #include "pkcs11f.h" 128 129 }; 130 #undef CK_PKCS11_3_2_ONLY 131 132 /* build the crypto module table */ 133 static CK_FUNCTION_LIST_3_0 sftk_funcList_v30 = { 134 { 3, 0 }, 135 136 #undef CK_PKCS11_FUNCTION_INFO 137 #undef CK_NEED_ARG_LIST 138 139 #define CK_PKCS11_3_0_ONLY 1 140 #define CK_PKCS11_FUNCTION_INFO(func) \ 141 __PASTE(NS, func) \ 142 , 143 #include "pkcs11f.h" 144 145 }; 146 #undef CK_PKCS11_3_0_ONLY 147 148 /* need a special version of get info for version 2 which returns the version 149 * 2.4 version number */ 150 CK_RV NSC_GetInfoV2(CK_INFO_PTR pInfo); 151 CK_RV NSC_GetMechanismInfoV2(CK_SLOT_ID slotID, CK_MECHANISM_TYPE type, 152 CK_MECHANISM_INFO_PTR pInfo); 153 154 /* build the crypto module table */ 155 static CK_FUNCTION_LIST sftk_funcList_v2 = { 156 { 2, 40 }, 157 158 #define CK_PKCS11_2_0_ONLY 1 159 #undef CK_PKCS11_FUNCTION_INFO 160 #undef CK_NEED_ARG_LIST 161 #define C_GetInfo C_GetInfoV2 162 #define C_GetMechanismInfo C_GetMechanismInfoV2 163 164 #define CK_PKCS11_FUNCTION_INFO(func) \ 165 __PASTE(NS, func) \ 166 , 167 #include "pkcs11f.h" 168 169 }; 170 171 #undef C_GetInfo 172 #undef C_GetMechanismInfo 173 #undef CK_PKCS_11_2_0_ONLY 174 #undef CK_PKCS11_FUNCTION_INFO 175 #undef CK_NEED_ARG_LIST 176 177 #undef __PASTE 178 179 CK_NSS_MODULE_FUNCTIONS sftk_module_funcList = { 180 { 1, 0 }, 181 NSC_ModuleDBFunc 182 }; 183 184 static CK_RV 185 nsc_NSSGetFIPSStatus(CK_SESSION_HANDLE hSession, 186 CK_OBJECT_HANDLE hObject, 187 CK_ULONG ulOperationType, 188 CK_ULONG *pulFIPSStatus); 189 CK_NSS_FIPS_FUNCTIONS sftk_fips_funcList = { 190 { 1, 0 }, 191 nsc_NSSGetFIPSStatus 192 }; 193 194 CK_NSS_KEM_FUNCTIONS sftk_kem_funcList = { 195 { 1, 0 }, 196 NSC_Encapsulate, 197 NSC_Decapsulate 198 }; 199 200 /* 201 * Array is orderd by default first 202 */ 203 static CK_INTERFACE nss_interfaces[] = { 204 { (CK_UTF8CHAR_PTR) "PKCS 11", &sftk_funcList_v32, NSS_INTERFACE_FLAGS }, 205 { (CK_UTF8CHAR_PTR) "PKCS 11", &sftk_funcList_v30, NSS_INTERFACE_FLAGS }, 206 { (CK_UTF8CHAR_PTR) "PKCS 11", &sftk_funcList_v2, NSS_INTERFACE_FLAGS }, 207 { (CK_UTF8CHAR_PTR) "Vendor NSS Module Interface", &sftk_module_funcList, NSS_INTERFACE_FLAGS }, 208 { (CK_UTF8CHAR_PTR) "Vendor NSS FIPS Interface", &sftk_fips_funcList, NSS_INTERFACE_FLAGS }, 209 { (CK_UTF8CHAR_PTR) "Vendor NSS KEM Interface", &sftk_kem_funcList, NSS_INTERFACE_FLAGS } 210 }; 211 /* must match the count of interfaces in nss_interfaces above */ 212 #define NSS_INTERFACE_COUNT PR_ARRAY_SIZE(nss_interfaces) 213 214 /* List of DES Weak Keys */ 215 typedef unsigned char desKey[8]; 216 static const desKey sftk_desWeakTable[] = { 217 #ifdef noParity 218 /* weak */ 219 { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, 220 { 0x1e, 0x1e, 0x1e, 0x1e, 0x0e, 0x0e, 0x0e, 0x0e }, 221 { 0xe0, 0xe0, 0xe0, 0xe0, 0xf0, 0xf0, 0xf0, 0xf0 }, 222 { 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe }, 223 /* semi-weak */ 224 { 0x00, 0xfe, 0x00, 0xfe, 0x00, 0xfe, 0x00, 0xfe }, 225 { 0xfe, 0x00, 0xfe, 0x00, 0x00, 0xfe, 0x00, 0xfe }, 226 227 { 0x1e, 0xe0, 0x1e, 0xe0, 0x0e, 0xf0, 0x0e, 0xf0 }, 228 { 0xe0, 0x1e, 0xe0, 0x1e, 0xf0, 0x0e, 0xf0, 0x0e }, 229 230 { 0x00, 0xe0, 0x00, 0xe0, 0x00, 0x0f, 0x00, 0x0f }, 231 { 0xe0, 0x00, 0xe0, 0x00, 0xf0, 0x00, 0xf0, 0x00 }, 232 233 { 0x1e, 0xfe, 0x1e, 0xfe, 0x0e, 0xfe, 0x0e, 0xfe }, 234 { 0xfe, 0x1e, 0xfe, 0x1e, 0xfe, 0x0e, 0xfe, 0x0e }, 235 236 { 0x00, 0x1e, 0x00, 0x1e, 0x00, 0x0e, 0x00, 0x0e }, 237 { 0x1e, 0x00, 0x1e, 0x00, 0x0e, 0x00, 0x0e, 0x00 }, 238 239 { 0xe0, 0xfe, 0xe0, 0xfe, 0xf0, 0xfe, 0xf0, 0xfe }, 240 { 0xfe, 0xe0, 0xfe, 0xe0, 0xfe, 0xf0, 0xfe, 0xf0 }, 241 #else 242 /* weak */ 243 { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, 244 { 0x1f, 0x1f, 0x1f, 0x1f, 0x0e, 0x0e, 0x0e, 0x0e }, 245 { 0xe0, 0xe0, 0xe0, 0xe0, 0xf1, 0xf1, 0xf1, 0xf1 }, 246 { 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe }, 247 248 /* semi-weak */ 249 { 0x01, 0xfe, 0x01, 0xfe, 0x01, 0xfe, 0x01, 0xfe }, 250 { 0xfe, 0x01, 0xfe, 0x01, 0xfe, 0x01, 0xfe, 0x01 }, 251 252 { 0x1f, 0xe0, 0x1f, 0xe0, 0x0e, 0xf1, 0x0e, 0xf1 }, 253 { 0xe0, 0x1f, 0xe0, 0x1f, 0xf1, 0x0e, 0xf1, 0x0e }, 254 255 { 0x01, 0xe0, 0x01, 0xe0, 0x01, 0xf1, 0x01, 0xf1 }, 256 { 0xe0, 0x01, 0xe0, 0x01, 0xf1, 0x01, 0xf1, 0x01 }, 257 258 { 0x1f, 0xfe, 0x1f, 0xfe, 0x0e, 0xfe, 0x0e, 0xfe }, 259 { 0xfe, 0x1f, 0xfe, 0x1f, 0xfe, 0x0e, 0xfe, 0x0e }, 260 261 { 0x01, 0x1f, 0x01, 0x1f, 0x01, 0x0e, 0x01, 0x0e }, 262 { 0x1f, 0x01, 0x1f, 0x01, 0x0e, 0x01, 0x0e, 0x01 }, 263 264 { 0xe0, 0xfe, 0xe0, 0xfe, 0xf1, 0xfe, 0xf1, 0xfe }, 265 { 0xfe, 0xe0, 0xfe, 0xe0, 0xfe, 0xf1, 0xfe, 0xf1 } 266 #endif 267 }; 268 269 static const int sftk_desWeakTableSize = sizeof(sftk_desWeakTable) / 270 sizeof(sftk_desWeakTable[0]); 271 272 /* DES KEY Parity conversion table. Takes each byte/2 as an index, returns 273 * that byte with the proper parity bit set */ 274 static const unsigned char parityTable[256] = { 275 /* Even...0x00,0x02,0x04,0x06,0x08,0x0a,0x0c,0x0e */ 276 /* E */ 0x01, 0x02, 0x04, 0x07, 0x08, 0x0b, 0x0d, 0x0e, 277 /* Odd....0x10,0x12,0x14,0x16,0x18,0x1a,0x1c,0x1e */ 278 /* O */ 0x10, 0x13, 0x15, 0x16, 0x19, 0x1a, 0x1c, 0x1f, 279 /* Odd....0x20,0x22,0x24,0x26,0x28,0x2a,0x2c,0x2e */ 280 /* O */ 0x20, 0x23, 0x25, 0x26, 0x29, 0x2a, 0x2c, 0x2f, 281 /* Even...0x30,0x32,0x34,0x36,0x38,0x3a,0x3c,0x3e */ 282 /* E */ 0x31, 0x32, 0x34, 0x37, 0x38, 0x3b, 0x3d, 0x3e, 283 /* Odd....0x40,0x42,0x44,0x46,0x48,0x4a,0x4c,0x4e */ 284 /* O */ 0x40, 0x43, 0x45, 0x46, 0x49, 0x4a, 0x4c, 0x4f, 285 /* Even...0x50,0x52,0x54,0x56,0x58,0x5a,0x5c,0x5e */ 286 /* E */ 0x51, 0x52, 0x54, 0x57, 0x58, 0x5b, 0x5d, 0x5e, 287 /* Even...0x60,0x62,0x64,0x66,0x68,0x6a,0x6c,0x6e */ 288 /* E */ 0x61, 0x62, 0x64, 0x67, 0x68, 0x6b, 0x6d, 0x6e, 289 /* Odd....0x70,0x72,0x74,0x76,0x78,0x7a,0x7c,0x7e */ 290 /* O */ 0x70, 0x73, 0x75, 0x76, 0x79, 0x7a, 0x7c, 0x7f, 291 /* Odd....0x80,0x82,0x84,0x86,0x88,0x8a,0x8c,0x8e */ 292 /* O */ 0x80, 0x83, 0x85, 0x86, 0x89, 0x8a, 0x8c, 0x8f, 293 /* Even...0x90,0x92,0x94,0x96,0x98,0x9a,0x9c,0x9e */ 294 /* E */ 0x91, 0x92, 0x94, 0x97, 0x98, 0x9b, 0x9d, 0x9e, 295 /* Even...0xa0,0xa2,0xa4,0xa6,0xa8,0xaa,0xac,0xae */ 296 /* E */ 0xa1, 0xa2, 0xa4, 0xa7, 0xa8, 0xab, 0xad, 0xae, 297 /* Odd....0xb0,0xb2,0xb4,0xb6,0xb8,0xba,0xbc,0xbe */ 298 /* O */ 0xb0, 0xb3, 0xb5, 0xb6, 0xb9, 0xba, 0xbc, 0xbf, 299 /* Even...0xc0,0xc2,0xc4,0xc6,0xc8,0xca,0xcc,0xce */ 300 /* E */ 0xc1, 0xc2, 0xc4, 0xc7, 0xc8, 0xcb, 0xcd, 0xce, 301 /* Odd....0xd0,0xd2,0xd4,0xd6,0xd8,0xda,0xdc,0xde */ 302 /* O */ 0xd0, 0xd3, 0xd5, 0xd6, 0xd9, 0xda, 0xdc, 0xdf, 303 /* Odd....0xe0,0xe2,0xe4,0xe6,0xe8,0xea,0xec,0xee */ 304 /* O */ 0xe0, 0xe3, 0xe5, 0xe6, 0xe9, 0xea, 0xec, 0xef, 305 /* Even...0xf0,0xf2,0xf4,0xf6,0xf8,0xfa,0xfc,0xfe */ 306 /* E */ 0xf1, 0xf2, 0xf4, 0xf7, 0xf8, 0xfb, 0xfd, 0xfe 307 }; 308 309 /* Mechanisms */ 310 struct mechanismList { 311 CK_MECHANISM_TYPE type; 312 CK_MECHANISM_INFO info; 313 PRBool privkey; 314 }; 315 316 /* 317 * the following table includes a complete list of mechanism defined by 318 * PKCS #11 version 2.01. Those Mechanisms not supported by this PKCS #11 319 * module are ifdef'ed out. 320 */ 321 #define CKF_EN_DE CKF_ENCRYPT | CKF_DECRYPT 322 #define CKF_WR_UN CKF_WRAP | CKF_UNWRAP 323 #define CKF_SN_VR CKF_SIGN | CKF_VERIFY 324 #define CKF_SN_RE CKF_SIGN_RECOVER | CKF_VERIFY_RECOVER 325 #define CKF_EN_DE_MSG CKF_ENCRYPT | CKF_DECRYPT | CKF_MESSAGE_ENCRYPT | CKF_MESSAGE_DECRYPT 326 #define CKF_KEM CKF_ENCAPSULATE | CKF_DECAPSULATE 327 328 #define CKF_EN_DE_WR_UN CKF_EN_DE | CKF_WR_UN 329 #define CKF_SN_VR_RE CKF_SN_VR | CKF_SN_RE 330 #define CKF_DUZ_IT_ALL CKF_EN_DE_WR_UN | CKF_SN_VR_RE 331 332 #define CKF_EC_PNU CKF_EC_F_P | CKF_EC_NAMEDCURVE | CKF_EC_UNCOMPRESS 333 334 #define CKF_EC_BPNU CKF_EC_F_2M | CKF_EC_PNU 335 #define CKF_EC_POC CKF_EC_F_P | CKF_EC_OID | CKF_EC_COMPRESS 336 337 #define CK_MAX 0xffffffff 338 339 static const struct mechanismList mechanisms[] = { 340 341 /* 342 * PKCS #11 Mechanism List. 343 * 344 * The first argument is the PKCS #11 Mechanism we support. 345 * The second argument is Mechanism info structure. It includes: 346 * The minimum key size, 347 * in bits for RSA, DSA, DH, EC*, KEA, RC2 and RC4 * algs. 348 * in bytes for RC5, AES, Camellia, and CAST* 349 * ignored for DES*, IDEA and FORTEZZA based 350 * The maximum key size, 351 * in bits for RSA, DSA, DH, EC*, KEA, RC2 and RC4 * algs. 352 * in bytes for RC5, AES, Camellia, and CAST* 353 * ignored for DES*, IDEA and FORTEZZA based 354 * Flags 355 * What operations are supported by this mechanism. 356 * The third argument is a bool which tells if this mechanism is 357 * supported in the database token. 358 * 359 */ 360 361 /* ------------------------- RSA Operations ---------------------------*/ 362 { CKM_RSA_PKCS_KEY_PAIR_GEN, { RSA_MIN_MODULUS_BITS, CK_MAX, CKF_GENERATE_KEY_PAIR }, PR_TRUE }, 363 { CKM_RSA_PKCS, { RSA_MIN_MODULUS_BITS, CK_MAX, CKF_DUZ_IT_ALL }, PR_TRUE }, 364 { CKM_RSA_PKCS_PSS, { RSA_MIN_MODULUS_BITS, CK_MAX, CKF_SN_VR }, PR_TRUE }, 365 { CKM_RSA_PKCS_OAEP, { RSA_MIN_MODULUS_BITS, CK_MAX, CKF_EN_DE_WR_UN }, PR_TRUE }, 366 #ifdef SFTK_RSA9796_SUPPORTED 367 { CKM_RSA_9796, { RSA_MIN_MODULUS_BITS, CK_MAX, CKF_DUZ_IT_ALL }, PR_TRUE }, 368 #endif 369 { CKM_RSA_X_509, { RSA_MIN_MODULUS_BITS, CK_MAX, CKF_DUZ_IT_ALL }, PR_TRUE }, 370 /* -------------- RSA Multipart Signing Operations -------------------- */ 371 { CKM_MD2_RSA_PKCS, { RSA_MIN_MODULUS_BITS, CK_MAX, CKF_SN_VR }, PR_TRUE }, 372 { CKM_MD5_RSA_PKCS, { RSA_MIN_MODULUS_BITS, CK_MAX, CKF_SN_VR }, PR_TRUE }, 373 { CKM_SHA1_RSA_PKCS, { RSA_MIN_MODULUS_BITS, CK_MAX, CKF_SN_VR }, PR_TRUE }, 374 { CKM_SHA224_RSA_PKCS, { RSA_MIN_MODULUS_BITS, CK_MAX, CKF_SN_VR }, PR_TRUE }, 375 { CKM_SHA256_RSA_PKCS, { RSA_MIN_MODULUS_BITS, CK_MAX, CKF_SN_VR }, PR_TRUE }, 376 { CKM_SHA384_RSA_PKCS, { RSA_MIN_MODULUS_BITS, CK_MAX, CKF_SN_VR }, PR_TRUE }, 377 { CKM_SHA512_RSA_PKCS, { RSA_MIN_MODULUS_BITS, CK_MAX, CKF_SN_VR }, PR_TRUE }, 378 { CKM_SHA1_RSA_PKCS_PSS, { RSA_MIN_MODULUS_BITS, CK_MAX, CKF_SN_VR }, PR_TRUE }, 379 { CKM_SHA224_RSA_PKCS_PSS, { RSA_MIN_MODULUS_BITS, CK_MAX, CKF_SN_VR }, PR_TRUE }, 380 { CKM_SHA256_RSA_PKCS_PSS, { RSA_MIN_MODULUS_BITS, CK_MAX, CKF_SN_VR }, PR_TRUE }, 381 { CKM_SHA384_RSA_PKCS_PSS, { RSA_MIN_MODULUS_BITS, CK_MAX, CKF_SN_VR }, PR_TRUE }, 382 { CKM_SHA512_RSA_PKCS_PSS, { RSA_MIN_MODULUS_BITS, CK_MAX, CKF_SN_VR }, PR_TRUE }, 383 /* ------------------------- DSA Operations --------------------------- */ 384 #ifndef NSS_DISABLE_DSA 385 { CKM_DSA_KEY_PAIR_GEN, { DSA_MIN_P_BITS, DSA_MAX_P_BITS, CKF_GENERATE_KEY_PAIR }, PR_TRUE }, 386 { CKM_DSA, { DSA_MIN_P_BITS, DSA_MAX_P_BITS, CKF_SN_VR }, PR_TRUE }, 387 { CKM_DSA_PARAMETER_GEN, { DSA_MIN_P_BITS, DSA_MAX_P_BITS, CKF_GENERATE }, PR_TRUE }, 388 { CKM_DSA_SHA1, { DSA_MIN_P_BITS, DSA_MAX_P_BITS, CKF_SN_VR }, PR_TRUE }, 389 { CKM_DSA_SHA224, { DSA_MIN_P_BITS, DSA_MAX_P_BITS, CKF_SN_VR }, PR_TRUE }, 390 { CKM_DSA_SHA256, { DSA_MIN_P_BITS, DSA_MAX_P_BITS, CKF_SN_VR }, PR_TRUE }, 391 { CKM_DSA_SHA384, { DSA_MIN_P_BITS, DSA_MAX_P_BITS, CKF_SN_VR }, PR_TRUE }, 392 { CKM_DSA_SHA512, { DSA_MIN_P_BITS, DSA_MAX_P_BITS, CKF_SN_VR }, PR_TRUE }, 393 #endif 394 /* -------------------- Diffie Hellman Operations --------------------- */ 395 /* no diffie hellman yet */ 396 { CKM_DH_PKCS_KEY_PAIR_GEN, { DH_MIN_P_BITS, DH_MAX_P_BITS, CKF_GENERATE_KEY_PAIR }, PR_TRUE }, 397 { CKM_DH_PKCS_DERIVE, { DH_MIN_P_BITS, DH_MAX_P_BITS, CKF_DERIVE }, PR_TRUE }, 398 /* -------------------- Elliptic Curve Operations --------------------- */ 399 { CKM_EC_KEY_PAIR_GEN, { EC_MIN_KEY_BITS, EC_MAX_KEY_BITS, CKF_GENERATE_KEY_PAIR | CKF_EC_BPNU }, PR_TRUE }, 400 { CKM_NSS_ECDHE_NO_PAIRWISE_CHECK_KEY_PAIR_GEN, { EC_MIN_KEY_BITS, EC_MAX_KEY_BITS, CKF_GENERATE_KEY_PAIR | CKF_EC_BPNU }, PR_TRUE }, 401 { CKM_ECDH1_DERIVE, { EC_MIN_KEY_BITS, EC_MAX_KEY_BITS, CKF_DERIVE | CKF_EC_BPNU }, PR_TRUE }, 402 { CKM_ECDSA, { EC_MIN_KEY_BITS, EC_MAX_KEY_BITS, CKF_SN_VR | CKF_EC_BPNU }, PR_TRUE }, 403 { CKM_ECDSA_SHA1, { EC_MIN_KEY_BITS, EC_MAX_KEY_BITS, CKF_SN_VR | CKF_EC_BPNU }, PR_TRUE }, 404 { CKM_ECDSA_SHA224, { EC_MIN_KEY_BITS, EC_MAX_KEY_BITS, CKF_SN_VR | CKF_EC_BPNU }, PR_TRUE }, 405 { CKM_ECDSA_SHA256, { EC_MIN_KEY_BITS, EC_MAX_KEY_BITS, CKF_SN_VR | CKF_EC_BPNU }, PR_TRUE }, 406 { CKM_ECDSA_SHA384, { EC_MIN_KEY_BITS, EC_MAX_KEY_BITS, CKF_SN_VR | CKF_EC_BPNU }, PR_TRUE }, 407 { CKM_ECDSA_SHA512, { EC_MIN_KEY_BITS, EC_MAX_KEY_BITS, CKF_SN_VR | CKF_EC_BPNU }, PR_TRUE }, 408 { CKM_EC_EDWARDS_KEY_PAIR_GEN, { ECD_MIN_KEY_BITS, ECD_MAX_KEY_BITS, CKF_GENERATE_KEY_PAIR }, PR_TRUE }, 409 { CKM_EC_MONTGOMERY_KEY_PAIR_GEN, { ECD_MIN_KEY_BITS, ECD_MAX_KEY_BITS, CKF_GENERATE_KEY_PAIR }, PR_TRUE }, 410 { CKM_EDDSA, { ECD_MIN_KEY_BITS, ECD_MAX_KEY_BITS, CKF_SN_VR | CKF_EC_POC }, PR_TRUE }, 411 /* ------------------------- RC2 Operations --------------------------- */ 412 { CKM_RC2_KEY_GEN, { 1, 128, CKF_GENERATE }, PR_TRUE }, 413 { CKM_RC2_ECB, { 1, 128, CKF_EN_DE_WR_UN }, PR_TRUE }, 414 { CKM_RC2_CBC, { 1, 128, CKF_EN_DE_WR_UN }, PR_TRUE }, 415 { CKM_RC2_MAC, { 1, 128, CKF_SN_VR }, PR_TRUE }, 416 { CKM_RC2_MAC_GENERAL, { 1, 128, CKF_SN_VR }, PR_TRUE }, 417 { CKM_RC2_CBC_PAD, { 1, 128, CKF_EN_DE_WR_UN }, PR_TRUE }, 418 /* ------------------------- RC4 Operations --------------------------- */ 419 { CKM_RC4_KEY_GEN, { 1, 256, CKF_GENERATE }, PR_FALSE }, 420 { CKM_RC4, { 1, 256, CKF_EN_DE_WR_UN }, PR_FALSE }, 421 /* ------------------------- DES Operations --------------------------- */ 422 { CKM_DES_KEY_GEN, { 8, 8, CKF_GENERATE }, PR_TRUE }, 423 { CKM_DES_ECB, { 8, 8, CKF_EN_DE_WR_UN }, PR_TRUE }, 424 { CKM_DES_CBC, { 8, 8, CKF_EN_DE_WR_UN }, PR_TRUE }, 425 { CKM_DES_MAC, { 8, 8, CKF_SN_VR }, PR_TRUE }, 426 { CKM_DES_MAC_GENERAL, { 8, 8, CKF_SN_VR }, PR_TRUE }, 427 { CKM_DES_CBC_PAD, { 8, 8, CKF_EN_DE_WR_UN }, PR_TRUE }, 428 { CKM_DES2_KEY_GEN, { 24, 24, CKF_GENERATE }, PR_TRUE }, 429 { CKM_DES3_KEY_GEN, { 24, 24, CKF_GENERATE }, PR_TRUE }, 430 { CKM_DES3_ECB, { 24, 24, CKF_EN_DE_WR_UN }, PR_TRUE }, 431 { CKM_DES3_CBC, { 24, 24, CKF_EN_DE_WR_UN }, PR_TRUE }, 432 { CKM_DES3_MAC, { 24, 24, CKF_SN_VR }, PR_TRUE }, 433 { CKM_DES3_MAC_GENERAL, { 24, 24, CKF_SN_VR }, PR_TRUE }, 434 { CKM_DES3_CBC_PAD, { 24, 24, CKF_EN_DE_WR_UN }, PR_TRUE }, 435 /* ------------------------- CDMF Operations --------------------------- */ 436 { CKM_CDMF_KEY_GEN, { 8, 8, CKF_GENERATE }, PR_TRUE }, 437 { CKM_CDMF_ECB, { 8, 8, CKF_EN_DE_WR_UN }, PR_TRUE }, 438 { CKM_CDMF_CBC, { 8, 8, CKF_EN_DE_WR_UN }, PR_TRUE }, 439 { CKM_CDMF_MAC, { 8, 8, CKF_SN_VR }, PR_TRUE }, 440 { CKM_CDMF_MAC_GENERAL, { 8, 8, CKF_SN_VR }, PR_TRUE }, 441 { CKM_CDMF_CBC_PAD, { 8, 8, CKF_EN_DE_WR_UN }, PR_TRUE }, 442 /* ------------------------- AES Operations --------------------------- */ 443 { CKM_AES_KEY_GEN, { 16, 32, CKF_GENERATE }, PR_TRUE }, 444 { CKM_AES_ECB, { 16, 32, CKF_EN_DE_WR_UN }, PR_TRUE }, 445 { CKM_AES_CBC, { 16, 32, CKF_EN_DE_WR_UN }, PR_TRUE }, 446 { CKM_AES_MAC, { 16, 32, CKF_SN_VR }, PR_TRUE }, 447 { CKM_AES_MAC_GENERAL, { 16, 32, CKF_SN_VR }, PR_TRUE }, 448 { CKM_AES_CMAC, { 16, 32, CKF_SN_VR }, PR_TRUE }, 449 { CKM_AES_CMAC_GENERAL, { 16, 32, CKF_SN_VR }, PR_TRUE }, 450 { CKM_AES_CBC_PAD, { 16, 32, CKF_EN_DE_WR_UN }, PR_TRUE }, 451 { CKM_AES_CTS, { 16, 32, CKF_EN_DE }, PR_TRUE }, 452 { CKM_AES_CTR, { 16, 32, CKF_EN_DE }, PR_TRUE }, 453 { CKM_AES_GCM, { 16, 32, CKF_EN_DE_MSG }, PR_TRUE }, 454 { CKM_AES_XCBC_MAC_96, { 12, 12, CKF_SN_VR }, PR_TRUE }, 455 { CKM_AES_XCBC_MAC, { 16, 16, CKF_SN_VR }, PR_TRUE }, 456 /* ------------------------- Camellia Operations --------------------- */ 457 { CKM_CAMELLIA_KEY_GEN, { 16, 32, CKF_GENERATE }, PR_TRUE }, 458 { CKM_CAMELLIA_ECB, { 16, 32, CKF_EN_DE_WR_UN }, PR_TRUE }, 459 { CKM_CAMELLIA_CBC, { 16, 32, CKF_EN_DE_WR_UN }, PR_TRUE }, 460 { CKM_CAMELLIA_MAC, { 16, 32, CKF_SN_VR }, PR_TRUE }, 461 { CKM_CAMELLIA_MAC_GENERAL, { 16, 32, CKF_SN_VR }, PR_TRUE }, 462 { CKM_CAMELLIA_CBC_PAD, { 16, 32, CKF_EN_DE_WR_UN }, PR_TRUE }, 463 /* ------------------------- SEED Operations --------------------------- */ 464 #ifndef NSS_DISABLE_DEPRECATED_SEED 465 { CKM_SEED_KEY_GEN, { 16, 16, CKF_GENERATE }, PR_TRUE }, 466 { CKM_SEED_ECB, { 16, 16, CKF_EN_DE_WR_UN }, PR_TRUE }, 467 { CKM_SEED_CBC, { 16, 16, CKF_EN_DE_WR_UN }, PR_TRUE }, 468 { CKM_SEED_MAC, { 16, 16, CKF_SN_VR }, PR_TRUE }, 469 { CKM_SEED_MAC_GENERAL, { 16, 16, CKF_SN_VR }, PR_TRUE }, 470 { CKM_SEED_CBC_PAD, { 16, 16, CKF_EN_DE_WR_UN }, PR_TRUE }, 471 #endif 472 /* ------------------------- ChaCha20 Operations ---------------------- */ 473 #ifndef NSS_DISABLE_CHACHAPOLY 474 { CKM_NSS_CHACHA20_KEY_GEN, { 32, 32, CKF_GENERATE }, PR_TRUE }, 475 { CKM_NSS_CHACHA20_POLY1305, { 32, 32, CKF_EN_DE }, PR_TRUE }, 476 { CKM_NSS_CHACHA20_CTR, { 32, 32, CKF_EN_DE }, PR_TRUE }, 477 { CKM_CHACHA20_KEY_GEN, { 32, 32, CKF_GENERATE }, PR_TRUE }, 478 { CKM_CHACHA20, { 32, 32, CKF_EN_DE }, PR_TRUE }, 479 { CKM_CHACHA20_POLY1305, { 32, 32, CKF_EN_DE_MSG }, PR_TRUE }, 480 #endif /* NSS_DISABLE_CHACHAPOLY */ 481 /* ------------------------- Hashing Operations ----------------------- */ 482 { CKM_MD2, { 0, 0, CKF_DIGEST }, PR_FALSE }, 483 { CKM_MD2_HMAC, { 1, 128, CKF_SN_VR }, PR_TRUE }, 484 { CKM_MD2_HMAC_GENERAL, { 1, 128, CKF_SN_VR }, PR_TRUE }, 485 { CKM_MD5, { 0, 0, CKF_DIGEST }, PR_FALSE }, 486 { CKM_MD5_HMAC, { 1, 128, CKF_SN_VR }, PR_TRUE }, 487 { CKM_MD5_HMAC_GENERAL, { 1, 128, CKF_SN_VR }, PR_TRUE }, 488 { CKM_SHA_1, { 0, 0, CKF_DIGEST }, PR_FALSE }, 489 { CKM_SHA_1_HMAC, { 1, 128, CKF_SN_VR }, PR_TRUE }, 490 { CKM_SHA_1_HMAC_GENERAL, { 1, 128, CKF_SN_VR }, PR_TRUE }, 491 { CKM_SHA224, { 0, 0, CKF_DIGEST }, PR_FALSE }, 492 { CKM_SHA224_HMAC, { 1, 128, CKF_SN_VR }, PR_TRUE }, 493 { CKM_SHA224_HMAC_GENERAL, { 1, 128, CKF_SN_VR }, PR_TRUE }, 494 { CKM_SHA256, { 0, 0, CKF_DIGEST }, PR_FALSE }, 495 { CKM_SHA256_HMAC, { 1, 128, CKF_SN_VR }, PR_TRUE }, 496 { CKM_SHA256_HMAC_GENERAL, { 1, 128, CKF_SN_VR }, PR_TRUE }, 497 { CKM_SHA384, { 0, 0, CKF_DIGEST }, PR_FALSE }, 498 { CKM_SHA384_HMAC, { 1, 128, CKF_SN_VR }, PR_TRUE }, 499 { CKM_SHA384_HMAC_GENERAL, { 1, 128, CKF_SN_VR }, PR_TRUE }, 500 { CKM_SHA512, { 0, 0, CKF_DIGEST }, PR_FALSE }, 501 { CKM_SHA512_HMAC, { 1, 128, CKF_SN_VR }, PR_TRUE }, 502 { CKM_SHA512_HMAC_GENERAL, { 1, 128, CKF_SN_VR }, PR_TRUE }, 503 { CKM_SHA3_224, { 0, 0, CKF_DIGEST }, PR_FALSE }, 504 { CKM_SHA3_224_HMAC, { 1, 128, CKF_SN_VR }, PR_TRUE }, 505 { CKM_SHA3_224_HMAC_GENERAL, { 1, 128, CKF_SN_VR }, PR_TRUE }, 506 { CKM_SHA3_256, { 0, 0, CKF_DIGEST }, PR_FALSE }, 507 { CKM_SHA3_256_HMAC, { 1, 128, CKF_SN_VR }, PR_TRUE }, 508 { CKM_SHA3_256_HMAC_GENERAL, { 1, 128, CKF_SN_VR }, PR_TRUE }, 509 { CKM_SHA3_384, { 0, 0, CKF_DIGEST }, PR_FALSE }, 510 { CKM_SHA3_384_HMAC, { 1, 128, CKF_SN_VR }, PR_TRUE }, 511 { CKM_SHA3_384_HMAC_GENERAL, { 1, 128, CKF_SN_VR }, PR_TRUE }, 512 { CKM_SHA3_512, { 0, 0, CKF_DIGEST }, PR_FALSE }, 513 { CKM_SHA3_512_HMAC, { 1, 128, CKF_SN_VR }, PR_TRUE }, 514 { CKM_SHA3_512_HMAC_GENERAL, { 1, 128, CKF_SN_VR }, PR_TRUE }, 515 { CKM_TLS_PRF_GENERAL, { 0, 512, CKF_SN_VR }, PR_FALSE }, 516 { CKM_TLS_MAC, { 0, 512, CKF_SN_VR }, PR_FALSE }, 517 { CKM_NSS_TLS_PRF_GENERAL_SHA256, 518 { 0, 512, CKF_SN_VR }, 519 PR_FALSE }, 520 /* ------------------------- HKDF Operations -------------------------- */ 521 { CKM_HKDF_DERIVE, { 1, 255 * 64, CKF_DERIVE }, PR_TRUE }, 522 { CKM_HKDF_DATA, { 1, 255 * 64, CKF_DERIVE }, PR_TRUE }, 523 { CKM_HKDF_KEY_GEN, { 20, 64, CKF_GENERATE }, PR_TRUE }, 524 { CKM_NSS_HKDF_SHA1, { 1, 128, CKF_DERIVE }, PR_TRUE }, 525 { CKM_NSS_HKDF_SHA256, { 1, 128, CKF_DERIVE }, PR_TRUE }, 526 { CKM_NSS_HKDF_SHA384, { 1, 128, CKF_DERIVE }, PR_TRUE }, 527 { CKM_NSS_HKDF_SHA512, { 1, 128, CKF_DERIVE }, PR_TRUE }, 528 /* ------------------------- CAST Operations --------------------------- */ 529 #ifdef NSS_SOFTOKEN_DOES_CAST 530 /* Cast operations are not supported ( yet? ) */ 531 { CKM_CAST_KEY_GEN, { 1, 8, CKF_GENERATE }, PR_TRUE }, 532 { CKM_CAST_ECB, { 1, 8, CKF_EN_DE_WR_UN }, PR_TRUE }, 533 { CKM_CAST_CBC, { 1, 8, CKF_EN_DE_WR_UN }, PR_TRUE }, 534 { CKM_CAST_MAC, { 1, 8, CKF_SN_VR }, PR_TRUE }, 535 { CKM_CAST_MAC_GENERAL, { 1, 8, CKF_SN_VR }, PR_TRUE }, 536 { CKM_CAST_CBC_PAD, { 1, 8, CKF_EN_DE_WR_UN }, PR_TRUE }, 537 { CKM_CAST3_KEY_GEN, { 1, 16, CKF_GENERATE }, PR_TRUE }, 538 { CKM_CAST3_ECB, { 1, 16, CKF_EN_DE_WR_UN }, PR_TRUE }, 539 { CKM_CAST3_CBC, { 1, 16, CKF_EN_DE_WR_UN }, PR_TRUE }, 540 { CKM_CAST3_MAC, { 1, 16, CKF_SN_VR }, PR_TRUE }, 541 { CKM_CAST3_MAC_GENERAL, { 1, 16, CKF_SN_VR }, PR_TRUE }, 542 { CKM_CAST3_CBC_PAD, { 1, 16, CKF_EN_DE_WR_UN }, PR_TRUE }, 543 { CKM_CAST5_KEY_GEN, { 1, 16, CKF_GENERATE }, PR_TRUE }, 544 { CKM_CAST5_ECB, { 1, 16, CKF_EN_DE_WR_UN }, PR_TRUE }, 545 { CKM_CAST5_CBC, { 1, 16, CKF_EN_DE_WR_UN }, PR_TRUE }, 546 { CKM_CAST5_MAC, { 1, 16, CKF_SN_VR }, PR_TRUE }, 547 { CKM_CAST5_MAC_GENERAL, { 1, 16, CKF_SN_VR }, PR_TRUE }, 548 { CKM_CAST5_CBC_PAD, { 1, 16, CKF_EN_DE_WR_UN }, PR_TRUE }, 549 #endif 550 #if NSS_SOFTOKEN_DOES_RC5 551 /* ------------------------- RC5 Operations --------------------------- */ 552 { CKM_RC5_KEY_GEN, { 1, 32, CKF_GENERATE }, PR_TRUE }, 553 { CKM_RC5_ECB, { 1, 32, CKF_EN_DE_WR_UN }, PR_TRUE }, 554 { CKM_RC5_CBC, { 1, 32, CKF_EN_DE_WR_UN }, PR_TRUE }, 555 { CKM_RC5_MAC, { 1, 32, CKF_SN_VR }, PR_TRUE }, 556 { CKM_RC5_MAC_GENERAL, { 1, 32, CKF_SN_VR }, PR_TRUE }, 557 { CKM_RC5_CBC_PAD, { 1, 32, CKF_EN_DE_WR_UN }, PR_TRUE }, 558 #endif 559 #ifdef NSS_SOFTOKEN_DOES_IDEA 560 /* ------------------------- IDEA Operations -------------------------- */ 561 { CKM_IDEA_KEY_GEN, { 16, 16, CKF_GENERATE }, PR_TRUE }, 562 { CKM_IDEA_ECB, { 16, 16, CKF_EN_DE_WR_UN }, PR_TRUE }, 563 { CKM_IDEA_CBC, { 16, 16, CKF_EN_DE_WR_UN }, PR_TRUE }, 564 { CKM_IDEA_MAC, { 16, 16, CKF_SN_VR }, PR_TRUE }, 565 { CKM_IDEA_MAC_GENERAL, { 16, 16, CKF_SN_VR }, PR_TRUE }, 566 { CKM_IDEA_CBC_PAD, { 16, 16, CKF_EN_DE_WR_UN }, PR_TRUE }, 567 #endif 568 /* --------------------- Secret Key Operations ------------------------ */ 569 { CKM_GENERIC_SECRET_KEY_GEN, { 1, 32, CKF_GENERATE }, PR_TRUE }, 570 { CKM_CONCATENATE_BASE_AND_KEY, { 1, 32, CKF_DERIVE }, PR_FALSE }, 571 { CKM_CONCATENATE_BASE_AND_DATA, { 1, 32, CKF_DERIVE }, PR_FALSE }, 572 { CKM_CONCATENATE_DATA_AND_BASE, { 1, 32, CKF_DERIVE }, PR_FALSE }, 573 { CKM_XOR_BASE_AND_DATA, { 1, 32, CKF_DERIVE }, PR_FALSE }, 574 { CKM_EXTRACT_KEY_FROM_KEY, { 1, 32, CKF_DERIVE }, PR_FALSE }, 575 { CKM_DES3_ECB_ENCRYPT_DATA, { 1, 32, CKF_DERIVE }, PR_FALSE }, 576 { CKM_DES3_CBC_ENCRYPT_DATA, { 1, 32, CKF_DERIVE }, PR_FALSE }, 577 { CKM_AES_ECB_ENCRYPT_DATA, { 1, 32, CKF_DERIVE }, PR_FALSE }, 578 { CKM_AES_CBC_ENCRYPT_DATA, { 1, 32, CKF_DERIVE }, PR_FALSE }, 579 { CKM_CAMELLIA_ECB_ENCRYPT_DATA, { 1, 32, CKF_DERIVE }, PR_FALSE }, 580 { CKM_CAMELLIA_CBC_ENCRYPT_DATA, { 1, 32, CKF_DERIVE }, PR_FALSE }, 581 #ifndef NSS_DISABLE_DEPRECATED_SEED 582 { CKM_SEED_ECB_ENCRYPT_DATA, { 1, 32, CKF_DERIVE }, PR_FALSE }, 583 { CKM_SEED_CBC_ENCRYPT_DATA, { 1, 32, CKF_DERIVE }, PR_FALSE }, 584 #endif 585 /* ---------------------- SSL Key Derivations ------------------------- */ 586 { CKM_SSL3_PRE_MASTER_KEY_GEN, { 48, 48, CKF_GENERATE }, PR_FALSE }, 587 { CKM_SSL3_MASTER_KEY_DERIVE, { 48, 48, CKF_DERIVE }, PR_FALSE }, 588 { CKM_SSL3_MASTER_KEY_DERIVE_DH, { 8, 128, CKF_DERIVE }, PR_FALSE }, 589 { CKM_SSL3_KEY_AND_MAC_DERIVE, { 48, 48, CKF_DERIVE }, PR_FALSE }, 590 { CKM_SSL3_MD5_MAC, { 0, 16, CKF_DERIVE }, PR_FALSE }, 591 { CKM_SSL3_SHA1_MAC, { 0, 20, CKF_DERIVE }, PR_FALSE }, 592 { CKM_MD5_KEY_DERIVATION, { 0, 16, CKF_DERIVE }, PR_FALSE }, 593 { CKM_MD2_KEY_DERIVATION, { 0, 16, CKF_DERIVE }, PR_FALSE }, 594 { CKM_SHA1_KEY_DERIVATION, { 0, 20, CKF_DERIVE }, PR_FALSE }, 595 { CKM_SHA224_KEY_DERIVATION, { 0, 28, CKF_DERIVE }, PR_FALSE }, 596 { CKM_SHA256_KEY_DERIVATION, { 0, 32, CKF_DERIVE }, PR_FALSE }, 597 { CKM_SHA384_KEY_DERIVATION, { 0, 48, CKF_DERIVE }, PR_FALSE }, 598 { CKM_SHA512_KEY_DERIVATION, { 0, 64, CKF_DERIVE }, PR_FALSE }, 599 { CKM_TLS_MASTER_KEY_DERIVE, { 48, 48, CKF_DERIVE }, PR_FALSE }, 600 { CKM_TLS12_MASTER_KEY_DERIVE, { 48, 48, CKF_DERIVE }, PR_FALSE }, 601 { CKM_NSS_TLS_MASTER_KEY_DERIVE_SHA256, 602 { 48, 48, CKF_DERIVE }, 603 PR_FALSE }, 604 { CKM_TLS_MASTER_KEY_DERIVE_DH, { 8, 128, CKF_DERIVE }, PR_FALSE }, 605 { CKM_TLS12_MASTER_KEY_DERIVE_DH, { 8, 128, CKF_DERIVE }, PR_FALSE }, 606 { CKM_TLS12_EXTENDED_MASTER_KEY_DERIVE, { 48, 128, CKF_DERIVE }, PR_FALSE }, 607 { CKM_TLS12_EXTENDED_MASTER_KEY_DERIVE_DH, { 48, 128, CKF_DERIVE }, PR_FALSE }, 608 { CKM_NSS_TLS_MASTER_KEY_DERIVE_DH_SHA256, 609 { 8, 128, CKF_DERIVE }, 610 PR_FALSE }, 611 { CKM_TLS_KEY_AND_MAC_DERIVE, { 48, 48, CKF_DERIVE }, PR_FALSE }, 612 { CKM_TLS12_KEY_AND_MAC_DERIVE, { 48, 48, CKF_DERIVE }, PR_FALSE }, 613 { CKM_NSS_TLS_KEY_AND_MAC_DERIVE_SHA256, 614 { 48, 48, CKF_DERIVE }, 615 PR_FALSE }, 616 { CKM_NSS_TLS_EXTENDED_MASTER_KEY_DERIVE, 617 { 48, 128, CKF_DERIVE }, 618 PR_FALSE }, 619 { CKM_NSS_TLS_EXTENDED_MASTER_KEY_DERIVE_DH, 620 { 48, 128, CKF_DERIVE }, 621 PR_FALSE }, 622 /* ---------------------- PBE Key Derivations ------------------------ */ 623 { CKM_PBE_MD2_DES_CBC, { 8, 8, CKF_DERIVE }, PR_TRUE }, 624 { CKM_PBE_MD5_DES_CBC, { 8, 8, CKF_DERIVE }, PR_TRUE }, 625 /* ------------------ NSS PBE Key Derivations ------------------- */ 626 { CKM_NSS_PBE_SHA1_DES_CBC, { 8, 8, CKF_GENERATE }, PR_TRUE }, 627 { CKM_NSS_PBE_SHA1_FAULTY_3DES_CBC, { 24, 24, CKF_GENERATE }, PR_TRUE }, 628 { CKM_PBE_SHA1_DES3_EDE_CBC, { 24, 24, CKF_GENERATE }, PR_TRUE }, 629 { CKM_PBE_SHA1_DES2_EDE_CBC, { 24, 24, CKF_GENERATE }, PR_TRUE }, 630 { CKM_PBE_SHA1_RC2_40_CBC, { 40, 40, CKF_GENERATE }, PR_TRUE }, 631 { CKM_PBE_SHA1_RC2_128_CBC, { 128, 128, CKF_GENERATE }, PR_TRUE }, 632 { CKM_PBE_SHA1_RC4_40, { 40, 40, CKF_GENERATE }, PR_TRUE }, 633 { CKM_PBE_SHA1_RC4_128, { 128, 128, CKF_GENERATE }, PR_TRUE }, 634 { CKM_PBA_SHA1_WITH_SHA1_HMAC, { 20, 20, CKF_GENERATE }, PR_TRUE }, 635 { CKM_PKCS5_PBKD2, { 1, 256, CKF_GENERATE }, PR_TRUE }, 636 { CKM_NSS_PBE_SHA1_HMAC_KEY_GEN, { 20, 20, CKF_GENERATE }, PR_TRUE }, 637 { CKM_NSS_PBE_MD5_HMAC_KEY_GEN, { 16, 16, CKF_GENERATE }, PR_TRUE }, 638 { CKM_NSS_PBE_MD2_HMAC_KEY_GEN, { 16, 16, CKF_GENERATE }, PR_TRUE }, 639 { CKM_NSS_PKCS12_PBE_SHA224_HMAC_KEY_GEN, { 28, 28, CKF_GENERATE }, PR_TRUE }, 640 { CKM_NSS_PKCS12_PBE_SHA256_HMAC_KEY_GEN, { 32, 32, CKF_GENERATE }, PR_TRUE }, 641 { CKM_NSS_PKCS12_PBE_SHA384_HMAC_KEY_GEN, { 48, 48, CKF_GENERATE }, PR_TRUE }, 642 { CKM_NSS_PKCS12_PBE_SHA512_HMAC_KEY_GEN, { 64, 64, CKF_GENERATE }, PR_TRUE }, 643 /* ------------------ NIST 800-108 Key Derivations ------------------- */ 644 { CKM_SP800_108_COUNTER_KDF, { 0, CK_MAX, CKF_DERIVE }, PR_TRUE }, 645 { CKM_SP800_108_FEEDBACK_KDF, { 0, CK_MAX, CKF_DERIVE }, PR_TRUE }, 646 { CKM_SP800_108_DOUBLE_PIPELINE_KDF, { 0, CK_MAX, CKF_DERIVE }, PR_TRUE }, 647 { CKM_NSS_SP800_108_COUNTER_KDF_DERIVE_DATA, { 0, CK_MAX, CKF_DERIVE }, PR_TRUE }, 648 { CKM_NSS_SP800_108_FEEDBACK_KDF_DERIVE_DATA, { 0, CK_MAX, CKF_DERIVE }, PR_TRUE }, 649 { CKM_NSS_SP800_108_DOUBLE_PIPELINE_KDF_DERIVE_DATA, { 0, CK_MAX, CKF_DERIVE }, PR_TRUE }, 650 /* ------------------ AES Key Wrap (also encrypt) ------------------- */ 651 { CKM_NSS_AES_KEY_WRAP, { 16, 32, CKF_EN_DE_WR_UN }, PR_TRUE }, 652 { CKM_NSS_AES_KEY_WRAP_PAD, { 16, 32, CKF_EN_DE_WR_UN }, PR_TRUE }, 653 { CKM_AES_KEY_WRAP, { 16, 32, CKF_EN_DE_WR_UN }, PR_TRUE }, 654 { CKM_AES_KEY_WRAP_PAD, { 16, 32, CKF_EN_DE_WR_UN }, PR_TRUE }, 655 { CKM_AES_KEY_WRAP_KWP, { 1, 32, CKF_EN_DE_WR_UN }, PR_TRUE }, 656 /* --------------------------- J-PAKE -------------------------------- */ 657 { CKM_NSS_JPAKE_ROUND1_SHA1, { 0, 0, CKF_GENERATE }, PR_TRUE }, 658 { CKM_NSS_JPAKE_ROUND1_SHA256, { 0, 0, CKF_GENERATE }, PR_TRUE }, 659 { CKM_NSS_JPAKE_ROUND1_SHA384, { 0, 0, CKF_GENERATE }, PR_TRUE }, 660 { CKM_NSS_JPAKE_ROUND1_SHA512, { 0, 0, CKF_GENERATE }, PR_TRUE }, 661 { CKM_NSS_JPAKE_ROUND2_SHA1, { 0, 0, CKF_DERIVE }, PR_TRUE }, 662 { CKM_NSS_JPAKE_ROUND2_SHA256, { 0, 0, CKF_DERIVE }, PR_TRUE }, 663 { CKM_NSS_JPAKE_ROUND2_SHA384, { 0, 0, CKF_DERIVE }, PR_TRUE }, 664 { CKM_NSS_JPAKE_ROUND2_SHA512, { 0, 0, CKF_DERIVE }, PR_TRUE }, 665 { CKM_NSS_JPAKE_FINAL_SHA1, { 0, 0, CKF_DERIVE }, PR_TRUE }, 666 { CKM_NSS_JPAKE_FINAL_SHA256, { 0, 0, CKF_DERIVE }, PR_TRUE }, 667 { CKM_NSS_JPAKE_FINAL_SHA384, { 0, 0, CKF_DERIVE }, PR_TRUE }, 668 { CKM_NSS_JPAKE_FINAL_SHA512, { 0, 0, CKF_DERIVE }, PR_TRUE }, 669 /* -------------------- Constant Time TLS MACs ----------------------- */ 670 { CKM_NSS_HMAC_CONSTANT_TIME, { 0, 0, CKF_DIGEST }, PR_TRUE }, 671 { CKM_NSS_SSL3_MAC_CONSTANT_TIME, { 0, 0, CKF_DIGEST }, PR_TRUE }, 672 /* -------------------- IPSEC ----------------------- */ 673 { CKM_IKE2_PRF_PLUS_DERIVE, { 8, 255 * 64, CKF_DERIVE }, PR_TRUE }, 674 { CKM_IKE_PRF_DERIVE, { 8, 64, CKF_DERIVE }, PR_TRUE }, 675 { CKM_IKE1_PRF_DERIVE, { 8, 64, CKF_DERIVE }, PR_TRUE }, 676 { CKM_IKE1_EXTENDED_DERIVE, { 8, 255 * 64, CKF_DERIVE }, PR_TRUE }, 677 { CKM_NSS_IKE_PRF_PLUS_DERIVE, { 8, 255 * 64, CKF_DERIVE }, PR_TRUE }, 678 { CKM_NSS_IKE_PRF_DERIVE, { 8, 64, CKF_DERIVE }, PR_TRUE }, 679 { CKM_NSS_IKE1_PRF_DERIVE, { 8, 64, CKF_DERIVE }, PR_TRUE }, 680 { CKM_NSS_IKE1_APP_B_PRF_DERIVE, { 8, 255 * 64, CKF_DERIVE }, PR_TRUE }, 681 /* -------------------- Kyber Operations ----------------------- */ 682 #ifndef NSS_DISABLE_KYBER 683 { CKM_NSS_KYBER_KEY_PAIR_GEN, { 0, 0, CKF_GENERATE_KEY_PAIR }, PR_TRUE }, 684 { CKM_NSS_KYBER, { 0, 0, CKF_KEM }, PR_TRUE }, 685 #endif 686 { CKM_NSS_ML_KEM_KEY_PAIR_GEN, { 0, 0, CKF_GENERATE_KEY_PAIR }, PR_TRUE }, 687 { CKM_NSS_ML_KEM, { 0, 0, CKF_KEM }, PR_TRUE }, 688 { CKM_ML_KEM_KEY_PAIR_GEN, { 0, 0, CKF_GENERATE_KEY_PAIR }, PR_TRUE }, 689 { CKM_ML_KEM, { 0, 0, CKF_KEM }, PR_TRUE }, 690 /* don't advertize ML_DSA support until we have it working in freebl */ 691 #ifdef NSS_ENABLE_ML_DSA 692 { CKM_ML_DSA_KEY_PAIR_GEN, { ML_DSA_44_PUBLICKEY_LEN, ML_DSA_87_PUBLICKEY_LEN, CKF_GENERATE }, PR_TRUE }, 693 { CKM_ML_DSA, { ML_DSA_44_PUBLICKEY_LEN, ML_DSA_87_PUBLICKEY_LEN, CKF_SN_VR }, PR_TRUE }, 694 #endif 695 }; 696 static const CK_ULONG mechanismCount = sizeof(mechanisms) / sizeof(mechanisms[0]); 697 698 /* sigh global so fipstokn can read it */ 699 PRBool nsc_init = PR_FALSE; 700 701 #if defined(CHECK_FORK_PTHREAD) || defined(CHECK_FORK_MIXED) 702 703 #include <pthread.h> 704 705 static void 706 ForkedChild(void) 707 { 708 if (nsc_init || nsf_init) { 709 forked = PR_TRUE; 710 } 711 } 712 713 #endif 714 715 #define SFTKFreeWrap(ctxtype, mmm) \ 716 void SFTKFree_##mmm(void *vp) \ 717 { \ 718 ctxtype *p = vp; \ 719 mmm(p); \ 720 } 721 722 SFTKFreeWrap(NSSLOWKEYPublicKey, nsslowkey_DestroyPublicKey); 723 SFTKFreeWrap(NSSLOWKEYPrivateKey, nsslowkey_DestroyPrivateKey); 724 725 static char * 726 sftk_setStringName(const char *inString, char *buffer, int buffer_length, PRBool nullTerminate) 727 { 728 int full_length, string_length; 729 730 full_length = nullTerminate ? buffer_length - 1 : buffer_length; 731 string_length = PORT_Strlen(inString); 732 /* 733 * shorten the string, respecting utf8 encoding 734 * to do so, we work backward from the end 735 * bytes looking from the end are either: 736 * - ascii [0x00,0x7f] 737 * - the [2-n]th byte of a multibyte sequence 738 * [0x3F,0xBF], i.e, most significant 2 bits are '10' 739 * - the first byte of a multibyte sequence [0xC0,0xFD], 740 * i.e, most significant 2 bits are '11' 741 * 742 * When the string is too long, we lop off any trailing '10' bytes, 743 * if any. When these are all eliminated we lop off 744 * one additional byte. Thus if we lopped any '10' 745 * we'll be lopping a '11' byte (the first byte of the multibyte sequence), 746 * otherwise we're lopping off an ascii character. 747 * 748 * To test for '10' bytes, we first AND it with 749 * 11000000 (0xc0) so that we get 10000000 (0x80) if and only if 750 * the byte starts with 10. We test for equality. 751 */ 752 while (string_length > full_length) { 753 /* need to shorten */ 754 while (string_length > 0 && 755 ((inString[string_length - 1] & (char)0xc0) == (char)0x80)) { 756 /* lop off '10' byte */ 757 string_length--; 758 } 759 /* 760 * test string_length in case bad data is received 761 * and string consisted of all '10' bytes, 762 * avoiding any infinite loop 763 */ 764 if (string_length) { 765 /* remove either '11' byte or an asci byte */ 766 string_length--; 767 } 768 } 769 PORT_Memset(buffer, ' ', full_length); 770 if (nullTerminate) { 771 buffer[full_length] = 0; 772 } 773 PORT_Memcpy(buffer, inString, string_length); 774 return buffer; 775 } 776 /* 777 * Configuration utils 778 */ 779 static CK_RV 780 sftk_configure(const char *man, const char *libdes) 781 { 782 783 /* make sure the internationalization was done correctly... */ 784 if (man) { 785 manufacturerID = sftk_setStringName(man, manufacturerID_space, 786 sizeof(manufacturerID_space), PR_TRUE); 787 } 788 if (libdes) { 789 libraryDescription = sftk_setStringName(libdes, 790 libraryDescription_space, sizeof(libraryDescription_space), 791 PR_TRUE); 792 } 793 794 return CKR_OK; 795 } 796 797 /* 798 * ******************** Password Utilities ******************************* 799 */ 800 801 /* 802 * see if the key DB password is enabled 803 */ 804 static PRBool 805 sftk_hasNullPassword(SFTKSlot *slot, SFTKDBHandle *keydb) 806 { 807 PRBool pwenabled; 808 809 pwenabled = PR_FALSE; 810 if (sftkdb_HasPasswordSet(keydb) == SECSuccess) { 811 PRBool tokenRemoved = PR_FALSE; 812 SECStatus rv = sftkdb_CheckPasswordNull(keydb, &tokenRemoved); 813 if (tokenRemoved) { 814 sftk_CloseAllSessions(slot, PR_FALSE); 815 } 816 return (rv == SECSuccess); 817 } 818 819 return pwenabled; 820 } 821 822 /* 823 * ******************** Object Creation Utilities *************************** 824 */ 825 826 /* Make sure a given attribute exists. If it doesn't, initialize it to 827 * value and len 828 */ 829 CK_RV 830 sftk_defaultAttribute(SFTKObject *object, CK_ATTRIBUTE_TYPE type, 831 const void *value, unsigned int len) 832 { 833 if (!sftk_hasAttribute(object, type)) { 834 return sftk_AddAttributeType(object, type, value, len); 835 } 836 return CKR_OK; 837 } 838 839 /* 840 * check the consistancy and initialize a Data Object 841 */ 842 static CK_RV 843 sftk_handleDataObject(SFTKSession *session, SFTKObject *object) 844 { 845 CK_RV crv; 846 847 /* first reject private and token data objects */ 848 if (sftk_isTrue(object, CKA_PRIVATE) || sftk_isTrue(object, CKA_TOKEN)) { 849 return CKR_ATTRIBUTE_VALUE_INVALID; 850 } 851 852 /* now just verify the required date fields */ 853 crv = sftk_defaultAttribute(object, CKA_APPLICATION, NULL, 0); 854 if (crv != CKR_OK) 855 return crv; 856 crv = sftk_defaultAttribute(object, CKA_VALUE, NULL, 0); 857 if (crv != CKR_OK) 858 return crv; 859 860 return CKR_OK; 861 } 862 863 /* 864 * check the consistancy and initialize a Certificate Object 865 */ 866 static CK_RV 867 sftk_handleCertObject(SFTKSession *session, SFTKObject *object) 868 { 869 CK_CERTIFICATE_TYPE type; 870 SFTKAttribute *attribute; 871 CK_RV crv; 872 873 /* certificates must have a type */ 874 if (!sftk_hasAttribute(object, CKA_CERTIFICATE_TYPE)) { 875 return CKR_TEMPLATE_INCOMPLETE; 876 } 877 878 /* we can't store any certs private */ 879 if (sftk_isTrue(object, CKA_PRIVATE)) { 880 return CKR_ATTRIBUTE_VALUE_INVALID; 881 } 882 883 /* We only support X.509 Certs for now */ 884 attribute = sftk_FindAttribute(object, CKA_CERTIFICATE_TYPE); 885 if (attribute == NULL) 886 return CKR_TEMPLATE_INCOMPLETE; 887 type = *(CK_CERTIFICATE_TYPE *)attribute->attrib.pValue; 888 sftk_FreeAttribute(attribute); 889 890 if (type != CKC_X_509) { 891 return CKR_ATTRIBUTE_VALUE_INVALID; 892 } 893 894 /* X.509 Certificate */ 895 896 /* make sure we have a cert */ 897 if (!sftk_hasAttribute(object, CKA_VALUE)) { 898 return CKR_TEMPLATE_INCOMPLETE; 899 } 900 901 /* in PKCS #11, Subject is a required field */ 902 if (!sftk_hasAttribute(object, CKA_SUBJECT)) { 903 return CKR_TEMPLATE_INCOMPLETE; 904 } 905 906 /* in PKCS #11, Issuer is a required field */ 907 if (!sftk_hasAttribute(object, CKA_ISSUER)) { 908 return CKR_TEMPLATE_INCOMPLETE; 909 } 910 911 /* in PKCS #11, Serial is a required field */ 912 if (!sftk_hasAttribute(object, CKA_SERIAL_NUMBER)) { 913 return CKR_TEMPLATE_INCOMPLETE; 914 } 915 916 /* add it to the object */ 917 object->objectInfo = NULL; 918 object->infoFree = (SFTKFree)NULL; 919 920 /* now just verify the required date fields */ 921 crv = sftk_defaultAttribute(object, CKA_ID, NULL, 0); 922 if (crv != CKR_OK) { 923 return crv; 924 } 925 926 if (sftk_isTrue(object, CKA_TOKEN)) { 927 SFTKSlot *slot = session->slot; 928 SFTKDBHandle *certHandle = sftk_getCertDB(slot); 929 930 if (certHandle == NULL) { 931 return CKR_TOKEN_WRITE_PROTECTED; 932 } 933 934 crv = sftkdb_write(certHandle, object, &object->handle); 935 sftk_freeDB(certHandle); 936 return crv; 937 } 938 939 return CKR_OK; 940 } 941 942 /* 943 * check the consistancy and initialize a Trust Object 944 */ 945 static CK_RV 946 sftk_handleNSSTrustObject(SFTKSession *session, SFTKObject *object) 947 { 948 /* we can't store any certs private */ 949 if (sftk_isTrue(object, CKA_PRIVATE)) { 950 return CKR_ATTRIBUTE_VALUE_INVALID; 951 } 952 953 /* certificates must have a type */ 954 if (!sftk_hasAttribute(object, CKA_ISSUER)) { 955 return CKR_TEMPLATE_INCOMPLETE; 956 } 957 if (!sftk_hasAttribute(object, CKA_SERIAL_NUMBER)) { 958 return CKR_TEMPLATE_INCOMPLETE; 959 } 960 if (!sftk_hasAttribute(object, CKA_NSS_CERT_SHA1_HASH)) { 961 return CKR_TEMPLATE_INCOMPLETE; 962 } 963 if (!sftk_hasAttribute(object, CKA_NSS_CERT_MD5_HASH)) { 964 return CKR_TEMPLATE_INCOMPLETE; 965 } 966 967 if (sftk_isTrue(object, CKA_TOKEN)) { 968 SFTKSlot *slot = session->slot; 969 SFTKDBHandle *certHandle = sftk_getCertDB(slot); 970 CK_RV crv; 971 972 if (certHandle == NULL) { 973 return CKR_TOKEN_WRITE_PROTECTED; 974 } 975 976 crv = sftkdb_write(certHandle, object, &object->handle); 977 sftk_freeDB(certHandle); 978 return crv; 979 } 980 981 return CKR_OK; 982 } 983 984 /* 985 * check the consistancy and initialize a Trust Object 986 */ 987 static CK_RV 988 sftk_handleTrustObject(SFTKSession *session, SFTKObject *object) 989 { 990 /* we can't store any certs private */ 991 if (sftk_isTrue(object, CKA_PRIVATE)) { 992 return CKR_ATTRIBUTE_VALUE_INVALID; 993 } 994 995 /* certificates must have a type */ 996 if (!sftk_hasAttribute(object, CKA_ISSUER)) { 997 return CKR_TEMPLATE_INCOMPLETE; 998 } 999 if (!sftk_hasAttribute(object, CKA_SERIAL_NUMBER)) { 1000 return CKR_TEMPLATE_INCOMPLETE; 1001 } 1002 if (!sftk_hasAttribute(object, CKA_HASH_OF_CERTIFICATE)) { 1003 return CKR_TEMPLATE_INCOMPLETE; 1004 } 1005 if (!sftk_hasAttribute(object, CKA_NAME_HASH_ALGORITHM)) { 1006 return CKR_TEMPLATE_INCOMPLETE; 1007 } 1008 1009 if (sftk_isTrue(object, CKA_TOKEN)) { 1010 SFTKSlot *slot = session->slot; 1011 SFTKDBHandle *certHandle = sftk_getCertDB(slot); 1012 CK_RV crv; 1013 1014 if (certHandle == NULL) { 1015 return CKR_TOKEN_WRITE_PROTECTED; 1016 } 1017 1018 crv = sftkdb_write(certHandle, object, &object->handle); 1019 sftk_freeDB(certHandle); 1020 return crv; 1021 } 1022 1023 return CKR_OK; 1024 } 1025 1026 /* 1027 * check the consistancy and initialize a Trust Object 1028 */ 1029 static CK_RV 1030 sftk_handleSMimeObject(SFTKSession *session, SFTKObject *object) 1031 { 1032 1033 /* we can't store any certs private */ 1034 if (sftk_isTrue(object, CKA_PRIVATE)) { 1035 return CKR_ATTRIBUTE_VALUE_INVALID; 1036 } 1037 1038 /* certificates must have a type */ 1039 if (!sftk_hasAttribute(object, CKA_SUBJECT)) { 1040 return CKR_TEMPLATE_INCOMPLETE; 1041 } 1042 if (!sftk_hasAttribute(object, CKA_NSS_EMAIL)) { 1043 return CKR_TEMPLATE_INCOMPLETE; 1044 } 1045 1046 if (sftk_isTrue(object, CKA_TOKEN)) { 1047 SFTKSlot *slot = session->slot; 1048 SFTKDBHandle *certHandle; 1049 CK_RV crv; 1050 1051 PORT_Assert(slot); 1052 if (slot == NULL) { 1053 return CKR_SESSION_HANDLE_INVALID; 1054 } 1055 1056 certHandle = sftk_getCertDB(slot); 1057 if (certHandle == NULL) { 1058 return CKR_TOKEN_WRITE_PROTECTED; 1059 } 1060 1061 crv = sftkdb_write(certHandle, object, &object->handle); 1062 sftk_freeDB(certHandle); 1063 return crv; 1064 } 1065 1066 return CKR_OK; 1067 } 1068 1069 /* 1070 * check the consistancy and initialize a Trust Object 1071 */ 1072 static CK_RV 1073 sftk_handleCrlObject(SFTKSession *session, SFTKObject *object) 1074 { 1075 1076 /* we can't store any certs private */ 1077 if (sftk_isTrue(object, CKA_PRIVATE)) { 1078 return CKR_ATTRIBUTE_VALUE_INVALID; 1079 } 1080 1081 /* certificates must have a type */ 1082 if (!sftk_hasAttribute(object, CKA_SUBJECT)) { 1083 return CKR_TEMPLATE_INCOMPLETE; 1084 } 1085 if (!sftk_hasAttribute(object, CKA_VALUE)) { 1086 return CKR_TEMPLATE_INCOMPLETE; 1087 } 1088 1089 if (sftk_isTrue(object, CKA_TOKEN)) { 1090 SFTKSlot *slot = session->slot; 1091 SFTKDBHandle *certHandle = sftk_getCertDB(slot); 1092 CK_RV crv; 1093 1094 if (certHandle == NULL) { 1095 return CKR_TOKEN_WRITE_PROTECTED; 1096 } 1097 1098 crv = sftkdb_write(certHandle, object, &object->handle); 1099 sftk_freeDB(certHandle); 1100 return crv; 1101 } 1102 1103 return CKR_OK; 1104 } 1105 1106 /* 1107 * check the consistancy and initialize a Public Key Object 1108 */ 1109 static CK_RV 1110 sftk_handlePublicKeyObject(SFTKSession *session, SFTKObject *object, 1111 CK_KEY_TYPE key_type) 1112 { 1113 CK_BBOOL encrypt = CK_TRUE; 1114 CK_BBOOL recover = CK_TRUE; 1115 CK_BBOOL wrap = CK_TRUE; 1116 CK_BBOOL derive = CK_FALSE; 1117 CK_BBOOL verify = CK_TRUE; 1118 CK_BBOOL encapsulate = CK_FALSE; 1119 CK_ULONG paramSet = 0; 1120 CK_RV crv; 1121 1122 switch (key_type) { 1123 case CKK_RSA: 1124 crv = sftk_ConstrainAttribute(object, CKA_MODULUS, 1125 RSA_MIN_MODULUS_BITS, 0, 0); 1126 if (crv != CKR_OK) { 1127 return crv; 1128 } 1129 crv = sftk_ConstrainAttribute(object, CKA_PUBLIC_EXPONENT, 2, 0, 0); 1130 if (crv != CKR_OK) { 1131 return crv; 1132 } 1133 break; 1134 case CKK_DSA: 1135 crv = sftk_ConstrainAttribute(object, CKA_SUBPRIME, 1136 DSA_MIN_Q_BITS, DSA_MAX_Q_BITS, 0); 1137 if (crv != CKR_OK) { 1138 return crv; 1139 } 1140 crv = sftk_ConstrainAttribute(object, CKA_PRIME, 1141 DSA_MIN_P_BITS, DSA_MAX_P_BITS, 64); 1142 if (crv != CKR_OK) { 1143 return crv; 1144 } 1145 crv = sftk_ConstrainAttribute(object, CKA_BASE, 2, DSA_MAX_P_BITS, 0); 1146 if (crv != CKR_OK) { 1147 return crv; 1148 } 1149 crv = sftk_ConstrainAttribute(object, CKA_VALUE, 2, DSA_MAX_P_BITS, 0); 1150 if (crv != CKR_OK) { 1151 return crv; 1152 } 1153 encrypt = CK_FALSE; 1154 recover = CK_FALSE; 1155 wrap = CK_FALSE; 1156 break; 1157 case CKK_DH: 1158 crv = sftk_ConstrainAttribute(object, CKA_PRIME, 1159 DH_MIN_P_BITS, DH_MAX_P_BITS, 0); 1160 if (crv != CKR_OK) { 1161 return crv; 1162 } 1163 crv = sftk_ConstrainAttribute(object, CKA_BASE, 2, DH_MAX_P_BITS, 0); 1164 if (crv != CKR_OK) { 1165 return crv; 1166 } 1167 crv = sftk_ConstrainAttribute(object, CKA_VALUE, 2, DH_MAX_P_BITS, 0); 1168 if (crv != CKR_OK) { 1169 return crv; 1170 } 1171 verify = CK_FALSE; 1172 derive = CK_TRUE; 1173 encrypt = CK_FALSE; 1174 recover = CK_FALSE; 1175 wrap = CK_FALSE; 1176 break; 1177 case CKK_EC_MONTGOMERY: 1178 case CKK_EC_EDWARDS: 1179 case CKK_EC: 1180 if (!sftk_hasAttribute(object, CKA_EC_PARAMS)) { 1181 return CKR_TEMPLATE_INCOMPLETE; 1182 } 1183 if (!sftk_hasAttribute(object, CKA_EC_POINT)) { 1184 return CKR_TEMPLATE_INCOMPLETE; 1185 } 1186 /* for ECDSA and EDDSA. Change if the structure of any of them is modified. */ 1187 derive = (key_type == CKK_EC_EDWARDS) ? CK_FALSE : CK_TRUE; /* CK_TRUE for ECDH */ 1188 verify = (key_type == CKK_EC_MONTGOMERY) ? CK_FALSE : CK_TRUE; /* for ECDSA and EDDSA */ 1189 encrypt = CK_FALSE; 1190 recover = CK_FALSE; 1191 wrap = CK_FALSE; 1192 break; 1193 #ifndef NSS_DISABLE_KYBER 1194 case CKK_NSS_KYBER: 1195 #endif 1196 case CKK_NSS_ML_KEM: 1197 case CKK_ML_KEM: 1198 if (!sftk_hasAttribute(object, CKA_PARAMETER_SET)) { 1199 if (!sftk_hasAttribute(object, CKA_NSS_PARAMETER_SET)) { 1200 return CKR_TEMPLATE_INCOMPLETE; 1201 } 1202 } 1203 derive = CK_FALSE; 1204 verify = CK_FALSE; 1205 encrypt = CK_FALSE; 1206 recover = CK_FALSE; 1207 wrap = CK_FALSE; 1208 encapsulate = CK_TRUE; 1209 break; 1210 case CKK_ML_DSA: 1211 if (!sftk_hasAttribute(object, CKA_PARAMETER_SET)) { 1212 return CKR_TEMPLATE_INCOMPLETE; 1213 } 1214 crv = sftk_GetULongAttribute(object, CKA_PARAMETER_SET, 1215 ¶mSet); 1216 if (crv != CKR_OK) { 1217 return crv; 1218 } 1219 if (sftk_MLDSAGetSigLen(paramSet) == 0) { 1220 return CKR_ATTRIBUTE_VALUE_INVALID; 1221 } 1222 derive = CK_FALSE; 1223 verify = CK_TRUE; 1224 encrypt = CK_FALSE; 1225 recover = CK_FALSE; 1226 wrap = CK_FALSE; 1227 encapsulate = CK_FALSE; 1228 break; 1229 default: 1230 return CKR_ATTRIBUTE_VALUE_INVALID; 1231 } 1232 1233 /* make sure the required fields exist */ 1234 crv = sftk_defaultAttribute(object, CKA_SUBJECT, NULL, 0); 1235 if (crv != CKR_OK) 1236 return crv; 1237 crv = sftk_defaultAttribute(object, CKA_ENCRYPT, &encrypt, sizeof(CK_BBOOL)); 1238 if (crv != CKR_OK) 1239 return crv; 1240 crv = sftk_defaultAttribute(object, CKA_VERIFY, &verify, sizeof(CK_BBOOL)); 1241 if (crv != CKR_OK) 1242 return crv; 1243 crv = sftk_defaultAttribute(object, CKA_VERIFY_RECOVER, 1244 &recover, sizeof(CK_BBOOL)); 1245 if (crv != CKR_OK) 1246 return crv; 1247 crv = sftk_defaultAttribute(object, CKA_WRAP, &wrap, sizeof(CK_BBOOL)); 1248 if (crv != CKR_OK) 1249 return crv; 1250 crv = sftk_defaultAttribute(object, CKA_DERIVE, &derive, sizeof(CK_BBOOL)); 1251 if (crv != CKR_OK) 1252 return crv; 1253 crv = sftk_defaultAttribute(object, CKA_ENCAPSULATE, &encapsulate, 1254 sizeof(CK_BBOOL)); 1255 if (crv != CKR_OK) 1256 return crv; 1257 object->objectInfo = sftk_GetPubKey(object, key_type, &crv); 1258 if (object->objectInfo == NULL) { 1259 return crv; 1260 } 1261 object->infoFree = SFTKFree_nsslowkey_DestroyPublicKey; 1262 1263 /* Check that an imported EC key is valid */ 1264 if (key_type == CKK_EC || key_type == CKK_EC_EDWARDS || key_type == CKK_EC_MONTGOMERY) { 1265 NSSLOWKEYPublicKey *pubKey = (NSSLOWKEYPublicKey *)object->objectInfo; 1266 SECStatus rv = EC_ValidatePublicKey(&pubKey->u.ec.ecParams, 1267 &pubKey->u.ec.publicValue); 1268 1269 if (rv != SECSuccess) { 1270 return CKR_TEMPLATE_INCONSISTENT; 1271 } 1272 } 1273 1274 if (sftk_isTrue(object, CKA_TOKEN)) { 1275 SFTKSlot *slot = session->slot; 1276 SFTKDBHandle *certHandle = sftk_getCertDB(slot); 1277 1278 if (certHandle == NULL) { 1279 return CKR_TOKEN_WRITE_PROTECTED; 1280 } 1281 1282 crv = sftkdb_write(certHandle, object, &object->handle); 1283 sftk_freeDB(certHandle); 1284 return crv; 1285 } 1286 1287 return CKR_OK; 1288 } 1289 1290 static NSSLOWKEYPrivateKey * 1291 sftk_mkPrivKey(SFTKObject *object, CK_KEY_TYPE key, CK_RV *rvp); 1292 1293 static SECStatus 1294 sftk_verifyRSAPrivateKey(SFTKObject *object, PRBool fillIfNeeded); 1295 1296 /* 1297 * check the consistancy and initialize a Private Key Object 1298 */ 1299 static CK_RV 1300 sftk_handlePrivateKeyObject(SFTKSession *session, SFTKObject *object, CK_KEY_TYPE key_type) 1301 { 1302 CK_BBOOL cktrue = CK_TRUE; 1303 CK_BBOOL encrypt = CK_TRUE; 1304 CK_BBOOL sign = CK_FALSE; 1305 CK_BBOOL recover = CK_TRUE; 1306 CK_BBOOL wrap = CK_TRUE; 1307 CK_BBOOL derive = CK_TRUE; 1308 CK_BBOOL decapsulate = CK_FALSE; 1309 CK_BBOOL ckfalse = CK_FALSE; 1310 CK_ULONG paramSet = 0; 1311 PRBool createObjectInfo = PR_TRUE; 1312 PRBool fillPrivateKey = PR_FALSE; 1313 int missing_rsa_mod_component = 0; 1314 int missing_rsa_exp_component = 0; 1315 int missing_rsa_crt_component = 0; 1316 1317 SECItem mod; 1318 CK_RV crv; 1319 SECStatus rv; 1320 1321 switch (key_type) { 1322 case CKK_RSA: 1323 if (!sftk_hasAttribute(object, CKA_MODULUS)) { 1324 missing_rsa_mod_component++; 1325 } 1326 if (!sftk_hasAttribute(object, CKA_PUBLIC_EXPONENT)) { 1327 missing_rsa_exp_component++; 1328 } 1329 if (!sftk_hasAttribute(object, CKA_PRIVATE_EXPONENT)) { 1330 missing_rsa_exp_component++; 1331 } 1332 if (!sftk_hasAttribute(object, CKA_PRIME_1)) { 1333 missing_rsa_mod_component++; 1334 } 1335 if (!sftk_hasAttribute(object, CKA_PRIME_2)) { 1336 missing_rsa_mod_component++; 1337 } 1338 if (!sftk_hasAttribute(object, CKA_EXPONENT_1)) { 1339 missing_rsa_crt_component++; 1340 } 1341 if (!sftk_hasAttribute(object, CKA_EXPONENT_2)) { 1342 missing_rsa_crt_component++; 1343 } 1344 if (!sftk_hasAttribute(object, CKA_COEFFICIENT)) { 1345 missing_rsa_crt_component++; 1346 } 1347 if (missing_rsa_mod_component || missing_rsa_exp_component || 1348 missing_rsa_crt_component) { 1349 /* we are missing a component, see if we have enough to rebuild 1350 * the rest */ 1351 int have_exp = 2 - missing_rsa_exp_component; 1352 int have_component = 5 - 1353 (missing_rsa_exp_component + missing_rsa_mod_component); 1354 1355 if ((have_exp == 0) || (have_component < 3)) { 1356 /* nope, not enough to reconstruct the private key */ 1357 return CKR_TEMPLATE_INCOMPLETE; 1358 } 1359 fillPrivateKey = PR_TRUE; 1360 } 1361 /*verify the parameters for consistency*/ 1362 rv = sftk_verifyRSAPrivateKey(object, fillPrivateKey); 1363 if (rv != SECSuccess) { 1364 return CKR_TEMPLATE_INCOMPLETE; 1365 } 1366 1367 /* make sure Netscape DB attribute is set correctly */ 1368 crv = sftk_Attribute2SSecItem(NULL, &mod, object, CKA_MODULUS); 1369 if (crv != CKR_OK) 1370 return crv; 1371 crv = sftk_forceAttribute(object, CKA_NSS_DB, 1372 sftk_item_expand(&mod)); 1373 if (mod.data) 1374 SECITEM_ZfreeItem(&mod, PR_FALSE); 1375 if (crv != CKR_OK) 1376 return crv; 1377 1378 sign = CK_TRUE; 1379 derive = CK_FALSE; 1380 break; 1381 case CKK_DSA: 1382 if (!sftk_hasAttribute(object, CKA_SUBPRIME)) { 1383 return CKR_TEMPLATE_INCOMPLETE; 1384 } 1385 sign = CK_TRUE; 1386 derive = CK_FALSE; 1387 /* fall through */ 1388 case CKK_DH: 1389 if (!sftk_hasAttribute(object, CKA_PRIME)) { 1390 return CKR_TEMPLATE_INCOMPLETE; 1391 } 1392 if (!sftk_hasAttribute(object, CKA_BASE)) { 1393 return CKR_TEMPLATE_INCOMPLETE; 1394 } 1395 if (!sftk_hasAttribute(object, CKA_VALUE)) { 1396 return CKR_TEMPLATE_INCOMPLETE; 1397 } 1398 /* allow subprime to be set after the fact */ 1399 crv = sftk_defaultAttribute(object, CKA_SUBPRIME, NULL, 0); 1400 if (crv != CKR_OK) { 1401 return crv; 1402 } 1403 encrypt = CK_FALSE; 1404 recover = CK_FALSE; 1405 wrap = CK_FALSE; 1406 break; 1407 case CKK_EC: 1408 case CKK_EC_EDWARDS: 1409 case CKK_EC_MONTGOMERY: 1410 if (!sftk_hasAttribute(object, CKA_EC_PARAMS)) { 1411 return CKR_TEMPLATE_INCOMPLETE; 1412 } 1413 if (!sftk_hasAttribute(object, CKA_VALUE)) { 1414 return CKR_TEMPLATE_INCOMPLETE; 1415 } 1416 /* for ECDSA and EDDSA. Change if the structure of any of them is modified. */ 1417 derive = (key_type == CKK_EC_EDWARDS) ? CK_FALSE : CK_TRUE; /* CK_TRUE for ECDH */ 1418 sign = (key_type == CKK_EC_MONTGOMERY) ? CK_FALSE : CK_TRUE; /* for ECDSA and EDDSA */ 1419 encrypt = CK_FALSE; 1420 recover = CK_FALSE; 1421 wrap = CK_FALSE; 1422 break; 1423 case CKK_NSS_JPAKE_ROUND1: 1424 if (!sftk_hasAttribute(object, CKA_PRIME) || 1425 !sftk_hasAttribute(object, CKA_SUBPRIME) || 1426 !sftk_hasAttribute(object, CKA_BASE)) { 1427 return CKR_TEMPLATE_INCOMPLETE; 1428 } 1429 /* fall through */ 1430 case CKK_NSS_JPAKE_ROUND2: 1431 /* CKA_NSS_JPAKE_SIGNERID and CKA_NSS_JPAKE_PEERID are checked in 1432 the J-PAKE code. */ 1433 encrypt = sign = recover = wrap = CK_FALSE; 1434 derive = CK_TRUE; 1435 createObjectInfo = PR_FALSE; 1436 break; 1437 #ifndef NSS_DISABLE_KYBER 1438 case CKK_NSS_KYBER: 1439 #endif 1440 case CKK_NSS_ML_KEM: 1441 case CKK_ML_KEM: 1442 if (!sftk_hasAttribute(object, CKA_KEY_TYPE)) { 1443 return CKR_TEMPLATE_INCOMPLETE; 1444 } 1445 if (!sftk_hasAttribute(object, CKA_VALUE)) { 1446 return CKR_TEMPLATE_INCOMPLETE; 1447 } 1448 if (!sftk_hasAttribute(object, CKA_PARAMETER_SET)) { 1449 if (!sftk_hasAttribute(object, CKA_NSS_PARAMETER_SET)) { 1450 return CKR_TEMPLATE_INCOMPLETE; 1451 } 1452 } 1453 derive = CK_FALSE; 1454 sign = CK_FALSE; 1455 encrypt = CK_FALSE; 1456 recover = CK_FALSE; 1457 wrap = CK_FALSE; 1458 decapsulate = CK_TRUE; 1459 break; 1460 case CKK_ML_DSA: 1461 if (!sftk_hasAttribute(object, CKA_KEY_TYPE)) { 1462 return CKR_TEMPLATE_INCOMPLETE; 1463 } 1464 /* make sure we have a CKA_PARAMETER_SET */ 1465 if (!sftk_hasAttribute(object, CKA_PARAMETER_SET)) { 1466 return CKR_TEMPLATE_INCOMPLETE; 1467 } 1468 /* make sure it's one we understand */ 1469 crv = sftk_GetULongAttribute(object, CKA_PARAMETER_SET, 1470 ¶mSet); 1471 if (crv != CKR_OK) { 1472 return crv; 1473 } 1474 if (sftk_MLDSAGetSigLen(paramSet) == 0) { 1475 return CKR_ATTRIBUTE_VALUE_INVALID; 1476 } 1477 /* 1478 * if we have a seed deal with making sure seed and 1479 * CKA_VALUE . We skip this step if the SEED and VALUE 1480 * was generated together by us. */ 1481 if (sftk_hasAttribute(object, CKA_SEED)) { 1482 PRBool seedOK = sftk_hasAttribute(object, CKA_NSS_SEED_OK); 1483 SFTKAttribute *seedAttribute = sftk_FindAttribute(object, 1484 CKA_SEED); 1485 PORT_Assert(seedAttribute); 1486 crv = CKR_OK; 1487 if (seedAttribute->attrib.ulValueLen != 0) { 1488 SFTKAttribute *valueAttribute = 1489 sftk_FindAttribute(object, CKA_VALUE); 1490 unsigned int valueLen = valueAttribute ? valueAttribute->attrib.ulValueLen : 0; 1491 if (!seedOK || valueLen == 0) { 1492 MLDSAPrivateKey privKey; 1493 MLDSAPublicKey pubKey; 1494 SECItem seedItem; 1495 1496 seedItem.data = seedAttribute->attrib.pValue; 1497 seedItem.len = seedAttribute->attrib.ulValueLen; 1498 rv = MLDSA_NewKey(paramSet, &seedItem, &privKey, 1499 &pubKey); 1500 if (rv != SECSuccess) { 1501 crv = CKR_ATTRIBUTE_VALUE_INVALID; 1502 } else if (valueLen == 0) { 1503 crv = sftk_forceAttribute(object, CKA_VALUE, 1504 privKey.keyVal, 1505 privKey.keyValLen); 1506 } else { 1507 /* we have the value, so we must need to 1508 * verify it */ 1509 PORT_Assert(!seedOK); 1510 if ((privKey.keyValLen != valueLen) || 1511 (PORT_Memcmp(valueAttribute->attrib.pValue, 1512 privKey.keyVal, valueLen) != 0)) { 1513 crv = CKR_ATTRIBUTE_VALUE_INVALID; 1514 } 1515 } 1516 PORT_SafeZero(&privKey, sizeof(privKey)); 1517 PORT_SafeZero(&pubKey, sizeof(pubKey)); 1518 } 1519 if (valueAttribute) 1520 sftk_FreeAttribute(valueAttribute); 1521 } 1522 sftk_FreeAttribute(seedAttribute); 1523 if (crv != CKR_OK) { 1524 return crv; 1525 } 1526 } 1527 sftk_DeleteAttributeType(object, CKA_NSS_SEED_OK); 1528 /* if we got this far, we should have a CKA_VALUE, either but 1529 * one given to us, or by it being generated above */ 1530 if (!sftk_hasAttribute(object, CKA_VALUE)) { 1531 return CKR_TEMPLATE_INCOMPLETE; 1532 } 1533 encrypt = decapsulate = recover = wrap = CK_FALSE; 1534 sign = CK_TRUE; 1535 break; 1536 1537 default: 1538 return CKR_ATTRIBUTE_VALUE_INVALID; 1539 } 1540 crv = sftk_defaultAttribute(object, CKA_SUBJECT, NULL, 0); 1541 if (crv != CKR_OK) 1542 return crv; 1543 crv = sftk_defaultAttribute(object, CKA_SENSITIVE, &cktrue, sizeof(CK_BBOOL)); 1544 if (crv != CKR_OK) 1545 return crv; 1546 crv = sftk_defaultAttribute(object, CKA_EXTRACTABLE, &cktrue, sizeof(CK_BBOOL)); 1547 if (crv != CKR_OK) 1548 return crv; 1549 crv = sftk_defaultAttribute(object, CKA_DECRYPT, &encrypt, sizeof(CK_BBOOL)); 1550 if (crv != CKR_OK) 1551 return crv; 1552 crv = sftk_defaultAttribute(object, CKA_SIGN, &sign, sizeof(CK_BBOOL)); 1553 if (crv != CKR_OK) 1554 return crv; 1555 crv = sftk_defaultAttribute(object, CKA_SIGN_RECOVER, &recover, 1556 sizeof(CK_BBOOL)); 1557 if (crv != CKR_OK) 1558 return crv; 1559 crv = sftk_defaultAttribute(object, CKA_UNWRAP, &wrap, sizeof(CK_BBOOL)); 1560 if (crv != CKR_OK) 1561 return crv; 1562 crv = sftk_defaultAttribute(object, CKA_DERIVE, &derive, sizeof(CK_BBOOL)); 1563 if (crv != CKR_OK) 1564 return crv; 1565 crv = sftk_defaultAttribute(object, CKA_DECAPSULATE, &decapsulate, 1566 sizeof(CK_BBOOL)); 1567 if (crv != CKR_OK) 1568 return crv; 1569 /* the next two bits get modified only in the key gen and token cases */ 1570 crv = sftk_forceAttribute(object, CKA_ALWAYS_SENSITIVE, 1571 &ckfalse, sizeof(CK_BBOOL)); 1572 if (crv != CKR_OK) 1573 return crv; 1574 crv = sftk_forceAttribute(object, CKA_NEVER_EXTRACTABLE, 1575 &ckfalse, sizeof(CK_BBOOL)); 1576 if (crv != CKR_OK) 1577 return crv; 1578 1579 /* should we check the non-token RSA private keys? */ 1580 1581 if (sftk_isTrue(object, CKA_TOKEN)) { 1582 SFTKSlot *slot = session->slot; 1583 SFTKDBHandle *keyHandle = sftk_getKeyDB(slot); 1584 1585 if (keyHandle == NULL) { 1586 return CKR_TOKEN_WRITE_PROTECTED; 1587 } 1588 1589 crv = sftkdb_write(keyHandle, object, &object->handle); 1590 sftk_freeDB(keyHandle); 1591 return crv; 1592 } else if (createObjectInfo) { 1593 object->objectInfo = sftk_mkPrivKey(object, key_type, &crv); 1594 if (object->objectInfo == NULL) 1595 return crv; 1596 object->infoFree = SFTKFree_nsslowkey_DestroyPrivateKey; 1597 } 1598 return CKR_OK; 1599 } 1600 1601 /* forward declare the DES formating function for handleSecretKey */ 1602 void sftk_FormatDESKey(unsigned char *key, int length); 1603 1604 /* Validate secret key data, and set defaults */ 1605 static CK_RV 1606 validateSecretKey(SFTKSession *session, SFTKObject *object, 1607 CK_KEY_TYPE key_type, PRBool isFIPS) 1608 { 1609 CK_RV crv; 1610 CK_BBOOL cktrue = CK_TRUE; 1611 CK_BBOOL ckfalse = CK_FALSE; 1612 SFTKAttribute *attribute = NULL; 1613 unsigned long requiredLen; 1614 1615 crv = sftk_defaultAttribute(object, CKA_SENSITIVE, 1616 isFIPS ? &cktrue : &ckfalse, sizeof(CK_BBOOL)); 1617 if (crv != CKR_OK) 1618 return crv; 1619 crv = sftk_defaultAttribute(object, CKA_EXTRACTABLE, 1620 &cktrue, sizeof(CK_BBOOL)); 1621 if (crv != CKR_OK) 1622 return crv; 1623 crv = sftk_defaultAttribute(object, CKA_ENCRYPT, &cktrue, sizeof(CK_BBOOL)); 1624 if (crv != CKR_OK) 1625 return crv; 1626 crv = sftk_defaultAttribute(object, CKA_DECRYPT, &cktrue, sizeof(CK_BBOOL)); 1627 if (crv != CKR_OK) 1628 return crv; 1629 crv = sftk_defaultAttribute(object, CKA_SIGN, &ckfalse, sizeof(CK_BBOOL)); 1630 if (crv != CKR_OK) 1631 return crv; 1632 crv = sftk_defaultAttribute(object, CKA_VERIFY, &ckfalse, sizeof(CK_BBOOL)); 1633 if (crv != CKR_OK) 1634 return crv; 1635 crv = sftk_defaultAttribute(object, CKA_WRAP, &cktrue, sizeof(CK_BBOOL)); 1636 if (crv != CKR_OK) 1637 return crv; 1638 crv = sftk_defaultAttribute(object, CKA_UNWRAP, &cktrue, sizeof(CK_BBOOL)); 1639 if (crv != CKR_OK) 1640 return crv; 1641 1642 if (!sftk_hasAttribute(object, CKA_VALUE)) { 1643 return CKR_TEMPLATE_INCOMPLETE; 1644 } 1645 /* the next two bits get modified only in the key gen and token cases */ 1646 crv = sftk_forceAttribute(object, CKA_ALWAYS_SENSITIVE, 1647 &ckfalse, sizeof(CK_BBOOL)); 1648 if (crv != CKR_OK) 1649 return crv; 1650 crv = sftk_forceAttribute(object, CKA_NEVER_EXTRACTABLE, 1651 &ckfalse, sizeof(CK_BBOOL)); 1652 if (crv != CKR_OK) 1653 return crv; 1654 1655 /* some types of keys have a value length */ 1656 crv = CKR_OK; 1657 switch (key_type) { 1658 /* force CKA_VALUE_LEN to be set */ 1659 case CKK_GENERIC_SECRET: 1660 case CKK_RC2: 1661 case CKK_RC4: 1662 #if NSS_SOFTOKEN_DOES_RC5 1663 case CKK_RC5: 1664 #endif 1665 #ifdef NSS_SOFTOKEN_DOES_CAST 1666 case CKK_CAST: 1667 case CKK_CAST3: 1668 case CKK_CAST5: 1669 #endif 1670 #if NSS_SOFTOKEN_DOES_IDEA 1671 case CKK_IDEA: 1672 #endif 1673 attribute = sftk_FindAttribute(object, CKA_VALUE); 1674 /* shouldn't happen */ 1675 if (attribute == NULL) 1676 return CKR_TEMPLATE_INCOMPLETE; 1677 crv = sftk_forceAttribute(object, CKA_VALUE_LEN, 1678 &attribute->attrib.ulValueLen, sizeof(CK_ULONG)); 1679 sftk_FreeAttribute(attribute); 1680 break; 1681 /* force the value to have the correct parity */ 1682 case CKK_DES: 1683 case CKK_DES2: 1684 case CKK_DES3: 1685 case CKK_CDMF: 1686 attribute = sftk_FindAttribute(object, CKA_VALUE); 1687 /* shouldn't happen */ 1688 if (attribute == NULL) 1689 return CKR_TEMPLATE_INCOMPLETE; 1690 requiredLen = sftk_MapKeySize(key_type); 1691 if (attribute->attrib.ulValueLen != requiredLen) { 1692 sftk_FreeAttribute(attribute); 1693 return CKR_KEY_SIZE_RANGE; 1694 } 1695 sftk_FormatDESKey((unsigned char *)attribute->attrib.pValue, 1696 attribute->attrib.ulValueLen); 1697 sftk_FreeAttribute(attribute); 1698 break; 1699 case CKK_AES: 1700 attribute = sftk_FindAttribute(object, CKA_VALUE); 1701 /* shouldn't happen */ 1702 if (attribute == NULL) 1703 return CKR_TEMPLATE_INCOMPLETE; 1704 if (attribute->attrib.ulValueLen != 16 && 1705 attribute->attrib.ulValueLen != 24 && 1706 attribute->attrib.ulValueLen != 32) { 1707 sftk_FreeAttribute(attribute); 1708 return CKR_KEY_SIZE_RANGE; 1709 } 1710 crv = sftk_forceAttribute(object, CKA_VALUE_LEN, 1711 &attribute->attrib.ulValueLen, sizeof(CK_ULONG)); 1712 sftk_FreeAttribute(attribute); 1713 break; 1714 default: 1715 break; 1716 } 1717 1718 return crv; 1719 } 1720 1721 /* 1722 * check the consistancy and initialize a Secret Key Object 1723 */ 1724 static CK_RV 1725 sftk_handleSecretKeyObject(SFTKSession *session, SFTKObject *object, 1726 CK_KEY_TYPE key_type, PRBool isFIPS) 1727 { 1728 CK_RV crv; 1729 1730 /* First validate and set defaults */ 1731 crv = validateSecretKey(session, object, key_type, isFIPS); 1732 if (crv != CKR_OK) 1733 goto loser; 1734 1735 /* If the object is a TOKEN object, store in the database */ 1736 if (sftk_isTrue(object, CKA_TOKEN)) { 1737 SFTKSlot *slot = session->slot; 1738 SFTKDBHandle *keyHandle = sftk_getKeyDB(slot); 1739 1740 if (keyHandle == NULL) { 1741 return CKR_TOKEN_WRITE_PROTECTED; 1742 } 1743 1744 crv = sftkdb_write(keyHandle, object, &object->handle); 1745 sftk_freeDB(keyHandle); 1746 return crv; 1747 } 1748 1749 loser: 1750 1751 return crv; 1752 } 1753 1754 /* 1755 * check the consistancy and initialize a Key Object 1756 */ 1757 static CK_RV 1758 sftk_handleKeyObject(SFTKSession *session, SFTKObject *object) 1759 { 1760 SFTKAttribute *attribute; 1761 CK_KEY_TYPE key_type; 1762 CK_BBOOL ckfalse = CK_FALSE; 1763 CK_RV crv; 1764 1765 /* verify the required fields */ 1766 if (!sftk_hasAttribute(object, CKA_KEY_TYPE)) { 1767 return CKR_TEMPLATE_INCOMPLETE; 1768 } 1769 1770 /* now verify the common fields */ 1771 crv = sftk_defaultAttribute(object, CKA_ID, NULL, 0); 1772 if (crv != CKR_OK) 1773 return crv; 1774 crv = sftk_defaultAttribute(object, CKA_START_DATE, NULL, 0); 1775 if (crv != CKR_OK) 1776 return crv; 1777 crv = sftk_defaultAttribute(object, CKA_END_DATE, NULL, 0); 1778 if (crv != CKR_OK) 1779 return crv; 1780 /* CKA_DERIVE is common to all keys, but it's default value is 1781 * key dependent */ 1782 crv = sftk_defaultAttribute(object, CKA_LOCAL, &ckfalse, sizeof(CK_BBOOL)); 1783 if (crv != CKR_OK) 1784 return crv; 1785 1786 /* get the key type */ 1787 attribute = sftk_FindAttribute(object, CKA_KEY_TYPE); 1788 if (!attribute) { 1789 return CKR_ATTRIBUTE_VALUE_INVALID; 1790 } 1791 key_type = *(CK_KEY_TYPE *)attribute->attrib.pValue; 1792 sftk_FreeAttribute(attribute); 1793 1794 switch (object->objclass) { 1795 case CKO_PUBLIC_KEY: 1796 return sftk_handlePublicKeyObject(session, object, key_type); 1797 case CKO_PRIVATE_KEY: 1798 return sftk_handlePrivateKeyObject(session, object, key_type); 1799 case CKO_SECRET_KEY: 1800 /* make sure the required fields exist */ 1801 return sftk_handleSecretKeyObject(session, object, key_type, 1802 (PRBool)(sftk_isFIPS(session->slot->slotID))); 1803 default: 1804 break; 1805 } 1806 return CKR_ATTRIBUTE_VALUE_INVALID; 1807 } 1808 1809 /* 1810 * check the consistancy and Verify a DSA Parameter Object 1811 */ 1812 static CK_RV 1813 sftk_handleDSAParameterObject(SFTKSession *session, SFTKObject *object) 1814 { 1815 SFTKAttribute *primeAttr = NULL; 1816 SFTKAttribute *subPrimeAttr = NULL; 1817 SFTKAttribute *baseAttr = NULL; 1818 SFTKAttribute *seedAttr = NULL; 1819 SFTKAttribute *hAttr = NULL; 1820 SFTKAttribute *attribute; 1821 CK_RV crv = CKR_TEMPLATE_INCOMPLETE; 1822 PQGParams params; 1823 PQGVerify vfy, *verify = NULL; 1824 SECStatus result, rv; 1825 /* This bool keeps track of whether or not we need verify parameters. 1826 * If a P, Q and G or supplied, we dont' need verify parameters, as we 1827 * have PQ and G. 1828 * - If G is not supplied, the presumption is that we want to 1829 * verify P and Q only. 1830 * - If counter is supplied, it is presumed we want to verify PQ because 1831 * the counter is only used in verification. 1832 * - If H is supplied, is is presumed we want to verify G because H is 1833 * only used to verify G. 1834 * - Any verification step must have the SEED (counter or H could be 1835 * missing depending on exactly what we want to verify). If SEED is supplied, 1836 * the code just goes ahead and runs verify (other errors are parameter 1837 * errors are detected by the PQG_VerifyParams function). If SEED is not 1838 * supplied, but we determined that we are trying to verify (because needVfy 1839 * is set, go ahead and return CKR_TEMPLATE_INCOMPLETE. 1840 */ 1841 PRBool needVfy = PR_FALSE; 1842 1843 primeAttr = sftk_FindAttribute(object, CKA_PRIME); 1844 if (primeAttr == NULL) 1845 goto loser; 1846 params.prime.data = primeAttr->attrib.pValue; 1847 params.prime.len = primeAttr->attrib.ulValueLen; 1848 1849 subPrimeAttr = sftk_FindAttribute(object, CKA_SUBPRIME); 1850 if (subPrimeAttr == NULL) 1851 goto loser; 1852 params.subPrime.data = subPrimeAttr->attrib.pValue; 1853 params.subPrime.len = subPrimeAttr->attrib.ulValueLen; 1854 1855 baseAttr = sftk_FindAttribute(object, CKA_BASE); 1856 if (baseAttr != NULL) { 1857 params.base.data = baseAttr->attrib.pValue; 1858 params.base.len = baseAttr->attrib.ulValueLen; 1859 } else { 1860 params.base.data = NULL; 1861 params.base.len = 0; 1862 needVfy = PR_TRUE; /* presumably only including PQ so we can verify 1863 * them. */ 1864 } 1865 1866 attribute = sftk_FindAttribute(object, CKA_NSS_PQG_COUNTER); 1867 if (attribute != NULL) { 1868 vfy.counter = *(CK_ULONG *)attribute->attrib.pValue; 1869 sftk_FreeAttribute(attribute); 1870 needVfy = PR_TRUE; /* included a count so we can verify PQ */ 1871 } else { 1872 vfy.counter = -1; 1873 } 1874 1875 hAttr = sftk_FindAttribute(object, CKA_NSS_PQG_H); 1876 if (hAttr != NULL) { 1877 vfy.h.data = hAttr->attrib.pValue; 1878 vfy.h.len = hAttr->attrib.ulValueLen; 1879 needVfy = PR_TRUE; /* included H so we can verify G */ 1880 } else { 1881 vfy.h.data = NULL; 1882 vfy.h.len = 0; 1883 } 1884 seedAttr = sftk_FindAttribute(object, CKA_NSS_PQG_SEED); 1885 if (seedAttr != NULL) { 1886 vfy.seed.data = seedAttr->attrib.pValue; 1887 vfy.seed.len = seedAttr->attrib.ulValueLen; 1888 1889 verify = &vfy; 1890 } else if (needVfy) { 1891 goto loser; /* Verify always needs seed, if we need verify and not seed 1892 * then fail */ 1893 } 1894 1895 crv = CKR_FUNCTION_FAILED; 1896 rv = PQG_VerifyParams(¶ms, verify, &result); 1897 if (rv == SECSuccess) { 1898 crv = (result == SECSuccess) ? CKR_OK : CKR_ATTRIBUTE_VALUE_INVALID; 1899 } 1900 1901 loser: 1902 if (hAttr) 1903 sftk_FreeAttribute(hAttr); 1904 if (seedAttr) 1905 sftk_FreeAttribute(seedAttr); 1906 if (baseAttr) 1907 sftk_FreeAttribute(baseAttr); 1908 if (subPrimeAttr) 1909 sftk_FreeAttribute(subPrimeAttr); 1910 if (primeAttr) 1911 sftk_FreeAttribute(primeAttr); 1912 1913 return crv; 1914 } 1915 1916 /* 1917 * check the consistancy and initialize a Key Parameter Object 1918 */ 1919 static CK_RV 1920 sftk_handleKeyParameterObject(SFTKSession *session, SFTKObject *object) 1921 { 1922 SFTKAttribute *attribute; 1923 CK_KEY_TYPE key_type; 1924 CK_BBOOL ckfalse = CK_FALSE; 1925 CK_RV crv; 1926 1927 /* verify the required fields */ 1928 if (!sftk_hasAttribute(object, CKA_KEY_TYPE)) { 1929 return CKR_TEMPLATE_INCOMPLETE; 1930 } 1931 1932 /* now verify the common fields */ 1933 crv = sftk_defaultAttribute(object, CKA_LOCAL, &ckfalse, sizeof(CK_BBOOL)); 1934 if (crv != CKR_OK) 1935 return crv; 1936 1937 /* get the key type */ 1938 attribute = sftk_FindAttribute(object, CKA_KEY_TYPE); 1939 if (!attribute) { 1940 return CKR_ATTRIBUTE_VALUE_INVALID; 1941 } 1942 key_type = *(CK_KEY_TYPE *)attribute->attrib.pValue; 1943 sftk_FreeAttribute(attribute); 1944 1945 switch (key_type) { 1946 case CKK_DSA: 1947 return sftk_handleDSAParameterObject(session, object); 1948 1949 default: 1950 break; 1951 } 1952 return CKR_KEY_TYPE_INCONSISTENT; 1953 } 1954 1955 /* 1956 * Handle Object does all the object consistancy checks, automatic attribute 1957 * generation, attribute defaulting, etc. If handleObject succeeds, the object 1958 * will be assigned an object handle, and the object installed in the session 1959 * or stored in the DB. 1960 */ 1961 CK_RV 1962 sftk_handleObject(SFTKObject *object, SFTKSession *session) 1963 { 1964 SFTKSlot *slot = session->slot; 1965 SFTKAttribute *attribute; 1966 CK_BBOOL ckfalse = CK_FALSE; 1967 CK_BBOOL cktrue = CK_TRUE; 1968 PRBool isLoggedIn, needLogin; 1969 CK_RV crv; 1970 1971 /* make sure all the base object types are defined. If not set the 1972 * defaults */ 1973 crv = sftk_defaultAttribute(object, CKA_TOKEN, &ckfalse, sizeof(CK_BBOOL)); 1974 if (crv != CKR_OK) 1975 return crv; 1976 crv = sftk_defaultAttribute(object, CKA_PRIVATE, &ckfalse, sizeof(CK_BBOOL)); 1977 if (crv != CKR_OK) 1978 return crv; 1979 crv = sftk_defaultAttribute(object, CKA_LABEL, NULL, 0); 1980 if (crv != CKR_OK) 1981 return crv; 1982 crv = sftk_defaultAttribute(object, CKA_MODIFIABLE, &cktrue, sizeof(CK_BBOOL)); 1983 if (crv != CKR_OK) 1984 return crv; 1985 1986 PZ_Lock(slot->slotLock); 1987 isLoggedIn = slot->isLoggedIn; 1988 needLogin = slot->needLogin; 1989 PZ_Unlock(slot->slotLock); 1990 1991 /* don't create a private object if we aren't logged in */ 1992 if (!isLoggedIn && needLogin && sftk_isTrue(object, CKA_PRIVATE)) { 1993 return CKR_USER_NOT_LOGGED_IN; 1994 } 1995 1996 if (((session->info.flags & CKF_RW_SESSION) == 0) && 1997 (sftk_isTrue(object, CKA_TOKEN))) { 1998 return CKR_SESSION_READ_ONLY; 1999 } 2000 2001 /* Assign a unique SESSION object handle to every new object, 2002 * whether it is a session object or a token object. 2003 * At this point, all new objects are structured as session objects. 2004 * Objects with the CKA_TOKEN attribute true will be turned into 2005 * token objects and will have a token object handle assigned to 2006 * them by a call to sftk_mkHandle in the handler for each object 2007 * class, invoked below. 2008 * 2009 * It may be helpful to note/remember that 2010 * sftk_narrowToXxxObject uses sftk_isToken, 2011 * sftk_isToken examines the sign bit of the object's handle, but 2012 * sftk_isTrue(...,CKA_TOKEN) examines the CKA_TOKEN attribute. 2013 */ 2014 object->handle = sftk_getNextHandle(slot); 2015 2016 /* get the object class */ 2017 attribute = sftk_FindAttribute(object, CKA_CLASS); 2018 if (attribute == NULL) { 2019 return CKR_TEMPLATE_INCOMPLETE; 2020 } 2021 object->objclass = *(CK_OBJECT_CLASS *)attribute->attrib.pValue; 2022 sftk_FreeAttribute(attribute); 2023 2024 /* Now handle the specific object class. 2025 * At this point, all objects are session objects, and the session 2026 * number must be passed to the object class handlers. 2027 */ 2028 switch (object->objclass) { 2029 case CKO_DATA: 2030 crv = sftk_handleDataObject(session, object); 2031 break; 2032 case CKO_CERTIFICATE: 2033 crv = sftk_handleCertObject(session, object); 2034 break; 2035 case CKO_NSS_TRUST: 2036 crv = sftk_handleNSSTrustObject(session, object); 2037 break; 2038 case CKO_TRUST: 2039 crv = sftk_handleTrustObject(session, object); 2040 break; 2041 case CKO_NSS_CRL: 2042 crv = sftk_handleCrlObject(session, object); 2043 break; 2044 case CKO_NSS_SMIME: 2045 crv = sftk_handleSMimeObject(session, object); 2046 break; 2047 case CKO_PRIVATE_KEY: 2048 case CKO_PUBLIC_KEY: 2049 case CKO_SECRET_KEY: 2050 crv = sftk_handleKeyObject(session, object); 2051 break; 2052 case CKO_DOMAIN_PARAMETERS: 2053 crv = sftk_handleKeyParameterObject(session, object); 2054 break; 2055 default: 2056 crv = CKR_ATTRIBUTE_VALUE_INVALID; 2057 break; 2058 } 2059 2060 /* can't fail from here on out unless the pk_handlXXX functions have 2061 * failed the request */ 2062 if (crv != CKR_OK) { 2063 return crv; 2064 } 2065 2066 /* Now link the object into the slot and session structures. 2067 * If the object has a true CKA_TOKEN attribute, the above object 2068 * class handlers will have set the sign bit in the object handle, 2069 * causing the following test to be true. 2070 */ 2071 if (sftk_isToken(object->handle)) { 2072 sftk_convertSessionToToken(object); 2073 } else { 2074 object->slot = slot; 2075 sftk_AddObject(session, object); 2076 } 2077 2078 return CKR_OK; 2079 } 2080 2081 /* 2082 * ******************** Public Key Utilities *************************** 2083 */ 2084 /* Generate a low public key structure from an object */ 2085 NSSLOWKEYPublicKey * 2086 sftk_GetPubKey(SFTKObject *object, CK_KEY_TYPE key_type, 2087 CK_RV *crvp) 2088 { 2089 NSSLOWKEYPublicKey *pubKey; 2090 PLArenaPool *arena; 2091 CK_RV crv; 2092 2093 if (object->objclass != CKO_PUBLIC_KEY) { 2094 *crvp = CKR_KEY_TYPE_INCONSISTENT; 2095 return NULL; 2096 } 2097 2098 if (sftk_isToken(object->handle)) { 2099 /* ferret out the token object handle */ 2100 } 2101 2102 /* If we already have a key, use it */ 2103 if (object->objectInfo) { 2104 *crvp = CKR_OK; 2105 return (NSSLOWKEYPublicKey *)object->objectInfo; 2106 } 2107 2108 /* allocate the structure */ 2109 arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); 2110 if (arena == NULL) { 2111 *crvp = CKR_HOST_MEMORY; 2112 return NULL; 2113 } 2114 2115 pubKey = (NSSLOWKEYPublicKey *) 2116 PORT_ArenaAlloc(arena, sizeof(NSSLOWKEYPublicKey)); 2117 if (pubKey == NULL) { 2118 PORT_FreeArena(arena, PR_FALSE); 2119 *crvp = CKR_HOST_MEMORY; 2120 return NULL; 2121 } 2122 2123 /* fill in the structure */ 2124 pubKey->arena = arena; 2125 switch (key_type) { 2126 case CKK_RSA: 2127 pubKey->keyType = NSSLOWKEYRSAKey; 2128 crv = sftk_Attribute2SSecItem(arena, &pubKey->u.rsa.modulus, 2129 object, CKA_MODULUS); 2130 if (crv != CKR_OK) 2131 break; 2132 crv = sftk_Attribute2SSecItem(arena, &pubKey->u.rsa.publicExponent, 2133 object, CKA_PUBLIC_EXPONENT); 2134 break; 2135 case CKK_DSA: 2136 pubKey->keyType = NSSLOWKEYDSAKey; 2137 crv = sftk_Attribute2SSecItem(arena, &pubKey->u.dsa.params.prime, 2138 object, CKA_PRIME); 2139 if (crv != CKR_OK) 2140 break; 2141 crv = sftk_Attribute2SSecItem(arena, &pubKey->u.dsa.params.subPrime, 2142 object, CKA_SUBPRIME); 2143 if (crv != CKR_OK) 2144 break; 2145 crv = sftk_Attribute2SSecItem(arena, &pubKey->u.dsa.params.base, 2146 object, CKA_BASE); 2147 if (crv != CKR_OK) 2148 break; 2149 crv = sftk_Attribute2SSecItem(arena, &pubKey->u.dsa.publicValue, 2150 object, CKA_VALUE); 2151 break; 2152 case CKK_DH: 2153 pubKey->keyType = NSSLOWKEYDHKey; 2154 crv = sftk_Attribute2SSecItem(arena, &pubKey->u.dh.prime, 2155 object, CKA_PRIME); 2156 if (crv != CKR_OK) 2157 break; 2158 crv = sftk_Attribute2SSecItem(arena, &pubKey->u.dh.base, 2159 object, CKA_BASE); 2160 if (crv != CKR_OK) 2161 break; 2162 crv = sftk_Attribute2SSecItem(arena, &pubKey->u.dh.publicValue, 2163 object, CKA_VALUE); 2164 break; 2165 case CKK_EC_EDWARDS: 2166 case CKK_EC_MONTGOMERY: 2167 case CKK_EC: 2168 pubKey->keyType = NSSLOWKEYECKey; 2169 crv = sftk_Attribute2SSecItem(arena, 2170 &pubKey->u.ec.ecParams.DEREncoding, 2171 object, CKA_EC_PARAMS); 2172 if (crv != CKR_OK) 2173 break; 2174 2175 /* Fill out the rest of the ecParams structure 2176 * based on the encoded params 2177 */ 2178 if (EC_FillParams(arena, &pubKey->u.ec.ecParams.DEREncoding, 2179 &pubKey->u.ec.ecParams) != SECSuccess) { 2180 crv = CKR_DOMAIN_PARAMS_INVALID; 2181 break; 2182 } 2183 2184 crv = sftk_Attribute2SSecItem(arena, &pubKey->u.ec.publicValue, 2185 object, CKA_EC_POINT); 2186 if (crv == CKR_OK) { 2187 unsigned int keyLen = EC_GetPointSize(&pubKey->u.ec.ecParams); 2188 /* special note: We can't just use the first byte to distinguish 2189 * between EC_POINT_FORM_UNCOMPRESSED and SEC_ASN1_OCTET_STRING. 2190 * Both are 0x04. */ 2191 2192 /* Handle the non-DER encoded case. 2193 * Some curves are always pressumed to be non-DER. 2194 */ 2195 2196 /* is the public key in uncompressed form? */ 2197 if (pubKey->u.ec.ecParams.type != ec_params_named || 2198 (pubKey->u.ec.publicValue.len == keyLen && 2199 pubKey->u.ec.publicValue.data[0] == EC_POINT_FORM_UNCOMPRESSED)) { 2200 break; /* key was not DER encoded, no need to unwrap */ 2201 } 2202 2203 /* handle the encoded case */ 2204 if (pubKey->u.ec.publicValue.data[0] == SEC_ASN1_OCTET_STRING) { 2205 SECItem publicValue; 2206 SECStatus rv; 2207 2208 rv = SEC_QuickDERDecodeItem(arena, &publicValue, 2209 SEC_ASN1_GET(SEC_OctetStringTemplate), 2210 &pubKey->u.ec.publicValue); 2211 /* nope, didn't decode correctly */ 2212 if (rv != SECSuccess) { 2213 crv = CKR_ATTRIBUTE_VALUE_INVALID; 2214 break; 2215 } 2216 2217 if (publicValue.len == keyLen && publicValue.data[0] == EC_POINT_FORM_UNCOMPRESSED) { 2218 /* Received uncompressed point */ 2219 pubKey->u.ec.publicValue = publicValue; 2220 break; 2221 } 2222 2223 /* Trying to decompress */ 2224 SECItem publicDecompressed = { siBuffer, NULL, 0 }; 2225 (void)SECITEM_AllocItem(arena, &publicDecompressed, keyLen); 2226 if (EC_DecompressPublicKey(&publicValue, &pubKey->u.ec.ecParams, &publicDecompressed) == SECFailure) { 2227 crv = CKR_ATTRIBUTE_VALUE_INVALID; 2228 break; 2229 } 2230 2231 /* replace our previous public key with the decoded decompressed key */ 2232 pubKey->u.ec.publicValue = publicDecompressed; 2233 2234 SECItem publicDecompressedEncoded = { siBuffer, NULL, 0 }; 2235 (void)SEC_ASN1EncodeItem(arena, &publicDecompressedEncoded, &publicDecompressed, 2236 SEC_ASN1_GET(SEC_OctetStringTemplate)); 2237 if (CKR_OK != sftk_forceAttribute(object, CKA_EC_POINT, sftk_item_expand(&publicDecompressedEncoded))) { 2238 crv = CKR_ATTRIBUTE_VALUE_INVALID; 2239 break; 2240 } 2241 2242 break; 2243 } 2244 crv = CKR_ATTRIBUTE_VALUE_INVALID; 2245 } 2246 break; 2247 #ifndef NSS_DISABLE_KYBER 2248 case CKK_NSS_KYBER: 2249 #endif 2250 case CKK_NSS_ML_KEM: 2251 case CKK_ML_KEM: 2252 crv = CKR_OK; 2253 break; 2254 case CKK_ML_DSA: 2255 pubKey->keyType = NSSLOWKEYMLDSAKey; 2256 crv = sftk_ReadAttribute(object, CKA_VALUE, 2257 pubKey->u.mldsa.keyVal, 2258 sizeof(pubKey->u.mldsa.keyVal), 2259 &pubKey->u.mldsa.keyValLen); 2260 if (crv != CKR_OK) { 2261 break; 2262 } 2263 crv = sftk_GetULongAttribute(object, CKA_PARAMETER_SET, 2264 &pubKey->u.mldsa.paramSet); 2265 2266 break; 2267 default: 2268 crv = CKR_KEY_TYPE_INCONSISTENT; 2269 break; 2270 } 2271 *crvp = crv; 2272 if (crv != CKR_OK) { 2273 PORT_FreeArena(arena, PR_TRUE); 2274 return NULL; 2275 } 2276 2277 object->objectInfo = pubKey; 2278 object->infoFree = SFTKFree_nsslowkey_DestroyPublicKey; 2279 return pubKey; 2280 } 2281 2282 /* make a private key from a verified object */ 2283 static NSSLOWKEYPrivateKey * 2284 sftk_mkPrivKey(SFTKObject *object, CK_KEY_TYPE key_type, CK_RV *crvp) 2285 { 2286 NSSLOWKEYPrivateKey *privKey; 2287 SFTKItemTemplate itemTemplate[SFTK_MAX_ITEM_TEMPLATE]; 2288 int itemTemplateCount = 0; 2289 PLArenaPool *arena; 2290 CK_RV crv = CKR_OK; 2291 SECStatus rv; 2292 2293 arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); 2294 if (arena == NULL) { 2295 *crvp = CKR_HOST_MEMORY; 2296 return NULL; 2297 } 2298 2299 privKey = (NSSLOWKEYPrivateKey *) 2300 PORT_ArenaZAlloc(arena, sizeof(NSSLOWKEYPrivateKey)); 2301 if (privKey == NULL) { 2302 PORT_FreeArena(arena, PR_FALSE); 2303 *crvp = CKR_HOST_MEMORY; 2304 return NULL; 2305 } 2306 2307 /* in future this would be a switch on key_type */ 2308 privKey->arena = arena; 2309 switch (key_type) { 2310 case CKK_RSA: 2311 privKey->keyType = NSSLOWKEYRSAKey; 2312 2313 SFTK_SET_ITEM_TEMPLATE(itemTemplate, itemTemplateCount, 2314 &privKey->u.rsa.modulus, CKA_MODULUS); 2315 itemTemplateCount++; 2316 SFTK_SET_ITEM_TEMPLATE(itemTemplate, itemTemplateCount, 2317 &privKey->u.rsa.publicExponent, CKA_PUBLIC_EXPONENT); 2318 itemTemplateCount++; 2319 SFTK_SET_ITEM_TEMPLATE(itemTemplate, itemTemplateCount, 2320 &privKey->u.rsa.privateExponent, CKA_PRIVATE_EXPONENT); 2321 itemTemplateCount++; 2322 SFTK_SET_ITEM_TEMPLATE(itemTemplate, itemTemplateCount, 2323 &privKey->u.rsa.prime1, CKA_PRIME_1); 2324 itemTemplateCount++; 2325 SFTK_SET_ITEM_TEMPLATE(itemTemplate, itemTemplateCount, 2326 &privKey->u.rsa.prime2, CKA_PRIME_2); 2327 itemTemplateCount++; 2328 SFTK_SET_ITEM_TEMPLATE(itemTemplate, itemTemplateCount, 2329 &privKey->u.rsa.exponent1, CKA_EXPONENT_1); 2330 itemTemplateCount++; 2331 SFTK_SET_ITEM_TEMPLATE(itemTemplate, itemTemplateCount, 2332 &privKey->u.rsa.exponent2, CKA_EXPONENT_2); 2333 itemTemplateCount++; 2334 SFTK_SET_ITEM_TEMPLATE(itemTemplate, itemTemplateCount, 2335 &privKey->u.rsa.coefficient, CKA_COEFFICIENT); 2336 itemTemplateCount++; 2337 rv = DER_SetUInteger(privKey->arena, &privKey->u.rsa.version, 2338 NSSLOWKEY_PRIVATE_KEY_INFO_VERSION); 2339 if (rv != SECSuccess) 2340 crv = CKR_HOST_MEMORY; 2341 break; 2342 2343 case CKK_DSA: 2344 privKey->keyType = NSSLOWKEYDSAKey; 2345 SFTK_SET_ITEM_TEMPLATE(itemTemplate, itemTemplateCount, 2346 &privKey->u.dsa.params.prime, CKA_PRIME); 2347 itemTemplateCount++; 2348 SFTK_SET_ITEM_TEMPLATE(itemTemplate, itemTemplateCount, 2349 &privKey->u.dsa.params.subPrime, CKA_SUBPRIME); 2350 itemTemplateCount++; 2351 SFTK_SET_ITEM_TEMPLATE(itemTemplate, itemTemplateCount, 2352 &privKey->u.dsa.params.base, CKA_BASE); 2353 itemTemplateCount++; 2354 SFTK_SET_ITEM_TEMPLATE(itemTemplate, itemTemplateCount, 2355 &privKey->u.dsa.privateValue, CKA_VALUE); 2356 itemTemplateCount++; 2357 /* privKey was zero'd so public value is already set to NULL, 0 2358 * if we don't set it explicitly */ 2359 break; 2360 2361 case CKK_DH: 2362 privKey->keyType = NSSLOWKEYDHKey; 2363 SFTK_SET_ITEM_TEMPLATE(itemTemplate, itemTemplateCount, 2364 &privKey->u.dh.prime, CKA_PRIME); 2365 itemTemplateCount++; 2366 SFTK_SET_ITEM_TEMPLATE(itemTemplate, itemTemplateCount, 2367 &privKey->u.dh.base, CKA_BASE); 2368 itemTemplateCount++; 2369 SFTK_SET_ITEM_TEMPLATE(itemTemplate, itemTemplateCount, 2370 &privKey->u.dh.privateValue, CKA_VALUE); 2371 itemTemplateCount++; 2372 /* privKey was zero'd so public value is already set to NULL, 0 2373 * if we don't set it explicitly */ 2374 break; 2375 case CKK_EC_EDWARDS: 2376 case CKK_EC_MONTGOMERY: 2377 case CKK_EC: 2378 privKey->keyType = NSSLOWKEYECKey; 2379 crv = sftk_Attribute2SSecItem(arena, 2380 &privKey->u.ec.ecParams.DEREncoding, 2381 object, CKA_EC_PARAMS); 2382 if (crv != CKR_OK) 2383 break; 2384 2385 /* Fill out the rest of the ecParams structure 2386 * based on the encoded params 2387 */ 2388 if (EC_FillParams(arena, &privKey->u.ec.ecParams.DEREncoding, 2389 &privKey->u.ec.ecParams) != SECSuccess) { 2390 crv = CKR_DOMAIN_PARAMS_INVALID; 2391 break; 2392 } 2393 crv = sftk_Attribute2SSecItem(arena, &privKey->u.ec.privateValue, 2394 object, CKA_VALUE); 2395 if (crv != CKR_OK) 2396 break; 2397 2398 if (sftk_hasAttribute(object, CKA_NSS_DB)) { 2399 crv = sftk_Attribute2SSecItem(arena, &privKey->u.ec.publicValue, 2400 object, CKA_NSS_DB); 2401 if (crv != CKR_OK) { 2402 break; 2403 } 2404 /* privKey was zero'd so public value is already set to NULL, 0 2405 * if we don't set it explicitly */ 2406 } else if (key_type == CKK_EC) { 2407 /* as no public key was provided during the import, we need to derive it here. 2408 See: PK11_ImportAndReturnPrivateKey*/ 2409 (void)SECITEM_AllocItem(arena, &privKey->u.ec.publicValue, EC_GetPointSize(&privKey->u.ec.ecParams)); 2410 rv = EC_DerivePublicKey(&privKey->u.ec.privateValue, &privKey->u.ec.ecParams, &privKey->u.ec.publicValue); 2411 if (rv != SECSuccess) { 2412 break; 2413 } 2414 sftk_forceAttribute(object, CKA_NSS_DB, privKey->u.ec.publicValue.data, privKey->u.ec.publicValue.len); 2415 } 2416 2417 rv = DER_SetUInteger(privKey->arena, &privKey->u.ec.version, 2418 NSSLOWKEY_EC_PRIVATE_KEY_VERSION); 2419 if (rv != SECSuccess) { 2420 crv = CKR_HOST_MEMORY; 2421 /* The following ifdef is needed for Linux arm distros and 2422 * Android as gcc 4.6 has a bug when targeting arm (but not 2423 * thumb). The bug has been fixed in gcc 4.7. 2424 * http://gcc.gnu.org/bugzilla/show_bug.cgi?id=56561 2425 */ 2426 #if defined(__arm__) && !defined(__thumb__) && defined(__GNUC__) 2427 *crvp = CKR_HOST_MEMORY; 2428 break; 2429 #endif 2430 } 2431 break; 2432 2433 #ifndef NSS_DISABLE_KYBER 2434 case CKK_NSS_KYBER: 2435 #endif 2436 case CKK_NSS_ML_KEM: 2437 case CKK_ML_KEM: 2438 break; 2439 2440 case CKK_ML_DSA: 2441 privKey->keyType = NSSLOWKEYMLDSAKey; 2442 crv = sftk_ReadAttribute(object, CKA_VALUE, 2443 privKey->u.mldsa.keyVal, 2444 sizeof(privKey->u.mldsa.keyVal), 2445 &privKey->u.mldsa.keyValLen); 2446 if (crv != CKR_OK) { 2447 break; 2448 } 2449 crv = sftk_ReadAttribute(object, CKA_SEED, 2450 privKey->u.mldsa.seed, 2451 sizeof(privKey->u.mldsa.seed), 2452 &privKey->u.mldsa.seedLen); 2453 if (crv != CKR_OK) { 2454 /* no seed value, just set it to zero. The seed 2455 * has been lost or discarded for this key */ 2456 privKey->u.mldsa.seedLen = 0; 2457 } 2458 crv = sftk_GetULongAttribute(object, CKA_PARAMETER_SET, 2459 &privKey->u.mldsa.paramSet); 2460 2461 break; 2462 2463 default: 2464 crv = CKR_KEY_TYPE_INCONSISTENT; 2465 break; 2466 } 2467 if (crv == CKR_OK && itemTemplateCount != 0) { 2468 PORT_Assert(itemTemplateCount > 0); 2469 PORT_Assert(itemTemplateCount <= SFTK_MAX_ITEM_TEMPLATE); 2470 crv = sftk_MultipleAttribute2SecItem(arena, object, itemTemplate, 2471 itemTemplateCount); 2472 } 2473 *crvp = crv; 2474 if (crv != CKR_OK) { 2475 PORT_FreeArena(arena, PR_TRUE); 2476 return NULL; 2477 } 2478 return privKey; 2479 } 2480 2481 /* 2482 * If a partial RSA private key is present, fill in the rest if necessary, 2483 * and then verify the parameters are well-formed 2484 */ 2485 static SECStatus 2486 sftk_verifyRSAPrivateKey(SFTKObject *object, PRBool fillIfNeeded) 2487 { 2488 RSAPrivateKey tmpKey = { 0 }; 2489 SFTKAttribute *modulus = NULL; 2490 SFTKAttribute *prime1 = NULL; 2491 SFTKAttribute *prime2 = NULL; 2492 SFTKAttribute *privateExponent = NULL; 2493 SFTKAttribute *publicExponent = NULL; 2494 SFTKAttribute *exponent1 = NULL; 2495 SFTKAttribute *exponent2 = NULL; 2496 SFTKAttribute *coefficient = NULL; 2497 SECStatus rv; 2498 CK_RV crv; 2499 2500 /* first fill in the components that we have. Populate only uses 2501 * the non-crt components, so only fill those in */ 2502 tmpKey.arena = NULL; 2503 modulus = sftk_FindAttribute(object, CKA_MODULUS); 2504 if (modulus) { 2505 tmpKey.modulus.data = modulus->attrib.pValue; 2506 tmpKey.modulus.len = modulus->attrib.ulValueLen; 2507 } 2508 prime1 = sftk_FindAttribute(object, CKA_PRIME_1); 2509 if (prime1) { 2510 tmpKey.prime1.data = prime1->attrib.pValue; 2511 tmpKey.prime1.len = prime1->attrib.ulValueLen; 2512 } 2513 prime2 = sftk_FindAttribute(object, CKA_PRIME_2); 2514 if (prime2) { 2515 tmpKey.prime2.data = prime2->attrib.pValue; 2516 tmpKey.prime2.len = prime2->attrib.ulValueLen; 2517 } 2518 privateExponent = sftk_FindAttribute(object, CKA_PRIVATE_EXPONENT); 2519 if (privateExponent) { 2520 tmpKey.privateExponent.data = privateExponent->attrib.pValue; 2521 tmpKey.privateExponent.len = privateExponent->attrib.ulValueLen; 2522 } 2523 publicExponent = sftk_FindAttribute(object, CKA_PUBLIC_EXPONENT); 2524 if (publicExponent) { 2525 tmpKey.publicExponent.data = publicExponent->attrib.pValue; 2526 tmpKey.publicExponent.len = publicExponent->attrib.ulValueLen; 2527 } 2528 exponent1 = sftk_FindAttribute(object, CKA_EXPONENT_1); 2529 if (exponent1) { 2530 tmpKey.exponent1.data = exponent1->attrib.pValue; 2531 tmpKey.exponent1.len = exponent1->attrib.ulValueLen; 2532 } 2533 exponent2 = sftk_FindAttribute(object, CKA_EXPONENT_2); 2534 if (exponent2) { 2535 tmpKey.exponent2.data = exponent2->attrib.pValue; 2536 tmpKey.exponent2.len = exponent2->attrib.ulValueLen; 2537 } 2538 coefficient = sftk_FindAttribute(object, CKA_COEFFICIENT); 2539 if (coefficient) { 2540 tmpKey.coefficient.data = coefficient->attrib.pValue; 2541 tmpKey.coefficient.len = coefficient->attrib.ulValueLen; 2542 } 2543 2544 if (fillIfNeeded) { 2545 /* 2546 * populate requires one exponent plus 2 other components to work. 2547 * we expected our caller to check that first. If that didn't happen, 2548 * populate will simply return an error here. 2549 */ 2550 rv = RSA_PopulatePrivateKey(&tmpKey); 2551 if (rv != SECSuccess) { 2552 goto loser; 2553 } 2554 } 2555 rv = RSA_PrivateKeyCheck(&tmpKey); 2556 if (rv != SECSuccess) { 2557 goto loser; 2558 } 2559 /* now that we have a fully populated key, set all our attribute values */ 2560 rv = SECFailure; 2561 if (!modulus || modulus->attrib.pValue != tmpKey.modulus.data) { 2562 crv = sftk_forceAttribute(object, CKA_MODULUS, 2563 sftk_item_expand(&tmpKey.modulus)); 2564 if (crv != CKR_OK) 2565 goto loser; 2566 } 2567 if (!publicExponent || 2568 publicExponent->attrib.pValue != tmpKey.publicExponent.data) { 2569 crv = sftk_forceAttribute(object, CKA_PUBLIC_EXPONENT, 2570 sftk_item_expand(&tmpKey.publicExponent)); 2571 if (crv != CKR_OK) 2572 goto loser; 2573 } 2574 if (!privateExponent || 2575 privateExponent->attrib.pValue != tmpKey.privateExponent.data) { 2576 crv = sftk_forceAttribute(object, CKA_PRIVATE_EXPONENT, 2577 sftk_item_expand(&tmpKey.privateExponent)); 2578 if (crv != CKR_OK) 2579 goto loser; 2580 } 2581 if (!prime1 || prime1->attrib.pValue != tmpKey.prime1.data) { 2582 crv = sftk_forceAttribute(object, CKA_PRIME_1, 2583 sftk_item_expand(&tmpKey.prime1)); 2584 if (crv != CKR_OK) 2585 goto loser; 2586 } 2587 if (!prime2 || prime2->attrib.pValue != tmpKey.prime2.data) { 2588 crv = sftk_forceAttribute(object, CKA_PRIME_2, 2589 sftk_item_expand(&tmpKey.prime2)); 2590 if (crv != CKR_OK) 2591 goto loser; 2592 } 2593 if (!exponent1 || exponent1->attrib.pValue != tmpKey.exponent1.data) { 2594 crv = sftk_forceAttribute(object, CKA_EXPONENT_1, 2595 sftk_item_expand(&tmpKey.exponent1)); 2596 if (crv != CKR_OK) 2597 goto loser; 2598 } 2599 if (!exponent2 || exponent2->attrib.pValue != tmpKey.exponent2.data) { 2600 crv = sftk_forceAttribute(object, CKA_EXPONENT_2, 2601 sftk_item_expand(&tmpKey.exponent2)); 2602 if (crv != CKR_OK) 2603 goto loser; 2604 } 2605 if (!coefficient || coefficient->attrib.pValue != tmpKey.coefficient.data) { 2606 crv = sftk_forceAttribute(object, CKA_COEFFICIENT, 2607 sftk_item_expand(&tmpKey.coefficient)); 2608 if (crv != CKR_OK) 2609 goto loser; 2610 } 2611 rv = SECSuccess; 2612 2613 /* we're done (one way or the other), clean up all our stuff */ 2614 loser: 2615 if (tmpKey.arena) { 2616 PORT_FreeArena(tmpKey.arena, PR_TRUE); 2617 } 2618 if (modulus) { 2619 sftk_FreeAttribute(modulus); 2620 } 2621 if (prime1) { 2622 sftk_FreeAttribute(prime1); 2623 } 2624 if (prime2) { 2625 sftk_FreeAttribute(prime2); 2626 } 2627 if (privateExponent) { 2628 sftk_FreeAttribute(privateExponent); 2629 } 2630 if (publicExponent) { 2631 sftk_FreeAttribute(publicExponent); 2632 } 2633 if (exponent1) { 2634 sftk_FreeAttribute(exponent1); 2635 } 2636 if (exponent2) { 2637 sftk_FreeAttribute(exponent2); 2638 } 2639 if (coefficient) { 2640 sftk_FreeAttribute(coefficient); 2641 } 2642 return rv; 2643 } 2644 2645 /* Generate a low private key structure from an object */ 2646 NSSLOWKEYPrivateKey * 2647 sftk_GetPrivKey(SFTKObject *object, CK_KEY_TYPE key_type, CK_RV *crvp) 2648 { 2649 NSSLOWKEYPrivateKey *priv = NULL; 2650 2651 if (object->objclass != CKO_PRIVATE_KEY) { 2652 *crvp = CKR_KEY_TYPE_INCONSISTENT; 2653 return NULL; 2654 } 2655 if (object->objectInfo) { 2656 *crvp = CKR_OK; 2657 return (NSSLOWKEYPrivateKey *)object->objectInfo; 2658 } 2659 2660 priv = sftk_mkPrivKey(object, key_type, crvp); 2661 object->objectInfo = priv; 2662 object->infoFree = SFTKFree_nsslowkey_DestroyPrivateKey; 2663 return priv; 2664 } 2665 2666 /* populate a public key object from a lowpublic keys structure */ 2667 CK_RV 2668 sftk_PutPubKey(SFTKObject *publicKey, SFTKObject *privateKey, CK_KEY_TYPE keyType, NSSLOWKEYPublicKey *pubKey) 2669 { 2670 CK_OBJECT_CLASS classType = CKO_PUBLIC_KEY; 2671 CK_BBOOL cktrue = CK_TRUE; 2672 CK_RV crv = CKR_OK; 2673 sftk_DeleteAttributeType(publicKey, CKA_CLASS); 2674 sftk_DeleteAttributeType(publicKey, CKA_KEY_TYPE); 2675 sftk_DeleteAttributeType(publicKey, CKA_VALUE); 2676 2677 switch (keyType) { 2678 case CKK_RSA: 2679 sftk_DeleteAttributeType(publicKey, CKA_MODULUS); 2680 sftk_DeleteAttributeType(publicKey, CKA_PUBLIC_EXPONENT); 2681 /* format the keys */ 2682 /* fill in the RSA dependent paramenters in the public key */ 2683 crv = sftk_AddAttributeType(publicKey, CKA_MODULUS, 2684 sftk_item_expand(&pubKey->u.rsa.modulus)); 2685 if (crv != CKR_OK) { 2686 break; 2687 } 2688 crv = sftk_AddAttributeType(publicKey, CKA_PUBLIC_EXPONENT, 2689 sftk_item_expand(&pubKey->u.rsa.publicExponent)); 2690 break; 2691 case CKK_DSA: 2692 sftk_DeleteAttributeType(publicKey, CKA_PRIME); 2693 sftk_DeleteAttributeType(publicKey, CKA_SUBPRIME); 2694 sftk_DeleteAttributeType(publicKey, CKA_BASE); 2695 crv = sftk_AddAttributeType(publicKey, CKA_PRIME, 2696 sftk_item_expand(&pubKey->u.dsa.params.prime)); 2697 if (crv != CKR_OK) { 2698 break; 2699 } 2700 crv = sftk_AddAttributeType(publicKey, CKA_SUBPRIME, 2701 sftk_item_expand(&pubKey->u.dsa.params.subPrime)); 2702 if (crv != CKR_OK) { 2703 break; 2704 } 2705 crv = sftk_AddAttributeType(publicKey, CKA_BASE, 2706 sftk_item_expand(&pubKey->u.dsa.params.base)); 2707 if (crv != CKR_OK) { 2708 break; 2709 } 2710 crv = sftk_AddAttributeType(publicKey, CKA_VALUE, 2711 sftk_item_expand(&pubKey->u.dsa.publicValue)); 2712 break; 2713 case CKK_ML_DSA: 2714 sftk_DeleteAttributeType(publicKey, CKA_VALUE); 2715 sftk_DeleteAttributeType(publicKey, CKA_PARAMETER_SET); 2716 crv = sftk_AddAttributeType(publicKey, CKA_VALUE, 2717 pubKey->u.mldsa.keyVal, 2718 pubKey->u.mldsa.keyValLen); 2719 if (crv != CKR_OK) { 2720 break; 2721 } 2722 crv = sftk_AddAttributeType(publicKey, CKA_PARAMETER_SET, 2723 (unsigned char *)&pubKey->u.mldsa.paramSet, 2724 sizeof(pubKey->u.mldsa.paramSet)); 2725 break; 2726 case CKK_DH: 2727 sftk_DeleteAttributeType(publicKey, CKA_PRIME); 2728 sftk_DeleteAttributeType(publicKey, CKA_BASE); 2729 crv = sftk_AddAttributeType(publicKey, CKA_PRIME, 2730 sftk_item_expand(&pubKey->u.dh.prime)); 2731 if (crv != CKR_OK) { 2732 break; 2733 } 2734 crv = sftk_AddAttributeType(publicKey, CKA_BASE, 2735 sftk_item_expand(&pubKey->u.dh.base)); 2736 if (crv != CKR_OK) { 2737 break; 2738 } 2739 crv = sftk_AddAttributeType(publicKey, CKA_VALUE, 2740 sftk_item_expand(&pubKey->u.dh.publicValue)); 2741 break; 2742 case CKK_EC: 2743 case CKK_EC_MONTGOMERY: 2744 case CKK_EC_EDWARDS: 2745 sftk_DeleteAttributeType(publicKey, CKA_EC_PARAMS); 2746 sftk_DeleteAttributeType(publicKey, CKA_EC_POINT); 2747 crv = sftk_AddAttributeType(publicKey, CKA_EC_PARAMS, 2748 sftk_item_expand(&pubKey->u.ec.ecParams.DEREncoding)); 2749 if (crv != CKR_OK) { 2750 break; 2751 } 2752 crv = sftk_AddAttributeType(publicKey, CKA_EC_POINT, 2753 sftk_item_expand(&pubKey->u.ec.publicValue)); 2754 break; 2755 default: 2756 return CKR_KEY_TYPE_INCONSISTENT; 2757 } 2758 if (crv != CKR_OK) { 2759 return crv; 2760 } 2761 crv = sftk_AddAttributeType(publicKey, CKA_CLASS, &classType, 2762 sizeof(CK_OBJECT_CLASS)); 2763 if (crv != CKR_OK) { 2764 return crv; 2765 } 2766 crv = sftk_AddAttributeType(publicKey, CKA_KEY_TYPE, &keyType, 2767 sizeof(CK_KEY_TYPE)); 2768 if (crv != CKR_OK) { 2769 return crv; 2770 } 2771 /* now handle the operator attributes */ 2772 if (sftk_isTrue(privateKey, CKA_DECRYPT)) { 2773 crv = sftk_forceAttribute(publicKey, CKA_ENCRYPT, &cktrue, sizeof(CK_BBOOL)); 2774 if (crv != CKR_OK) { 2775 return crv; 2776 } 2777 } 2778 if (sftk_isTrue(privateKey, CKA_SIGN)) { 2779 crv = sftk_forceAttribute(publicKey, CKA_VERIFY, &cktrue, sizeof(CK_BBOOL)); 2780 if (crv != CKR_OK) { 2781 return crv; 2782 } 2783 } 2784 if (sftk_isTrue(privateKey, CKA_SIGN_RECOVER)) { 2785 crv = sftk_forceAttribute(publicKey, CKA_VERIFY_RECOVER, &cktrue, sizeof(CK_BBOOL)); 2786 if (crv != CKR_OK) { 2787 return crv; 2788 } 2789 } 2790 if (sftk_isTrue(privateKey, CKA_DECAPSULATE)) { 2791 crv = sftk_forceAttribute(publicKey, CKA_ENCAPSULATE, &cktrue, sizeof(CK_BBOOL)); 2792 if (crv != CKR_OK) { 2793 return crv; 2794 } 2795 } 2796 if (sftk_isTrue(privateKey, CKA_DERIVE)) { 2797 crv = sftk_forceAttribute(publicKey, CKA_DERIVE, &cktrue, sizeof(CK_BBOOL)); 2798 if (crv != CKR_OK) { 2799 return crv; 2800 } 2801 } 2802 return crv; 2803 } 2804 2805 /* 2806 **************************** Symetric Key utils ************************ 2807 */ 2808 /* 2809 * set the DES key with parity bits correctly 2810 */ 2811 void 2812 sftk_FormatDESKey(unsigned char *key, int length) 2813 { 2814 int i; 2815 2816 /* format the des key */ 2817 for (i = 0; i < length; i++) { 2818 key[i] = parityTable[key[i] >> 1]; 2819 } 2820 } 2821 2822 /* 2823 * check a des key (des2 or des3 subkey) for weak keys. 2824 */ 2825 PRBool 2826 sftk_CheckDESKey(unsigned char *key) 2827 { 2828 int i; 2829 2830 /* format the des key with parity */ 2831 sftk_FormatDESKey(key, 8); 2832 2833 for (i = 0; i < sftk_desWeakTableSize; i++) { 2834 if (PORT_Memcmp(key, sftk_desWeakTable[i], 8) == 0) { 2835 return PR_TRUE; 2836 } 2837 } 2838 return PR_FALSE; 2839 } 2840 2841 /* 2842 * check if a des or triple des key is weak. 2843 */ 2844 PRBool 2845 sftk_IsWeakKey(unsigned char *key, CK_KEY_TYPE key_type) 2846 { 2847 2848 switch (key_type) { 2849 case CKK_DES: 2850 return sftk_CheckDESKey(key); 2851 case CKM_DES2_KEY_GEN: 2852 if (sftk_CheckDESKey(key)) 2853 return PR_TRUE; 2854 return sftk_CheckDESKey(&key[8]); 2855 case CKM_DES3_KEY_GEN: 2856 if (sftk_CheckDESKey(key)) 2857 return PR_TRUE; 2858 if (sftk_CheckDESKey(&key[8])) 2859 return PR_TRUE; 2860 return sftk_CheckDESKey(&key[16]); 2861 default: 2862 break; 2863 } 2864 return PR_FALSE; 2865 } 2866 2867 /********************************************************************** 2868 * 2869 * Start of PKCS 11 functions 2870 * 2871 **********************************************************************/ 2872 2873 /* return the function list */ 2874 CK_RV 2875 NSC_GetFunctionList(CK_FUNCTION_LIST_PTR *pFunctionList) 2876 { 2877 *pFunctionList = (CK_FUNCTION_LIST_PTR)&sftk_funcList_v2; 2878 return CKR_OK; 2879 } 2880 2881 /* return the function list */ 2882 CK_RV 2883 C_GetFunctionList(CK_FUNCTION_LIST_PTR *pFunctionList) 2884 { 2885 #ifdef NSS_FIPS_DISABLED 2886 return NSC_GetFunctionList(pFunctionList); 2887 #else 2888 if (NSS_GetSystemFIPSEnabled()) { 2889 return FC_GetFunctionList(pFunctionList); 2890 } else { 2891 return NSC_GetFunctionList(pFunctionList); 2892 } 2893 #endif 2894 } 2895 2896 CK_RV 2897 NSC_GetInterfaceList(CK_INTERFACE_PTR interfaces, CK_ULONG_PTR pulCount) 2898 { 2899 CK_ULONG count = *pulCount; 2900 *pulCount = NSS_INTERFACE_COUNT; 2901 if (interfaces == NULL) { 2902 return CKR_OK; 2903 } 2904 if (count < NSS_INTERFACE_COUNT) { 2905 return CKR_BUFFER_TOO_SMALL; 2906 } 2907 PORT_Memcpy(interfaces, nss_interfaces, sizeof(nss_interfaces)); 2908 return CKR_OK; 2909 } 2910 2911 CK_RV 2912 C_GetInterfaceList(CK_INTERFACE_PTR interfaces, CK_ULONG_PTR pulCount) 2913 { 2914 #ifdef NSS_FIPS_DISABLED 2915 return NSC_GetInterfaceList(interfaces, pulCount); 2916 #else 2917 if (NSS_GetSystemFIPSEnabled()) { 2918 return FC_GetInterfaceList(interfaces, pulCount); 2919 } else { 2920 return NSC_GetInterfaceList(interfaces, pulCount); 2921 } 2922 #endif 2923 } 2924 2925 /* 2926 * Get the requested interface, use the nss_interfaces array so we can 2927 * easily add new interfaces as they occur. 2928 */ 2929 CK_RV 2930 NSC_GetInterface(CK_UTF8CHAR_PTR pInterfaceName, CK_VERSION_PTR pVersion, 2931 CK_INTERFACE_PTR_PTR ppInterface, CK_FLAGS flags) 2932 { 2933 int i; 2934 for (i = 0; i < NSS_INTERFACE_COUNT; i++) { 2935 CK_INTERFACE_PTR interface = &nss_interfaces[i]; 2936 if (pInterfaceName && PORT_Strcmp((char *)pInterfaceName, (char *)interface->pInterfaceName) != 0) { 2937 continue; 2938 } 2939 if (pVersion && PORT_Memcmp(pVersion, (CK_VERSION *)interface->pFunctionList, sizeof(CK_VERSION)) != 0) { 2940 continue; 2941 } 2942 if (flags & ((interface->flags & flags) != flags)) { 2943 continue; 2944 } 2945 *ppInterface = interface; 2946 return CKR_OK; 2947 } 2948 return CKR_ARGUMENTS_BAD; 2949 } 2950 2951 CK_RV 2952 C_GetInterface(CK_UTF8CHAR_PTR pInterfaceName, CK_VERSION_PTR pVersion, 2953 CK_INTERFACE_PTR_PTR ppInterface, CK_FLAGS flags) 2954 { 2955 #ifdef NSS_FIPS_DISABLED 2956 return NSC_GetInterface(pInterfaceName, pVersion, ppInterface, flags); 2957 #else 2958 if (NSS_GetSystemFIPSEnabled()) { 2959 return FC_GetInterface(pInterfaceName, pVersion, ppInterface, flags); 2960 } else { 2961 return NSC_GetInterface(pInterfaceName, pVersion, ppInterface, flags); 2962 } 2963 #endif 2964 } 2965 2966 static PLHashNumber 2967 sftk_HashNumber(const void *key) 2968 { 2969 return (PLHashNumber)((char *)key - (char *)NULL); 2970 } 2971 2972 /* 2973 * eventually I'd like to expunge all occurances of XXX_SLOT_ID and 2974 * just go with the info in the slot. This is one place, however, 2975 * where it might be a little difficult. 2976 */ 2977 const char * 2978 sftk_getDefTokName(CK_SLOT_ID slotID) 2979 { 2980 static char buf[33]; 2981 2982 switch (slotID) { 2983 case NETSCAPE_SLOT_ID: 2984 return "NSS Generic Crypto Services "; 2985 case PRIVATE_KEY_SLOT_ID: 2986 return "NSS Certificate DB "; 2987 case FIPS_SLOT_ID: 2988 return "NSS FIPS 140-2 Certificate DB "; 2989 default: 2990 break; 2991 } 2992 snprintf(buf, sizeof(buf), "NSS Application Token %08x ", (unsigned int)slotID); 2993 return buf; 2994 } 2995 2996 const char * 2997 sftk_getDefSlotName(CK_SLOT_ID slotID) 2998 { 2999 static char buf[65]; 3000 3001 switch (slotID) { 3002 case NETSCAPE_SLOT_ID: 3003 return "NSS Internal Cryptographic Services "; 3004 case PRIVATE_KEY_SLOT_ID: 3005 return "NSS User Private Key and Certificate Services "; 3006 case FIPS_SLOT_ID: 3007 return "NSS FIPS 140-2 User Private Key Services "; 3008 default: 3009 break; 3010 } 3011 snprintf(buf, sizeof(buf), 3012 "NSS Application Slot %08x ", 3013 (unsigned int)slotID); 3014 return buf; 3015 } 3016 3017 static CK_ULONG nscSlotCount[2] = { 0, 0 }; 3018 static CK_SLOT_ID_PTR nscSlotList[2] = { NULL, NULL }; 3019 static CK_ULONG nscSlotListSize[2] = { 0, 0 }; 3020 static PLHashTable *nscSlotHashTable[2] = { NULL, NULL }; 3021 3022 static unsigned int 3023 sftk_GetModuleIndex(CK_SLOT_ID slotID) 3024 { 3025 if (sftk_isFIPS(slotID)) { 3026 return NSC_FIPS_MODULE; 3027 } 3028 return NSC_NON_FIPS_MODULE; 3029 } 3030 3031 /* look up a slot structure from the ID (used to be a macro when we only 3032 * had two slots) */ 3033 /* if all is true, return the slot even if it has been 'unloaded' */ 3034 /* if all is false, only return the slots which are present */ 3035 SFTKSlot * 3036 sftk_SlotFromID(CK_SLOT_ID slotID, PRBool all) 3037 { 3038 SFTKSlot *slot; 3039 unsigned int index = sftk_GetModuleIndex(slotID); 3040 3041 if (nscSlotHashTable[index] == NULL) 3042 return NULL; 3043 slot = (SFTKSlot *)PL_HashTableLookupConst(nscSlotHashTable[index], 3044 (void *)(uintptr_t)slotID); 3045 /* cleared slots shouldn't 'show up' */ 3046 if (slot && !all && !slot->present) 3047 slot = NULL; 3048 return slot; 3049 } 3050 3051 CK_SLOT_ID 3052 sftk_SlotIDFromSessionHandle(CK_SESSION_HANDLE handle) 3053 { 3054 CK_ULONG slotIDIndex = (handle >> 24) & 0x7f; 3055 CK_ULONG moduleIndex = (handle >> 31) & 1; 3056 3057 if (slotIDIndex >= nscSlotCount[moduleIndex]) { 3058 return (CK_SLOT_ID)-1; 3059 } 3060 return nscSlotList[moduleIndex][slotIDIndex]; 3061 } 3062 3063 SFTKSlot * 3064 sftk_SlotFromSessionHandle(CK_SESSION_HANDLE handle) 3065 { 3066 return sftk_SlotFromID(sftk_SlotIDFromSessionHandle(handle), PR_FALSE); 3067 } 3068 3069 static CK_RV 3070 sftk_RegisterSlot(SFTKSlot *slot, unsigned int moduleIndex) 3071 { 3072 PLHashEntry *entry; 3073 unsigned int index; 3074 3075 index = sftk_GetModuleIndex(slot->slotID); 3076 3077 /* make sure the slotID for this module is valid */ 3078 if (moduleIndex != index) { 3079 return CKR_SLOT_ID_INVALID; 3080 } 3081 3082 if (nscSlotList[index] == NULL) { 3083 nscSlotListSize[index] = NSC_SLOT_LIST_BLOCK_SIZE; 3084 nscSlotList[index] = (CK_SLOT_ID *) 3085 PORT_ZAlloc(nscSlotListSize[index] * sizeof(CK_SLOT_ID)); 3086 if (nscSlotList[index] == NULL) { 3087 return CKR_HOST_MEMORY; 3088 } 3089 } 3090 if (nscSlotCount[index] >= nscSlotListSize[index]) { 3091 CK_SLOT_ID *oldNscSlotList = nscSlotList[index]; 3092 CK_ULONG oldNscSlotListSize = nscSlotListSize[index]; 3093 nscSlotListSize[index] += NSC_SLOT_LIST_BLOCK_SIZE; 3094 nscSlotList[index] = (CK_SLOT_ID *)PORT_Realloc(oldNscSlotList, 3095 nscSlotListSize[index] * sizeof(CK_SLOT_ID)); 3096 if (nscSlotList[index] == NULL) { 3097 /* evidently coverity doesn't know realloc does not 3098 * free var if it fails ! */ 3099 /* coverity [use_after_free : FALSE] */ 3100 nscSlotList[index] = oldNscSlotList; 3101 nscSlotListSize[index] = oldNscSlotListSize; 3102 return CKR_HOST_MEMORY; 3103 } 3104 } 3105 3106 if (nscSlotHashTable[index] == NULL) { 3107 nscSlotHashTable[index] = PL_NewHashTable(64, sftk_HashNumber, 3108 PL_CompareValues, PL_CompareValues, NULL, 0); 3109 if (nscSlotHashTable[index] == NULL) { 3110 return CKR_HOST_MEMORY; 3111 } 3112 } 3113 3114 entry = PL_HashTableAdd(nscSlotHashTable[index], (void *)(uintptr_t)slot->slotID, slot); 3115 if (entry == NULL) { 3116 return CKR_HOST_MEMORY; 3117 } 3118 slot->index = (nscSlotCount[index] & 0x7f) | ((index << 7) & 0x80); 3119 nscSlotList[index][nscSlotCount[index]++] = slot->slotID; 3120 3121 return CKR_OK; 3122 } 3123 3124 /* 3125 * ths function has all the common initialization that happens whenever we 3126 * create a new slot or repurpose an old slot (only valid for slotID's 4 3127 * and greater). 3128 * 3129 * things that are not reinitialized are: 3130 * slotID (can't change) 3131 * slotDescription (can't change once defined) 3132 * the locks and hash tables (difficult to change in running code, and 3133 * unnecessary. hash tables and list are cleared on shutdown, but they 3134 * are cleared in a 'friendly' way). 3135 * session and object ID counters -- so any old sessions and objects in the 3136 * application will get properly notified that the world has changed. 3137 * 3138 * things that are reinitialized: 3139 * database (otherwise what would the point be;). 3140 * state variables related to databases. 3141 * session count stat info. 3142 * tokenDescription. 3143 * 3144 * NOTE: slotID's 4 and greater show up as removable devices. 3145 * 3146 */ 3147 CK_RV 3148 SFTK_SlotReInit(SFTKSlot *slot, char *configdir, char *updatedir, 3149 char *updateID, sftk_token_parameters *params, 3150 unsigned int moduleIndex) 3151 { 3152 PRBool needLogin = !params->noKeyDB; 3153 CK_RV crv; 3154 3155 slot->hasTokens = PR_FALSE; 3156 slot->sessionIDConflict = 0; 3157 slot->sessionCount = 0; 3158 slot->rwSessionCount = 0; 3159 slot->needLogin = PR_FALSE; 3160 slot->isLoggedIn = PR_FALSE; 3161 slot->ssoLoggedIn = PR_FALSE; 3162 slot->DB_loaded = PR_FALSE; 3163 slot->certDB = NULL; 3164 slot->keyDB = NULL; 3165 slot->minimumPinLen = 0; 3166 slot->readOnly = params->readOnly; 3167 sftk_setStringName(params->tokdes ? params->tokdes : sftk_getDefTokName(slot->slotID), slot->tokDescription, 3168 sizeof(slot->tokDescription), PR_TRUE); 3169 sftk_setStringName(params->updtokdes ? params->updtokdes : " ", 3170 slot->updateTokDescription, 3171 sizeof(slot->updateTokDescription), PR_TRUE); 3172 3173 if ((!params->noCertDB) || (!params->noKeyDB)) { 3174 SFTKDBHandle *certHandle = NULL; 3175 SFTKDBHandle *keyHandle = NULL; 3176 crv = sftk_DBInit(params->configdir ? params->configdir : configdir, 3177 params->certPrefix, params->keyPrefix, 3178 params->updatedir ? params->updatedir : updatedir, 3179 params->updCertPrefix, params->updKeyPrefix, 3180 params->updateID ? params->updateID : updateID, 3181 params->readOnly, params->noCertDB, params->noKeyDB, 3182 params->forceOpen, 3183 moduleIndex == NSC_FIPS_MODULE, 3184 &certHandle, &keyHandle); 3185 if (crv != CKR_OK) { 3186 goto loser; 3187 } 3188 3189 slot->certDB = certHandle; 3190 slot->keyDB = keyHandle; 3191 } 3192 if (needLogin) { 3193 /* if the data base is initialized with a null password,remember that */ 3194 slot->needLogin = 3195 (PRBool)!sftk_hasNullPassword(slot, slot->keyDB); 3196 if ((params->minPW >= 0) && (params->minPW <= SFTK_MAX_PIN)) { 3197 slot->minimumPinLen = params->minPW; 3198 } 3199 if ((slot->minimumPinLen == 0) && (params->pwRequired)) { 3200 slot->minimumPinLen = 1; 3201 } 3202 /* Make sure the pin len is set to the Minimum allowed value for fips 3203 * when in FIPS mode. NOTE: we don't set it if the database has not 3204 * been initialized yet so that we can init into level1 mode if needed 3205 */ 3206 if ((sftkdb_HasPasswordSet(slot->keyDB) == SECSuccess) && 3207 (moduleIndex == NSC_FIPS_MODULE) && 3208 (slot->minimumPinLen < FIPS_MIN_PIN)) { 3209 slot->minimumPinLen = FIPS_MIN_PIN; 3210 } 3211 } 3212 3213 slot->present = PR_TRUE; 3214 return CKR_OK; 3215 3216 loser: 3217 SFTK_ShutdownSlot(slot); 3218 return crv; 3219 } 3220 3221 /* 3222 * initialize one of the slot structures. figure out which by the ID 3223 */ 3224 CK_RV 3225 SFTK_SlotInit(char *configdir, char *updatedir, char *updateID, 3226 sftk_token_parameters *params, unsigned int moduleIndex) 3227 { 3228 unsigned int i; 3229 CK_SLOT_ID slotID = params->slotID; 3230 SFTKSlot *slot; 3231 CK_RV crv = CKR_HOST_MEMORY; 3232 3233 /* 3234 * first we initialize everything that is 'permanent' with this slot. 3235 * that is everything we aren't going to shutdown if we close this slot 3236 * and open it up again with different databases */ 3237 3238 slot = PORT_ZNew(SFTKSlot); 3239 3240 if (slot == NULL) { 3241 return CKR_HOST_MEMORY; 3242 } 3243 3244 slot->optimizeSpace = params->optimizeSpace; 3245 if (slot->optimizeSpace) { 3246 slot->sessObjHashSize = SPACE_SESSION_OBJECT_HASH_SIZE; 3247 slot->sessHashSize = SPACE_SESSION_HASH_SIZE; 3248 slot->numSessionLocks = 1; 3249 } else { 3250 slot->sessObjHashSize = TIME_SESSION_OBJECT_HASH_SIZE; 3251 slot->sessHashSize = TIME_SESSION_HASH_SIZE; 3252 slot->numSessionLocks = slot->sessHashSize / BUCKETS_PER_SESSION_LOCK; 3253 } 3254 slot->sessionLockMask = slot->numSessionLocks - 1; 3255 3256 slot->slotLock = PZ_NewLock(nssILockSession); 3257 if (slot->slotLock == NULL) 3258 goto mem_loser; 3259 slot->sessionLock = PORT_ZNewArray(PZLock *, slot->numSessionLocks); 3260 if (slot->sessionLock == NULL) 3261 goto mem_loser; 3262 for (i = 0; i < slot->numSessionLocks; i++) { 3263 slot->sessionLock[i] = PZ_NewLock(nssILockSession); 3264 if (slot->sessionLock[i] == NULL) 3265 goto mem_loser; 3266 } 3267 slot->objectLock = PZ_NewLock(nssILockObject); 3268 if (slot->objectLock == NULL) 3269 goto mem_loser; 3270 slot->pwCheckLock = PR_NewLock(); 3271 if (slot->pwCheckLock == NULL) 3272 goto mem_loser; 3273 slot->head = PORT_ZNewArray(SFTKSession *, slot->sessHashSize); 3274 if (slot->head == NULL) 3275 goto mem_loser; 3276 slot->sessObjHashTable = PORT_ZNewArray(SFTKObject *, slot->sessObjHashSize); 3277 if (slot->sessObjHashTable == NULL) 3278 goto mem_loser; 3279 slot->tokObjHashTable = PL_NewHashTable(64, sftk_HashNumber, PL_CompareValues, 3280 SECITEM_HashCompare, NULL, 0); 3281 if (slot->tokObjHashTable == NULL) 3282 goto mem_loser; 3283 3284 slot->sessionIDCount = 0; 3285 slot->sessionObjectHandleCount = NSC_MIN_SESSION_OBJECT_HANDLE; 3286 slot->slotID = slotID; 3287 sftk_setStringName(params->slotdes ? params->slotdes : sftk_getDefSlotName(slotID), slot->slotDescription, 3288 sizeof(slot->slotDescription), PR_TRUE); 3289 crv = sftk_InitSession(&slot->moduleObjects, slot, slotID, NULL, NULL, 3290 CKF_SERIAL_SESSION); 3291 if (crv != CKR_OK) { 3292 goto loser; 3293 } 3294 3295 /* call the reinit code to set everything that changes between token 3296 * init calls */ 3297 crv = SFTK_SlotReInit(slot, configdir, updatedir, updateID, 3298 params, moduleIndex); 3299 if (crv != CKR_OK) { 3300 goto loser; 3301 } 3302 if (sftk_isFIPS(slotID)) { 3303 crv = sftk_CreateValidationObjects(slot); 3304 if (crv != CKR_OK) { 3305 goto loser; 3306 } 3307 } 3308 crv = sftk_RegisterSlot(slot, moduleIndex); 3309 if (crv != CKR_OK) { 3310 goto loser; 3311 } 3312 return CKR_OK; 3313 3314 mem_loser: 3315 crv = CKR_HOST_MEMORY; 3316 loser: 3317 SFTK_DestroySlotData(slot); 3318 return crv; 3319 } 3320 3321 CK_RV 3322 sftk_CloseAllSessions(SFTKSlot *slot, PRBool logout) 3323 { 3324 SFTKSession *session; 3325 unsigned int i; 3326 SFTKDBHandle *handle; 3327 3328 /* first log out the card */ 3329 /* special case - if we are in a middle of upgrade, we want to close the 3330 * sessions to fake a token removal to tell the upper level code we have 3331 * switched from one database to another, but we don't want to 3332 * explicity logout in case we can continue the upgrade with the 3333 * existing password if possible. 3334 */ 3335 if (logout) { 3336 handle = sftk_getKeyDB(slot); 3337 SKIP_AFTER_FORK(PZ_Lock(slot->slotLock)); 3338 slot->isLoggedIn = PR_FALSE; 3339 if (slot->needLogin && handle) { 3340 sftkdb_ClearPassword(handle); 3341 } 3342 SKIP_AFTER_FORK(PZ_Unlock(slot->slotLock)); 3343 if (handle) { 3344 sftk_freeDB(handle); 3345 } 3346 } 3347 3348 /* now close all the current sessions */ 3349 /* NOTE: If you try to open new sessions before NSC_CloseAllSessions 3350 * completes, some of those new sessions may or may not be closed by 3351 * NSC_CloseAllSessions... but any session running when this code starts 3352 * will guarrenteed be close, and no session will be partially closed */ 3353 for (i = 0; i < slot->sessHashSize; i++) { 3354 PZLock *lock = SFTK_SESSION_LOCK(slot, i); 3355 do { 3356 SKIP_AFTER_FORK(PZ_Lock(lock)); 3357 session = slot->head[i]; 3358 /* hand deque */ 3359 /* this duplicates function of NSC_close session functions, but 3360 * because we know that we are freeing all the sessions, we can 3361 * do more efficient processing */ 3362 if (session) { 3363 slot->head[i] = session->next; 3364 if (session->next) 3365 session->next->prev = NULL; 3366 session->next = session->prev = NULL; 3367 SKIP_AFTER_FORK(PZ_Unlock(lock)); 3368 SKIP_AFTER_FORK(PZ_Lock(slot->slotLock)); 3369 --slot->sessionCount; 3370 SKIP_AFTER_FORK(PZ_Unlock(slot->slotLock)); 3371 if (session->info.flags & CKF_RW_SESSION) { 3372 (void)PR_ATOMIC_DECREMENT(&slot->rwSessionCount); 3373 } 3374 } else { 3375 SKIP_AFTER_FORK(PZ_Unlock(lock)); 3376 } 3377 if (session) { 3378 sftk_DestroySession(session); 3379 } 3380 } while (session != NULL); 3381 } 3382 return CKR_OK; 3383 } 3384 3385 /* 3386 * shut down the databases. 3387 * we get the slot lock (which also protects slot->certDB and slot->keyDB) 3388 * and clear the values so the new users will not find the databases. 3389 * once things are clear, we can release our references to the databases. 3390 * The databases will close when the last reference is released. 3391 * 3392 * We use reference counts so that we don't crash if someone shuts down 3393 * a token that another thread is actively using. 3394 */ 3395 static void 3396 sftk_DBShutdown(SFTKSlot *slot) 3397 { 3398 SFTKDBHandle *certHandle; 3399 SFTKDBHandle *keyHandle; 3400 SKIP_AFTER_FORK(PZ_Lock(slot->slotLock)); 3401 certHandle = slot->certDB; 3402 slot->certDB = NULL; 3403 keyHandle = slot->keyDB; 3404 slot->keyDB = NULL; 3405 SKIP_AFTER_FORK(PZ_Unlock(slot->slotLock)); 3406 if (certHandle) { 3407 sftk_freeDB(certHandle); 3408 } 3409 if (keyHandle) { 3410 sftk_freeDB(keyHandle); 3411 } 3412 } 3413 3414 CK_RV 3415 SFTK_ShutdownSlot(SFTKSlot *slot) 3416 { 3417 /* make sure no new PK11 calls work except C_GetSlotInfo */ 3418 slot->present = PR_FALSE; 3419 3420 /* close all outstanding sessions 3421 * the sessHashSize variable guarentees we have all the session 3422 * mechanism set up */ 3423 if (slot->head) { 3424 sftk_CloseAllSessions(slot, PR_TRUE); 3425 } 3426 3427 /* clear all objects.. session objects are cleared as a result of 3428 * closing all the sessions. We just need to clear the token object 3429 * cache. slot->tokObjHashTable guarentees we have the token 3430 * infrastructure set up. */ 3431 if (slot->tokObjHashTable) { 3432 SFTK_ClearTokenKeyHashTable(slot); 3433 } 3434 3435 /* clear the slot description for the next guy */ 3436 PORT_Memset(slot->tokDescription, 0, sizeof(slot->tokDescription)); 3437 3438 /* now shut down the databases. */ 3439 sftk_DBShutdown(slot); 3440 return CKR_OK; 3441 } 3442 3443 /* 3444 * initialize one of the slot structures. figure out which by the ID 3445 */ 3446 CK_RV 3447 SFTK_DestroySlotData(SFTKSlot *slot) 3448 { 3449 unsigned int i; 3450 3451 SFTK_ShutdownSlot(slot); 3452 3453 sftk_ClearSession(&slot->moduleObjects); 3454 3455 if (slot->tokObjHashTable) { 3456 PL_HashTableDestroy(slot->tokObjHashTable); 3457 slot->tokObjHashTable = NULL; 3458 } 3459 3460 if (slot->sessObjHashTable) { 3461 PORT_Free(slot->sessObjHashTable); 3462 slot->sessObjHashTable = NULL; 3463 } 3464 slot->sessObjHashSize = 0; 3465 3466 if (slot->head) { 3467 PORT_Free(slot->head); 3468 slot->head = NULL; 3469 } 3470 slot->sessHashSize = 0; 3471 3472 /* OK everything has been disassembled, now we can finally get rid 3473 * of the locks */ 3474 SKIP_AFTER_FORK(PZ_DestroyLock(slot->slotLock)); 3475 slot->slotLock = NULL; 3476 if (slot->sessionLock) { 3477 for (i = 0; i < slot->numSessionLocks; i++) { 3478 if (slot->sessionLock[i]) { 3479 SKIP_AFTER_FORK(PZ_DestroyLock(slot->sessionLock[i])); 3480 slot->sessionLock[i] = NULL; 3481 } 3482 } 3483 PORT_Free(slot->sessionLock); 3484 slot->sessionLock = NULL; 3485 } 3486 if (slot->objectLock) { 3487 SKIP_AFTER_FORK(PZ_DestroyLock(slot->objectLock)); 3488 slot->objectLock = NULL; 3489 } 3490 if (slot->pwCheckLock) { 3491 SKIP_AFTER_FORK(PR_DestroyLock(slot->pwCheckLock)); 3492 slot->pwCheckLock = NULL; 3493 } 3494 PORT_Free(slot); 3495 return CKR_OK; 3496 } 3497 3498 /* 3499 * handle the SECMOD.db 3500 */ 3501 char ** 3502 NSC_ModuleDBFunc(unsigned long function, char *parameters, void *args) 3503 { 3504 #ifdef NSS_DISABLE_DBM 3505 return NSSUTIL_DoModuleDBFunction(function, parameters, args); 3506 #else 3507 char *secmod = NULL; 3508 char *appName = NULL; 3509 char *filename = NULL; 3510 NSSDBType dbType = NSS_DB_TYPE_NONE; 3511 PRBool rw; 3512 static char *success = "Success"; 3513 char **rvstr = NULL; 3514 3515 rvstr = NSSUTIL_DoModuleDBFunction(function, parameters, args); 3516 if (rvstr != NULL) { 3517 return rvstr; 3518 } 3519 3520 if (PORT_GetError() != SEC_ERROR_LEGACY_DATABASE) { 3521 return NULL; 3522 } 3523 3524 /* The legacy database uses the old dbm, which is only linked with the 3525 * legacy DB handler, which is only callable from softoken */ 3526 3527 secmod = _NSSUTIL_GetSecmodName(parameters, &dbType, &appName, 3528 &filename, &rw); 3529 3530 switch (function) { 3531 case SECMOD_MODULE_DB_FUNCTION_FIND: 3532 if (secmod == NULL) { 3533 PORT_SetError(SEC_ERROR_INVALID_ARGS); 3534 goto loser; 3535 } 3536 if (rw && (dbType != NSS_DB_TYPE_LEGACY) && 3537 (dbType != NSS_DB_TYPE_MULTIACCESS)) { 3538 /* if we get here, we are trying to update the local database */ 3539 /* force data from the legacy DB */ 3540 char *oldSecmod = NULL; 3541 char *oldAppName = NULL; 3542 char *oldFilename = NULL; 3543 PRBool oldrw; 3544 char **strings = NULL; 3545 int i; 3546 3547 dbType = NSS_DB_TYPE_LEGACY; 3548 oldSecmod = _NSSUTIL_GetSecmodName(parameters, &dbType, &oldAppName, 3549 &oldFilename, &oldrw); 3550 strings = sftkdbCall_ReadSecmodDB(appName, oldFilename, oldSecmod, 3551 (char *)parameters, oldrw); 3552 if (strings) { 3553 /* write out the strings */ 3554 for (i = 0; strings[i]; i++) { 3555 NSSUTIL_DoModuleDBFunction(SECMOD_MODULE_DB_FUNCTION_ADD, 3556 parameters, strings[i]); 3557 } 3558 sftkdbCall_ReleaseSecmodDBData(oldAppName, oldFilename, oldSecmod, 3559 (char **)strings, oldrw); 3560 } else { 3561 /* write out a dummy record */ 3562 NSSUTIL_DoModuleDBFunction(SECMOD_MODULE_DB_FUNCTION_ADD, 3563 parameters, " "); 3564 } 3565 if (oldSecmod) { 3566 PR_smprintf_free(oldSecmod); 3567 } 3568 if (oldAppName) { 3569 PORT_Free(oldAppName); 3570 } 3571 if (oldFilename) { 3572 PORT_Free(oldFilename); 3573 } 3574 rvstr = NSSUTIL_DoModuleDBFunction(function, parameters, args); 3575 break; 3576 } 3577 rvstr = sftkdbCall_ReadSecmodDB(appName, filename, secmod, 3578 (char *)parameters, rw); 3579 break; 3580 case SECMOD_MODULE_DB_FUNCTION_ADD: 3581 if (secmod == NULL) { 3582 PORT_SetError(SEC_ERROR_INVALID_ARGS); 3583 goto loser; 3584 } 3585 rvstr = (sftkdbCall_AddSecmodDB(appName, filename, secmod, 3586 (char *)args, rw) == SECSuccess) 3587 ? &success 3588 : NULL; 3589 break; 3590 case SECMOD_MODULE_DB_FUNCTION_DEL: 3591 if (secmod == NULL) { 3592 PORT_SetError(SEC_ERROR_INVALID_ARGS); 3593 goto loser; 3594 } 3595 rvstr = (sftkdbCall_DeleteSecmodDB(appName, filename, secmod, 3596 (char *)args, rw) == SECSuccess) 3597 ? &success 3598 : NULL; 3599 break; 3600 case SECMOD_MODULE_DB_FUNCTION_RELEASE: 3601 rvstr = (sftkdbCall_ReleaseSecmodDBData(appName, filename, secmod, 3602 (char **)args, rw) == SECSuccess) 3603 ? &success 3604 : NULL; 3605 break; 3606 } 3607 3608 loser: 3609 if (secmod) 3610 PR_smprintf_free(secmod); 3611 if (appName) 3612 PORT_Free(appName); 3613 if (filename) 3614 PORT_Free(filename); 3615 return rvstr; 3616 #endif /* NSS_DISABLE_DBM */ 3617 } 3618 3619 static void 3620 nscFreeAllSlots(unsigned int moduleIndex) 3621 { 3622 /* free all the slots */ 3623 SFTKSlot *slot = NULL; 3624 CK_SLOT_ID slotID; 3625 int i; 3626 3627 if (nscSlotList[moduleIndex]) { 3628 CK_ULONG tmpSlotCount = nscSlotCount[moduleIndex]; 3629 CK_SLOT_ID_PTR tmpSlotList = nscSlotList[moduleIndex]; 3630 PLHashTable *tmpSlotHashTable = nscSlotHashTable[moduleIndex]; 3631 3632 /* first close all the session */ 3633 for (i = 0; i < (int)tmpSlotCount; i++) { 3634 slotID = tmpSlotList[i]; 3635 (void)NSC_CloseAllSessions(slotID); 3636 } 3637 3638 /* now clear out the statics */ 3639 nscSlotList[moduleIndex] = NULL; 3640 nscSlotCount[moduleIndex] = 0; 3641 nscSlotHashTable[moduleIndex] = NULL; 3642 nscSlotListSize[moduleIndex] = 0; 3643 3644 for (i = 0; i < (int)tmpSlotCount; i++) { 3645 slotID = tmpSlotList[i]; 3646 slot = (SFTKSlot *) 3647 PL_HashTableLookup(tmpSlotHashTable, (void *)(uintptr_t)slotID); 3648 PORT_Assert(slot); 3649 if (!slot) 3650 continue; 3651 SFTK_DestroySlotData(slot); 3652 PL_HashTableRemove(tmpSlotHashTable, (void *)(uintptr_t)slotID); 3653 } 3654 PORT_Free(tmpSlotList); 3655 PL_HashTableDestroy(tmpSlotHashTable); 3656 } 3657 } 3658 3659 static void 3660 sftk_closePeer(PRBool isFIPS) 3661 { 3662 CK_SLOT_ID slotID = isFIPS ? PRIVATE_KEY_SLOT_ID : FIPS_SLOT_ID; 3663 SFTKSlot *slot; 3664 unsigned int moduleIndex = isFIPS ? NSC_NON_FIPS_MODULE : NSC_FIPS_MODULE; 3665 PLHashTable *tmpSlotHashTable = nscSlotHashTable[moduleIndex]; 3666 3667 slot = (SFTKSlot *)PL_HashTableLookup(tmpSlotHashTable, (void *)(uintptr_t)slotID); 3668 if (slot == NULL) { 3669 return; 3670 } 3671 sftk_DBShutdown(slot); 3672 return; 3673 } 3674 3675 extern void sftk_PBELockInit(void); 3676 extern void sftk_PBELockShutdown(void); 3677 3678 /* Parse the library parameters from the first occurance in the following src.: 3679 * 1. C_INITIALIZED_ARGS - lib params are included in LibraryParameters field 3680 * 2. NSS_LIB_PARAMS - env. var. containing the lib. params. 3681 * 3. NSS_LIB_PARAMS_FILE - env. var. pointion to a file with lib. params. 3682 * 4. /etc/nss/params.config - default lib. param. file location [Linux only] 3683 * 5. LIB_PARAM_DEFAULT - string ensureing the pressence at all times 3684 * "configdir='' certPrefix='' keyPrefix='' secmod='' flags=noCertDB,noModDB" 3685 */ 3686 static CK_RV 3687 sftk_getParameters(CK_C_INITIALIZE_ARGS *init_args, PRBool isFIPS, 3688 sftk_parameters *paramStrings) 3689 { 3690 CK_RV crv; 3691 char *libParams; 3692 const char *filename; 3693 PRFileDesc *file_dc; 3694 PRBool free_mem = PR_FALSE; 3695 3696 if (!init_args || !init_args->LibraryParameters) { 3697 /* Library parameters were not provided via C_Initialize_args*/ 3698 3699 /* Enviromental value has precedence to configuration filename */ 3700 libParams = PR_GetEnvSecure("NSS_LIB_PARAMS"); 3701 3702 if (!libParams) { 3703 /* Load from config filename or use default */ 3704 filename = PR_GetEnvSecure("NSS_LIB_PARAMS_FILE"); 3705 #ifdef XP_UNIX 3706 /* Use default configuration file for Linux only */ 3707 if (!filename) 3708 filename = LIB_PARAM_DEFAULT_FILE_LOCATION; 3709 #endif 3710 if (filename) { 3711 file_dc = PR_OpenFile(filename, PR_RDONLY, 444); 3712 if (file_dc) { 3713 /* file opened */ 3714 PRInt32 len = PR_Available(file_dc); 3715 libParams = PORT_NewArray(char, len + 1); 3716 if (libParams) { 3717 /* memory allocated */ 3718 if (PR_Read(file_dc, libParams, len) == -1) { 3719 PORT_Free(libParams); 3720 libParams = NULL; 3721 } else { 3722 free_mem = PR_TRUE; 3723 libParams[len] = '\0'; 3724 } 3725 } 3726 3727 PR_Close(file_dc); 3728 } 3729 } 3730 } 3731 3732 if (libParams == NULL) 3733 libParams = LIB_PARAM_DEFAULT; 3734 3735 } else { 3736 /* Use parameters provided with C_Initialize_args */ 3737 libParams = (char *)init_args->LibraryParameters; 3738 } 3739 3740 crv = sftk_parseParameters(libParams, paramStrings, isFIPS); 3741 if (crv != CKR_OK) { 3742 crv = CKR_ARGUMENTS_BAD; 3743 goto loser; 3744 } 3745 3746 crv = CKR_OK; 3747 loser: 3748 if (free_mem) 3749 PORT_Free(libParams); 3750 3751 return crv; 3752 } 3753 3754 /* NSC_Initialize initializes the Cryptoki library. */ 3755 CK_RV 3756 nsc_CommonInitialize(CK_VOID_PTR pReserved, PRBool isFIPS) 3757 { 3758 CK_RV crv = CKR_OK; 3759 SECStatus rv; 3760 CK_C_INITIALIZE_ARGS *init_args = (CK_C_INITIALIZE_ARGS *)pReserved; 3761 PRBool destroy_freelist_on_error = PR_TRUE; 3762 int i; 3763 unsigned int moduleIndex = isFIPS ? NSC_FIPS_MODULE : NSC_NON_FIPS_MODULE; 3764 3765 if (isFIPS) { 3766 loginWaitTime = PR_SecondsToInterval(1); 3767 } 3768 3769 ENABLE_FORK_CHECK(); 3770 3771 sftk_PBELockInit(); 3772 3773 rv = SECOID_Init(); 3774 if (rv != SECSuccess) { 3775 crv = CKR_DEVICE_ERROR; 3776 return crv; 3777 } 3778 3779 rv = BL_Init(); /* initialize freebl engine */ 3780 if (rv != SECSuccess) { 3781 crv = CKR_DEVICE_ERROR; 3782 return crv; 3783 } 3784 3785 rv = RNG_RNGInit(); /* initialize random number generator */ 3786 if (rv != SECSuccess) { 3787 crv = CKR_DEVICE_ERROR; 3788 return crv; 3789 } 3790 3791 /* NOTE: 3792 * we should be getting out mutexes from this list, not statically binding 3793 * them from NSPR. This should happen before we allow the internal to split 3794 * off from the rest on NSS. 3795 */ 3796 3797 /* initialize the key and cert db's */ 3798 if (init_args && (!(init_args->flags & CKF_OS_LOCKING_OK))) { 3799 if (init_args->CreateMutex && init_args->DestroyMutex && 3800 init_args->LockMutex && init_args->UnlockMutex) { 3801 /* softoken always uses NSPR (ie. OS locking), and doesn't know how 3802 * to use the lock functions provided by the application. 3803 */ 3804 crv = CKR_CANT_LOCK; 3805 return crv; 3806 } 3807 if (init_args->CreateMutex || init_args->DestroyMutex || 3808 init_args->LockMutex || init_args->UnlockMutex) { 3809 /* only some of the lock functions were provided by the 3810 * application. This is invalid per PKCS#11 spec. 3811 */ 3812 crv = CKR_ARGUMENTS_BAD; 3813 return crv; 3814 } 3815 } 3816 3817 sftk_parameters paramStrings; 3818 3819 /* load and parse the library parameters */ 3820 crv = sftk_getParameters(init_args, isFIPS, ¶mStrings); 3821 if (crv != CKR_OK) { 3822 goto loser; 3823 } 3824 3825 crv = sftk_configure(paramStrings.man, paramStrings.libdes); 3826 if (crv != CKR_OK) { 3827 goto loser; 3828 } 3829 3830 /* if we have a peer already open, have him close his DB's so we 3831 * don't clobber each other. */ 3832 if ((isFIPS && nsc_init) || (!isFIPS && nsf_init)) { 3833 sftk_closePeer(isFIPS); 3834 if (sftk_audit_enabled) { 3835 if (isFIPS && nsc_init) { 3836 sftk_LogAuditMessage(NSS_AUDIT_INFO, NSS_AUDIT_FIPS_STATE, 3837 "enabled FIPS mode"); 3838 } else { 3839 sftk_LogAuditMessage(NSS_AUDIT_INFO, NSS_AUDIT_FIPS_STATE, 3840 "disabled FIPS mode"); 3841 } 3842 } 3843 /* if we have a peer open, we don't want to destroy the freelist 3844 * from under the peer if we fail, the free list will be 3845 * destroyed in that case when the C_Finalize is called for 3846 * the peer */ 3847 destroy_freelist_on_error = PR_FALSE; 3848 } 3849 /* allow us to create objects in SFTK_SlotInit */ 3850 sftk_InitFreeLists(); 3851 3852 for (i = 0; i < paramStrings.token_count; i++) { 3853 crv = SFTK_SlotInit(paramStrings.configdir, 3854 paramStrings.updatedir, paramStrings.updateID, 3855 ¶mStrings.tokens[i], moduleIndex); 3856 if (crv != CKR_OK) { 3857 nscFreeAllSlots(moduleIndex); 3858 break; 3859 } 3860 } 3861 3862 loser: 3863 3864 sftk_freeParams(¶mStrings); 3865 3866 if (destroy_freelist_on_error && (CKR_OK != crv)) { 3867 /* idempotent. If the list are already freed, this is a noop */ 3868 sftk_CleanupFreeLists(); 3869 } 3870 3871 #ifndef NO_FORK_CHECK 3872 if (CKR_OK == crv) { 3873 #if defined(CHECK_FORK_MIXED) 3874 /* Before Solaris 10, fork handlers are not unregistered at dlclose() 3875 * time. So, we only use pthread_atfork on Solaris 10 and later. For 3876 * earlier versions, we use PID checks. 3877 */ 3878 char buf[200]; 3879 int major = 0, minor = 0; 3880 3881 long rv = sysinfo(SI_RELEASE, buf, sizeof(buf)); 3882 if (rv > 0 && rv < sizeof(buf)) { 3883 if (2 == sscanf(buf, "%d.%d", &major, &minor)) { 3884 /* Are we on Solaris 10 or greater ? */ 3885 if (major > 5 || (5 == major && minor >= 10)) { 3886 /* we are safe to use pthread_atfork */ 3887 usePthread_atfork = PR_TRUE; 3888 } 3889 } 3890 } 3891 if (usePthread_atfork) { 3892 pthread_atfork(NULL, NULL, ForkedChild); 3893 } else { 3894 myPid = getpid(); 3895 } 3896 3897 #elif defined(CHECK_FORK_PTHREAD) 3898 pthread_atfork(NULL, NULL, ForkedChild); 3899 #elif defined(CHECK_FORK_GETPID) 3900 myPid = getpid(); 3901 #else 3902 #error Incorrect fork check method. 3903 #endif 3904 } 3905 #endif 3906 return crv; 3907 } 3908 3909 CK_RV 3910 NSC_Initialize(CK_VOID_PTR pReserved) 3911 { 3912 CK_RV crv; 3913 3914 sftk_ForkReset(pReserved, &crv); 3915 3916 if (nsc_init) { 3917 return CKR_CRYPTOKI_ALREADY_INITIALIZED; 3918 } 3919 crv = nsc_CommonInitialize(pReserved, PR_FALSE); 3920 nsc_init = (PRBool)(crv == CKR_OK); 3921 return crv; 3922 } 3923 3924 /* NSC_Finalize indicates that an application is done with the 3925 * Cryptoki library.*/ 3926 CK_RV 3927 nsc_CommonFinalize(CK_VOID_PTR pReserved, PRBool isFIPS) 3928 { 3929 /* propagate the fork status to freebl and util */ 3930 BL_SetForkState(parentForkedAfterC_Initialize); 3931 UTIL_SetForkState(parentForkedAfterC_Initialize); 3932 3933 nscFreeAllSlots(isFIPS ? NSC_FIPS_MODULE : NSC_NON_FIPS_MODULE); 3934 3935 /* don't muck with the globals if our peer is still initialized */ 3936 if (isFIPS && nsc_init) { 3937 return CKR_OK; 3938 } 3939 if (!isFIPS && nsf_init) { 3940 return CKR_OK; 3941 } 3942 3943 sftk_CleanupFreeLists(); 3944 sftkdb_Shutdown(); 3945 3946 /* This function does not discard all our previously aquired entropy. */ 3947 RNG_RNGShutdown(); 3948 3949 /* tell freeBL to clean up after itself */ 3950 BL_Cleanup(); 3951 3952 /* reset fork status in freebl. We must do this before BL_Unload so that 3953 * this call doesn't force freebl to be reloaded. */ 3954 BL_SetForkState(PR_FALSE); 3955 3956 #ifndef NSS_STATIC_SOFTOKEN 3957 /* unload freeBL shared library from memory. This may only decrement the 3958 * OS refcount if it's been loaded multiple times, eg. by libssl */ 3959 BL_Unload(); 3960 #endif 3961 3962 /* clean up the default OID table */ 3963 SECOID_Shutdown(); 3964 3965 sftk_PBELockShutdown(); 3966 3967 /* reset fork status in util */ 3968 UTIL_SetForkState(PR_FALSE); 3969 3970 nsc_init = PR_FALSE; 3971 3972 #ifndef NO_FORK_CHECK 3973 #ifdef CHECK_FORK_MIXED 3974 if (!usePthread_atfork) { 3975 myPid = 0; /* allow CHECK_FORK in the next softoken initialization to 3976 * succeed */ 3977 } else { 3978 forked = PR_FALSE; /* allow reinitialization */ 3979 } 3980 #elif defined(CHECK_FORK_GETPID) 3981 myPid = 0; /* allow reinitialization */ 3982 #elif defined(CHECK_FORK_PTHREAD) 3983 forked = PR_FALSE; /* allow reinitialization */ 3984 #endif 3985 #endif 3986 return CKR_OK; 3987 } 3988 3989 /* Hard-reset the entire softoken PKCS#11 module if the parent process forked 3990 * while it was initialized. */ 3991 PRBool 3992 sftk_ForkReset(CK_VOID_PTR pReserved, CK_RV *crv) 3993 { 3994 #ifndef NO_FORK_CHECK 3995 if (PARENT_FORKED()) { 3996 parentForkedAfterC_Initialize = PR_TRUE; 3997 if (nsc_init) { 3998 /* finalize non-FIPS token */ 3999 *crv = nsc_CommonFinalize(pReserved, PR_FALSE); 4000 PORT_Assert(CKR_OK == *crv); 4001 nsc_init = (PRBool) !(*crv == CKR_OK); 4002 } 4003 if (nsf_init) { 4004 /* finalize FIPS token */ 4005 *crv = nsc_CommonFinalize(pReserved, PR_TRUE); 4006 PORT_Assert(CKR_OK == *crv); 4007 nsf_init = (PRBool) !(*crv == CKR_OK); 4008 } 4009 parentForkedAfterC_Initialize = PR_FALSE; 4010 return PR_TRUE; 4011 } 4012 #endif 4013 return PR_FALSE; 4014 } 4015 4016 /* NSC_Finalize indicates that an application is done with the 4017 * Cryptoki library.*/ 4018 CK_RV 4019 NSC_Finalize(CK_VOID_PTR pReserved) 4020 { 4021 CK_RV crv; 4022 4023 /* reset entire PKCS#11 module upon fork */ 4024 if (sftk_ForkReset(pReserved, &crv)) { 4025 return crv; 4026 } 4027 4028 if (!nsc_init) { 4029 return CKR_OK; 4030 } 4031 4032 crv = nsc_CommonFinalize(pReserved, PR_FALSE); 4033 4034 nsc_init = (PRBool) !(crv == CKR_OK); 4035 4036 return crv; 4037 } 4038 4039 extern const char __nss_softokn_version[]; 4040 4041 /* NSC_GetInfo returns general information about Cryptoki. */ 4042 CK_RV 4043 NSC_GetInfo(CK_INFO_PTR pInfo) 4044 { 4045 #define NSS_VERSION_VARIABLE __nss_softokn_version 4046 #include "verref.h" 4047 4048 CHECK_FORK(); 4049 4050 pInfo->cryptokiVersion.major = CRYPTOKI_VERSION_MAJOR; 4051 pInfo->cryptokiVersion.minor = CRYPTOKI_VERSION_MINOR; 4052 PORT_Memcpy(pInfo->manufacturerID, manufacturerID, 32); 4053 pInfo->libraryVersion.major = SOFTOKEN_VMAJOR; 4054 pInfo->libraryVersion.minor = SOFTOKEN_VMINOR; 4055 PORT_Memcpy(pInfo->libraryDescription, libraryDescription, 32); 4056 pInfo->flags = 0; 4057 return CKR_OK; 4058 } 4059 4060 /* NSC_GetInfo returns general information about Cryptoki. */ 4061 CK_RV 4062 NSC_GetInfoV2(CK_INFO_PTR pInfo) 4063 { 4064 CHECK_FORK(); 4065 4066 pInfo->cryptokiVersion.major = 2; 4067 pInfo->cryptokiVersion.minor = 40; 4068 PORT_Memcpy(pInfo->manufacturerID, manufacturerID, 32); 4069 pInfo->libraryVersion.major = SOFTOKEN_VMAJOR; 4070 pInfo->libraryVersion.minor = SOFTOKEN_VMINOR; 4071 PORT_Memcpy(pInfo->libraryDescription, libraryDescription, 32); 4072 pInfo->flags = 0; 4073 return CKR_OK; 4074 } 4075 4076 /* NSC_GetSlotList obtains a list of slots in the system. */ 4077 CK_RV 4078 nsc_CommonGetSlotList(CK_BBOOL tokenPresent, 4079 CK_SLOT_ID_PTR pSlotList, CK_ULONG_PTR pulCount, 4080 unsigned int moduleIndex) 4081 { 4082 *pulCount = nscSlotCount[moduleIndex]; 4083 if (pSlotList != NULL) { 4084 PORT_Memcpy(pSlotList, nscSlotList[moduleIndex], 4085 nscSlotCount[moduleIndex] * sizeof(CK_SLOT_ID)); 4086 } 4087 return CKR_OK; 4088 } 4089 4090 /* NSC_GetSlotList obtains a list of slots in the system. */ 4091 CK_RV 4092 NSC_GetSlotList(CK_BBOOL tokenPresent, 4093 CK_SLOT_ID_PTR pSlotList, CK_ULONG_PTR pulCount) 4094 { 4095 CHECK_FORK(); 4096 return nsc_CommonGetSlotList(tokenPresent, pSlotList, pulCount, 4097 NSC_NON_FIPS_MODULE); 4098 } 4099 4100 /* NSC_GetSlotInfo obtains information about a particular slot in the system. */ 4101 CK_RV 4102 NSC_GetSlotInfo(CK_SLOT_ID slotID, CK_SLOT_INFO_PTR pInfo) 4103 { 4104 SFTKSlot *slot = sftk_SlotFromID(slotID, PR_TRUE); 4105 4106 CHECK_FORK(); 4107 4108 if (slot == NULL) 4109 return CKR_SLOT_ID_INVALID; 4110 4111 PORT_Memcpy(pInfo->manufacturerID, manufacturerID, 4112 sizeof(pInfo->manufacturerID)); 4113 PORT_Memcpy(pInfo->slotDescription, slot->slotDescription, 4114 sizeof(pInfo->slotDescription)); 4115 pInfo->flags = (slot->present) ? CKF_TOKEN_PRESENT : 0; 4116 4117 /* all user defined slots are defined as removable */ 4118 if (slotID >= SFTK_MIN_USER_SLOT_ID) { 4119 pInfo->flags |= CKF_REMOVABLE_DEVICE; 4120 } else { 4121 /* In the case where we are doing a merge update, we need 4122 * the DB slot to be removable so the token name can change 4123 * appropriately. */ 4124 SFTKDBHandle *handle = sftk_getKeyDB(slot); 4125 if (handle) { 4126 if (sftkdb_InUpdateMerge(handle)) { 4127 pInfo->flags |= CKF_REMOVABLE_DEVICE; 4128 } 4129 sftk_freeDB(handle); 4130 } 4131 } 4132 4133 /* If there is no key database, this is for example the case when NSS was 4134 * initialized with NSS_NoDbInit(), then there won't be any point in 4135 * requesting a PIN. Set the CKF_USER_PIN_INITIALIZED bit so that 4136 * PK11_NeedUserInit() doesn't indicate that a PIN is needed. 4137 */ 4138 if (slot->keyDB == NULL) { 4139 pInfo->flags |= CKF_USER_PIN_INITIALIZED; 4140 } 4141 4142 /* ok we really should read it out of the keydb file. */ 4143 /* pInfo->hardwareVersion.major = NSSLOWKEY_DB_FILE_VERSION; */ 4144 pInfo->hardwareVersion.major = SOFTOKEN_VMAJOR; 4145 pInfo->hardwareVersion.minor = SOFTOKEN_VMINOR; 4146 pInfo->firmwareVersion.major = SOFTOKEN_VPATCH; 4147 pInfo->firmwareVersion.minor = SOFTOKEN_VBUILD; 4148 return CKR_OK; 4149 } 4150 4151 /* 4152 * check the current state of the 'needLogin' flag in case the database has 4153 * been changed underneath us. 4154 */ 4155 static PRBool 4156 sftk_checkNeedLogin(SFTKSlot *slot, SFTKDBHandle *keyHandle) 4157 { 4158 PRBool needLogin; 4159 if (sftkdb_PWCached(keyHandle) == SECSuccess) { 4160 PZ_Lock(slot->slotLock); 4161 needLogin = slot->needLogin; 4162 PZ_Unlock(slot->slotLock); 4163 } else { 4164 needLogin = (PRBool)!sftk_hasNullPassword(slot, keyHandle); 4165 PZ_Lock(slot->slotLock); 4166 slot->needLogin = needLogin; 4167 PZ_Unlock(slot->slotLock); 4168 } 4169 return needLogin; 4170 } 4171 4172 static PRBool 4173 sftk_isBlank(const char *s, int len) 4174 { 4175 int i; 4176 for (i = 0; i < len; i++) { 4177 if (s[i] != ' ') { 4178 return PR_FALSE; 4179 } 4180 } 4181 return PR_TRUE; 4182 } 4183 4184 /* NSC_GetTokenInfo obtains information about a particular token in 4185 * the system. */ 4186 CK_RV 4187 NSC_GetTokenInfo(CK_SLOT_ID slotID, CK_TOKEN_INFO_PTR pInfo) 4188 { 4189 SFTKSlot *slot; 4190 SFTKDBHandle *handle; 4191 4192 CHECK_FORK(); 4193 4194 if (!nsc_init && !nsf_init) 4195 return CKR_CRYPTOKI_NOT_INITIALIZED; 4196 slot = sftk_SlotFromID(slotID, PR_FALSE); 4197 if (slot == NULL) 4198 return CKR_SLOT_ID_INVALID; 4199 4200 PORT_Memcpy(pInfo->manufacturerID, manufacturerID, 32); 4201 PORT_Memcpy(pInfo->model, "NSS 3 ", 16); 4202 PORT_Memcpy(pInfo->serialNumber, "0000000000000000", 16); 4203 PORT_Memcpy(pInfo->utcTime, "0000000000000000", 16); 4204 pInfo->ulMaxSessionCount = 0; /* arbitrarily large */ 4205 pInfo->ulMaxRwSessionCount = 0; /* arbitarily large */ 4206 PZ_Lock(slot->slotLock); /* Protect sessionCount / rwSessioncount */ 4207 pInfo->ulSessionCount = slot->sessionCount; 4208 pInfo->ulRwSessionCount = slot->rwSessionCount; 4209 PZ_Unlock(slot->slotLock); /* Unlock before sftk_getKeyDB */ 4210 pInfo->firmwareVersion.major = 0; 4211 pInfo->firmwareVersion.minor = 0; 4212 PORT_Memcpy(pInfo->label, slot->tokDescription, sizeof(pInfo->label)); 4213 handle = sftk_getKeyDB(slot); 4214 pInfo->flags = CKF_RNG | CKF_DUAL_CRYPTO_OPERATIONS; 4215 if (handle == NULL) { 4216 pInfo->flags |= CKF_WRITE_PROTECTED; 4217 pInfo->ulMaxPinLen = 0; 4218 pInfo->ulMinPinLen = 0; 4219 pInfo->ulTotalPublicMemory = 0; 4220 pInfo->ulFreePublicMemory = 0; 4221 pInfo->ulTotalPrivateMemory = 0; 4222 pInfo->ulFreePrivateMemory = 0; 4223 pInfo->hardwareVersion.major = 4; 4224 pInfo->hardwareVersion.minor = 0; 4225 } else { 4226 /* 4227 * we have three possible states which we may be in: 4228 * (1) No DB password has been initialized. This also means we 4229 * have no keys in the key db. 4230 * (2) Password initialized to NULL. This means we have keys, but 4231 * the user has chosen not use a password. 4232 * (3) Finally we have an initialized password whicn is not NULL, and 4233 * we will need to prompt for it. 4234 */ 4235 if (sftkdb_HasPasswordSet(handle) == SECFailure) { 4236 pInfo->flags |= CKF_LOGIN_REQUIRED; 4237 } else if (!sftk_checkNeedLogin(slot, handle)) { 4238 pInfo->flags |= CKF_USER_PIN_INITIALIZED; 4239 } else { 4240 pInfo->flags |= CKF_LOGIN_REQUIRED | CKF_USER_PIN_INITIALIZED; 4241 /* 4242 * if we are doing a merge style update, and we need to get the password 4243 * of our source database (the database we are updating from), make sure we 4244 * return a token name that will match the database we are prompting for. 4245 */ 4246 if (sftkdb_NeedUpdateDBPassword(handle)) { 4247 /* if we have an update tok description, use it. otherwise 4248 * use the updateID for this database */ 4249 if (!sftk_isBlank(slot->updateTokDescription, 4250 sizeof(pInfo->label))) { 4251 PORT_Memcpy(pInfo->label, slot->updateTokDescription, 4252 sizeof(pInfo->label)); 4253 } else { 4254 /* build from updateID */ 4255 const char *updateID = sftkdb_GetUpdateID(handle); 4256 if (updateID) { 4257 sftk_setStringName(updateID, (char *)pInfo->label, 4258 sizeof(pInfo->label), PR_FALSE); 4259 } 4260 } 4261 } 4262 } 4263 pInfo->ulMaxPinLen = SFTK_MAX_PIN; 4264 pInfo->ulMinPinLen = (CK_ULONG)slot->minimumPinLen; 4265 pInfo->ulTotalPublicMemory = 1; 4266 pInfo->ulFreePublicMemory = 1; 4267 pInfo->ulTotalPrivateMemory = 1; 4268 pInfo->ulFreePrivateMemory = 1; 4269 #ifdef SHDB_FIXME 4270 pInfo->hardwareVersion.major = CERT_DB_FILE_VERSION; 4271 pInfo->hardwareVersion.minor = handle->version; 4272 #else 4273 pInfo->hardwareVersion.major = 0; 4274 pInfo->hardwareVersion.minor = 0; 4275 #endif 4276 sftk_freeDB(handle); 4277 } 4278 /* 4279 * CKF_LOGIN_REQUIRED CKF_USER_PIN_INITIALIZED how CKF_TOKEN_INITIALIZED 4280 * should be set 4281 * 0 0 1 4282 * 1 0 0 4283 * 0 1 1 4284 * 1 1 1 4285 */ 4286 if (!(pInfo->flags & CKF_LOGIN_REQUIRED) || 4287 (pInfo->flags & CKF_USER_PIN_INITIALIZED)) { 4288 pInfo->flags |= CKF_TOKEN_INITIALIZED; 4289 } 4290 return CKR_OK; 4291 } 4292 4293 /* NSC_GetMechanismList obtains a list of mechanism types 4294 * supported by a token. */ 4295 CK_RV 4296 NSC_GetMechanismList(CK_SLOT_ID slotID, 4297 CK_MECHANISM_TYPE_PTR pMechanismList, CK_ULONG_PTR pulCount) 4298 { 4299 CK_ULONG i; 4300 4301 CHECK_FORK(); 4302 4303 switch (slotID) { 4304 /* default: */ 4305 case NETSCAPE_SLOT_ID: 4306 *pulCount = mechanismCount; 4307 if (pMechanismList != NULL) { 4308 for (i = 0; i < mechanismCount; i++) { 4309 pMechanismList[i] = mechanisms[i].type; 4310 } 4311 } 4312 break; 4313 default: 4314 *pulCount = 0; 4315 for (i = 0; i < mechanismCount; i++) { 4316 if (mechanisms[i].privkey) { 4317 (*pulCount)++; 4318 if (pMechanismList != NULL) { 4319 *pMechanismList++ = mechanisms[i].type; 4320 } 4321 } 4322 } 4323 break; 4324 } 4325 return CKR_OK; 4326 } 4327 4328 /* NSC_GetMechanismInfo obtains information about a particular mechanism 4329 * possibly supported by a token. */ 4330 CK_RV 4331 NSC_GetMechanismInfo(CK_SLOT_ID slotID, CK_MECHANISM_TYPE type, 4332 CK_MECHANISM_INFO_PTR pInfo) 4333 { 4334 PRBool isPrivateKey; 4335 CK_ULONG i; 4336 4337 CHECK_FORK(); 4338 4339 switch (slotID) { 4340 case NETSCAPE_SLOT_ID: 4341 isPrivateKey = PR_FALSE; 4342 break; 4343 default: 4344 isPrivateKey = PR_TRUE; 4345 break; 4346 } 4347 for (i = 0; i < mechanismCount; i++) { 4348 if (type == mechanisms[i].type) { 4349 if (isPrivateKey && !mechanisms[i].privkey) { 4350 return CKR_MECHANISM_INVALID; 4351 } 4352 PORT_Memcpy(pInfo, &mechanisms[i].info, sizeof(CK_MECHANISM_INFO)); 4353 return CKR_OK; 4354 } 4355 } 4356 return CKR_MECHANISM_INVALID; 4357 } 4358 4359 /* 4360 * If we are using the V2 interface, strip out the message flags 4361 */ 4362 #define SFTK_MESSAGE_FLAGS (CKF_MESSAGE_ENCRYPT | CKF_MESSAGE_DECRYPT | CKF_MESSAGE_SIGN | CKF_MESSAGE_VERIFY) 4363 CK_RV 4364 NSC_GetMechanismInfoV2(CK_SLOT_ID slotID, CK_MECHANISM_TYPE type, 4365 CK_MECHANISM_INFO_PTR pInfo) 4366 { 4367 CK_RV crv; 4368 crv = NSC_GetMechanismInfo(slotID, type, pInfo); 4369 if (crv == CKR_OK) { 4370 pInfo->flags = pInfo->flags & ~SFTK_MESSAGE_FLAGS; 4371 } 4372 return crv; 4373 } 4374 4375 CK_RV 4376 sftk_MechAllowsOperation(CK_MECHANISM_TYPE type, CK_ATTRIBUTE_TYPE op) 4377 { 4378 CK_ULONG i; 4379 CK_FLAGS flags = sftk_AttributeToFlags(op); 4380 4381 if (flags == 0) { 4382 return CKR_ARGUMENTS_BAD; 4383 } 4384 for (i = 0; i < mechanismCount; i++) { 4385 if (type == mechanisms[i].type) { 4386 return (flags & mechanisms[i].info.flags) ? CKR_OK 4387 : CKR_MECHANISM_INVALID; 4388 } 4389 } 4390 return CKR_MECHANISM_INVALID; 4391 } 4392 4393 /* NSC_InitToken initializes a token. */ 4394 CK_RV 4395 NSC_InitToken(CK_SLOT_ID slotID, CK_CHAR_PTR pPin, 4396 CK_ULONG ulPinLen, CK_CHAR_PTR pLabel) 4397 { 4398 SFTKSlot *slot = sftk_SlotFromID(slotID, PR_FALSE); 4399 SFTKDBHandle *handle; 4400 SECStatus rv; 4401 unsigned int i; 4402 SFTKObject *object; 4403 4404 CHECK_FORK(); 4405 4406 if (slot == NULL) 4407 return CKR_SLOT_ID_INVALID; 4408 4409 /* don't initialize the database if we aren't talking to a token 4410 * that uses the key database. 4411 */ 4412 if (slotID == NETSCAPE_SLOT_ID) { 4413 return CKR_TOKEN_WRITE_PROTECTED; 4414 } 4415 4416 /* first, delete all our loaded key and cert objects from our 4417 * internal list. */ 4418 PZ_Lock(slot->objectLock); 4419 for (i = 0; i < slot->sessObjHashSize; i++) { 4420 do { 4421 object = slot->sessObjHashTable[i]; 4422 /* hand deque */ 4423 /* this duplicates function of NSC_close session functions, but 4424 * because we know that we are freeing all the sessions, we can 4425 * do more efficient processing */ 4426 if (object) { 4427 slot->sessObjHashTable[i] = object->next; 4428 4429 if (object->next) 4430 object->next->prev = NULL; 4431 object->next = object->prev = NULL; 4432 } 4433 if (object) 4434 sftk_FreeObject(object); 4435 } while (object != NULL); 4436 } 4437 slot->DB_loaded = PR_FALSE; 4438 PZ_Unlock(slot->objectLock); 4439 4440 /* then clear out the key database */ 4441 handle = sftk_getKeyDB(slot); 4442 if (handle == NULL) { 4443 return CKR_TOKEN_WRITE_PROTECTED; 4444 } 4445 4446 rv = sftkdb_ResetKeyDB(handle); 4447 /* clear the password */ 4448 sftkdb_ClearPassword(handle); 4449 /* update slot->needLogin (should be true now since no password is set) */ 4450 sftk_checkNeedLogin(slot, handle); 4451 sftk_freeDB(handle); 4452 if (rv != SECSuccess) { 4453 return CKR_DEVICE_ERROR; 4454 } 4455 4456 return CKR_OK; 4457 } 4458 4459 /* NSC_InitPIN initializes the normal user's PIN. */ 4460 CK_RV 4461 NSC_InitPIN(CK_SESSION_HANDLE hSession, 4462 CK_CHAR_PTR pPin, CK_ULONG ulPinLen) 4463 { 4464 SFTKSession *sp = NULL; 4465 SFTKSlot *slot; 4466 SFTKDBHandle *handle = NULL; 4467 char newPinStr[SFTK_MAX_PIN + 1]; 4468 SECStatus rv; 4469 CK_RV crv = CKR_SESSION_HANDLE_INVALID; 4470 PRBool tokenRemoved = PR_FALSE; 4471 4472 CHECK_FORK(); 4473 4474 sp = sftk_SessionFromHandle(hSession); 4475 if (sp == NULL) { 4476 goto loser; 4477 } 4478 4479 slot = sftk_SlotFromSession(sp); 4480 if (slot == NULL) { 4481 goto loser; 4482 } 4483 4484 handle = sftk_getKeyDB(slot); 4485 if (handle == NULL) { 4486 crv = CKR_PIN_LEN_RANGE; 4487 goto loser; 4488 } 4489 4490 if (sp->info.state != CKS_RW_SO_FUNCTIONS) { 4491 crv = CKR_USER_NOT_LOGGED_IN; 4492 goto loser; 4493 } 4494 4495 sftk_FreeSession(sp); 4496 sp = NULL; 4497 4498 /* make sure the pins aren't too long */ 4499 if (ulPinLen > SFTK_MAX_PIN) { 4500 crv = CKR_PIN_LEN_RANGE; 4501 goto loser; 4502 } 4503 if (ulPinLen < (CK_ULONG)slot->minimumPinLen) { 4504 crv = CKR_PIN_LEN_RANGE; 4505 goto loser; 4506 } 4507 4508 if (sftkdb_HasPasswordSet(handle) != SECFailure) { 4509 crv = CKR_DEVICE_ERROR; 4510 goto loser; 4511 } 4512 4513 /* convert to null terminated string */ 4514 PORT_Memcpy(newPinStr, pPin, ulPinLen); 4515 newPinStr[ulPinLen] = 0; 4516 4517 /* build the hashed pins which we pass around */ 4518 4519 /* change the data base */ 4520 rv = sftkdb_ChangePassword(handle, NULL, newPinStr, &tokenRemoved); 4521 if (tokenRemoved) { 4522 sftk_CloseAllSessions(slot, PR_FALSE); 4523 } 4524 PORT_Memset(newPinStr, 0, ulPinLen); 4525 sftk_freeDB(handle); 4526 handle = NULL; 4527 4528 /* Now update our local copy of the pin */ 4529 if (rv == SECSuccess) { 4530 if (ulPinLen == 0) { 4531 PZ_Lock(slot->slotLock); 4532 slot->needLogin = PR_FALSE; 4533 PZ_Unlock(slot->slotLock); 4534 } 4535 /* database has been initialized, now force min password in FIPS 4536 * mode. NOTE: if we are in level1, we may not have a password, but 4537 * forcing it now will prevent an insufficient password from being set. 4538 */ 4539 if ((sftk_GetModuleIndex(slot->slotID) == NSC_FIPS_MODULE) && 4540 (slot->minimumPinLen < FIPS_MIN_PIN)) { 4541 slot->minimumPinLen = FIPS_MIN_PIN; 4542 } 4543 return CKR_OK; 4544 } 4545 crv = CKR_PIN_INCORRECT; 4546 4547 loser: 4548 if (sp) { 4549 sftk_FreeSession(sp); 4550 } 4551 if (handle) { 4552 sftk_freeDB(handle); 4553 } 4554 return crv; 4555 } 4556 4557 /* NSC_SetPIN modifies the PIN of user that is currently logged in. */ 4558 /* NOTE: This is only valid for the PRIVATE_KEY_SLOT */ 4559 CK_RV 4560 NSC_SetPIN(CK_SESSION_HANDLE hSession, CK_CHAR_PTR pOldPin, 4561 CK_ULONG ulOldLen, CK_CHAR_PTR pNewPin, CK_ULONG ulNewLen) 4562 { 4563 SFTKSession *sp = NULL; 4564 SFTKSlot *slot; 4565 SFTKDBHandle *handle = NULL; 4566 char newPinStr[SFTK_MAX_PIN + 1], oldPinStr[SFTK_MAX_PIN + 1]; 4567 SECStatus rv; 4568 CK_RV crv = CKR_SESSION_HANDLE_INVALID; 4569 PRBool needLogin; 4570 PRBool tokenRemoved = PR_FALSE; 4571 4572 CHECK_FORK(); 4573 4574 sp = sftk_SessionFromHandle(hSession); 4575 if (sp == NULL) { 4576 goto loser; 4577 } 4578 4579 slot = sftk_SlotFromSession(sp); 4580 if (!slot) { 4581 goto loser; 4582 } 4583 4584 handle = sftk_getKeyDB(slot); 4585 if (handle == NULL) { 4586 sftk_FreeSession(sp); 4587 return CKR_PIN_LEN_RANGE; /* XXX FIXME wrong return value */ 4588 } 4589 4590 PZ_Lock(slot->slotLock); 4591 needLogin = slot->needLogin; 4592 PZ_Unlock(slot->slotLock); 4593 if (needLogin && sp->info.state != CKS_RW_USER_FUNCTIONS) { 4594 crv = CKR_USER_NOT_LOGGED_IN; 4595 goto loser; 4596 } 4597 4598 sftk_FreeSession(sp); 4599 sp = NULL; 4600 4601 /* make sure the pins aren't too long */ 4602 if ((ulNewLen > SFTK_MAX_PIN) || (ulOldLen > SFTK_MAX_PIN)) { 4603 crv = CKR_PIN_LEN_RANGE; 4604 goto loser; 4605 } 4606 /* check the length of new pin, unless both old and new passwords 4607 * are empty */ 4608 if ((ulNewLen != 0 || ulOldLen != 0) && 4609 ulNewLen < (CK_ULONG)slot->minimumPinLen) { 4610 crv = CKR_PIN_LEN_RANGE; 4611 goto loser; 4612 } 4613 4614 /* convert to null terminated string */ 4615 PORT_Memcpy(newPinStr, pNewPin, ulNewLen); 4616 newPinStr[ulNewLen] = 0; 4617 PORT_Memcpy(oldPinStr, pOldPin, ulOldLen); 4618 oldPinStr[ulOldLen] = 0; 4619 4620 /* change the data base password */ 4621 PR_Lock(slot->pwCheckLock); 4622 rv = sftkdb_ChangePassword(handle, oldPinStr, newPinStr, &tokenRemoved); 4623 PORT_Memset(newPinStr, 0, ulNewLen); 4624 PORT_Memset(oldPinStr, 0, ulOldLen); 4625 if (tokenRemoved) { 4626 sftk_CloseAllSessions(slot, PR_FALSE); 4627 } 4628 if ((rv != SECSuccess) && (sftk_isFIPS(slot->slotID))) { 4629 PR_Sleep(loginWaitTime); 4630 } 4631 PR_Unlock(slot->pwCheckLock); 4632 4633 /* Now update our local copy of the pin */ 4634 if (rv == SECSuccess) { 4635 PZ_Lock(slot->slotLock); 4636 slot->needLogin = (PRBool)(ulNewLen != 0); 4637 slot->isLoggedIn = (PRBool)(sftkdb_PWCached(handle) == SECSuccess); 4638 PZ_Unlock(slot->slotLock); 4639 /* Reset login flags. */ 4640 if (ulNewLen == 0) { 4641 PZ_Lock(slot->slotLock); 4642 slot->isLoggedIn = PR_FALSE; 4643 slot->ssoLoggedIn = PR_FALSE; 4644 PZ_Unlock(slot->slotLock); 4645 4646 tokenRemoved = PR_FALSE; 4647 rv = sftkdb_CheckPasswordNull(handle, &tokenRemoved); 4648 if (tokenRemoved) { 4649 sftk_CloseAllSessions(slot, PR_FALSE); 4650 } 4651 } 4652 sftk_update_all_states(slot); 4653 sftk_freeDB(handle); 4654 return CKR_OK; 4655 } 4656 crv = CKR_PIN_INCORRECT; 4657 loser: 4658 if (sp) { 4659 sftk_FreeSession(sp); 4660 } 4661 if (handle) { 4662 sftk_freeDB(handle); 4663 } 4664 return crv; 4665 } 4666 4667 /* NSC_OpenSession opens a session between an application and a token. */ 4668 CK_RV 4669 NSC_OpenSession(CK_SLOT_ID slotID, CK_FLAGS flags, 4670 CK_VOID_PTR pApplication, CK_NOTIFY Notify, CK_SESSION_HANDLE_PTR phSession) 4671 { 4672 SFTKSlot *slot; 4673 CK_SESSION_HANDLE sessionID; 4674 SFTKSession *session; 4675 SFTKSession *sameID; 4676 4677 CHECK_FORK(); 4678 4679 slot = sftk_SlotFromID(slotID, PR_FALSE); 4680 if (slot == NULL) 4681 return CKR_SLOT_ID_INVALID; 4682 4683 /* new session (we only have serial sessions) */ 4684 session = sftk_NewSession(slotID, Notify, pApplication, 4685 flags | CKF_SERIAL_SESSION); 4686 if (session == NULL) 4687 return CKR_HOST_MEMORY; 4688 4689 if (slot->readOnly && (flags & CKF_RW_SESSION)) { 4690 /* NETSCAPE_SLOT_ID is Read ONLY */ 4691 session->info.flags &= ~CKF_RW_SESSION; 4692 } 4693 PZ_Lock(slot->slotLock); 4694 ++slot->sessionCount; 4695 PZ_Unlock(slot->slotLock); 4696 if (session->info.flags & CKF_RW_SESSION) { 4697 (void)PR_ATOMIC_INCREMENT(&slot->rwSessionCount); 4698 } 4699 4700 do { 4701 PZLock *lock; 4702 do { 4703 sessionID = (PR_ATOMIC_INCREMENT(&slot->sessionIDCount) & 0xffffff) | (slot->index << 24); 4704 } while (sessionID == CK_INVALID_HANDLE); 4705 lock = SFTK_SESSION_LOCK(slot, sessionID); 4706 PZ_Lock(lock); 4707 sftkqueue_find(sameID, sessionID, slot->head, slot->sessHashSize); 4708 if (sameID == NULL) { 4709 session->handle = sessionID; 4710 sftk_update_state(slot, session); 4711 sftkqueue_add(session, sessionID, slot->head, slot->sessHashSize); 4712 } else { 4713 slot->sessionIDConflict++; /* for debugging */ 4714 } 4715 PZ_Unlock(lock); 4716 } while (sameID != NULL); 4717 4718 *phSession = sessionID; 4719 return CKR_OK; 4720 } 4721 4722 /* NSC_CloseSession closes a session between an application and a token. */ 4723 CK_RV 4724 NSC_CloseSession(CK_SESSION_HANDLE hSession) 4725 { 4726 SFTKSlot *slot; 4727 SFTKSession *session; 4728 PRBool sessionFound; 4729 PZLock *lock; 4730 4731 CHECK_FORK(); 4732 4733 session = sftk_SessionFromHandle(hSession); 4734 if (session == NULL) 4735 return CKR_SESSION_HANDLE_INVALID; 4736 slot = sftk_SlotFromSession(session); 4737 sessionFound = PR_FALSE; 4738 4739 /* lock */ 4740 lock = SFTK_SESSION_LOCK(slot, hSession); 4741 PZ_Lock(lock); 4742 if (sftkqueue_is_queued(session, hSession, slot->head, slot->sessHashSize)) { 4743 sessionFound = PR_TRUE; 4744 sftkqueue_delete(session, hSession, slot->head, slot->sessHashSize); 4745 } 4746 PZ_Unlock(lock); 4747 4748 if (sessionFound) { 4749 SFTKDBHandle *handle; 4750 handle = sftk_getKeyDB(slot); 4751 PZ_Lock(slot->slotLock); 4752 if (--slot->sessionCount == 0) { 4753 slot->isLoggedIn = PR_FALSE; 4754 if (slot->needLogin && handle) { 4755 sftkdb_ClearPassword(handle); 4756 } 4757 } 4758 PZ_Unlock(slot->slotLock); 4759 if (handle) { 4760 sftk_freeDB(handle); 4761 } 4762 if (session->info.flags & CKF_RW_SESSION) { 4763 (void)PR_ATOMIC_DECREMENT(&slot->rwSessionCount); 4764 } 4765 sftk_DestroySession(session); 4766 session = NULL; 4767 } 4768 4769 return CKR_OK; 4770 } 4771 4772 /* NSC_CloseAllSessions closes all sessions with a token. */ 4773 CK_RV 4774 NSC_CloseAllSessions(CK_SLOT_ID slotID) 4775 { 4776 SFTKSlot *slot; 4777 4778 #ifndef NO_FORK_CHECK 4779 /* skip fork check if we are being called from C_Initialize or C_Finalize */ 4780 if (!parentForkedAfterC_Initialize) { 4781 CHECK_FORK(); 4782 } 4783 #endif 4784 4785 slot = sftk_SlotFromID(slotID, PR_FALSE); 4786 if (slot == NULL) 4787 return CKR_SLOT_ID_INVALID; 4788 4789 return sftk_CloseAllSessions(slot, PR_TRUE); 4790 } 4791 4792 /* NSC_GetSessionInfo obtains information about the session. */ 4793 CK_RV 4794 NSC_GetSessionInfo(CK_SESSION_HANDLE hSession, 4795 CK_SESSION_INFO_PTR pInfo) 4796 { 4797 SFTKSession *session; 4798 4799 CHECK_FORK(); 4800 4801 session = sftk_SessionFromHandle(hSession); 4802 if (session == NULL) 4803 return CKR_SESSION_HANDLE_INVALID; 4804 4805 PORT_Memcpy(pInfo, &session->info, sizeof(CK_SESSION_INFO)); 4806 sftk_FreeSession(session); 4807 return CKR_OK; 4808 } 4809 4810 /* NSC_Login logs a user into a token. */ 4811 CK_RV 4812 NSC_Login(CK_SESSION_HANDLE hSession, CK_USER_TYPE userType, 4813 CK_CHAR_PTR pPin, CK_ULONG ulPinLen) 4814 { 4815 SFTKSlot *slot; 4816 SFTKSession *session; 4817 SFTKDBHandle *handle; 4818 CK_FLAGS sessionFlags; 4819 SECStatus rv; 4820 CK_RV crv; 4821 char pinStr[SFTK_MAX_PIN + 1]; 4822 PRBool tokenRemoved = PR_FALSE; 4823 PRBool isLoggedIn; 4824 PRBool needLogin; 4825 4826 CHECK_FORK(); 4827 4828 /* get the slot */ 4829 slot = sftk_SlotFromSessionHandle(hSession); 4830 if (slot == NULL) { 4831 return CKR_SESSION_HANDLE_INVALID; 4832 } 4833 4834 /* make sure the session is valid */ 4835 session = sftk_SessionFromHandle(hSession); 4836 if (session == NULL) { 4837 return CKR_SESSION_HANDLE_INVALID; 4838 } 4839 sessionFlags = session->info.flags; 4840 sftk_FreeSession(session); 4841 session = NULL; 4842 4843 /* can't log into the Netscape Slot */ 4844 if (slot->slotID == NETSCAPE_SLOT_ID) { 4845 return CKR_USER_TYPE_INVALID; 4846 } 4847 4848 PZ_Lock(slot->slotLock); 4849 isLoggedIn = slot->isLoggedIn; 4850 needLogin = slot->needLogin; 4851 PZ_Unlock(slot->slotLock); 4852 4853 if (isLoggedIn) 4854 return CKR_USER_ALREADY_LOGGED_IN; 4855 if (!needLogin) { 4856 return ulPinLen ? CKR_PIN_INCORRECT : CKR_OK; 4857 } 4858 slot->ssoLoggedIn = PR_FALSE; 4859 4860 if (ulPinLen > SFTK_MAX_PIN) 4861 return CKR_PIN_LEN_RANGE; 4862 4863 /* convert to null terminated string */ 4864 if (ulPinLen) { 4865 PORT_Memcpy(pinStr, pPin, ulPinLen); 4866 } 4867 pinStr[ulPinLen] = 0; 4868 4869 handle = sftk_getKeyDB(slot); 4870 if (handle == NULL) { 4871 PORT_Memset(pinStr, 0, ulPinLen); 4872 return CKR_USER_TYPE_INVALID; 4873 } 4874 4875 /* 4876 * Deal with bootstrap. We allow the SSO to login in with a NULL 4877 * password if and only if we haven't initialized the KEY DB yet. 4878 * We only allow this on a RW session. 4879 */ 4880 rv = sftkdb_HasPasswordSet(handle); 4881 if (rv == SECFailure) { 4882 /* allow SSO's to log in only if there is not password on the 4883 * key database */ 4884 if (((userType == CKU_SO) && (sessionFlags & CKF_RW_SESSION)) 4885 /* fips always needs to authenticate, even if there isn't a db */ 4886 || (sftk_isFIPS(slot->slotID))) { 4887 /* should this be a fixed password? */ 4888 if (ulPinLen == 0) { 4889 sftkdb_ClearPassword(handle); 4890 PZ_Lock(slot->slotLock); 4891 slot->isLoggedIn = PR_TRUE; 4892 slot->ssoLoggedIn = (PRBool)(userType == CKU_SO); 4893 PZ_Unlock(slot->slotLock); 4894 sftk_update_all_states(slot); 4895 crv = CKR_OK; 4896 goto done; 4897 } 4898 crv = CKR_PIN_INCORRECT; 4899 goto done; 4900 } 4901 crv = CKR_USER_TYPE_INVALID; 4902 goto done; 4903 } 4904 4905 /* don't allow the SSO to log in if the user is already initialized */ 4906 if (userType != CKU_USER) { 4907 crv = CKR_USER_TYPE_INVALID; 4908 goto done; 4909 } 4910 4911 /* build the hashed pins which we pass around */ 4912 PR_Lock(slot->pwCheckLock); 4913 rv = sftkdb_CheckPassword(handle, pinStr, &tokenRemoved); 4914 if (tokenRemoved) { 4915 sftk_CloseAllSessions(slot, PR_FALSE); 4916 } 4917 if ((rv != SECSuccess) && (sftk_isFIPS(slot->slotID))) { 4918 PR_Sleep(loginWaitTime); 4919 } 4920 PR_Unlock(slot->pwCheckLock); 4921 if (rv == SECSuccess) { 4922 PZ_Lock(slot->slotLock); 4923 /* make sure the login state matches the underlying 4924 * database state */ 4925 slot->isLoggedIn = sftkdb_PWCached(handle) == SECSuccess ? PR_TRUE : PR_FALSE; 4926 PZ_Unlock(slot->slotLock); 4927 4928 sftk_freeDB(handle); 4929 handle = NULL; 4930 4931 /* update all sessions */ 4932 sftk_update_all_states(slot); 4933 return CKR_OK; 4934 } 4935 4936 crv = CKR_PIN_INCORRECT; 4937 done: 4938 PORT_Memset(pinStr, 0, ulPinLen); 4939 if (handle) { 4940 sftk_freeDB(handle); 4941 } 4942 return crv; 4943 } 4944 4945 CK_RV 4946 NSC_LoginUser(CK_SESSION_HANDLE hSession, CK_USER_TYPE userType, 4947 CK_CHAR_PTR pPin, CK_ULONG ulPinLen, CK_UTF8CHAR_PTR pUsername, 4948 CK_ULONG ulUsernameLen) 4949 { 4950 /* softoken currently does not support additional users */ 4951 return CKR_OPERATION_NOT_INITIALIZED; 4952 } 4953 4954 /* NSC_Logout logs a user out from a token. */ 4955 CK_RV 4956 NSC_Logout(CK_SESSION_HANDLE hSession) 4957 { 4958 SFTKSlot *slot = sftk_SlotFromSessionHandle(hSession); 4959 SFTKSession *session; 4960 SFTKDBHandle *handle; 4961 4962 CHECK_FORK(); 4963 4964 if (slot == NULL) { 4965 return CKR_SESSION_HANDLE_INVALID; 4966 } 4967 session = sftk_SessionFromHandle(hSession); 4968 if (session == NULL) 4969 return CKR_SESSION_HANDLE_INVALID; 4970 sftk_FreeSession(session); 4971 session = NULL; 4972 4973 if (!slot->isLoggedIn) 4974 return CKR_USER_NOT_LOGGED_IN; 4975 4976 handle = sftk_getKeyDB(slot); 4977 PZ_Lock(slot->slotLock); 4978 slot->isLoggedIn = PR_FALSE; 4979 slot->ssoLoggedIn = PR_FALSE; 4980 if (slot->needLogin && handle) { 4981 sftkdb_ClearPassword(handle); 4982 } 4983 PZ_Unlock(slot->slotLock); 4984 if (handle) { 4985 sftk_freeDB(handle); 4986 } 4987 4988 sftk_update_all_states(slot); 4989 return CKR_OK; 4990 } 4991 4992 /* 4993 * Create or remove a new slot on the fly. 4994 * When creating a slot, "slot" is the slot that the request came from. The 4995 * resulting slot will live in the same module as "slot". 4996 * When removing a slot, "slot" is the slot to be removed. 4997 * "object" is the creation object that specifies the module spec for the slot 4998 * to add or remove. 4999 */ 5000 static CK_RV 5001 sftk_CreateNewSlot(SFTKSlot *slot, CK_OBJECT_CLASS class, 5002 SFTKObject *object) 5003 { 5004 PRBool isValidUserSlot = PR_FALSE; 5005 PRBool isValidFIPSUserSlot = PR_FALSE; 5006 PRBool isValidSlot = PR_FALSE; 5007 PRBool isFIPS = PR_FALSE; 5008 unsigned int moduleIndex = NSC_NON_FIPS_MODULE; 5009 SFTKAttribute *attribute; 5010 sftk_parameters paramStrings; 5011 char *paramString; 5012 CK_SLOT_ID slotID = 0; 5013 SFTKSlot *newSlot = NULL; 5014 CK_RV crv = CKR_OK; 5015 5016 if (class != CKO_NSS_DELSLOT && class != CKO_NSS_NEWSLOT) { 5017 return CKR_ATTRIBUTE_VALUE_INVALID; 5018 } 5019 if (class == CKO_NSS_NEWSLOT && slot->slotID == FIPS_SLOT_ID) { 5020 isFIPS = PR_TRUE; 5021 } 5022 attribute = sftk_FindAttribute(object, CKA_NSS_MODULE_SPEC); 5023 if (attribute == NULL) { 5024 return CKR_TEMPLATE_INCOMPLETE; 5025 } 5026 paramString = (char *)attribute->attrib.pValue; 5027 crv = sftk_parseParameters(paramString, ¶mStrings, isFIPS); 5028 if (crv != CKR_OK) { 5029 goto loser; 5030 } 5031 5032 /* enforce only one at a time */ 5033 if (paramStrings.token_count != 1) { 5034 crv = CKR_ATTRIBUTE_VALUE_INVALID; 5035 goto loser; 5036 } 5037 5038 slotID = paramStrings.tokens[0].slotID; 5039 5040 /* stay within the valid ID space */ 5041 isValidUserSlot = (slotID >= SFTK_MIN_USER_SLOT_ID && 5042 slotID <= SFTK_MAX_USER_SLOT_ID); 5043 isValidFIPSUserSlot = (slotID >= SFTK_MIN_FIPS_USER_SLOT_ID && 5044 slotID <= SFTK_MAX_FIPS_USER_SLOT_ID); 5045 5046 if (class == CKO_NSS_DELSLOT) { 5047 if (slot->slotID == slotID) { 5048 isValidSlot = isValidUserSlot || isValidFIPSUserSlot; 5049 } 5050 } else { 5051 /* only the crypto or FIPS slots can create new slot objects */ 5052 if (slot->slotID == NETSCAPE_SLOT_ID) { 5053 isValidSlot = isValidUserSlot; 5054 moduleIndex = NSC_NON_FIPS_MODULE; 5055 } else if (slot->slotID == FIPS_SLOT_ID) { 5056 isValidSlot = isValidFIPSUserSlot; 5057 moduleIndex = NSC_FIPS_MODULE; 5058 } 5059 } 5060 5061 if (!isValidSlot) { 5062 crv = CKR_ATTRIBUTE_VALUE_INVALID; 5063 goto loser; 5064 } 5065 5066 /* unload any existing slot at this id */ 5067 newSlot = sftk_SlotFromID(slotID, PR_TRUE); 5068 if (newSlot && newSlot->present) { 5069 crv = SFTK_ShutdownSlot(newSlot); 5070 if (crv != CKR_OK) { 5071 goto loser; 5072 } 5073 } 5074 5075 /* if we were just planning on deleting the slot, then do so now */ 5076 if (class == CKO_NSS_DELSLOT) { 5077 /* sort of a unconventional use of this error code, be we are 5078 * overusing CKR_ATTRIBUTE_VALUE_INVALID, and it does apply */ 5079 crv = newSlot ? CKR_OK : CKR_SLOT_ID_INVALID; 5080 goto loser; /* really exit */ 5081 } 5082 5083 if (newSlot) { 5084 crv = SFTK_SlotReInit(newSlot, paramStrings.configdir, 5085 paramStrings.updatedir, paramStrings.updateID, 5086 ¶mStrings.tokens[0], moduleIndex); 5087 } else { 5088 crv = SFTK_SlotInit(paramStrings.configdir, 5089 paramStrings.updatedir, paramStrings.updateID, 5090 ¶mStrings.tokens[0], moduleIndex); 5091 } 5092 5093 loser: 5094 sftk_freeParams(¶mStrings); 5095 sftk_FreeAttribute(attribute); 5096 5097 return crv; 5098 } 5099 5100 /* NSC_CreateObject creates a new object. */ 5101 CK_RV 5102 NSC_CreateObject(CK_SESSION_HANDLE hSession, 5103 CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount, 5104 CK_OBJECT_HANDLE_PTR phObject) 5105 { 5106 SFTKSlot *slot = sftk_SlotFromSessionHandle(hSession); 5107 SFTKSession *session; 5108 SFTKObject *object; 5109 /* make sure class isn't randomly CKO_NSS_NEWSLOT or 5110 * CKO_NETSCPE_DELSLOT. */ 5111 CK_OBJECT_CLASS class = CKO_VENDOR_DEFINED; 5112 CK_RV crv; 5113 int i; 5114 5115 CHECK_FORK(); 5116 5117 *phObject = CK_INVALID_HANDLE; 5118 5119 if (slot == NULL) { 5120 return CKR_SESSION_HANDLE_INVALID; 5121 } 5122 /* 5123 * now lets create an object to hang the attributes off of 5124 */ 5125 object = sftk_NewObject(slot); /* fill in the handle later */ 5126 if (object == NULL) { 5127 return CKR_HOST_MEMORY; 5128 } 5129 5130 /* 5131 * sftk_NewObject will set object->validation_value to 5132 * SFTK_VALIDATION_FIPS_FLAG if the slot is FIPS. 5133 * We don't need to worry about that here, as FC_CreateObject will always 5134 * disallow the import of secret and private keys, regardless of isFIPS 5135 * approval status. Therefore, at this point we know that the key is a 5136 * public key, which is acceptable to be imported in plaintext. 5137 */ 5138 5139 /* 5140 * load the template values into the object 5141 */ 5142 for (i = 0; i < (int)ulCount; i++) { 5143 crv = sftk_AddAttributeType(object, sftk_attr_expand(&pTemplate[i])); 5144 if (crv != CKR_OK) { 5145 sftk_FreeObject(object); 5146 return crv; 5147 } 5148 if ((pTemplate[i].type == CKA_CLASS) && pTemplate[i].pValue) { 5149 class = *(CK_OBJECT_CLASS *)pTemplate[i].pValue; 5150 } 5151 } 5152 5153 /* get the session */ 5154 session = sftk_SessionFromHandle(hSession); 5155 if (session == NULL) { 5156 sftk_FreeObject(object); 5157 return CKR_SESSION_HANDLE_INVALID; 5158 } 5159 5160 /* 5161 * handle pseudo objects (CKO_NEWSLOT) 5162 */ 5163 if ((class == CKO_NSS_NEWSLOT) || (class == CKO_NSS_DELSLOT)) { 5164 crv = sftk_CreateNewSlot(slot, class, object); 5165 goto done; 5166 } 5167 5168 /* 5169 * handle the base object stuff 5170 */ 5171 crv = sftk_handleObject(object, session); 5172 *phObject = object->handle; 5173 done: 5174 sftk_FreeSession(session); 5175 sftk_FreeObject(object); 5176 5177 return crv; 5178 } 5179 5180 /* NSC_CopyObject copies an object, creating a new object for the copy. */ 5181 CK_RV 5182 NSC_CopyObject(CK_SESSION_HANDLE hSession, 5183 CK_OBJECT_HANDLE hObject, CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount, 5184 CK_OBJECT_HANDLE_PTR phNewObject) 5185 { 5186 SFTKObject *destObject, *srcObject; 5187 SFTKSession *session; 5188 CK_RV crv = CKR_OK; 5189 SFTKSlot *slot = sftk_SlotFromSessionHandle(hSession); 5190 int i; 5191 5192 CHECK_FORK(); 5193 5194 if (slot == NULL) { 5195 return CKR_SESSION_HANDLE_INVALID; 5196 } 5197 /* Get srcObject so we can find the class */ 5198 session = sftk_SessionFromHandle(hSession); 5199 if (session == NULL) { 5200 return CKR_SESSION_HANDLE_INVALID; 5201 } 5202 srcObject = sftk_ObjectFromHandle(hObject, session); 5203 if (srcObject == NULL) { 5204 sftk_FreeSession(session); 5205 return CKR_OBJECT_HANDLE_INVALID; 5206 } 5207 /* 5208 * create an object to hang the attributes off of 5209 */ 5210 destObject = sftk_NewObject(slot); /* fill in the handle later */ 5211 if (destObject == NULL) { 5212 sftk_FreeSession(session); 5213 sftk_FreeObject(srcObject); 5214 return CKR_HOST_MEMORY; 5215 } 5216 5217 /* 5218 * load the template values into the object 5219 */ 5220 for (i = 0; i < (int)ulCount; i++) { 5221 if (sftk_modifyType(pTemplate[i].type, srcObject->objclass) == SFTK_NEVER) { 5222 crv = CKR_ATTRIBUTE_READ_ONLY; 5223 break; 5224 } 5225 crv = sftk_AddAttributeType(destObject, sftk_attr_expand(&pTemplate[i])); 5226 if (crv != CKR_OK) { 5227 break; 5228 } 5229 } 5230 if (crv != CKR_OK) { 5231 sftk_FreeSession(session); 5232 sftk_FreeObject(srcObject); 5233 sftk_FreeObject(destObject); 5234 return crv; 5235 } 5236 5237 /* sensitive can only be changed to CK_TRUE */ 5238 if (sftk_hasAttribute(destObject, CKA_SENSITIVE)) { 5239 if (!sftk_isTrue(destObject, CKA_SENSITIVE)) { 5240 sftk_FreeSession(session); 5241 sftk_FreeObject(srcObject); 5242 sftk_FreeObject(destObject); 5243 return CKR_ATTRIBUTE_READ_ONLY; 5244 } 5245 } 5246 5247 /* 5248 * now copy the old attributes from the new attributes 5249 */ 5250 /* don't create a token object if we aren't in a rw session */ 5251 /* we need to hold the lock to copy a consistant version of 5252 * the object. */ 5253 crv = sftk_CopyObject(destObject, srcObject); 5254 5255 destObject->objclass = srcObject->objclass; 5256 sftk_FreeObject(srcObject); 5257 if (crv != CKR_OK) { 5258 sftk_FreeObject(destObject); 5259 sftk_FreeSession(session); 5260 return crv; 5261 } 5262 5263 crv = sftk_handleObject(destObject, session); 5264 *phNewObject = destObject->handle; 5265 sftk_FreeSession(session); 5266 sftk_FreeObject(destObject); 5267 5268 return crv; 5269 } 5270 5271 /* NSC_GetObjectSize gets the size of an object in bytes. */ 5272 CK_RV 5273 NSC_GetObjectSize(CK_SESSION_HANDLE hSession, 5274 CK_OBJECT_HANDLE hObject, CK_ULONG_PTR pulSize) 5275 { 5276 CHECK_FORK(); 5277 5278 *pulSize = 0; 5279 return CKR_OK; 5280 } 5281 5282 static CK_RV 5283 nsc_GetTokenAttributeValue(SFTKSession *session, CK_OBJECT_HANDLE hObject, 5284 CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount) 5285 { 5286 SFTKSlot *slot = sftk_SlotFromSession(session); 5287 SFTKDBHandle *dbHandle = sftk_getDBForTokenObject(slot, hObject); 5288 SFTKDBHandle *keydb = NULL; 5289 CK_RV crv; 5290 5291 if (dbHandle == NULL) { 5292 return CKR_OBJECT_HANDLE_INVALID; 5293 } 5294 5295 crv = sftkdb_GetAttributeValue(dbHandle, hObject, pTemplate, ulCount); 5296 5297 /* make sure we don't export any sensitive information */ 5298 keydb = sftk_getKeyDB(slot); 5299 if (dbHandle == keydb) { 5300 CK_ULONG i; 5301 for (i = 0; i < ulCount; i++) { 5302 if (sftk_isSensitive(pTemplate[i].type, CKO_PRIVATE_KEY)) { 5303 crv = CKR_ATTRIBUTE_SENSITIVE; 5304 if (pTemplate[i].pValue && (pTemplate[i].ulValueLen != -1)) { 5305 PORT_Memset(pTemplate[i].pValue, 0, 5306 pTemplate[i].ulValueLen); 5307 } 5308 pTemplate[i].ulValueLen = -1; 5309 } 5310 } 5311 } 5312 5313 sftk_freeDB(dbHandle); 5314 if (keydb) { 5315 sftk_freeDB(keydb); 5316 } 5317 return crv; 5318 } 5319 5320 PRBool 5321 sftk_template_hasAttribute(CK_ATTRIBUTE_TYPE type, CK_ATTRIBUTE *pTemplate, 5322 CK_ULONG ulCount) 5323 { 5324 for (int i = 0; i < ulCount; i++) { 5325 if (pTemplate[i].type == type) { 5326 return PR_TRUE; 5327 } 5328 } 5329 return PR_FALSE; 5330 } 5331 5332 /* NSC_GetAttributeValue obtains the value of one or more object attributes. */ 5333 CK_RV 5334 NSC_GetAttributeValue(CK_SESSION_HANDLE hSession, 5335 CK_OBJECT_HANDLE hObject, CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount) 5336 { 5337 SFTKSlot *slot = sftk_SlotFromSessionHandle(hSession); 5338 SFTKSession *session; 5339 SFTKObject *object; 5340 SFTKAttribute *attribute; 5341 PRBool sensitive, isLoggedIn, needLogin; 5342 CK_RV crv; 5343 int i; 5344 5345 CHECK_FORK(); 5346 5347 if (slot == NULL) { 5348 return CKR_SESSION_HANDLE_INVALID; 5349 } 5350 /* 5351 * make sure we're allowed 5352 */ 5353 session = sftk_SessionFromHandle(hSession); 5354 if (session == NULL) { 5355 return CKR_SESSION_HANDLE_INVALID; 5356 } 5357 5358 /* short circuit everything for token objects */ 5359 if (sftk_isToken(hObject) && 5360 /* we we have a CKA_OBJECT_VALIDATION_FLAG, don't do the 5361 * short circuit. the SDB code doesn't know how to process 5362 * this attribute */ 5363 !sftk_template_hasAttribute(CKA_OBJECT_VALIDATION_FLAGS, pTemplate, 5364 ulCount)) { 5365 crv = nsc_GetTokenAttributeValue(session, hObject, pTemplate, ulCount); 5366 sftk_FreeSession(session); 5367 return crv; 5368 } 5369 5370 /* handle the session object */ 5371 object = sftk_ObjectFromHandle(hObject, session); 5372 sftk_FreeSession(session); 5373 if (object == NULL) { 5374 return CKR_OBJECT_HANDLE_INVALID; 5375 } 5376 5377 PZ_Lock(slot->slotLock); 5378 isLoggedIn = slot->isLoggedIn; 5379 needLogin = slot->needLogin; 5380 PZ_Unlock(slot->slotLock); 5381 5382 /* don't read a private object if we aren't logged in */ 5383 if (!isLoggedIn && needLogin && sftk_isTrue(object, CKA_PRIVATE)) { 5384 sftk_FreeObject(object); 5385 return CKR_USER_NOT_LOGGED_IN; 5386 } 5387 5388 crv = CKR_OK; 5389 sensitive = sftk_isTrue(object, CKA_SENSITIVE); 5390 for (i = 0; i < (int)ulCount; i++) { 5391 /* Make sure that this attribute is retrievable */ 5392 if (sensitive && sftk_isSensitive(pTemplate[i].type, object->objclass)) { 5393 crv = CKR_ATTRIBUTE_SENSITIVE; 5394 pTemplate[i].ulValueLen = -1; 5395 continue; 5396 } 5397 attribute = sftk_FindAttribute(object, pTemplate[i].type); 5398 if (attribute == NULL) { 5399 crv = CKR_ATTRIBUTE_TYPE_INVALID; 5400 pTemplate[i].ulValueLen = -1; 5401 continue; 5402 } 5403 if (pTemplate[i].pValue != NULL) { 5404 PORT_Memcpy(pTemplate[i].pValue, attribute->attrib.pValue, 5405 attribute->attrib.ulValueLen); 5406 } 5407 pTemplate[i].ulValueLen = attribute->attrib.ulValueLen; 5408 sftk_FreeAttribute(attribute); 5409 } 5410 5411 sftk_FreeObject(object); 5412 return crv; 5413 } 5414 5415 /* NSC_SetAttributeValue modifies the value of one or more object attributes */ 5416 CK_RV 5417 NSC_SetAttributeValue(CK_SESSION_HANDLE hSession, 5418 CK_OBJECT_HANDLE hObject, CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount) 5419 { 5420 SFTKSlot *slot = sftk_SlotFromSessionHandle(hSession); 5421 SFTKSession *session; 5422 SFTKAttribute *attribute; 5423 SFTKObject *object; 5424 PRBool isToken, isLoggedIn, needLogin; 5425 CK_RV crv = CKR_OK; 5426 CK_BBOOL legal; 5427 int i; 5428 5429 CHECK_FORK(); 5430 5431 if (slot == NULL) { 5432 return CKR_SESSION_HANDLE_INVALID; 5433 } 5434 /* 5435 * make sure we're allowed 5436 */ 5437 session = sftk_SessionFromHandle(hSession); 5438 if (session == NULL) { 5439 return CKR_SESSION_HANDLE_INVALID; 5440 } 5441 5442 object = sftk_ObjectFromHandle(hObject, session); 5443 if (object == NULL) { 5444 sftk_FreeSession(session); 5445 return CKR_OBJECT_HANDLE_INVALID; 5446 } 5447 5448 PZ_Lock(slot->slotLock); 5449 isLoggedIn = slot->isLoggedIn; 5450 needLogin = slot->needLogin; 5451 PZ_Unlock(slot->slotLock); 5452 5453 /* don't modify a private object if we aren't logged in */ 5454 if (!isLoggedIn && needLogin && sftk_isTrue(object, CKA_PRIVATE)) { 5455 sftk_FreeSession(session); 5456 sftk_FreeObject(object); 5457 return CKR_USER_NOT_LOGGED_IN; 5458 } 5459 5460 /* don't modify a token object if we aren't in a rw session */ 5461 isToken = sftk_isTrue(object, CKA_TOKEN); 5462 if (((session->info.flags & CKF_RW_SESSION) == 0) && isToken) { 5463 sftk_FreeSession(session); 5464 sftk_FreeObject(object); 5465 return CKR_SESSION_READ_ONLY; 5466 } 5467 sftk_FreeSession(session); 5468 5469 /* only change modifiable objects */ 5470 if (!sftk_isTrue(object, CKA_MODIFIABLE)) { 5471 sftk_FreeObject(object); 5472 return CKR_ATTRIBUTE_READ_ONLY; 5473 } 5474 5475 for (i = 0; i < (int)ulCount; i++) { 5476 /* Make sure that this attribute is changeable */ 5477 switch (sftk_modifyType(pTemplate[i].type, object->objclass)) { 5478 case SFTK_NEVER: 5479 case SFTK_ONCOPY: 5480 default: 5481 crv = CKR_ATTRIBUTE_READ_ONLY; 5482 break; 5483 5484 case SFTK_SENSITIVE: 5485 legal = (pTemplate[i].type == CKA_EXTRACTABLE) ? CK_FALSE : CK_TRUE; 5486 if ((*(CK_BBOOL *)pTemplate[i].pValue) != legal) { 5487 crv = CKR_ATTRIBUTE_READ_ONLY; 5488 } 5489 break; 5490 case SFTK_ALWAYS: 5491 break; 5492 } 5493 if (crv != CKR_OK) 5494 break; 5495 5496 /* find the old attribute */ 5497 attribute = sftk_FindAttribute(object, pTemplate[i].type); 5498 if (attribute == NULL) { 5499 crv = CKR_ATTRIBUTE_TYPE_INVALID; 5500 break; 5501 } 5502 sftk_FreeAttribute(attribute); 5503 crv = sftk_forceAttribute(object, sftk_attr_expand(&pTemplate[i])); 5504 if (crv != CKR_OK) 5505 break; 5506 } 5507 5508 sftk_FreeObject(object); 5509 return crv; 5510 } 5511 5512 static CK_RV 5513 sftk_expandSearchList(SFTKSearchResults *search, int count) 5514 { 5515 search->array_size += count; 5516 search->handles = (CK_OBJECT_HANDLE *)PORT_Realloc(search->handles, 5517 sizeof(CK_OBJECT_HANDLE) * search->array_size); 5518 return search->handles ? CKR_OK : CKR_HOST_MEMORY; 5519 } 5520 5521 static CK_RV 5522 sftk_searchDatabase(SFTKDBHandle *handle, SFTKSearchResults *search, 5523 const CK_ATTRIBUTE *pTemplate, CK_ULONG ulCount) 5524 { 5525 CK_RV crv; 5526 int objectListSize = search->array_size - search->size; 5527 CK_OBJECT_HANDLE *array = &search->handles[search->size]; 5528 SDBFind *find = NULL; 5529 CK_ULONG count; 5530 5531 crv = sftkdb_FindObjectsInit(handle, pTemplate, ulCount, &find); 5532 if (crv != CKR_OK) 5533 return crv; 5534 do { 5535 crv = sftkdb_FindObjects(handle, find, array, objectListSize, &count); 5536 if ((crv != CKR_OK) || (count == 0)) 5537 break; 5538 search->size += count; 5539 objectListSize -= count; 5540 if (objectListSize > 0) 5541 break; 5542 crv = sftk_expandSearchList(search, NSC_SEARCH_BLOCK_SIZE); 5543 objectListSize = NSC_SEARCH_BLOCK_SIZE; 5544 array = &search->handles[search->size]; 5545 } while (crv == CKR_OK); 5546 sftkdb_FindObjectsFinal(handle, find); 5547 5548 return crv; 5549 } 5550 5551 /* softoken used to search the SMimeEntries automatically instead of 5552 * doing this in pk11wrap. This code should really be up in 5553 * pk11wrap so that it will work with other tokens other than softoken. 5554 */ 5555 CK_RV 5556 sftk_emailhack(SFTKSlot *slot, SFTKDBHandle *handle, 5557 SFTKSearchResults *search, CK_ATTRIBUTE *pTemplate, CK_ULONG ulCount) 5558 { 5559 PRBool isCert = PR_FALSE; 5560 int emailIndex = -1; 5561 unsigned int i; 5562 SFTKSearchResults smime_search; 5563 CK_ATTRIBUTE smime_template[2]; 5564 CK_OBJECT_CLASS smime_class = CKO_NSS_SMIME; 5565 SFTKAttribute *attribute = NULL; 5566 SFTKObject *object = NULL; 5567 CK_RV crv = CKR_OK; 5568 5569 smime_search.handles = NULL; /* paranoia, some one is bound to add a goto 5570 * loser before this gets initialized */ 5571 5572 /* see if we are looking for email certs */ 5573 for (i = 0; i < ulCount; i++) { 5574 if (pTemplate[i].type == CKA_CLASS) { 5575 if ((pTemplate[i].ulValueLen != sizeof(CK_OBJECT_CLASS) || 5576 (*(CK_OBJECT_CLASS *)pTemplate[i].pValue) != CKO_CERTIFICATE)) { 5577 /* not a cert, skip out */ 5578 break; 5579 } 5580 isCert = PR_TRUE; 5581 } else if (pTemplate[i].type == CKA_NSS_EMAIL) { 5582 emailIndex = i; 5583 } 5584 if (isCert && (emailIndex != -1)) 5585 break; 5586 } 5587 5588 if (!isCert || (emailIndex == -1)) { 5589 return CKR_OK; 5590 } 5591 5592 /* we are doing a cert and email search, find the SMimeEntry */ 5593 smime_template[0].type = CKA_CLASS; 5594 smime_template[0].pValue = &smime_class; 5595 smime_template[0].ulValueLen = sizeof(smime_class); 5596 smime_template[1] = pTemplate[emailIndex]; 5597 5598 smime_search.handles = (CK_OBJECT_HANDLE *) 5599 PORT_Alloc(sizeof(CK_OBJECT_HANDLE) * NSC_SEARCH_BLOCK_SIZE); 5600 if (smime_search.handles == NULL) { 5601 crv = CKR_HOST_MEMORY; 5602 goto loser; 5603 } 5604 smime_search.index = 0; 5605 smime_search.size = 0; 5606 smime_search.array_size = NSC_SEARCH_BLOCK_SIZE; 5607 5608 crv = sftk_searchDatabase(handle, &smime_search, smime_template, 2); 5609 if (crv != CKR_OK || smime_search.size == 0) { 5610 goto loser; 5611 } 5612 5613 /* get the SMime subject */ 5614 object = sftk_NewTokenObject(slot, NULL, smime_search.handles[0]); 5615 if (object == NULL) { 5616 crv = CKR_HOST_MEMORY; /* is there any other reason for this failure? */ 5617 goto loser; 5618 } 5619 attribute = sftk_FindAttribute(object, CKA_SUBJECT); 5620 if (attribute == NULL) { 5621 crv = CKR_ATTRIBUTE_TYPE_INVALID; 5622 goto loser; 5623 } 5624 5625 /* now find the certs with that subject */ 5626 pTemplate[emailIndex] = attribute->attrib; 5627 /* now add the appropriate certs to the search list */ 5628 crv = sftk_searchDatabase(handle, search, pTemplate, ulCount); 5629 pTemplate[emailIndex] = smime_template[1]; /* restore the user's template*/ 5630 5631 loser: 5632 if (attribute) { 5633 sftk_FreeAttribute(attribute); 5634 } 5635 if (object) { 5636 sftk_FreeObject(object); 5637 } 5638 if (smime_search.handles) { 5639 PORT_Free(smime_search.handles); 5640 } 5641 5642 return crv; 5643 } 5644 5645 static void 5646 sftk_pruneSearch(CK_ATTRIBUTE *pTemplate, CK_ULONG ulCount, 5647 PRBool *searchCertDB, PRBool *searchKeyDB) 5648 { 5649 CK_ULONG i; 5650 5651 *searchCertDB = PR_TRUE; 5652 *searchKeyDB = PR_TRUE; 5653 for (i = 0; i < ulCount; i++) { 5654 if (pTemplate[i].type == CKA_CLASS && pTemplate[i].pValue != NULL) { 5655 CK_OBJECT_CLASS class = *((CK_OBJECT_CLASS *)pTemplate[i].pValue); 5656 if (class == CKO_PRIVATE_KEY || class == CKO_SECRET_KEY) { 5657 *searchCertDB = PR_FALSE; 5658 } else { 5659 *searchKeyDB = PR_FALSE; 5660 } 5661 break; 5662 } 5663 } 5664 } 5665 5666 static CK_RV 5667 sftk_searchTokenList(SFTKSlot *slot, SFTKSearchResults *search, 5668 CK_ATTRIBUTE *pTemplate, CK_ULONG ulCount, 5669 PRBool isLoggedIn) 5670 { 5671 CK_RV crv = CKR_OK; 5672 CK_RV crv2; 5673 PRBool searchCertDB; 5674 PRBool searchKeyDB; 5675 5676 sftk_pruneSearch(pTemplate, ulCount, &searchCertDB, &searchKeyDB); 5677 5678 if (searchCertDB) { 5679 SFTKDBHandle *certHandle = sftk_getCertDB(slot); 5680 crv = sftk_searchDatabase(certHandle, search, pTemplate, ulCount); 5681 crv2 = sftk_emailhack(slot, certHandle, search, pTemplate, ulCount); 5682 if (crv == CKR_OK) 5683 crv = crv2; 5684 sftk_freeDB(certHandle); 5685 } 5686 5687 if (crv == CKR_OK && isLoggedIn && searchKeyDB) { 5688 SFTKDBHandle *keyHandle = sftk_getKeyDB(slot); 5689 crv = sftk_searchDatabase(keyHandle, search, pTemplate, ulCount); 5690 sftk_freeDB(keyHandle); 5691 } 5692 return crv; 5693 } 5694 5695 /* NSC_FindObjectsInit initializes a search for token and session objects 5696 * that match a template. */ 5697 CK_RV 5698 NSC_FindObjectsInit(CK_SESSION_HANDLE hSession, 5699 CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount) 5700 { 5701 SFTKSearchResults *search = NULL, *freeSearch = NULL; 5702 SFTKSession *session = NULL; 5703 SFTKSlot *slot = sftk_SlotFromSessionHandle(hSession); 5704 CK_RV crv = CKR_OK; 5705 PRBool isLoggedIn; 5706 5707 CHECK_FORK(); 5708 5709 if (slot == NULL) { 5710 return CKR_SESSION_HANDLE_INVALID; 5711 } 5712 session = sftk_SessionFromHandle(hSession); 5713 if (session == NULL) { 5714 crv = CKR_SESSION_HANDLE_INVALID; 5715 goto loser; 5716 } 5717 5718 search = (SFTKSearchResults *)PORT_Alloc(sizeof(SFTKSearchResults)); 5719 if (search == NULL) { 5720 crv = CKR_HOST_MEMORY; 5721 goto loser; 5722 } 5723 search->handles = (CK_OBJECT_HANDLE *) 5724 PORT_Alloc(sizeof(CK_OBJECT_HANDLE) * NSC_SEARCH_BLOCK_SIZE); 5725 if (search->handles == NULL) { 5726 crv = CKR_HOST_MEMORY; 5727 goto loser; 5728 } 5729 search->index = 0; 5730 search->size = 0; 5731 search->array_size = NSC_SEARCH_BLOCK_SIZE; 5732 5733 PZ_Lock(slot->slotLock); 5734 isLoggedIn = (PRBool)((!slot->needLogin) || slot->isLoggedIn); 5735 PZ_Unlock(slot->slotLock); 5736 5737 PRBool validTokenAttribute = PR_FALSE; 5738 PRBool tokenAttributeValue = PR_FALSE; 5739 for (CK_ULONG i = 0; i < ulCount; i++) { 5740 CK_ATTRIBUTE_PTR attr = &pTemplate[i]; 5741 if (attr->type == CKA_TOKEN && attr->pValue && attr->ulValueLen == sizeof(CK_BBOOL)) { 5742 if (*(CK_BBOOL *)attr->pValue == CK_TRUE) { 5743 validTokenAttribute = PR_TRUE; 5744 tokenAttributeValue = PR_TRUE; 5745 } else if (*(CK_BBOOL *)attr->pValue == CK_FALSE) { 5746 validTokenAttribute = PR_TRUE; 5747 tokenAttributeValue = PR_FALSE; 5748 } 5749 break; 5750 } 5751 } 5752 5753 // Search over the token object list if the template's CKA_TOKEN attribute is set to 5754 // CK_TRUE or if it is not set. 5755 if (validTokenAttribute == PR_FALSE || tokenAttributeValue == PR_TRUE) { 5756 crv = sftk_searchTokenList(slot, search, pTemplate, ulCount, isLoggedIn); 5757 if (crv != CKR_OK) { 5758 goto loser; 5759 } 5760 } 5761 5762 // Search over the session object list if the template's CKA_TOKEN attribute is set to 5763 // CK_FALSE or if it is not set. 5764 if (validTokenAttribute == PR_FALSE || tokenAttributeValue == PR_FALSE) { 5765 crv = sftk_searchObjectList(search, slot->sessObjHashTable, 5766 slot->sessObjHashSize, slot->objectLock, 5767 pTemplate, ulCount, isLoggedIn); 5768 if (crv != CKR_OK) { 5769 goto loser; 5770 } 5771 } 5772 5773 if ((freeSearch = session->search) != NULL) { 5774 session->search = NULL; 5775 sftk_FreeSearch(freeSearch); 5776 } 5777 session->search = search; 5778 sftk_FreeSession(session); 5779 return CKR_OK; 5780 5781 loser: 5782 if (search) { 5783 sftk_FreeSearch(search); 5784 } 5785 if (session) { 5786 sftk_FreeSession(session); 5787 } 5788 return crv; 5789 } 5790 5791 /* NSC_FindObjects continues a search for token and session objects 5792 * that match a template, obtaining additional object handles. */ 5793 CK_RV 5794 NSC_FindObjects(CK_SESSION_HANDLE hSession, 5795 CK_OBJECT_HANDLE_PTR phObject, CK_ULONG ulMaxObjectCount, 5796 CK_ULONG_PTR pulObjectCount) 5797 { 5798 SFTKSession *session; 5799 SFTKSearchResults *search; 5800 int transfer; 5801 int left; 5802 5803 CHECK_FORK(); 5804 5805 *pulObjectCount = 0; 5806 session = sftk_SessionFromHandle(hSession); 5807 if (session == NULL) 5808 return CKR_SESSION_HANDLE_INVALID; 5809 if (session->search == NULL) { 5810 sftk_FreeSession(session); 5811 return CKR_OK; 5812 } 5813 search = session->search; 5814 left = session->search->size - session->search->index; 5815 transfer = ((int)ulMaxObjectCount > left) ? left : ulMaxObjectCount; 5816 if (transfer > 0) { 5817 PORT_Memcpy(phObject, &search->handles[search->index], 5818 transfer * sizeof(CK_OBJECT_HANDLE)); 5819 } else { 5820 *phObject = CK_INVALID_HANDLE; 5821 } 5822 5823 search->index += transfer; 5824 if (search->index == search->size) { 5825 session->search = NULL; 5826 sftk_FreeSearch(search); 5827 } 5828 *pulObjectCount = transfer; 5829 sftk_FreeSession(session); 5830 return CKR_OK; 5831 } 5832 5833 /* NSC_FindObjectsFinal finishes a search for token and session objects. */ 5834 CK_RV 5835 NSC_FindObjectsFinal(CK_SESSION_HANDLE hSession) 5836 { 5837 SFTKSession *session; 5838 SFTKSearchResults *search; 5839 5840 CHECK_FORK(); 5841 5842 session = sftk_SessionFromHandle(hSession); 5843 if (session == NULL) 5844 return CKR_SESSION_HANDLE_INVALID; 5845 search = session->search; 5846 session->search = NULL; 5847 sftk_FreeSession(session); 5848 if (search != NULL) { 5849 sftk_FreeSearch(search); 5850 } 5851 return CKR_OK; 5852 } 5853 5854 CK_RV 5855 NSC_WaitForSlotEvent(CK_FLAGS flags, CK_SLOT_ID_PTR pSlot, 5856 CK_VOID_PTR pReserved) 5857 { 5858 CHECK_FORK(); 5859 5860 return CKR_FUNCTION_NOT_SUPPORTED; 5861 } 5862 5863 CK_RV 5864 NSC_AsyncComplete(CK_SESSION_HANDLE hSession, CK_UTF8CHAR_PTR pFunctionName, 5865 CK_ASYNC_DATA_PTR pResult) 5866 { 5867 CHECK_FORK(); 5868 5869 return CKR_FUNCTION_NOT_SUPPORTED; 5870 } 5871 5872 CK_RV 5873 NSC_AsyncGetID(CK_SESSION_HANDLE hSession, CK_UTF8CHAR_PTR pFunctionName, 5874 CK_ULONG_PTR pulID) 5875 { 5876 CHECK_FORK(); 5877 5878 return CKR_FUNCTION_NOT_SUPPORTED; 5879 } 5880 5881 CK_RV 5882 NSC_AsyncJoin(CK_SESSION_HANDLE hSession, CK_UTF8CHAR_PTR pFunctionName, 5883 CK_ULONG ulID, CK_BYTE_PTR pData, CK_ULONG ulData) 5884 { 5885 CHECK_FORK(); 5886 5887 return CKR_FUNCTION_NOT_SUPPORTED; 5888 } 5889 5890 static CK_RV 5891 nsc_NSSGetFIPSStatus(CK_SESSION_HANDLE hSession, 5892 CK_OBJECT_HANDLE hObject, 5893 CK_ULONG ulOperationType, 5894 CK_ULONG *pulFIPSStatus) 5895 { 5896 CK_ULONG sessionState = CKS_NSS_UNINITIALIZED; 5897 CK_ULONG objectState = CKS_NSS_UNINITIALIZED; 5898 PRBool needSession = PR_FALSE; 5899 PRBool needObject = PR_FALSE; 5900 SFTKSession *session; 5901 SFTKObject *object; 5902 5903 *pulFIPSStatus = CKS_NSS_FIPS_NOT_OK; 5904 5905 /* first determine what we need to look up */ 5906 switch (ulOperationType) { 5907 case CKT_NSS_SESSION_CHECK: 5908 case CKT_NSS_SESSION_LAST_CHECK: 5909 needSession = PR_TRUE; 5910 needObject = PR_FALSE; 5911 break; 5912 case CKT_NSS_OBJECT_CHECK: 5913 needSession = PR_FALSE; 5914 needObject = PR_TRUE; 5915 break; 5916 case CKT_NSS_BOTH_CHECK: 5917 needSession = PR_TRUE; 5918 needObject = PR_TRUE; 5919 break; 5920 default: 5921 return CKR_ARGUMENTS_BAD; 5922 } 5923 5924 /* we always need the session handle, the object handle is only 5925 * meaningful if there is a session */ 5926 session = sftk_SessionFromHandle(hSession); 5927 if (!session) { 5928 return CKR_SESSION_HANDLE_INVALID; 5929 } 5930 if (needSession) { 5931 if (CKT_NSS_SESSION_LAST_CHECK == ulOperationType) { 5932 sessionState = session->lastOpWasFIPS ? CKS_NSS_FIPS_OK : CKS_NSS_FIPS_NOT_OK; 5933 } else { 5934 if (session->enc_context) { 5935 sessionState = session->enc_context->isFIPS ? CKS_NSS_FIPS_OK : CKS_NSS_FIPS_NOT_OK; 5936 } 5937 if (sessionState != CKS_NSS_FIPS_NOT_OK && session->hash_context) { 5938 sessionState = session->hash_context->isFIPS ? CKS_NSS_FIPS_OK : CKS_NSS_FIPS_NOT_OK; 5939 } 5940 /* sessionState is set to CKS_NSS_UNINITIALIZED if neither 5941 * context exists */ 5942 } 5943 } 5944 5945 if (needObject) { 5946 object = sftk_ObjectFromHandle(hObject, session); 5947 if (!object) { 5948 sftk_FreeSession(session); 5949 return CKR_OBJECT_HANDLE_INVALID; 5950 } 5951 objectState = sftk_hasFIPS(object) ? CKS_NSS_FIPS_OK : CKS_NSS_FIPS_NOT_OK; 5952 sftk_FreeObject(object); 5953 } 5954 5955 sftk_FreeSession(session); 5956 5957 /* If we didn't fetch the state, then it is uninitialized. 5958 * The session state can also be uninitialized if there are no active 5959 * crypto operations on the session. Turns out the rules for combining 5960 * the states are the same whether or not the state was uninitialzed 5961 * because we didn't fetch it or because there wasn't a state to fetch. 5962 */ 5963 5964 /* if the object State is uninitialized, return the state of the session. */ 5965 if (objectState == CKS_NSS_UNINITIALIZED) { 5966 /* if they are both uninitalized, return CKS_FIPS_NOT_OK */ 5967 if (sessionState == CKS_NSS_UNINITIALIZED) { 5968 /* *pulFIPSStatus already set to CKS_FIPS_NOT_OK */ 5969 return CKR_OK; 5970 } 5971 *pulFIPSStatus = sessionState; 5972 return CKR_OK; 5973 } 5974 /* objectState is initialized, if sessionState is uninitialized, we can 5975 * just return objectState */ 5976 if (sessionState == CKS_NSS_UNINITIALIZED) { 5977 *pulFIPSStatus = objectState; 5978 return CKR_OK; 5979 } 5980 5981 /* they are are not equal, one must be CKS_FIPS_NOT_OK, so we return that 5982 * value CKS_FIPS_NOT_OK */ 5983 if (objectState != sessionState) { 5984 /* *pulFIPSStatus already set to CKS_FIPS_NOT_OK */ 5985 return CKR_OK; 5986 } 5987 5988 /* objectState and sessionState or the same, so we can return either */ 5989 *pulFIPSStatus = sessionState; 5990 return CKR_OK; 5991 } 5992 5993 CK_RV 5994 NSC_GetSessionValidationFlags(CK_SESSION_HANDLE hSession, 5995 CK_SESSION_VALIDATION_FLAGS_TYPE type, 5996 CK_FLAGS_PTR pFlags) 5997 { 5998 CK_RV crv; 5999 CK_ULONG status = CKS_NSS_UNINITIALIZED; 6000 CK_ULONG status1 = CKS_NSS_UNINITIALIZED; 6001 6002 *pFlags = 0; 6003 6004 crv = nsc_NSSGetFIPSStatus(hSession, CK_INVALID_HANDLE, 6005 CKT_NSS_SESSION_LAST_CHECK, &status); 6006 if (crv != CKR_OK) { 6007 return crv; 6008 } 6009 crv = nsc_NSSGetFIPSStatus(hSession, CK_INVALID_HANDLE, 6010 CKT_NSS_SESSION_CHECK, &status1); 6011 if (crv != CKR_OK) { 6012 return crv; 6013 } 6014 /* PCKS #11 only defines the last operation. For us this includes 6015 * things in the CKT_NSS_SESSION_CHECK */ 6016 if ((status == CKS_NSS_FIPS_OK) || (status1 == CKS_NSS_FIPS_OK)) { 6017 *pFlags = SFTK_VALIDATION_FIPS_FLAG; 6018 } 6019 return CKR_OK; 6020 }