1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/security/nss/lib/ckfw/capi/cobject.c Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,2305 @@ 1.4 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.5 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.6 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.7 + 1.8 +#include "ckcapi.h" 1.9 +#include "nssbase.h" 1.10 + 1.11 +/* 1.12 + * ckcapi/cobject.c 1.13 + * 1.14 + * This file implements the NSSCKMDObject object for the 1.15 + * "nss to capi objects" cryptoki module. 1.16 + */ 1.17 + 1.18 +const CK_ATTRIBUTE_TYPE certAttrs[] = { 1.19 + CKA_CLASS, 1.20 + CKA_TOKEN, 1.21 + CKA_PRIVATE, 1.22 + CKA_MODIFIABLE, 1.23 + CKA_LABEL, 1.24 + CKA_CERTIFICATE_TYPE, 1.25 + CKA_SUBJECT, 1.26 + CKA_ISSUER, 1.27 + CKA_SERIAL_NUMBER, 1.28 + CKA_VALUE 1.29 +}; 1.30 +const PRUint32 certAttrsCount = NSS_CKCAPI_ARRAY_SIZE(certAttrs); 1.31 + 1.32 +/* private keys, for now only support RSA */ 1.33 +const CK_ATTRIBUTE_TYPE privKeyAttrs[] = { 1.34 + CKA_CLASS, 1.35 + CKA_TOKEN, 1.36 + CKA_PRIVATE, 1.37 + CKA_MODIFIABLE, 1.38 + CKA_LABEL, 1.39 + CKA_KEY_TYPE, 1.40 + CKA_DERIVE, 1.41 + CKA_LOCAL, 1.42 + CKA_SUBJECT, 1.43 + CKA_SENSITIVE, 1.44 + CKA_DECRYPT, 1.45 + CKA_SIGN, 1.46 + CKA_SIGN_RECOVER, 1.47 + CKA_UNWRAP, 1.48 + CKA_EXTRACTABLE, 1.49 + CKA_ALWAYS_SENSITIVE, 1.50 + CKA_NEVER_EXTRACTABLE, 1.51 + CKA_MODULUS, 1.52 + CKA_PUBLIC_EXPONENT, 1.53 +}; 1.54 +const PRUint32 privKeyAttrsCount = NSS_CKCAPI_ARRAY_SIZE(privKeyAttrs); 1.55 + 1.56 +/* public keys, for now only support RSA */ 1.57 +const CK_ATTRIBUTE_TYPE pubKeyAttrs[] = { 1.58 + CKA_CLASS, 1.59 + CKA_TOKEN, 1.60 + CKA_PRIVATE, 1.61 + CKA_MODIFIABLE, 1.62 + CKA_LABEL, 1.63 + CKA_KEY_TYPE, 1.64 + CKA_DERIVE, 1.65 + CKA_LOCAL, 1.66 + CKA_SUBJECT, 1.67 + CKA_ENCRYPT, 1.68 + CKA_VERIFY, 1.69 + CKA_VERIFY_RECOVER, 1.70 + CKA_WRAP, 1.71 + CKA_MODULUS, 1.72 + CKA_PUBLIC_EXPONENT, 1.73 +}; 1.74 +const PRUint32 pubKeyAttrsCount = NSS_CKCAPI_ARRAY_SIZE(pubKeyAttrs); 1.75 +static const CK_BBOOL ck_true = CK_TRUE; 1.76 +static const CK_BBOOL ck_false = CK_FALSE; 1.77 +static const CK_CERTIFICATE_TYPE ckc_x509 = CKC_X_509; 1.78 +static const CK_KEY_TYPE ckk_rsa = CKK_RSA; 1.79 +static const CK_OBJECT_CLASS cko_certificate = CKO_CERTIFICATE; 1.80 +static const CK_OBJECT_CLASS cko_private_key = CKO_PRIVATE_KEY; 1.81 +static const CK_OBJECT_CLASS cko_public_key = CKO_PUBLIC_KEY; 1.82 +static const NSSItem ckcapi_trueItem = { 1.83 + (void *)&ck_true, (PRUint32)sizeof(CK_BBOOL) }; 1.84 +static const NSSItem ckcapi_falseItem = { 1.85 + (void *)&ck_false, (PRUint32)sizeof(CK_BBOOL) }; 1.86 +static const NSSItem ckcapi_x509Item = { 1.87 + (void *)&ckc_x509, (PRUint32)sizeof(CK_CERTIFICATE_TYPE) }; 1.88 +static const NSSItem ckcapi_rsaItem = { 1.89 + (void *)&ckk_rsa, (PRUint32)sizeof(CK_KEY_TYPE) }; 1.90 +static const NSSItem ckcapi_certClassItem = { 1.91 + (void *)&cko_certificate, (PRUint32)sizeof(CK_OBJECT_CLASS) }; 1.92 +static const NSSItem ckcapi_privKeyClassItem = { 1.93 + (void *)&cko_private_key, (PRUint32)sizeof(CK_OBJECT_CLASS) }; 1.94 +static const NSSItem ckcapi_pubKeyClassItem = { 1.95 + (void *)&cko_public_key, (PRUint32)sizeof(CK_OBJECT_CLASS) }; 1.96 +static const NSSItem ckcapi_emptyItem = { 1.97 + (void *)&ck_true, 0}; 1.98 + 1.99 +/* 1.100 + * these are utilities. The chould be moved to a new utilities file. 1.101 + */ 1.102 + 1.103 +/* 1.104 + * unwrap a single DER value 1.105 + */ 1.106 +unsigned char * 1.107 +nss_ckcapi_DERUnwrap 1.108 +( 1.109 + unsigned char *src, 1.110 + unsigned int size, 1.111 + unsigned int *outSize, 1.112 + unsigned char **next 1.113 +) 1.114 +{ 1.115 + unsigned char *start = src; 1.116 + unsigned char *end = src+size; 1.117 + unsigned int len = 0; 1.118 + 1.119 + /* initialize error condition return values */ 1.120 + *outSize = 0; 1.121 + if (next) { 1.122 + *next = src; 1.123 + } 1.124 + 1.125 + if (size < 2) { 1.126 + return start; 1.127 + } 1.128 + src++; /* skip the tag -- should check it against an expected value! */ 1.129 + len = (unsigned) *src++; 1.130 + if (len & 0x80) { 1.131 + unsigned int count = len & 0x7f; 1.132 + len = 0; 1.133 + 1.134 + if (count+2 > size) { 1.135 + return start; 1.136 + } 1.137 + while (count-- > 0) { 1.138 + len = (len << 8) | (unsigned) *src++; 1.139 + } 1.140 + } 1.141 + if (len + (src-start) > size) { 1.142 + return start; 1.143 + } 1.144 + if (next) { 1.145 + *next = src+len; 1.146 + } 1.147 + *outSize = len; 1.148 + 1.149 + return src; 1.150 +} 1.151 + 1.152 +/* 1.153 + * convert a PKCS #11 bytestrin into a CK_ULONG, the byte stream must be 1.154 + * less than sizeof (CK_ULONG). 1.155 + */ 1.156 +CK_ULONG 1.157 +nss_ckcapi_DataToInt 1.158 +( 1.159 + NSSItem *data, 1.160 + CK_RV *pError 1.161 +) 1.162 +{ 1.163 + CK_ULONG value = 0; 1.164 + unsigned long count = data->size; 1.165 + unsigned char *dataPtr = data->data; 1.166 + unsigned long size = 0; 1.167 + 1.168 + *pError = CKR_OK; 1.169 + 1.170 + while (count--) { 1.171 + value = value << 8; 1.172 + value = value + *dataPtr++; 1.173 + if (size || value) { 1.174 + size++; 1.175 + } 1.176 + } 1.177 + if (size > sizeof(CK_ULONG)) { 1.178 + *pError = CKR_ATTRIBUTE_VALUE_INVALID; 1.179 + } 1.180 + return value; 1.181 +} 1.182 + 1.183 +/* 1.184 + * convert a CK_ULONG to a bytestream. Data is stored in the buffer 'buf' 1.185 + * and must be at least CK_ULONG. Caller must provide buf. 1.186 + */ 1.187 +CK_ULONG 1.188 +nss_ckcapi_IntToData 1.189 +( 1.190 + CK_ULONG value, 1.191 + NSSItem *data, 1.192 + unsigned char *dataPtr, 1.193 + CK_RV *pError 1.194 +) 1.195 +{ 1.196 + unsigned long count = 0; 1.197 + unsigned long i; 1.198 +#define SHIFT ((sizeof(CK_ULONG)-1)*8) 1.199 + PRBool first = 0; 1.200 + 1.201 + *pError = CKR_OK; 1.202 + 1.203 + data->data = dataPtr; 1.204 + for (i=0; i < sizeof(CK_ULONG); i++) { 1.205 + unsigned char digit = (unsigned char)((value >> SHIFT) & 0xff); 1.206 + 1.207 + value = value << 8; 1.208 + 1.209 + /* drop leading zero bytes */ 1.210 + if (first && (0 == digit)) { 1.211 + continue; 1.212 + } 1.213 + *dataPtr++ = digit; 1.214 + count++; 1.215 + } 1.216 + data->size = count; 1.217 + return count; 1.218 +} 1.219 + 1.220 +/* 1.221 + * get an attribute from a template. Value is returned in NSS item. 1.222 + * data for the item is owned by the template. 1.223 + */ 1.224 +CK_RV 1.225 +nss_ckcapi_GetAttribute 1.226 +( 1.227 + CK_ATTRIBUTE_TYPE type, 1.228 + CK_ATTRIBUTE *template, 1.229 + CK_ULONG templateSize, 1.230 + NSSItem *item 1.231 +) 1.232 +{ 1.233 + CK_ULONG i; 1.234 + 1.235 + for (i=0; i < templateSize; i++) { 1.236 + if (template[i].type == type) { 1.237 + item->data = template[i].pValue; 1.238 + item->size = template[i].ulValueLen; 1.239 + return CKR_OK; 1.240 + } 1.241 + } 1.242 + return CKR_TEMPLATE_INCOMPLETE; 1.243 +} 1.244 + 1.245 +/* 1.246 + * get an attribute which is type CK_ULONG. 1.247 + */ 1.248 +CK_ULONG 1.249 +nss_ckcapi_GetULongAttribute 1.250 +( 1.251 + CK_ATTRIBUTE_TYPE type, 1.252 + CK_ATTRIBUTE *template, 1.253 + CK_ULONG templateSize, 1.254 + CK_RV *pError 1.255 +) 1.256 +{ 1.257 + NSSItem item; 1.258 + 1.259 + *pError = nss_ckcapi_GetAttribute(type, template, templateSize, &item); 1.260 + if (CKR_OK != *pError) { 1.261 + return (CK_ULONG) 0; 1.262 + } 1.263 + if (item.size != sizeof(CK_ULONG)) { 1.264 + *pError = CKR_ATTRIBUTE_VALUE_INVALID; 1.265 + return (CK_ULONG) 0; 1.266 + } 1.267 + return *(CK_ULONG *)item.data; 1.268 +} 1.269 + 1.270 +/* 1.271 + * get an attribute which is type CK_BBOOL. 1.272 + */ 1.273 +CK_BBOOL 1.274 +nss_ckcapi_GetBoolAttribute 1.275 +( 1.276 + CK_ATTRIBUTE_TYPE type, 1.277 + CK_ATTRIBUTE *template, 1.278 + CK_ULONG templateSize, 1.279 + CK_RV *pError 1.280 +) 1.281 +{ 1.282 + NSSItem item; 1.283 + 1.284 + *pError = nss_ckcapi_GetAttribute(type, template, templateSize, &item); 1.285 + if (CKR_OK != *pError) { 1.286 + return (CK_BBOOL) 0; 1.287 + } 1.288 + if (item.size != sizeof(CK_BBOOL)) { 1.289 + *pError = CKR_ATTRIBUTE_VALUE_INVALID; 1.290 + return (CK_BBOOL) 0; 1.291 + } 1.292 + return *(CK_BBOOL *)item.data; 1.293 +} 1.294 + 1.295 +/* 1.296 + * get an attribute which is type CK_BBOOL. 1.297 + */ 1.298 +char * 1.299 +nss_ckcapi_GetStringAttribute 1.300 +( 1.301 + CK_ATTRIBUTE_TYPE type, 1.302 + CK_ATTRIBUTE *template, 1.303 + CK_ULONG templateSize, 1.304 + CK_RV *pError 1.305 +) 1.306 +{ 1.307 + NSSItem item; 1.308 + char *str; 1.309 + 1.310 + /* get the attribute */ 1.311 + *pError = nss_ckcapi_GetAttribute(type, template, templateSize, &item); 1.312 + if (CKR_OK != *pError) { 1.313 + return (char *)NULL; 1.314 + } 1.315 + /* make sure it is null terminated */ 1.316 + str = nss_ZNEWARRAY(NULL, char, item.size+1); 1.317 + if ((char *)NULL == str) { 1.318 + *pError = CKR_HOST_MEMORY; 1.319 + return (char *)NULL; 1.320 + } 1.321 + 1.322 + nsslibc_memcpy(str, item.data, item.size); 1.323 + str[item.size] = 0; 1.324 + 1.325 + return str; 1.326 +} 1.327 + 1.328 +/* 1.329 + * Return the size in bytes of a wide string, including the terminating null 1.330 + * character 1.331 + */ 1.332 +int 1.333 +nss_ckcapi_WideSize 1.334 +( 1.335 + LPCWSTR wide 1.336 +) 1.337 +{ 1.338 + DWORD size; 1.339 + 1.340 + if ((LPWSTR)NULL == wide) { 1.341 + return 0; 1.342 + } 1.343 + size = wcslen(wide)+1; 1.344 + return size*sizeof(WCHAR); 1.345 +} 1.346 + 1.347 +/* 1.348 + * Covert a Unicode wide character string to a UTF8 string 1.349 + */ 1.350 +char * 1.351 +nss_ckcapi_WideToUTF8 1.352 +( 1.353 + LPCWSTR wide 1.354 +) 1.355 +{ 1.356 + DWORD size; 1.357 + char *buf; 1.358 + 1.359 + if ((LPWSTR)NULL == wide) { 1.360 + return (char *)NULL; 1.361 + } 1.362 + 1.363 + size = WideCharToMultiByte(CP_UTF8, 0, wide, -1, NULL, 0, NULL, 0); 1.364 + if (size == 0) { 1.365 + return (char *)NULL; 1.366 + } 1.367 + buf = nss_ZNEWARRAY(NULL, char, size); 1.368 + size = WideCharToMultiByte(CP_UTF8, 0, wide, -1, buf, size, NULL, 0); 1.369 + if (size == 0) { 1.370 + nss_ZFreeIf(buf); 1.371 + return (char *)NULL; 1.372 + } 1.373 + return buf; 1.374 +} 1.375 + 1.376 +/* 1.377 + * Return a Wide String duplicated with nss allocated memory. 1.378 + */ 1.379 +LPWSTR 1.380 +nss_ckcapi_WideDup 1.381 +( 1.382 + LPCWSTR wide 1.383 +) 1.384 +{ 1.385 + DWORD len; 1.386 + LPWSTR buf; 1.387 + 1.388 + if ((LPWSTR)NULL == wide) { 1.389 + return (LPWSTR)NULL; 1.390 + } 1.391 + 1.392 + len = wcslen(wide)+1; 1.393 + 1.394 + buf = nss_ZNEWARRAY(NULL, WCHAR, len); 1.395 + if ((LPWSTR) NULL == buf) { 1.396 + return buf; 1.397 + } 1.398 + nsslibc_memcpy(buf, wide, len*sizeof(WCHAR)); 1.399 + return buf; 1.400 +} 1.401 + 1.402 +/* 1.403 + * Covert a UTF8 string to Unicode wide character 1.404 + */ 1.405 +LPWSTR 1.406 +nss_ckcapi_UTF8ToWide 1.407 +( 1.408 + char *buf 1.409 +) 1.410 +{ 1.411 + DWORD size; 1.412 + LPWSTR wide; 1.413 + 1.414 + if ((char *)NULL == buf) { 1.415 + return (LPWSTR) NULL; 1.416 + } 1.417 + 1.418 + size = MultiByteToWideChar(CP_UTF8, 0, buf, -1, NULL, 0); 1.419 + if (size == 0) { 1.420 + return (LPWSTR) NULL; 1.421 + } 1.422 + wide = nss_ZNEWARRAY(NULL, WCHAR, size); 1.423 + size = MultiByteToWideChar(CP_UTF8, 0, buf, -1, wide, size); 1.424 + if (size == 0) { 1.425 + nss_ZFreeIf(wide); 1.426 + return (LPWSTR) NULL; 1.427 + } 1.428 + return wide; 1.429 +} 1.430 + 1.431 + 1.432 +/* 1.433 + * keep all the knowlege of how the internalObject is laid out in this function 1.434 + * 1.435 + * nss_ckcapi_FetchKeyContainer 1.436 + * 1.437 + * fetches the Provider container and info as well as a key handle for a 1.438 + * private key. If something other than a private key is passed in, 1.439 + * this function fails with CKR_KEY_TYPE_INCONSISTENT 1.440 + */ 1.441 +NSS_EXTERN CK_RV 1.442 +nss_ckcapi_FetchKeyContainer 1.443 +( 1.444 + ckcapiInternalObject *iKey, 1.445 + HCRYPTPROV *hProv, 1.446 + DWORD *keySpec, 1.447 + HCRYPTKEY *hKey 1.448 +) 1.449 +{ 1.450 + ckcapiCertObject *co; 1.451 + ckcapiKeyObject *ko; 1.452 + BOOL rc, dummy; 1.453 + DWORD msError; 1.454 + 1.455 + 1.456 + switch (iKey->type) { 1.457 + default: 1.458 + case ckcapiRaw: 1.459 + /* can't have raw private keys */ 1.460 + return CKR_KEY_TYPE_INCONSISTENT; 1.461 + case ckcapiCert: 1.462 + if (iKey->objClass != CKO_PRIVATE_KEY) { 1.463 + /* Only private keys have private key provider handles */ 1.464 + return CKR_KEY_TYPE_INCONSISTENT; 1.465 + } 1.466 + co = &iKey->u.cert; 1.467 + 1.468 + /* OK, get the Provider */ 1.469 + rc = CryptAcquireCertificatePrivateKey(co->certContext, 1.470 + CRYPT_ACQUIRE_CACHE_FLAG|CRYPT_ACQUIRE_COMPARE_KEY_FLAG, NULL, hProv, 1.471 + keySpec, &dummy); 1.472 + if (!rc) { 1.473 + goto loser; 1.474 + } 1.475 + break; 1.476 + case ckcapiBareKey: 1.477 + if (iKey->objClass != CKO_PRIVATE_KEY) { 1.478 + /* Only private keys have private key provider handles */ 1.479 + return CKR_KEY_TYPE_INCONSISTENT; 1.480 + } 1.481 + ko = &iKey->u.key; 1.482 + 1.483 + /* OK, get the Provider */ 1.484 + if (0 == ko->hProv) { 1.485 + rc = CryptAcquireContext(hProv, 1.486 + ko->containerName, 1.487 + ko->provName, 1.488 + ko->provInfo.dwProvType , 0); 1.489 + if (!rc) { 1.490 + goto loser; 1.491 + } 1.492 + } else { 1.493 + *hProv = ko->hProv; 1.494 + } 1.495 + *keySpec = ko->provInfo.dwKeySpec; 1.496 + break; 1.497 + } 1.498 + 1.499 + /* and get the crypto handle */ 1.500 + rc = CryptGetUserKey(*hProv, *keySpec, hKey); 1.501 + if (!rc) { 1.502 + goto loser; 1.503 + } 1.504 + return CKR_OK; 1.505 +loser: 1.506 + /* map the microsoft error before leaving */ 1.507 + msError = GetLastError(); 1.508 + switch (msError) { 1.509 + case ERROR_INVALID_HANDLE: 1.510 + case ERROR_INVALID_PARAMETER: 1.511 + case NTE_BAD_KEY: 1.512 + case NTE_NO_KEY: 1.513 + case NTE_BAD_PUBLIC_KEY: 1.514 + case NTE_BAD_KEYSET: 1.515 + case NTE_KEYSET_NOT_DEF: 1.516 + return CKR_KEY_TYPE_INCONSISTENT; 1.517 + case NTE_BAD_UID: 1.518 + case NTE_KEYSET_ENTRY_BAD: 1.519 + return CKR_DEVICE_ERROR; 1.520 + } 1.521 + return CKR_GENERAL_ERROR; 1.522 +} 1.523 + 1.524 + 1.525 +/* 1.526 + * take a DER PUBLIC Key block and return the modulus and exponent 1.527 + */ 1.528 +static void 1.529 +ckcapi_CertPopulateModulusExponent 1.530 +( 1.531 + ckcapiInternalObject *io 1.532 +) 1.533 +{ 1.534 + ckcapiKeyParams *kp = &io->u.cert.key; 1.535 + PCCERT_CONTEXT certContext = io->u.cert.certContext; 1.536 + unsigned char *pkData = 1.537 + certContext->pCertInfo->SubjectPublicKeyInfo.PublicKey.pbData; 1.538 + unsigned int size= 1.539 + certContext->pCertInfo->SubjectPublicKeyInfo.PublicKey.cbData; 1.540 + unsigned int newSize; 1.541 + unsigned char *ptr, *newptr; 1.542 + 1.543 + /* find the start of the modulus -- this will not give good results if 1.544 + * the key isn't an rsa key! */ 1.545 + ptr = nss_ckcapi_DERUnwrap(pkData, size, &newSize, NULL); 1.546 + kp->modulus.data = nss_ckcapi_DERUnwrap(ptr, newSize, 1.547 + &kp->modulus.size, &newptr); 1.548 + /* changed from signed to unsigned int */ 1.549 + if (0 == *(char *)kp->modulus.data) { 1.550 + kp->modulus.data = ((char *)kp->modulus.data)+1; 1.551 + kp->modulus.size = kp->modulus.size - 1; 1.552 + } 1.553 + /* changed from signed to unsigned int */ 1.554 + kp->exponent.data = nss_ckcapi_DERUnwrap(newptr, (newptr-ptr)+newSize, 1.555 + &kp->exponent.size, NULL); 1.556 + if (0 == *(char *)kp->exponent.data) { 1.557 + kp->exponent.data = ((char *)kp->exponent.data)+1; 1.558 + kp->exponent.size = kp->exponent.size - 1; 1.559 + } 1.560 + return; 1.561 +} 1.562 + 1.563 +typedef struct _CAPI_RSA_KEY_BLOB { 1.564 + PUBLICKEYSTRUC header; 1.565 + RSAPUBKEY rsa; 1.566 + char data[1]; 1.567 +} CAPI_RSA_KEY_BLOB; 1.568 + 1.569 +#define CAPI_MODULUS_OFFSET(modSize) 0 1.570 +#define CAPI_PRIME_1_OFFSET(modSize) (modSize) 1.571 +#define CAPI_PRIME_2_OFFSET(modSize) ((modSize)+(modSize)/2) 1.572 +#define CAPI_EXPONENT_1_OFFSET(modSize) ((modSize)*2) 1.573 +#define CAPI_EXPONENT_2_OFFSET(modSize) ((modSize)*2+(modSize)/2) 1.574 +#define CAPI_COEFFICIENT_OFFSET(modSize) ((modSize)*3) 1.575 +#define CAPI_PRIVATE_EXP_OFFSET(modSize) ((modSize)*3+(modSize)/2) 1.576 + 1.577 +void 1.578 +ckcapi_FetchPublicKey 1.579 +( 1.580 + ckcapiInternalObject *io 1.581 +) 1.582 +{ 1.583 + ckcapiKeyParams *kp; 1.584 + HCRYPTPROV hProv; 1.585 + DWORD keySpec; 1.586 + HCRYPTKEY hKey = 0; 1.587 + CK_RV error; 1.588 + DWORD bufLen; 1.589 + BOOL rc; 1.590 + unsigned long modulus; 1.591 + char *buf = NULL; 1.592 + CAPI_RSA_KEY_BLOB *blob; 1.593 + 1.594 + error = nss_ckcapi_FetchKeyContainer(io, &hProv, &keySpec, &hKey); 1.595 + if (CKR_OK != error) { 1.596 + goto loser; 1.597 + } 1.598 + kp = (ckcapiCert == io->type) ? &io->u.cert.key : &io->u.key.key; 1.599 + 1.600 + rc = CryptExportKey(hKey, 0, PUBLICKEYBLOB, 0, buf, &bufLen); 1.601 + if (!rc) { 1.602 + goto loser; 1.603 + } 1.604 + buf = nss_ZNEWARRAY(NULL, char, bufLen); 1.605 + rc = CryptExportKey(hKey, 0, PUBLICKEYBLOB, 0, buf, &bufLen); 1.606 + if (!rc) { 1.607 + goto loser; 1.608 + } 1.609 + /* validate the blob */ 1.610 + blob = (CAPI_RSA_KEY_BLOB *)buf; 1.611 + if ((PUBLICKEYBLOB != blob->header.bType) || 1.612 + (0x02 != blob->header.bVersion) || 1.613 + (0x31415352 != blob->rsa.magic)) { 1.614 + goto loser; 1.615 + } 1.616 + modulus = blob->rsa.bitlen/8; 1.617 + kp->pubKey = buf; 1.618 + buf = NULL; 1.619 + 1.620 + kp->modulus.data = &blob->data[CAPI_MODULUS_OFFSET(modulus)]; 1.621 + kp->modulus.size = modulus; 1.622 + ckcapi_ReverseData(&kp->modulus); 1.623 + nss_ckcapi_IntToData(blob->rsa.pubexp, &kp->exponent, 1.624 + kp->publicExponentData, &error); 1.625 + 1.626 +loser: 1.627 + nss_ZFreeIf(buf); 1.628 + if (0 != hKey) { 1.629 + CryptDestroyKey(hKey); 1.630 + } 1.631 + return; 1.632 +} 1.633 + 1.634 +void 1.635 +ckcapi_FetchPrivateKey 1.636 +( 1.637 + ckcapiInternalObject *io 1.638 +) 1.639 +{ 1.640 + ckcapiKeyParams *kp; 1.641 + HCRYPTPROV hProv; 1.642 + DWORD keySpec; 1.643 + HCRYPTKEY hKey = 0; 1.644 + CK_RV error; 1.645 + DWORD bufLen; 1.646 + BOOL rc; 1.647 + unsigned long modulus; 1.648 + char *buf = NULL; 1.649 + CAPI_RSA_KEY_BLOB *blob; 1.650 + 1.651 + error = nss_ckcapi_FetchKeyContainer(io, &hProv, &keySpec, &hKey); 1.652 + if (CKR_OK != error) { 1.653 + goto loser; 1.654 + } 1.655 + kp = (ckcapiCert == io->type) ? &io->u.cert.key : &io->u.key.key; 1.656 + 1.657 + rc = CryptExportKey(hKey, 0, PRIVATEKEYBLOB, 0, buf, &bufLen); 1.658 + if (!rc) { 1.659 + goto loser; 1.660 + } 1.661 + buf = nss_ZNEWARRAY(NULL, char, bufLen); 1.662 + rc = CryptExportKey(hKey, 0, PRIVATEKEYBLOB, 0, buf, &bufLen); 1.663 + if (!rc) { 1.664 + goto loser; 1.665 + } 1.666 + /* validate the blob */ 1.667 + blob = (CAPI_RSA_KEY_BLOB *)buf; 1.668 + if ((PRIVATEKEYBLOB != blob->header.bType) || 1.669 + (0x02 != blob->header.bVersion) || 1.670 + (0x32415352 != blob->rsa.magic)) { 1.671 + goto loser; 1.672 + } 1.673 + modulus = blob->rsa.bitlen/8; 1.674 + kp->privateKey = buf; 1.675 + buf = NULL; 1.676 + 1.677 + kp->privateExponent.data = &blob->data[CAPI_PRIVATE_EXP_OFFSET(modulus)]; 1.678 + kp->privateExponent.size = modulus; 1.679 + ckcapi_ReverseData(&kp->privateExponent); 1.680 + kp->prime1.data = &blob->data[CAPI_PRIME_1_OFFSET(modulus)]; 1.681 + kp->prime1.size = modulus/2; 1.682 + ckcapi_ReverseData(&kp->prime1); 1.683 + kp->prime2.data = &blob->data[CAPI_PRIME_2_OFFSET(modulus)]; 1.684 + kp->prime2.size = modulus/2; 1.685 + ckcapi_ReverseData(&kp->prime2); 1.686 + kp->exponent1.data = &blob->data[CAPI_EXPONENT_1_OFFSET(modulus)]; 1.687 + kp->exponent1.size = modulus/2; 1.688 + ckcapi_ReverseData(&kp->exponent1); 1.689 + kp->exponent2.data = &blob->data[CAPI_EXPONENT_2_OFFSET(modulus)]; 1.690 + kp->exponent2.size = modulus/2; 1.691 + ckcapi_ReverseData(&kp->exponent2); 1.692 + kp->coefficient.data = &blob->data[CAPI_COEFFICIENT_OFFSET(modulus)]; 1.693 + kp->coefficient.size = modulus/2; 1.694 + ckcapi_ReverseData(&kp->coefficient); 1.695 + 1.696 +loser: 1.697 + nss_ZFreeIf(buf); 1.698 + if (0 != hKey) { 1.699 + CryptDestroyKey(hKey); 1.700 + } 1.701 + return; 1.702 +} 1.703 + 1.704 + 1.705 +void 1.706 +ckcapi_PopulateModulusExponent 1.707 +( 1.708 + ckcapiInternalObject *io 1.709 +) 1.710 +{ 1.711 + if (ckcapiCert == io->type) { 1.712 + ckcapi_CertPopulateModulusExponent(io); 1.713 + } else { 1.714 + ckcapi_FetchPublicKey(io); 1.715 + } 1.716 + return; 1.717 +} 1.718 + 1.719 +/* 1.720 + * fetch the friendly name attribute. 1.721 + * can only be called with ckcapiCert type objects! 1.722 + */ 1.723 +void 1.724 +ckcapi_FetchLabel 1.725 +( 1.726 + ckcapiInternalObject *io 1.727 +) 1.728 +{ 1.729 + ckcapiCertObject *co = &io->u.cert; 1.730 + char *label; 1.731 + PCCERT_CONTEXT certContext = io->u.cert.certContext; 1.732 + char labelDataUTF16[128]; 1.733 + DWORD size = sizeof(labelDataUTF16); 1.734 + DWORD size8 = sizeof(co->labelData); 1.735 + BOOL rv; 1.736 + 1.737 + rv = CertGetCertificateContextProperty(certContext, 1.738 + CERT_FRIENDLY_NAME_PROP_ID, labelDataUTF16, &size); 1.739 + if (rv) { 1.740 + co->labelData = nss_ckcapi_WideToUTF8((LPCWSTR)labelDataUTF16); 1.741 + if ((CHAR *)NULL == co->labelData) { 1.742 + rv = 0; 1.743 + } else { 1.744 + size = strlen(co->labelData); 1.745 + } 1.746 + } 1.747 + label = co->labelData; 1.748 + /* we are presuming a user cert, make sure it has a nickname, even if 1.749 + * Microsoft never gave it one */ 1.750 + if (!rv && co->hasID) { 1.751 + DWORD mserror = GetLastError(); 1.752 +#define DEFAULT_NICKNAME "no Microsoft nickname" 1.753 + label = DEFAULT_NICKNAME; 1.754 + size = sizeof(DEFAULT_NICKNAME); 1.755 + rv = 1; 1.756 + } 1.757 + 1.758 + if (rv) { 1.759 + co->label.data = label; 1.760 + co->label.size = size; 1.761 + } 1.762 + return; 1.763 +} 1.764 + 1.765 +void 1.766 +ckcapi_FetchSerial 1.767 +( 1.768 + ckcapiInternalObject *io 1.769 +) 1.770 +{ 1.771 + ckcapiCertObject *co = &io->u.cert; 1.772 + PCCERT_CONTEXT certContext = io->u.cert.certContext; 1.773 + DWORD size = sizeof(co->derSerial); 1.774 + 1.775 + BOOL rc = CryptEncodeObject(X509_ASN_ENCODING, 1.776 + X509_MULTI_BYTE_INTEGER, 1.777 + &certContext->pCertInfo->SerialNumber, 1.778 + co->derSerial, 1.779 + &size); 1.780 + if (rc) { 1.781 + co->serial.data = co->derSerial; 1.782 + co->serial.size = size; 1.783 + } 1.784 + return; 1.785 +} 1.786 + 1.787 +/* 1.788 + * fetch the key ID. 1.789 + */ 1.790 +void 1.791 +ckcapi_FetchID 1.792 +( 1.793 + ckcapiInternalObject *io 1.794 +) 1.795 +{ 1.796 + PCCERT_CONTEXT certContext = io->u.cert.certContext; 1.797 + DWORD size = 0; 1.798 + BOOL rc; 1.799 + 1.800 + rc = CertGetCertificateContextProperty(certContext, 1.801 + CERT_KEY_IDENTIFIER_PROP_ID, NULL, &size); 1.802 + if (!rc) { 1.803 + return; 1.804 + } 1.805 + io->idData = nss_ZNEWARRAY(NULL, char, size); 1.806 + if (io->idData == NULL) { 1.807 + return; 1.808 + } 1.809 + 1.810 + rc = CertGetCertificateContextProperty(certContext, 1.811 + CERT_KEY_IDENTIFIER_PROP_ID, io->idData, &size); 1.812 + if (!rc) { 1.813 + nss_ZFreeIf(io->idData); 1.814 + io->idData = NULL; 1.815 + return; 1.816 + } 1.817 + io->id.data = io->idData; 1.818 + io->id.size = size; 1.819 + return; 1.820 +} 1.821 + 1.822 +/* 1.823 + * fetch the hash key. 1.824 + */ 1.825 +void 1.826 +ckcapi_CertFetchHashKey 1.827 +( 1.828 + ckcapiInternalObject *io 1.829 +) 1.830 +{ 1.831 + ckcapiCertObject *co = &io->u.cert; 1.832 + PCCERT_CONTEXT certContext = io->u.cert.certContext; 1.833 + DWORD size = certContext->cbCertEncoded; 1.834 + DWORD max = sizeof(io->hashKeyData)-1; 1.835 + DWORD offset = 0; 1.836 + 1.837 + /* make sure we don't over flow. NOTE: cutting the top of a cert is 1.838 + * not a big issue because the signature for will be unique for the cert */ 1.839 + if (size > max) { 1.840 + offset = size - max; 1.841 + size = max; 1.842 + } 1.843 + 1.844 + nsslibc_memcpy(io->hashKeyData,certContext->pbCertEncoded+offset, size); 1.845 + io->hashKeyData[size] = (char)(io->objClass & 0xff); 1.846 + 1.847 + io->hashKey.data = io->hashKeyData; 1.848 + io->hashKey.size = size+1; 1.849 + return; 1.850 +} 1.851 + 1.852 +/* 1.853 + * fetch the hash key. 1.854 + */ 1.855 +void 1.856 +ckcapi_KeyFetchHashKey 1.857 +( 1.858 + ckcapiInternalObject *io 1.859 +) 1.860 +{ 1.861 + ckcapiKeyObject *ko = &io->u.key; 1.862 + DWORD size; 1.863 + DWORD max = sizeof(io->hashKeyData)-2; 1.864 + DWORD offset = 0; 1.865 + DWORD provLen = strlen(ko->provName); 1.866 + DWORD containerLen = strlen(ko->containerName); 1.867 + 1.868 + 1.869 + size = provLen + containerLen; 1.870 + 1.871 + /* make sure we don't overflow, try to keep things unique */ 1.872 + if (size > max) { 1.873 + DWORD diff = ((size - max)+1)/2; 1.874 + provLen -= diff; 1.875 + containerLen -= diff; 1.876 + size = provLen+containerLen; 1.877 + } 1.878 + 1.879 + nsslibc_memcpy(io->hashKeyData, ko->provName, provLen); 1.880 + nsslibc_memcpy(&io->hashKeyData[provLen], 1.881 + ko->containerName, 1.882 + containerLen); 1.883 + io->hashKeyData[size] = (char)(io->objClass & 0xff); 1.884 + io->hashKeyData[size+1] = (char)(ko->provInfo.dwKeySpec & 0xff); 1.885 + 1.886 + io->hashKey.data = io->hashKeyData; 1.887 + io->hashKey.size = size+2; 1.888 + return; 1.889 +} 1.890 + 1.891 +/* 1.892 + * fetch the hash key. 1.893 + */ 1.894 +void 1.895 +ckcapi_FetchHashKey 1.896 +( 1.897 + ckcapiInternalObject *io 1.898 +) 1.899 +{ 1.900 + if (ckcapiCert == io->type) { 1.901 + ckcapi_CertFetchHashKey(io); 1.902 + } else { 1.903 + ckcapi_KeyFetchHashKey(io); 1.904 + } 1.905 + return; 1.906 +} 1.907 + 1.908 +const NSSItem * 1.909 +ckcapi_FetchCertAttribute 1.910 +( 1.911 + ckcapiInternalObject *io, 1.912 + CK_ATTRIBUTE_TYPE type 1.913 +) 1.914 +{ 1.915 + PCCERT_CONTEXT certContext = io->u.cert.certContext; 1.916 + switch(type) { 1.917 + case CKA_CLASS: 1.918 + return &ckcapi_certClassItem; 1.919 + case CKA_TOKEN: 1.920 + return &ckcapi_trueItem; 1.921 + case CKA_MODIFIABLE: 1.922 + case CKA_PRIVATE: 1.923 + return &ckcapi_falseItem; 1.924 + case CKA_CERTIFICATE_TYPE: 1.925 + return &ckcapi_x509Item; 1.926 + case CKA_LABEL: 1.927 + if (0 == io->u.cert.label.size) { 1.928 + ckcapi_FetchLabel(io); 1.929 + } 1.930 + return &io->u.cert.label; 1.931 + case CKA_SUBJECT: 1.932 + if (0 == io->u.cert.subject.size) { 1.933 + io->u.cert.subject.data = certContext->pCertInfo->Subject.pbData; 1.934 + io->u.cert.subject.size = certContext->pCertInfo->Subject.cbData; 1.935 + } 1.936 + return &io->u.cert.subject; 1.937 + case CKA_ISSUER: 1.938 + if (0 == io->u.cert.issuer.size) { 1.939 + io->u.cert.issuer.data = certContext->pCertInfo->Issuer.pbData; 1.940 + io->u.cert.issuer.size = certContext->pCertInfo->Issuer.cbData; 1.941 + } 1.942 + return &io->u.cert.issuer; 1.943 + case CKA_SERIAL_NUMBER: 1.944 + if (0 == io->u.cert.serial.size) { 1.945 + /* not exactly right. This should be the encoded serial number, but 1.946 + * it's the decoded serial number! */ 1.947 + ckcapi_FetchSerial(io); 1.948 + } 1.949 + return &io->u.cert.serial; 1.950 + case CKA_VALUE: 1.951 + if (0 == io->u.cert.derCert.size) { 1.952 + io->u.cert.derCert.data = io->u.cert.certContext->pbCertEncoded; 1.953 + io->u.cert.derCert.size = io->u.cert.certContext->cbCertEncoded; 1.954 + } 1.955 + return &io->u.cert.derCert; 1.956 + case CKA_ID: 1.957 + if (!io->u.cert.hasID) { 1.958 + return NULL; 1.959 + } 1.960 + if (0 == io->id.size) { 1.961 + ckcapi_FetchID(io); 1.962 + } 1.963 + return &io->id; 1.964 + default: 1.965 + break; 1.966 + } 1.967 + return NULL; 1.968 +} 1.969 + 1.970 +const NSSItem * 1.971 +ckcapi_FetchPubKeyAttribute 1.972 +( 1.973 + ckcapiInternalObject *io, 1.974 + CK_ATTRIBUTE_TYPE type 1.975 +) 1.976 +{ 1.977 + PRBool isCertType = (ckcapiCert == io->type); 1.978 + ckcapiKeyParams *kp = isCertType ? &io->u.cert.key : &io->u.key.key; 1.979 + 1.980 + switch(type) { 1.981 + case CKA_CLASS: 1.982 + return &ckcapi_pubKeyClassItem; 1.983 + case CKA_TOKEN: 1.984 + case CKA_LOCAL: 1.985 + case CKA_ENCRYPT: 1.986 + case CKA_VERIFY: 1.987 + case CKA_VERIFY_RECOVER: 1.988 + return &ckcapi_trueItem; 1.989 + case CKA_PRIVATE: 1.990 + case CKA_MODIFIABLE: 1.991 + case CKA_DERIVE: 1.992 + case CKA_WRAP: 1.993 + return &ckcapi_falseItem; 1.994 + case CKA_KEY_TYPE: 1.995 + return &ckcapi_rsaItem; 1.996 + case CKA_LABEL: 1.997 + if (!isCertType) { 1.998 + return &ckcapi_emptyItem; 1.999 + } 1.1000 + if (0 == io->u.cert.label.size) { 1.1001 + ckcapi_FetchLabel(io); 1.1002 + } 1.1003 + return &io->u.cert.label; 1.1004 + case CKA_SUBJECT: 1.1005 + if (!isCertType) { 1.1006 + return &ckcapi_emptyItem; 1.1007 + } 1.1008 + if (0 == io->u.cert.subject.size) { 1.1009 + PCCERT_CONTEXT certContext= io->u.cert.certContext; 1.1010 + io->u.cert.subject.data = certContext->pCertInfo->Subject.pbData; 1.1011 + io->u.cert.subject.size = certContext->pCertInfo->Subject.cbData; 1.1012 + } 1.1013 + return &io->u.cert.subject; 1.1014 + case CKA_MODULUS: 1.1015 + if (0 == kp->modulus.size) { 1.1016 + ckcapi_PopulateModulusExponent(io); 1.1017 + } 1.1018 + return &kp->modulus; 1.1019 + case CKA_PUBLIC_EXPONENT: 1.1020 + if (0 == kp->modulus.size) { 1.1021 + ckcapi_PopulateModulusExponent(io); 1.1022 + } 1.1023 + return &kp->exponent; 1.1024 + case CKA_ID: 1.1025 + if (0 == io->id.size) { 1.1026 + ckcapi_FetchID(io); 1.1027 + } 1.1028 + return &io->id; 1.1029 + default: 1.1030 + break; 1.1031 + } 1.1032 + return NULL; 1.1033 +} 1.1034 + 1.1035 +const NSSItem * 1.1036 +ckcapi_FetchPrivKeyAttribute 1.1037 +( 1.1038 + ckcapiInternalObject *io, 1.1039 + CK_ATTRIBUTE_TYPE type 1.1040 +) 1.1041 +{ 1.1042 + PRBool isCertType = (ckcapiCert == io->type); 1.1043 + ckcapiKeyParams *kp = isCertType ? &io->u.cert.key : &io->u.key.key; 1.1044 + 1.1045 + switch(type) { 1.1046 + case CKA_CLASS: 1.1047 + return &ckcapi_privKeyClassItem; 1.1048 + case CKA_TOKEN: 1.1049 + case CKA_LOCAL: 1.1050 + case CKA_SIGN: 1.1051 + case CKA_DECRYPT: 1.1052 + case CKA_SIGN_RECOVER: 1.1053 + return &ckcapi_trueItem; 1.1054 + case CKA_SENSITIVE: 1.1055 + case CKA_PRIVATE: /* should move in the future */ 1.1056 + case CKA_MODIFIABLE: 1.1057 + case CKA_DERIVE: 1.1058 + case CKA_UNWRAP: 1.1059 + case CKA_EXTRACTABLE: /* will probably move in the future */ 1.1060 + case CKA_ALWAYS_SENSITIVE: 1.1061 + case CKA_NEVER_EXTRACTABLE: 1.1062 + return &ckcapi_falseItem; 1.1063 + case CKA_KEY_TYPE: 1.1064 + return &ckcapi_rsaItem; 1.1065 + case CKA_LABEL: 1.1066 + if (!isCertType) { 1.1067 + return &ckcapi_emptyItem; 1.1068 + } 1.1069 + if (0 == io->u.cert.label.size) { 1.1070 + ckcapi_FetchLabel(io); 1.1071 + } 1.1072 + return &io->u.cert.label; 1.1073 + case CKA_SUBJECT: 1.1074 + if (!isCertType) { 1.1075 + return &ckcapi_emptyItem; 1.1076 + } 1.1077 + if (0 == io->u.cert.subject.size) { 1.1078 + PCCERT_CONTEXT certContext= io->u.cert.certContext; 1.1079 + io->u.cert.subject.data = certContext->pCertInfo->Subject.pbData; 1.1080 + io->u.cert.subject.size = certContext->pCertInfo->Subject.cbData; 1.1081 + } 1.1082 + return &io->u.cert.subject; 1.1083 + case CKA_MODULUS: 1.1084 + if (0 == kp->modulus.size) { 1.1085 + ckcapi_PopulateModulusExponent(io); 1.1086 + } 1.1087 + return &kp->modulus; 1.1088 + case CKA_PUBLIC_EXPONENT: 1.1089 + if (0 == kp->modulus.size) { 1.1090 + ckcapi_PopulateModulusExponent(io); 1.1091 + } 1.1092 + return &kp->exponent; 1.1093 + case CKA_PRIVATE_EXPONENT: 1.1094 + if (0 == kp->privateExponent.size) { 1.1095 + ckcapi_FetchPrivateKey(io); 1.1096 + } 1.1097 + return &kp->privateExponent; 1.1098 + case CKA_PRIME_1: 1.1099 + if (0 == kp->privateExponent.size) { 1.1100 + ckcapi_FetchPrivateKey(io); 1.1101 + } 1.1102 + return &kp->prime1; 1.1103 + case CKA_PRIME_2: 1.1104 + if (0 == kp->privateExponent.size) { 1.1105 + ckcapi_FetchPrivateKey(io); 1.1106 + } 1.1107 + return &kp->prime2; 1.1108 + case CKA_EXPONENT_1: 1.1109 + if (0 == kp->privateExponent.size) { 1.1110 + ckcapi_FetchPrivateKey(io); 1.1111 + } 1.1112 + return &kp->exponent1; 1.1113 + case CKA_EXPONENT_2: 1.1114 + if (0 == kp->privateExponent.size) { 1.1115 + ckcapi_FetchPrivateKey(io); 1.1116 + } 1.1117 + return &kp->exponent2; 1.1118 + case CKA_COEFFICIENT: 1.1119 + if (0 == kp->privateExponent.size) { 1.1120 + ckcapi_FetchPrivateKey(io); 1.1121 + } 1.1122 + return &kp->coefficient; 1.1123 + case CKA_ID: 1.1124 + if (0 == io->id.size) { 1.1125 + ckcapi_FetchID(io); 1.1126 + } 1.1127 + return &io->id; 1.1128 + default: 1.1129 + return NULL; 1.1130 + } 1.1131 +} 1.1132 + 1.1133 +const NSSItem * 1.1134 +nss_ckcapi_FetchAttribute 1.1135 +( 1.1136 + ckcapiInternalObject *io, 1.1137 + CK_ATTRIBUTE_TYPE type 1.1138 +) 1.1139 +{ 1.1140 + CK_ULONG i; 1.1141 + 1.1142 + if (io->type == ckcapiRaw) { 1.1143 + for( i = 0; i < io->u.raw.n; i++ ) { 1.1144 + if( type == io->u.raw.types[i] ) { 1.1145 + return &io->u.raw.items[i]; 1.1146 + } 1.1147 + } 1.1148 + return NULL; 1.1149 + } 1.1150 + /* deal with the common attributes */ 1.1151 + switch (io->objClass) { 1.1152 + case CKO_CERTIFICATE: 1.1153 + return ckcapi_FetchCertAttribute(io, type); 1.1154 + case CKO_PRIVATE_KEY: 1.1155 + return ckcapi_FetchPrivKeyAttribute(io, type); 1.1156 + case CKO_PUBLIC_KEY: 1.1157 + return ckcapi_FetchPubKeyAttribute(io, type); 1.1158 + } 1.1159 + return NULL; 1.1160 +} 1.1161 + 1.1162 +/* 1.1163 + * check to see if the certificate already exists 1.1164 + */ 1.1165 +static PRBool 1.1166 +ckcapi_cert_exists( 1.1167 + NSSItem *value, 1.1168 + ckcapiInternalObject **io 1.1169 +) 1.1170 +{ 1.1171 + int count,i; 1.1172 + PRUint32 size = 0; 1.1173 + ckcapiInternalObject **listp = NULL; 1.1174 + CK_ATTRIBUTE myTemplate[2]; 1.1175 + CK_OBJECT_CLASS cert_class = CKO_CERTIFICATE; 1.1176 + CK_ULONG templateCount = 2; 1.1177 + CK_RV error; 1.1178 + PRBool found = PR_FALSE; 1.1179 + 1.1180 + myTemplate[0].type = CKA_CLASS; 1.1181 + myTemplate[0].pValue = &cert_class; 1.1182 + myTemplate[0].ulValueLen = sizeof(cert_class); 1.1183 + myTemplate[1].type = CKA_VALUE; 1.1184 + myTemplate[1].pValue = value->data; 1.1185 + myTemplate[1].ulValueLen = value->size; 1.1186 + 1.1187 + count = nss_ckcapi_collect_all_certs(myTemplate, templateCount, &listp, 1.1188 + &size, 0, &error); 1.1189 + 1.1190 + /* free them */ 1.1191 + if (count > 1) { 1.1192 + *io = listp[0]; 1.1193 + found = PR_TRUE; 1.1194 + } 1.1195 + 1.1196 + for (i=1; i < count; i++) { 1.1197 + nss_ckcapi_DestroyInternalObject(listp[i]); 1.1198 + } 1.1199 + nss_ZFreeIf(listp); 1.1200 + return found; 1.1201 +} 1.1202 + 1.1203 +static PRBool 1.1204 +ckcapi_cert_hasEmail 1.1205 +( 1.1206 + PCCERT_CONTEXT certContext 1.1207 +) 1.1208 +{ 1.1209 + int count; 1.1210 + 1.1211 + count = CertGetNameString(certContext, CERT_NAME_EMAIL_TYPE, 1.1212 + 0, NULL, NULL, 0); 1.1213 + 1.1214 + return count > 1 ? PR_TRUE : PR_FALSE; 1.1215 +} 1.1216 + 1.1217 +static PRBool 1.1218 +ckcapi_cert_isRoot 1.1219 +( 1.1220 + PCCERT_CONTEXT certContext 1.1221 +) 1.1222 +{ 1.1223 + return CertCompareCertificateName(certContext->dwCertEncodingType, 1.1224 + &certContext->pCertInfo->Issuer, &certContext->pCertInfo->Subject); 1.1225 +} 1.1226 + 1.1227 +static PRBool 1.1228 +ckcapi_cert_isCA 1.1229 +( 1.1230 + PCCERT_CONTEXT certContext 1.1231 +) 1.1232 +{ 1.1233 + PCERT_EXTENSION extension; 1.1234 + CERT_BASIC_CONSTRAINTS2_INFO basicInfo; 1.1235 + DWORD size = sizeof(basicInfo); 1.1236 + BOOL rc; 1.1237 + 1.1238 + extension = CertFindExtension (szOID_BASIC_CONSTRAINTS, 1.1239 + certContext->pCertInfo->cExtension, 1.1240 + certContext->pCertInfo->rgExtension); 1.1241 + if ((PCERT_EXTENSION) NULL == extension ) { 1.1242 + return PR_FALSE; 1.1243 + } 1.1244 + rc = CryptDecodeObject(X509_ASN_ENCODING, szOID_BASIC_CONSTRAINTS2, 1.1245 + extension->Value.pbData, extension->Value.cbData, 1.1246 + 0, &basicInfo, &size); 1.1247 + if (!rc) { 1.1248 + return PR_FALSE; 1.1249 + } 1.1250 + return (PRBool) basicInfo.fCA; 1.1251 +} 1.1252 + 1.1253 +static CRYPT_KEY_PROV_INFO * 1.1254 +ckcapi_cert_getPrivateKeyInfo 1.1255 +( 1.1256 + PCCERT_CONTEXT certContext, 1.1257 + NSSItem *keyID 1.1258 +) 1.1259 +{ 1.1260 + BOOL rc; 1.1261 + CRYPT_HASH_BLOB msKeyID; 1.1262 + DWORD size = 0; 1.1263 + CRYPT_KEY_PROV_INFO *prov = NULL; 1.1264 + 1.1265 + msKeyID.cbData = keyID->size; 1.1266 + msKeyID.pbData = keyID->data; 1.1267 + 1.1268 + rc = CryptGetKeyIdentifierProperty( 1.1269 + &msKeyID, 1.1270 + CERT_KEY_PROV_INFO_PROP_ID, 1.1271 + 0, NULL, NULL, NULL, &size); 1.1272 + if (!rc) { 1.1273 + return (CRYPT_KEY_PROV_INFO *)NULL; 1.1274 + } 1.1275 + prov = (CRYPT_KEY_PROV_INFO *)nss_ZAlloc(NULL, size); 1.1276 + if ((CRYPT_KEY_PROV_INFO *)prov == NULL) { 1.1277 + return (CRYPT_KEY_PROV_INFO *) NULL; 1.1278 + } 1.1279 + rc = CryptGetKeyIdentifierProperty( 1.1280 + &msKeyID, 1.1281 + CERT_KEY_PROV_INFO_PROP_ID, 1.1282 + 0, NULL, NULL, prov, &size); 1.1283 + if (!rc) { 1.1284 + nss_ZFreeIf(prov); 1.1285 + return (CRYPT_KEY_PROV_INFO *)NULL; 1.1286 + } 1.1287 + 1.1288 + return prov; 1.1289 +} 1.1290 + 1.1291 +static CRYPT_KEY_PROV_INFO * 1.1292 +ckcapi_cert_getProvInfo 1.1293 +( 1.1294 + ckcapiInternalObject *io 1.1295 +) 1.1296 +{ 1.1297 + BOOL rc; 1.1298 + DWORD size = 0; 1.1299 + CRYPT_KEY_PROV_INFO *prov = NULL; 1.1300 + 1.1301 + rc = CertGetCertificateContextProperty( 1.1302 + io->u.cert.certContext, 1.1303 + CERT_KEY_PROV_INFO_PROP_ID, 1.1304 + NULL, &size); 1.1305 + if (!rc) { 1.1306 + return (CRYPT_KEY_PROV_INFO *)NULL; 1.1307 + } 1.1308 + prov = (CRYPT_KEY_PROV_INFO *)nss_ZAlloc(NULL, size); 1.1309 + if ((CRYPT_KEY_PROV_INFO *)prov == NULL) { 1.1310 + return (CRYPT_KEY_PROV_INFO *) NULL; 1.1311 + } 1.1312 + rc = CertGetCertificateContextProperty( 1.1313 + io->u.cert.certContext, 1.1314 + CERT_KEY_PROV_INFO_PROP_ID, 1.1315 + prov, &size); 1.1316 + if (!rc) { 1.1317 + nss_ZFreeIf(prov); 1.1318 + return (CRYPT_KEY_PROV_INFO *)NULL; 1.1319 + } 1.1320 + 1.1321 + return prov; 1.1322 +} 1.1323 + 1.1324 +/* forward declaration */ 1.1325 +static void 1.1326 +ckcapi_removeObjectFromHash 1.1327 +( 1.1328 + ckcapiInternalObject *io 1.1329 +); 1.1330 + 1.1331 +/* 1.1332 + * Finalize - unneeded 1.1333 + * Destroy 1.1334 + * IsTokenObject - CK_TRUE 1.1335 + * GetAttributeCount 1.1336 + * GetAttributeTypes 1.1337 + * GetAttributeSize 1.1338 + * GetAttribute 1.1339 + * SetAttribute 1.1340 + * GetObjectSize 1.1341 + */ 1.1342 + 1.1343 +static CK_RV 1.1344 +ckcapi_mdObject_Destroy 1.1345 +( 1.1346 + NSSCKMDObject *mdObject, 1.1347 + NSSCKFWObject *fwObject, 1.1348 + NSSCKMDSession *mdSession, 1.1349 + NSSCKFWSession *fwSession, 1.1350 + NSSCKMDToken *mdToken, 1.1351 + NSSCKFWToken *fwToken, 1.1352 + NSSCKMDInstance *mdInstance, 1.1353 + NSSCKFWInstance *fwInstance 1.1354 +) 1.1355 +{ 1.1356 + ckcapiInternalObject *io = (ckcapiInternalObject *)mdObject->etc; 1.1357 + CK_OBJECT_CLASS objClass; 1.1358 + BOOL rc; 1.1359 + DWORD provType; 1.1360 + DWORD msError; 1.1361 + PRBool isCertType = (PRBool)(ckcapiCert == io->type); 1.1362 + HCERTSTORE hStore = 0; 1.1363 + 1.1364 + if (ckcapiRaw == io->type) { 1.1365 + /* there is not 'object write protected' error, use the next best thing */ 1.1366 + return CKR_TOKEN_WRITE_PROTECTED; 1.1367 + } 1.1368 + 1.1369 + objClass = io->objClass; 1.1370 + if (CKO_CERTIFICATE == objClass) { 1.1371 + PCCERT_CONTEXT certContext; 1.1372 + 1.1373 + /* get the store */ 1.1374 + hStore = CertOpenSystemStore(0, io->u.cert.certStore); 1.1375 + if (0 == hStore) { 1.1376 + rc = 0; 1.1377 + goto loser; 1.1378 + } 1.1379 + certContext = CertFindCertificateInStore(hStore, X509_ASN_ENCODING, 0, 1.1380 + CERT_FIND_EXISTING, io->u.cert.certContext, NULL); 1.1381 + if ((PCCERT_CONTEXT)NULL == certContext) { 1.1382 + rc = 0; 1.1383 + goto loser; 1.1384 + } 1.1385 + rc = CertDeleteCertificateFromStore(certContext); 1.1386 + } else { 1.1387 + char *provName = NULL; 1.1388 + char *containerName = NULL; 1.1389 + HCRYPTPROV hProv; 1.1390 + CRYPT_HASH_BLOB msKeyID; 1.1391 + 1.1392 + if (0 == io->id.size) { 1.1393 + ckcapi_FetchID(io); 1.1394 + } 1.1395 + 1.1396 + if (isCertType) { 1.1397 + CRYPT_KEY_PROV_INFO * provInfo = ckcapi_cert_getProvInfo(io); 1.1398 + provName = nss_ckcapi_WideToUTF8(provInfo->pwszProvName); 1.1399 + containerName = nss_ckcapi_WideToUTF8(provInfo->pwszContainerName); 1.1400 + provType = provInfo->dwProvType; 1.1401 + nss_ZFreeIf(provInfo); 1.1402 + } else { 1.1403 + provName = io->u.key.provName; 1.1404 + containerName = io->u.key.containerName; 1.1405 + provType = io->u.key.provInfo.dwProvType; 1.1406 + io->u.key.provName = NULL; 1.1407 + io->u.key.containerName = NULL; 1.1408 + } 1.1409 + /* first remove the key id pointer */ 1.1410 + msKeyID.cbData = io->id.size; 1.1411 + msKeyID.pbData = io->id.data; 1.1412 + rc = CryptSetKeyIdentifierProperty(&msKeyID, 1.1413 + CERT_KEY_PROV_INFO_PROP_ID, CRYPT_KEYID_DELETE_FLAG, NULL, NULL, NULL); 1.1414 + if (rc) { 1.1415 + rc = CryptAcquireContext(&hProv, containerName, provName, provType, 1.1416 + CRYPT_DELETEKEYSET); 1.1417 + } 1.1418 + nss_ZFreeIf(provName); 1.1419 + nss_ZFreeIf(containerName); 1.1420 + } 1.1421 +loser: 1.1422 + 1.1423 + if (hStore) { 1.1424 + CertCloseStore(hStore, 0); 1.1425 + } 1.1426 + if (!rc) { 1.1427 + msError = GetLastError(); 1.1428 + return CKR_GENERAL_ERROR; 1.1429 + } 1.1430 + 1.1431 + /* remove it from the hash */ 1.1432 + ckcapi_removeObjectFromHash(io); 1.1433 + 1.1434 + /* free the puppy.. */ 1.1435 + nss_ckcapi_DestroyInternalObject(io); 1.1436 + return CKR_OK; 1.1437 +} 1.1438 + 1.1439 +static CK_BBOOL 1.1440 +ckcapi_mdObject_IsTokenObject 1.1441 +( 1.1442 + NSSCKMDObject *mdObject, 1.1443 + NSSCKFWObject *fwObject, 1.1444 + NSSCKMDSession *mdSession, 1.1445 + NSSCKFWSession *fwSession, 1.1446 + NSSCKMDToken *mdToken, 1.1447 + NSSCKFWToken *fwToken, 1.1448 + NSSCKMDInstance *mdInstance, 1.1449 + NSSCKFWInstance *fwInstance 1.1450 +) 1.1451 +{ 1.1452 + return CK_TRUE; 1.1453 +} 1.1454 + 1.1455 +static CK_ULONG 1.1456 +ckcapi_mdObject_GetAttributeCount 1.1457 +( 1.1458 + NSSCKMDObject *mdObject, 1.1459 + NSSCKFWObject *fwObject, 1.1460 + NSSCKMDSession *mdSession, 1.1461 + NSSCKFWSession *fwSession, 1.1462 + NSSCKMDToken *mdToken, 1.1463 + NSSCKFWToken *fwToken, 1.1464 + NSSCKMDInstance *mdInstance, 1.1465 + NSSCKFWInstance *fwInstance, 1.1466 + CK_RV *pError 1.1467 +) 1.1468 +{ 1.1469 + ckcapiInternalObject *io = (ckcapiInternalObject *)mdObject->etc; 1.1470 + 1.1471 + if (ckcapiRaw == io->type) { 1.1472 + return io->u.raw.n; 1.1473 + } 1.1474 + switch (io->objClass) { 1.1475 + case CKO_CERTIFICATE: 1.1476 + return certAttrsCount; 1.1477 + case CKO_PUBLIC_KEY: 1.1478 + return pubKeyAttrsCount; 1.1479 + case CKO_PRIVATE_KEY: 1.1480 + return privKeyAttrsCount; 1.1481 + default: 1.1482 + break; 1.1483 + } 1.1484 + return 0; 1.1485 +} 1.1486 + 1.1487 +static CK_RV 1.1488 +ckcapi_mdObject_GetAttributeTypes 1.1489 +( 1.1490 + NSSCKMDObject *mdObject, 1.1491 + NSSCKFWObject *fwObject, 1.1492 + NSSCKMDSession *mdSession, 1.1493 + NSSCKFWSession *fwSession, 1.1494 + NSSCKMDToken *mdToken, 1.1495 + NSSCKFWToken *fwToken, 1.1496 + NSSCKMDInstance *mdInstance, 1.1497 + NSSCKFWInstance *fwInstance, 1.1498 + CK_ATTRIBUTE_TYPE_PTR typeArray, 1.1499 + CK_ULONG ulCount 1.1500 +) 1.1501 +{ 1.1502 + ckcapiInternalObject *io = (ckcapiInternalObject *)mdObject->etc; 1.1503 + CK_ULONG i; 1.1504 + CK_RV error = CKR_OK; 1.1505 + const CK_ATTRIBUTE_TYPE *attrs = NULL; 1.1506 + CK_ULONG size = ckcapi_mdObject_GetAttributeCount( 1.1507 + mdObject, fwObject, mdSession, fwSession, 1.1508 + mdToken, fwToken, mdInstance, fwInstance, &error); 1.1509 + 1.1510 + if( size != ulCount ) { 1.1511 + return CKR_BUFFER_TOO_SMALL; 1.1512 + } 1.1513 + if (io->type == ckcapiRaw) { 1.1514 + attrs = io->u.raw.types; 1.1515 + } else switch(io->objClass) { 1.1516 + case CKO_CERTIFICATE: 1.1517 + attrs = certAttrs; 1.1518 + break; 1.1519 + case CKO_PUBLIC_KEY: 1.1520 + attrs = pubKeyAttrs; 1.1521 + break; 1.1522 + case CKO_PRIVATE_KEY: 1.1523 + attrs = privKeyAttrs; 1.1524 + break; 1.1525 + default: 1.1526 + return CKR_OK; 1.1527 + } 1.1528 + 1.1529 + for( i = 0; i < size; i++) { 1.1530 + typeArray[i] = attrs[i]; 1.1531 + } 1.1532 + 1.1533 + return CKR_OK; 1.1534 +} 1.1535 + 1.1536 +static CK_ULONG 1.1537 +ckcapi_mdObject_GetAttributeSize 1.1538 +( 1.1539 + NSSCKMDObject *mdObject, 1.1540 + NSSCKFWObject *fwObject, 1.1541 + NSSCKMDSession *mdSession, 1.1542 + NSSCKFWSession *fwSession, 1.1543 + NSSCKMDToken *mdToken, 1.1544 + NSSCKFWToken *fwToken, 1.1545 + NSSCKMDInstance *mdInstance, 1.1546 + NSSCKFWInstance *fwInstance, 1.1547 + CK_ATTRIBUTE_TYPE attribute, 1.1548 + CK_RV *pError 1.1549 +) 1.1550 +{ 1.1551 + ckcapiInternalObject *io = (ckcapiInternalObject *)mdObject->etc; 1.1552 + 1.1553 + const NSSItem *b; 1.1554 + 1.1555 + b = nss_ckcapi_FetchAttribute(io, attribute); 1.1556 + 1.1557 + if ((const NSSItem *)NULL == b) { 1.1558 + *pError = CKR_ATTRIBUTE_TYPE_INVALID; 1.1559 + return 0; 1.1560 + } 1.1561 + return b->size; 1.1562 +} 1.1563 + 1.1564 +static CK_RV 1.1565 +ckcapi_mdObject_SetAttribute 1.1566 +( 1.1567 + NSSCKMDObject *mdObject, 1.1568 + NSSCKFWObject *fwObject, 1.1569 + NSSCKMDSession *mdSession, 1.1570 + NSSCKFWSession *fwSession, 1.1571 + NSSCKMDToken *mdToken, 1.1572 + NSSCKFWToken *fwToken, 1.1573 + NSSCKMDInstance *mdInstance, 1.1574 + NSSCKFWInstance *fwInstance, 1.1575 + CK_ATTRIBUTE_TYPE attribute, 1.1576 + NSSItem *value 1.1577 +) 1.1578 +{ 1.1579 + return CKR_OK; 1.1580 +} 1.1581 + 1.1582 +static NSSCKFWItem 1.1583 +ckcapi_mdObject_GetAttribute 1.1584 +( 1.1585 + NSSCKMDObject *mdObject, 1.1586 + NSSCKFWObject *fwObject, 1.1587 + NSSCKMDSession *mdSession, 1.1588 + NSSCKFWSession *fwSession, 1.1589 + NSSCKMDToken *mdToken, 1.1590 + NSSCKFWToken *fwToken, 1.1591 + NSSCKMDInstance *mdInstance, 1.1592 + NSSCKFWInstance *fwInstance, 1.1593 + CK_ATTRIBUTE_TYPE attribute, 1.1594 + CK_RV *pError 1.1595 +) 1.1596 +{ 1.1597 + NSSCKFWItem mdItem; 1.1598 + ckcapiInternalObject *io = (ckcapiInternalObject *)mdObject->etc; 1.1599 + 1.1600 + mdItem.needsFreeing = PR_FALSE; 1.1601 + mdItem.item = (NSSItem*)nss_ckcapi_FetchAttribute(io, attribute); 1.1602 + 1.1603 + if ((NSSItem *)NULL == mdItem.item) { 1.1604 + *pError = CKR_ATTRIBUTE_TYPE_INVALID; 1.1605 + } 1.1606 + 1.1607 + return mdItem; 1.1608 +} 1.1609 + 1.1610 +static CK_ULONG 1.1611 +ckcapi_mdObject_GetObjectSize 1.1612 +( 1.1613 + NSSCKMDObject *mdObject, 1.1614 + NSSCKFWObject *fwObject, 1.1615 + NSSCKMDSession *mdSession, 1.1616 + NSSCKFWSession *fwSession, 1.1617 + NSSCKMDToken *mdToken, 1.1618 + NSSCKFWToken *fwToken, 1.1619 + NSSCKMDInstance *mdInstance, 1.1620 + NSSCKFWInstance *fwInstance, 1.1621 + CK_RV *pError 1.1622 +) 1.1623 +{ 1.1624 + ckcapiInternalObject *io = (ckcapiInternalObject *)mdObject->etc; 1.1625 + CK_ULONG rv = 1; 1.1626 + 1.1627 + /* size is irrelevant to this token */ 1.1628 + return rv; 1.1629 +} 1.1630 + 1.1631 +static const NSSCKMDObject 1.1632 +ckcapi_prototype_mdObject = { 1.1633 + (void *)NULL, /* etc */ 1.1634 + NULL, /* Finalize */ 1.1635 + ckcapi_mdObject_Destroy, 1.1636 + ckcapi_mdObject_IsTokenObject, 1.1637 + ckcapi_mdObject_GetAttributeCount, 1.1638 + ckcapi_mdObject_GetAttributeTypes, 1.1639 + ckcapi_mdObject_GetAttributeSize, 1.1640 + ckcapi_mdObject_GetAttribute, 1.1641 + NULL, /* FreeAttribute */ 1.1642 + ckcapi_mdObject_SetAttribute, 1.1643 + ckcapi_mdObject_GetObjectSize, 1.1644 + (void *)NULL /* null terminator */ 1.1645 +}; 1.1646 + 1.1647 +static nssHash *ckcapiInternalObjectHash = NULL; 1.1648 + 1.1649 +NSS_IMPLEMENT NSSCKMDObject * 1.1650 +nss_ckcapi_CreateMDObject 1.1651 +( 1.1652 + NSSArena *arena, 1.1653 + ckcapiInternalObject *io, 1.1654 + CK_RV *pError 1.1655 +) 1.1656 +{ 1.1657 + if ((nssHash *)NULL == ckcapiInternalObjectHash) { 1.1658 + ckcapiInternalObjectHash = nssHash_CreateItem(NULL, 10); 1.1659 + } 1.1660 + if (ckcapiCert == io->type) { 1.1661 + /* the hash key, not a cryptographic key */ 1.1662 + NSSItem *key = &io->hashKey; 1.1663 + ckcapiInternalObject *old_o = NULL; 1.1664 + 1.1665 + if (key->size == 0) { 1.1666 + ckcapi_FetchHashKey(io); 1.1667 + } 1.1668 + old_o = (ckcapiInternalObject *) 1.1669 + nssHash_Lookup(ckcapiInternalObjectHash, key); 1.1670 + if (!old_o) { 1.1671 + nssHash_Add(ckcapiInternalObjectHash, key, io); 1.1672 + } else if (old_o != io) { 1.1673 + nss_ckcapi_DestroyInternalObject(io); 1.1674 + io = old_o; 1.1675 + } 1.1676 + } 1.1677 + 1.1678 + if ( (void*)NULL == io->mdObject.etc) { 1.1679 + (void) nsslibc_memcpy(&io->mdObject,&ckcapi_prototype_mdObject, 1.1680 + sizeof(ckcapi_prototype_mdObject)); 1.1681 + io->mdObject.etc = (void *)io; 1.1682 + } 1.1683 + return &io->mdObject; 1.1684 +} 1.1685 + 1.1686 +static void 1.1687 +ckcapi_removeObjectFromHash 1.1688 +( 1.1689 + ckcapiInternalObject *io 1.1690 +) 1.1691 +{ 1.1692 + NSSItem *key = &io->hashKey; 1.1693 + 1.1694 + if ((nssHash *)NULL == ckcapiInternalObjectHash) { 1.1695 + return; 1.1696 + } 1.1697 + if (key->size == 0) { 1.1698 + ckcapi_FetchHashKey(io); 1.1699 + } 1.1700 + nssHash_Remove(ckcapiInternalObjectHash, key); 1.1701 + return; 1.1702 +} 1.1703 + 1.1704 +void 1.1705 +nss_ckcapi_DestroyInternalObject 1.1706 +( 1.1707 + ckcapiInternalObject *io 1.1708 +) 1.1709 +{ 1.1710 + switch (io->type) { 1.1711 + case ckcapiRaw: 1.1712 + return; 1.1713 + case ckcapiCert: 1.1714 + CertFreeCertificateContext(io->u.cert.certContext); 1.1715 + nss_ZFreeIf(io->u.cert.labelData); 1.1716 + nss_ZFreeIf(io->u.cert.key.privateKey); 1.1717 + nss_ZFreeIf(io->u.cert.key.pubKey); 1.1718 + nss_ZFreeIf(io->idData); 1.1719 + break; 1.1720 + case ckcapiBareKey: 1.1721 + nss_ZFreeIf(io->u.key.provInfo.pwszContainerName); 1.1722 + nss_ZFreeIf(io->u.key.provInfo.pwszProvName); 1.1723 + nss_ZFreeIf(io->u.key.provName); 1.1724 + nss_ZFreeIf(io->u.key.containerName); 1.1725 + nss_ZFreeIf(io->u.key.key.privateKey); 1.1726 + nss_ZFreeIf(io->u.key.key.pubKey); 1.1727 + if (0 != io->u.key.hProv) { 1.1728 + CryptReleaseContext(io->u.key.hProv, 0); 1.1729 + } 1.1730 + nss_ZFreeIf(io->idData); 1.1731 + break; 1.1732 + } 1.1733 + nss_ZFreeIf(io); 1.1734 + return; 1.1735 +} 1.1736 + 1.1737 +static ckcapiInternalObject * 1.1738 +nss_ckcapi_CreateCertificate 1.1739 +( 1.1740 + NSSCKFWSession *fwSession, 1.1741 + CK_ATTRIBUTE_PTR pTemplate, 1.1742 + CK_ULONG ulAttributeCount, 1.1743 + CK_RV *pError 1.1744 +) 1.1745 +{ 1.1746 + NSSItem value; 1.1747 + NSSItem keyID; 1.1748 + char *storeStr; 1.1749 + ckcapiInternalObject *io = NULL; 1.1750 + PCCERT_CONTEXT certContext = NULL; 1.1751 + PCCERT_CONTEXT storedCertContext = NULL; 1.1752 + CRYPT_KEY_PROV_INFO *prov_info = NULL; 1.1753 + char *nickname = NULL; 1.1754 + HCERTSTORE hStore = 0; 1.1755 + DWORD msError = 0; 1.1756 + PRBool hasID; 1.1757 + CK_RV dummy; 1.1758 + BOOL rc; 1.1759 + 1.1760 + *pError = nss_ckcapi_GetAttribute(CKA_VALUE, pTemplate, 1.1761 + ulAttributeCount, &value); 1.1762 + 1.1763 + if (CKR_OK != *pError) { 1.1764 + return (ckcapiInternalObject *)NULL; 1.1765 + } 1.1766 + 1.1767 + *pError = nss_ckcapi_GetAttribute(CKA_ID, pTemplate, 1.1768 + ulAttributeCount, &keyID); 1.1769 + 1.1770 + if (CKR_OK != *pError) { 1.1771 + return (ckcapiInternalObject *)NULL; 1.1772 + } 1.1773 + 1.1774 + if (ckcapi_cert_exists(&value, &io)) { 1.1775 + return io; 1.1776 + } 1.1777 + 1.1778 + /* OK, we are creating a new one, figure out what store it belongs to.. 1.1779 + * first get a certContext handle.. */ 1.1780 + certContext = CertCreateCertificateContext(X509_ASN_ENCODING, 1.1781 + value.data, value.size); 1.1782 + if ((PCCERT_CONTEXT) NULL == certContext) { 1.1783 + msError = GetLastError(); 1.1784 + *pError = CKR_ATTRIBUTE_VALUE_INVALID; 1.1785 + goto loser; 1.1786 + } 1.1787 + 1.1788 + /* do we have a private key laying around... */ 1.1789 + prov_info = ckcapi_cert_getPrivateKeyInfo(certContext, &keyID); 1.1790 + if (prov_info) { 1.1791 + CRYPT_DATA_BLOB msKeyID; 1.1792 + storeStr = "My"; 1.1793 + hasID = PR_TRUE; 1.1794 + rc = CertSetCertificateContextProperty(certContext, 1.1795 + CERT_KEY_PROV_INFO_PROP_ID, 1.1796 + 0, prov_info); 1.1797 + nss_ZFreeIf(prov_info); 1.1798 + if (!rc) { 1.1799 + msError = GetLastError(); 1.1800 + *pError = CKR_DEVICE_ERROR; 1.1801 + goto loser; 1.1802 + } 1.1803 + msKeyID.cbData = keyID.size; 1.1804 + msKeyID.pbData = keyID.data; 1.1805 + rc = CertSetCertificateContextProperty(certContext, 1.1806 + CERT_KEY_IDENTIFIER_PROP_ID, 1.1807 + 0, &msKeyID); 1.1808 + if (!rc) { 1.1809 + msError = GetLastError(); 1.1810 + *pError = CKR_DEVICE_ERROR; 1.1811 + goto loser; 1.1812 + } 1.1813 + 1.1814 + /* does it look like a CA */ 1.1815 + } else if (ckcapi_cert_isCA(certContext)) { 1.1816 + storeStr = ckcapi_cert_isRoot(certContext) ? "CA" : "Root"; 1.1817 + /* does it look like an S/MIME cert */ 1.1818 + } else if (ckcapi_cert_hasEmail(certContext)) { 1.1819 + storeStr = "AddressBook"; 1.1820 + } else { 1.1821 + /* just pick a store */ 1.1822 + storeStr = "CA"; 1.1823 + } 1.1824 + 1.1825 + /* get the nickname, not an error if we can't find it */ 1.1826 + nickname = nss_ckcapi_GetStringAttribute(CKA_LABEL, pTemplate, 1.1827 + ulAttributeCount, &dummy); 1.1828 + if (nickname) { 1.1829 + LPWSTR nicknameUTF16 = NULL; 1.1830 + CRYPT_DATA_BLOB nicknameBlob; 1.1831 + 1.1832 + nicknameUTF16 = nss_ckcapi_UTF8ToWide(nickname); 1.1833 + nss_ZFreeIf(nickname); 1.1834 + nickname = NULL; 1.1835 + if ((LPWSTR)NULL == nicknameUTF16) { 1.1836 + *pError = CKR_HOST_MEMORY; 1.1837 + goto loser; 1.1838 + } 1.1839 + nicknameBlob.cbData = nss_ckcapi_WideSize(nicknameUTF16); 1.1840 + nicknameBlob.pbData = (BYTE *)nicknameUTF16; 1.1841 + rc = CertSetCertificateContextProperty(certContext, 1.1842 + CERT_FRIENDLY_NAME_PROP_ID, 0, &nicknameBlob); 1.1843 + nss_ZFreeIf(nicknameUTF16); 1.1844 + if (!rc) { 1.1845 + msError = GetLastError(); 1.1846 + *pError = CKR_DEVICE_ERROR; 1.1847 + goto loser; 1.1848 + } 1.1849 + } 1.1850 + 1.1851 + hStore = CertOpenSystemStore((HCRYPTPROV) NULL, storeStr); 1.1852 + if (0 == hStore) { 1.1853 + msError = GetLastError(); 1.1854 + *pError = CKR_DEVICE_ERROR; 1.1855 + goto loser; 1.1856 + } 1.1857 + 1.1858 + rc = CertAddCertificateContextToStore(hStore, certContext, 1.1859 + CERT_STORE_ADD_REPLACE_EXISTING_INHERIT_PROPERTIES, &storedCertContext); 1.1860 + CertFreeCertificateContext(certContext); 1.1861 + certContext = NULL; 1.1862 + CertCloseStore(hStore, 0); 1.1863 + hStore = 0; 1.1864 + if (!rc) { 1.1865 + msError = GetLastError(); 1.1866 + *pError = CKR_DEVICE_ERROR; 1.1867 + goto loser; 1.1868 + } 1.1869 + 1.1870 + io = nss_ZNEW(NULL, ckcapiInternalObject); 1.1871 + if ((ckcapiInternalObject *)NULL == io) { 1.1872 + *pError = CKR_HOST_MEMORY; 1.1873 + goto loser; 1.1874 + } 1.1875 + io->type = ckcapiCert; 1.1876 + io->objClass = CKO_CERTIFICATE; 1.1877 + io->u.cert.certContext = storedCertContext; 1.1878 + io->u.cert.hasID = hasID; 1.1879 + return io; 1.1880 + 1.1881 +loser: 1.1882 + if (certContext) { 1.1883 + CertFreeCertificateContext(certContext); 1.1884 + certContext = NULL; 1.1885 + } 1.1886 + if (storedCertContext) { 1.1887 + CertFreeCertificateContext(storedCertContext); 1.1888 + storedCertContext = NULL; 1.1889 + } 1.1890 + if (0 != hStore) { 1.1891 + CertCloseStore(hStore, 0); 1.1892 + } 1.1893 + return (ckcapiInternalObject *)NULL; 1.1894 + 1.1895 +} 1.1896 + 1.1897 +static char * 1.1898 +ckcapi_getDefaultProvider 1.1899 +( 1.1900 + CK_RV *pError 1.1901 +) 1.1902 +{ 1.1903 + char *name = NULL; 1.1904 + BOOL rc; 1.1905 + DWORD nameLength = 0; 1.1906 + 1.1907 + rc = CryptGetDefaultProvider(PROV_RSA_FULL, NULL, CRYPT_USER_DEFAULT, NULL, 1.1908 + &nameLength); 1.1909 + if (!rc) { 1.1910 + return (char *)NULL; 1.1911 + } 1.1912 + 1.1913 + name = nss_ZNEWARRAY(NULL, char, nameLength); 1.1914 + if ((char *)NULL == name ) { 1.1915 + return (char *)NULL; 1.1916 + } 1.1917 + rc = CryptGetDefaultProvider(PROV_RSA_FULL, NULL, CRYPT_USER_DEFAULT, name, 1.1918 + &nameLength); 1.1919 + if (!rc) { 1.1920 + nss_ZFreeIf(name); 1.1921 + return (char *)NULL; 1.1922 + } 1.1923 + 1.1924 + return name; 1.1925 +} 1.1926 + 1.1927 +static char * 1.1928 +ckcapi_getContainer 1.1929 +( 1.1930 + CK_RV *pError, 1.1931 + NSSItem *id 1.1932 +) 1.1933 +{ 1.1934 + RPC_STATUS rstat; 1.1935 + UUID uuid; 1.1936 + char *uuidStr; 1.1937 + char *container; 1.1938 + 1.1939 + rstat = UuidCreate(&uuid); 1.1940 + rstat = UuidToString(&uuid, &uuidStr); 1.1941 + 1.1942 + /* convert it from rcp memory to our own */ 1.1943 + container = nssUTF8_Duplicate(uuidStr, NULL); 1.1944 + RpcStringFree(&uuidStr); 1.1945 + 1.1946 + return container; 1.1947 +} 1.1948 + 1.1949 +static CK_RV 1.1950 +ckcapi_buildPrivateKeyBlob 1.1951 +( 1.1952 + NSSItem *keyBlob, 1.1953 + NSSItem *modulus, 1.1954 + NSSItem *publicExponent, 1.1955 + NSSItem *privateExponent, 1.1956 + NSSItem *prime1, 1.1957 + NSSItem *prime2, 1.1958 + NSSItem *exponent1, 1.1959 + NSSItem *exponent2, 1.1960 + NSSItem *coefficient, 1.1961 + PRBool isKeyExchange 1.1962 +) 1.1963 +{ 1.1964 + CAPI_RSA_KEY_BLOB *keyBlobData = NULL; 1.1965 + unsigned char *target; 1.1966 + unsigned long modSize = modulus->size; 1.1967 + unsigned long dataSize; 1.1968 + CK_RV error = CKR_OK; 1.1969 + 1.1970 + /* validate extras */ 1.1971 + if (privateExponent->size != modSize) { 1.1972 + error = CKR_ATTRIBUTE_VALUE_INVALID; 1.1973 + goto loser; 1.1974 + } 1.1975 + if (prime1->size != modSize/2) { 1.1976 + error = CKR_ATTRIBUTE_VALUE_INVALID; 1.1977 + goto loser; 1.1978 + } 1.1979 + if (prime2->size != modSize/2) { 1.1980 + error = CKR_ATTRIBUTE_VALUE_INVALID; 1.1981 + goto loser; 1.1982 + } 1.1983 + if (exponent1->size != modSize/2) { 1.1984 + error = CKR_ATTRIBUTE_VALUE_INVALID; 1.1985 + goto loser; 1.1986 + } 1.1987 + if (exponent2->size != modSize/2) { 1.1988 + error = CKR_ATTRIBUTE_VALUE_INVALID; 1.1989 + goto loser; 1.1990 + } 1.1991 + if (coefficient->size != modSize/2) { 1.1992 + error = CKR_ATTRIBUTE_VALUE_INVALID; 1.1993 + goto loser; 1.1994 + } 1.1995 + dataSize = (modSize*4)+(modSize/2) + sizeof(CAPI_RSA_KEY_BLOB); 1.1996 + keyBlobData = (CAPI_RSA_KEY_BLOB *)nss_ZAlloc(NULL, dataSize); 1.1997 + if ((CAPI_RSA_KEY_BLOB *)NULL == keyBlobData) { 1.1998 + error = CKR_HOST_MEMORY; 1.1999 + goto loser; 1.2000 + } 1.2001 + 1.2002 + keyBlobData->header.bType = PRIVATEKEYBLOB; 1.2003 + keyBlobData->header.bVersion = 0x02; 1.2004 + keyBlobData->header.reserved = 0x00; 1.2005 + keyBlobData->header.aiKeyAlg = isKeyExchange ? CALG_RSA_KEYX:CALG_RSA_SIGN; 1.2006 + keyBlobData->rsa.magic = 0x32415352; 1.2007 + keyBlobData->rsa.bitlen = modSize * 8; 1.2008 + keyBlobData->rsa.pubexp = nss_ckcapi_DataToInt(publicExponent,&error); 1.2009 + if (CKR_OK != error) { 1.2010 + goto loser; 1.2011 + } 1.2012 + 1.2013 + target = &keyBlobData->data[CAPI_MODULUS_OFFSET(modSize)]; 1.2014 + nsslibc_memcpy(target, modulus->data, modulus->size); 1.2015 + modulus->data = target; 1.2016 + ckcapi_ReverseData(modulus); 1.2017 + 1.2018 + target = &keyBlobData->data[CAPI_PRIVATE_EXP_OFFSET(modSize)]; 1.2019 + nsslibc_memcpy(target, privateExponent->data, privateExponent->size); 1.2020 + privateExponent->data = target; 1.2021 + ckcapi_ReverseData(privateExponent); 1.2022 + 1.2023 + target = &keyBlobData->data[CAPI_PRIME_1_OFFSET(modSize)]; 1.2024 + nsslibc_memcpy(target, prime1->data, prime1->size); 1.2025 + prime1->data = target; 1.2026 + ckcapi_ReverseData(prime1); 1.2027 + 1.2028 + target = &keyBlobData->data[CAPI_PRIME_2_OFFSET(modSize)]; 1.2029 + nsslibc_memcpy(target, prime2->data, prime2->size); 1.2030 + prime2->data = target; 1.2031 + ckcapi_ReverseData(prime2); 1.2032 + 1.2033 + target = &keyBlobData->data[CAPI_EXPONENT_1_OFFSET(modSize)]; 1.2034 + nsslibc_memcpy(target, exponent1->data, exponent1->size); 1.2035 + exponent1->data = target; 1.2036 + ckcapi_ReverseData(exponent1); 1.2037 + 1.2038 + target = &keyBlobData->data[CAPI_EXPONENT_2_OFFSET(modSize)]; 1.2039 + nsslibc_memcpy(target, exponent2->data, exponent2->size); 1.2040 + exponent2->data = target; 1.2041 + ckcapi_ReverseData(exponent2); 1.2042 + 1.2043 + target = &keyBlobData->data[CAPI_COEFFICIENT_OFFSET(modSize)]; 1.2044 + nsslibc_memcpy(target, coefficient->data, coefficient->size); 1.2045 + coefficient->data = target; 1.2046 + ckcapi_ReverseData(coefficient); 1.2047 + 1.2048 + keyBlob->data = keyBlobData; 1.2049 + keyBlob->size = dataSize; 1.2050 + 1.2051 + return CKR_OK; 1.2052 + 1.2053 +loser: 1.2054 + nss_ZFreeIf(keyBlobData); 1.2055 + return error; 1.2056 +} 1.2057 + 1.2058 +static ckcapiInternalObject * 1.2059 +nss_ckcapi_CreatePrivateKey 1.2060 +( 1.2061 + NSSCKFWSession *fwSession, 1.2062 + CK_ATTRIBUTE_PTR pTemplate, 1.2063 + CK_ULONG ulAttributeCount, 1.2064 + CK_RV *pError 1.2065 +) 1.2066 +{ 1.2067 + NSSItem modulus; 1.2068 + NSSItem publicExponent; 1.2069 + NSSItem privateExponent; 1.2070 + NSSItem exponent1; 1.2071 + NSSItem exponent2; 1.2072 + NSSItem prime1; 1.2073 + NSSItem prime2; 1.2074 + NSSItem coefficient; 1.2075 + NSSItem keyID; 1.2076 + NSSItem keyBlob; 1.2077 + ckcapiInternalObject *io = NULL; 1.2078 + char *providerName = NULL; 1.2079 + char *containerName = NULL; 1.2080 + char *idData = NULL; 1.2081 + CRYPT_KEY_PROV_INFO provInfo; 1.2082 + CRYPT_HASH_BLOB msKeyID; 1.2083 + CK_KEY_TYPE keyType; 1.2084 + HCRYPTPROV hProv = 0; 1.2085 + HCRYPTKEY hKey = 0; 1.2086 + PRBool decrypt; 1.2087 + DWORD keySpec; 1.2088 + DWORD msError; 1.2089 + BOOL rc; 1.2090 + 1.2091 + keyType = nss_ckcapi_GetULongAttribute 1.2092 + (CKA_KEY_TYPE, pTemplate, ulAttributeCount, pError); 1.2093 + if (CKR_OK != *pError) { 1.2094 + return (ckcapiInternalObject *)NULL; 1.2095 + } 1.2096 + if (CKK_RSA != keyType) { 1.2097 + *pError = CKR_ATTRIBUTE_VALUE_INVALID; 1.2098 + return (ckcapiInternalObject *)NULL; 1.2099 + } 1.2100 + 1.2101 + decrypt = nss_ckcapi_GetBoolAttribute(CKA_DECRYPT, 1.2102 + pTemplate, ulAttributeCount, pError); 1.2103 + if (CKR_TEMPLATE_INCOMPLETE == *pError) { 1.2104 + decrypt = PR_TRUE; /* default to true */ 1.2105 + } 1.2106 + decrypt = decrypt || nss_ckcapi_GetBoolAttribute(CKA_UNWRAP, 1.2107 + pTemplate, ulAttributeCount, pError); 1.2108 + if (CKR_TEMPLATE_INCOMPLETE == *pError) { 1.2109 + decrypt = PR_TRUE; /* default to true */ 1.2110 + } 1.2111 + keySpec = decrypt ? AT_KEYEXCHANGE : AT_SIGNATURE; 1.2112 + 1.2113 + *pError = nss_ckcapi_GetAttribute(CKA_MODULUS, pTemplate, 1.2114 + ulAttributeCount, &modulus); 1.2115 + if (CKR_OK != *pError) { 1.2116 + return (ckcapiInternalObject *)NULL; 1.2117 + } 1.2118 + *pError = nss_ckcapi_GetAttribute(CKA_PUBLIC_EXPONENT, pTemplate, 1.2119 + ulAttributeCount, &publicExponent); 1.2120 + if (CKR_OK != *pError) { 1.2121 + return (ckcapiInternalObject *)NULL; 1.2122 + } 1.2123 + *pError = nss_ckcapi_GetAttribute(CKA_PRIVATE_EXPONENT, pTemplate, 1.2124 + ulAttributeCount, &privateExponent); 1.2125 + if (CKR_OK != *pError) { 1.2126 + return (ckcapiInternalObject *)NULL; 1.2127 + } 1.2128 + *pError = nss_ckcapi_GetAttribute(CKA_PRIME_1, pTemplate, 1.2129 + ulAttributeCount, &prime1); 1.2130 + if (CKR_OK != *pError) { 1.2131 + return (ckcapiInternalObject *)NULL; 1.2132 + } 1.2133 + *pError = nss_ckcapi_GetAttribute(CKA_PRIME_2, pTemplate, 1.2134 + ulAttributeCount, &prime2); 1.2135 + if (CKR_OK != *pError) { 1.2136 + return (ckcapiInternalObject *)NULL; 1.2137 + } 1.2138 + *pError = nss_ckcapi_GetAttribute(CKA_EXPONENT_1, pTemplate, 1.2139 + ulAttributeCount, &exponent1); 1.2140 + if (CKR_OK != *pError) { 1.2141 + return (ckcapiInternalObject *)NULL; 1.2142 + } 1.2143 + *pError = nss_ckcapi_GetAttribute(CKA_EXPONENT_2, pTemplate, 1.2144 + ulAttributeCount, &exponent2); 1.2145 + if (CKR_OK != *pError) { 1.2146 + return (ckcapiInternalObject *)NULL; 1.2147 + } 1.2148 + *pError = nss_ckcapi_GetAttribute(CKA_COEFFICIENT, pTemplate, 1.2149 + ulAttributeCount, &coefficient); 1.2150 + if (CKR_OK != *pError) { 1.2151 + return (ckcapiInternalObject *)NULL; 1.2152 + } 1.2153 + *pError = nss_ckcapi_GetAttribute(CKA_ID, pTemplate, 1.2154 + ulAttributeCount, &keyID); 1.2155 + if (CKR_OK != *pError) { 1.2156 + return (ckcapiInternalObject *)NULL; 1.2157 + } 1.2158 + providerName = ckcapi_getDefaultProvider(pError); 1.2159 + if ((char *)NULL == providerName ) { 1.2160 + return (ckcapiInternalObject *)NULL; 1.2161 + } 1.2162 + containerName = ckcapi_getContainer(pError, &keyID); 1.2163 + if ((char *)NULL == containerName) { 1.2164 + goto loser; 1.2165 + } 1.2166 + rc = CryptAcquireContext(&hProv, containerName, providerName, 1.2167 + PROV_RSA_FULL, CRYPT_NEWKEYSET); 1.2168 + if (!rc) { 1.2169 + msError = GetLastError(); 1.2170 + *pError = CKR_DEVICE_ERROR; 1.2171 + goto loser; 1.2172 + } 1.2173 + 1.2174 + *pError = ckcapi_buildPrivateKeyBlob( 1.2175 + &keyBlob, 1.2176 + &modulus, 1.2177 + &publicExponent, 1.2178 + &privateExponent, 1.2179 + &prime1, 1.2180 + &prime2, 1.2181 + &exponent1, 1.2182 + &exponent2, 1.2183 + &coefficient, 1.2184 + decrypt); 1.2185 + if (CKR_OK != *pError) { 1.2186 + goto loser; 1.2187 + } 1.2188 + 1.2189 + rc = CryptImportKey(hProv, keyBlob.data, keyBlob.size, 1.2190 + 0, CRYPT_EXPORTABLE, &hKey); 1.2191 + if (!rc) { 1.2192 + msError = GetLastError(); 1.2193 + *pError = CKR_DEVICE_ERROR; 1.2194 + goto loser; 1.2195 + } 1.2196 + 1.2197 + idData = nss_ZNEWARRAY(NULL, char, keyID.size); 1.2198 + if ((void *)NULL == idData) { 1.2199 + *pError = CKR_HOST_MEMORY; 1.2200 + goto loser; 1.2201 + } 1.2202 + nsslibc_memcpy(idData, keyID.data, keyID.size); 1.2203 + 1.2204 + provInfo.pwszContainerName = nss_ckcapi_UTF8ToWide(containerName); 1.2205 + provInfo.pwszProvName = nss_ckcapi_UTF8ToWide(providerName); 1.2206 + provInfo.dwProvType = PROV_RSA_FULL; 1.2207 + provInfo.dwFlags = 0; 1.2208 + provInfo.cProvParam = 0; 1.2209 + provInfo.rgProvParam = NULL; 1.2210 + provInfo.dwKeySpec = keySpec; 1.2211 + 1.2212 + msKeyID.cbData = keyID.size; 1.2213 + msKeyID.pbData = keyID.data; 1.2214 + 1.2215 + rc = CryptSetKeyIdentifierProperty(&msKeyID, CERT_KEY_PROV_INFO_PROP_ID, 1.2216 + 0, NULL, NULL, &provInfo); 1.2217 + if (!rc) { 1.2218 + goto loser; 1.2219 + } 1.2220 + 1.2221 + /* handle error here */ 1.2222 + io = nss_ZNEW(NULL, ckcapiInternalObject); 1.2223 + if ((ckcapiInternalObject *)NULL == io) { 1.2224 + *pError = CKR_HOST_MEMORY; 1.2225 + goto loser; 1.2226 + } 1.2227 + io->type = ckcapiBareKey; 1.2228 + io->objClass = CKO_PRIVATE_KEY; 1.2229 + io->u.key.provInfo = provInfo; 1.2230 + io->u.key.provName = providerName; 1.2231 + io->u.key.containerName = containerName; 1.2232 + io->u.key.hProv = hProv; /* save the handle */ 1.2233 + io->idData = idData; 1.2234 + io->id.data = idData; 1.2235 + io->id.size = keyID.size; 1.2236 + /* done with the key handle */ 1.2237 + CryptDestroyKey(hKey); 1.2238 + return io; 1.2239 + 1.2240 +loser: 1.2241 + nss_ZFreeIf(containerName); 1.2242 + nss_ZFreeIf(providerName); 1.2243 + nss_ZFreeIf(idData); 1.2244 + if (0 != hProv) { 1.2245 + CryptReleaseContext(hProv, 0); 1.2246 + } 1.2247 + if (0 != hKey) { 1.2248 + CryptDestroyKey(hKey); 1.2249 + } 1.2250 + return (ckcapiInternalObject *)NULL; 1.2251 +} 1.2252 + 1.2253 + 1.2254 +NSS_EXTERN NSSCKMDObject * 1.2255 +nss_ckcapi_CreateObject 1.2256 +( 1.2257 + NSSCKFWSession *fwSession, 1.2258 + CK_ATTRIBUTE_PTR pTemplate, 1.2259 + CK_ULONG ulAttributeCount, 1.2260 + CK_RV *pError 1.2261 +) 1.2262 +{ 1.2263 + CK_OBJECT_CLASS objClass; 1.2264 + ckcapiInternalObject *io = NULL; 1.2265 + CK_BBOOL isToken; 1.2266 + 1.2267 + /* 1.2268 + * only create token objects 1.2269 + */ 1.2270 + isToken = nss_ckcapi_GetBoolAttribute(CKA_TOKEN, pTemplate, 1.2271 + ulAttributeCount, pError); 1.2272 + if (CKR_OK != *pError) { 1.2273 + return (NSSCKMDObject *) NULL; 1.2274 + } 1.2275 + if (!isToken) { 1.2276 + *pError = CKR_ATTRIBUTE_VALUE_INVALID; 1.2277 + return (NSSCKMDObject *) NULL; 1.2278 + } 1.2279 + 1.2280 + /* 1.2281 + * only create keys and certs. 1.2282 + */ 1.2283 + objClass = nss_ckcapi_GetULongAttribute(CKA_CLASS, pTemplate, 1.2284 + ulAttributeCount, pError); 1.2285 + if (CKR_OK != *pError) { 1.2286 + return (NSSCKMDObject *) NULL; 1.2287 + } 1.2288 +#ifdef notdef 1.2289 + if (objClass == CKO_PUBLIC_KEY) { 1.2290 + return CKR_OK; /* fake public key creation, happens as a side effect of 1.2291 + * private key creation */ 1.2292 + } 1.2293 +#endif 1.2294 + if (objClass == CKO_CERTIFICATE) { 1.2295 + io = nss_ckcapi_CreateCertificate(fwSession, pTemplate, 1.2296 + ulAttributeCount, pError); 1.2297 + } else if (objClass == CKO_PRIVATE_KEY) { 1.2298 + io = nss_ckcapi_CreatePrivateKey(fwSession, pTemplate, 1.2299 + ulAttributeCount, pError); 1.2300 + } else { 1.2301 + *pError = CKR_ATTRIBUTE_VALUE_INVALID; 1.2302 + } 1.2303 + 1.2304 + if ((ckcapiInternalObject *)NULL == io) { 1.2305 + return (NSSCKMDObject *) NULL; 1.2306 + } 1.2307 + return nss_ckcapi_CreateMDObject(NULL, io, pError); 1.2308 +}