security/nss/lib/ckfw/capi/cobject.c

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

michael@0 1 /* This Source Code Form is subject to the terms of the Mozilla Public
michael@0 2 * License, v. 2.0. If a copy of the MPL was not distributed with this
michael@0 3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
michael@0 4
michael@0 5 #include "ckcapi.h"
michael@0 6 #include "nssbase.h"
michael@0 7
michael@0 8 /*
michael@0 9 * ckcapi/cobject.c
michael@0 10 *
michael@0 11 * This file implements the NSSCKMDObject object for the
michael@0 12 * "nss to capi objects" cryptoki module.
michael@0 13 */
michael@0 14
michael@0 15 const CK_ATTRIBUTE_TYPE certAttrs[] = {
michael@0 16 CKA_CLASS,
michael@0 17 CKA_TOKEN,
michael@0 18 CKA_PRIVATE,
michael@0 19 CKA_MODIFIABLE,
michael@0 20 CKA_LABEL,
michael@0 21 CKA_CERTIFICATE_TYPE,
michael@0 22 CKA_SUBJECT,
michael@0 23 CKA_ISSUER,
michael@0 24 CKA_SERIAL_NUMBER,
michael@0 25 CKA_VALUE
michael@0 26 };
michael@0 27 const PRUint32 certAttrsCount = NSS_CKCAPI_ARRAY_SIZE(certAttrs);
michael@0 28
michael@0 29 /* private keys, for now only support RSA */
michael@0 30 const CK_ATTRIBUTE_TYPE privKeyAttrs[] = {
michael@0 31 CKA_CLASS,
michael@0 32 CKA_TOKEN,
michael@0 33 CKA_PRIVATE,
michael@0 34 CKA_MODIFIABLE,
michael@0 35 CKA_LABEL,
michael@0 36 CKA_KEY_TYPE,
michael@0 37 CKA_DERIVE,
michael@0 38 CKA_LOCAL,
michael@0 39 CKA_SUBJECT,
michael@0 40 CKA_SENSITIVE,
michael@0 41 CKA_DECRYPT,
michael@0 42 CKA_SIGN,
michael@0 43 CKA_SIGN_RECOVER,
michael@0 44 CKA_UNWRAP,
michael@0 45 CKA_EXTRACTABLE,
michael@0 46 CKA_ALWAYS_SENSITIVE,
michael@0 47 CKA_NEVER_EXTRACTABLE,
michael@0 48 CKA_MODULUS,
michael@0 49 CKA_PUBLIC_EXPONENT,
michael@0 50 };
michael@0 51 const PRUint32 privKeyAttrsCount = NSS_CKCAPI_ARRAY_SIZE(privKeyAttrs);
michael@0 52
michael@0 53 /* public keys, for now only support RSA */
michael@0 54 const CK_ATTRIBUTE_TYPE pubKeyAttrs[] = {
michael@0 55 CKA_CLASS,
michael@0 56 CKA_TOKEN,
michael@0 57 CKA_PRIVATE,
michael@0 58 CKA_MODIFIABLE,
michael@0 59 CKA_LABEL,
michael@0 60 CKA_KEY_TYPE,
michael@0 61 CKA_DERIVE,
michael@0 62 CKA_LOCAL,
michael@0 63 CKA_SUBJECT,
michael@0 64 CKA_ENCRYPT,
michael@0 65 CKA_VERIFY,
michael@0 66 CKA_VERIFY_RECOVER,
michael@0 67 CKA_WRAP,
michael@0 68 CKA_MODULUS,
michael@0 69 CKA_PUBLIC_EXPONENT,
michael@0 70 };
michael@0 71 const PRUint32 pubKeyAttrsCount = NSS_CKCAPI_ARRAY_SIZE(pubKeyAttrs);
michael@0 72 static const CK_BBOOL ck_true = CK_TRUE;
michael@0 73 static const CK_BBOOL ck_false = CK_FALSE;
michael@0 74 static const CK_CERTIFICATE_TYPE ckc_x509 = CKC_X_509;
michael@0 75 static const CK_KEY_TYPE ckk_rsa = CKK_RSA;
michael@0 76 static const CK_OBJECT_CLASS cko_certificate = CKO_CERTIFICATE;
michael@0 77 static const CK_OBJECT_CLASS cko_private_key = CKO_PRIVATE_KEY;
michael@0 78 static const CK_OBJECT_CLASS cko_public_key = CKO_PUBLIC_KEY;
michael@0 79 static const NSSItem ckcapi_trueItem = {
michael@0 80 (void *)&ck_true, (PRUint32)sizeof(CK_BBOOL) };
michael@0 81 static const NSSItem ckcapi_falseItem = {
michael@0 82 (void *)&ck_false, (PRUint32)sizeof(CK_BBOOL) };
michael@0 83 static const NSSItem ckcapi_x509Item = {
michael@0 84 (void *)&ckc_x509, (PRUint32)sizeof(CK_CERTIFICATE_TYPE) };
michael@0 85 static const NSSItem ckcapi_rsaItem = {
michael@0 86 (void *)&ckk_rsa, (PRUint32)sizeof(CK_KEY_TYPE) };
michael@0 87 static const NSSItem ckcapi_certClassItem = {
michael@0 88 (void *)&cko_certificate, (PRUint32)sizeof(CK_OBJECT_CLASS) };
michael@0 89 static const NSSItem ckcapi_privKeyClassItem = {
michael@0 90 (void *)&cko_private_key, (PRUint32)sizeof(CK_OBJECT_CLASS) };
michael@0 91 static const NSSItem ckcapi_pubKeyClassItem = {
michael@0 92 (void *)&cko_public_key, (PRUint32)sizeof(CK_OBJECT_CLASS) };
michael@0 93 static const NSSItem ckcapi_emptyItem = {
michael@0 94 (void *)&ck_true, 0};
michael@0 95
michael@0 96 /*
michael@0 97 * these are utilities. The chould be moved to a new utilities file.
michael@0 98 */
michael@0 99
michael@0 100 /*
michael@0 101 * unwrap a single DER value
michael@0 102 */
michael@0 103 unsigned char *
michael@0 104 nss_ckcapi_DERUnwrap
michael@0 105 (
michael@0 106 unsigned char *src,
michael@0 107 unsigned int size,
michael@0 108 unsigned int *outSize,
michael@0 109 unsigned char **next
michael@0 110 )
michael@0 111 {
michael@0 112 unsigned char *start = src;
michael@0 113 unsigned char *end = src+size;
michael@0 114 unsigned int len = 0;
michael@0 115
michael@0 116 /* initialize error condition return values */
michael@0 117 *outSize = 0;
michael@0 118 if (next) {
michael@0 119 *next = src;
michael@0 120 }
michael@0 121
michael@0 122 if (size < 2) {
michael@0 123 return start;
michael@0 124 }
michael@0 125 src++; /* skip the tag -- should check it against an expected value! */
michael@0 126 len = (unsigned) *src++;
michael@0 127 if (len & 0x80) {
michael@0 128 unsigned int count = len & 0x7f;
michael@0 129 len = 0;
michael@0 130
michael@0 131 if (count+2 > size) {
michael@0 132 return start;
michael@0 133 }
michael@0 134 while (count-- > 0) {
michael@0 135 len = (len << 8) | (unsigned) *src++;
michael@0 136 }
michael@0 137 }
michael@0 138 if (len + (src-start) > size) {
michael@0 139 return start;
michael@0 140 }
michael@0 141 if (next) {
michael@0 142 *next = src+len;
michael@0 143 }
michael@0 144 *outSize = len;
michael@0 145
michael@0 146 return src;
michael@0 147 }
michael@0 148
michael@0 149 /*
michael@0 150 * convert a PKCS #11 bytestrin into a CK_ULONG, the byte stream must be
michael@0 151 * less than sizeof (CK_ULONG).
michael@0 152 */
michael@0 153 CK_ULONG
michael@0 154 nss_ckcapi_DataToInt
michael@0 155 (
michael@0 156 NSSItem *data,
michael@0 157 CK_RV *pError
michael@0 158 )
michael@0 159 {
michael@0 160 CK_ULONG value = 0;
michael@0 161 unsigned long count = data->size;
michael@0 162 unsigned char *dataPtr = data->data;
michael@0 163 unsigned long size = 0;
michael@0 164
michael@0 165 *pError = CKR_OK;
michael@0 166
michael@0 167 while (count--) {
michael@0 168 value = value << 8;
michael@0 169 value = value + *dataPtr++;
michael@0 170 if (size || value) {
michael@0 171 size++;
michael@0 172 }
michael@0 173 }
michael@0 174 if (size > sizeof(CK_ULONG)) {
michael@0 175 *pError = CKR_ATTRIBUTE_VALUE_INVALID;
michael@0 176 }
michael@0 177 return value;
michael@0 178 }
michael@0 179
michael@0 180 /*
michael@0 181 * convert a CK_ULONG to a bytestream. Data is stored in the buffer 'buf'
michael@0 182 * and must be at least CK_ULONG. Caller must provide buf.
michael@0 183 */
michael@0 184 CK_ULONG
michael@0 185 nss_ckcapi_IntToData
michael@0 186 (
michael@0 187 CK_ULONG value,
michael@0 188 NSSItem *data,
michael@0 189 unsigned char *dataPtr,
michael@0 190 CK_RV *pError
michael@0 191 )
michael@0 192 {
michael@0 193 unsigned long count = 0;
michael@0 194 unsigned long i;
michael@0 195 #define SHIFT ((sizeof(CK_ULONG)-1)*8)
michael@0 196 PRBool first = 0;
michael@0 197
michael@0 198 *pError = CKR_OK;
michael@0 199
michael@0 200 data->data = dataPtr;
michael@0 201 for (i=0; i < sizeof(CK_ULONG); i++) {
michael@0 202 unsigned char digit = (unsigned char)((value >> SHIFT) & 0xff);
michael@0 203
michael@0 204 value = value << 8;
michael@0 205
michael@0 206 /* drop leading zero bytes */
michael@0 207 if (first && (0 == digit)) {
michael@0 208 continue;
michael@0 209 }
michael@0 210 *dataPtr++ = digit;
michael@0 211 count++;
michael@0 212 }
michael@0 213 data->size = count;
michael@0 214 return count;
michael@0 215 }
michael@0 216
michael@0 217 /*
michael@0 218 * get an attribute from a template. Value is returned in NSS item.
michael@0 219 * data for the item is owned by the template.
michael@0 220 */
michael@0 221 CK_RV
michael@0 222 nss_ckcapi_GetAttribute
michael@0 223 (
michael@0 224 CK_ATTRIBUTE_TYPE type,
michael@0 225 CK_ATTRIBUTE *template,
michael@0 226 CK_ULONG templateSize,
michael@0 227 NSSItem *item
michael@0 228 )
michael@0 229 {
michael@0 230 CK_ULONG i;
michael@0 231
michael@0 232 for (i=0; i < templateSize; i++) {
michael@0 233 if (template[i].type == type) {
michael@0 234 item->data = template[i].pValue;
michael@0 235 item->size = template[i].ulValueLen;
michael@0 236 return CKR_OK;
michael@0 237 }
michael@0 238 }
michael@0 239 return CKR_TEMPLATE_INCOMPLETE;
michael@0 240 }
michael@0 241
michael@0 242 /*
michael@0 243 * get an attribute which is type CK_ULONG.
michael@0 244 */
michael@0 245 CK_ULONG
michael@0 246 nss_ckcapi_GetULongAttribute
michael@0 247 (
michael@0 248 CK_ATTRIBUTE_TYPE type,
michael@0 249 CK_ATTRIBUTE *template,
michael@0 250 CK_ULONG templateSize,
michael@0 251 CK_RV *pError
michael@0 252 )
michael@0 253 {
michael@0 254 NSSItem item;
michael@0 255
michael@0 256 *pError = nss_ckcapi_GetAttribute(type, template, templateSize, &item);
michael@0 257 if (CKR_OK != *pError) {
michael@0 258 return (CK_ULONG) 0;
michael@0 259 }
michael@0 260 if (item.size != sizeof(CK_ULONG)) {
michael@0 261 *pError = CKR_ATTRIBUTE_VALUE_INVALID;
michael@0 262 return (CK_ULONG) 0;
michael@0 263 }
michael@0 264 return *(CK_ULONG *)item.data;
michael@0 265 }
michael@0 266
michael@0 267 /*
michael@0 268 * get an attribute which is type CK_BBOOL.
michael@0 269 */
michael@0 270 CK_BBOOL
michael@0 271 nss_ckcapi_GetBoolAttribute
michael@0 272 (
michael@0 273 CK_ATTRIBUTE_TYPE type,
michael@0 274 CK_ATTRIBUTE *template,
michael@0 275 CK_ULONG templateSize,
michael@0 276 CK_RV *pError
michael@0 277 )
michael@0 278 {
michael@0 279 NSSItem item;
michael@0 280
michael@0 281 *pError = nss_ckcapi_GetAttribute(type, template, templateSize, &item);
michael@0 282 if (CKR_OK != *pError) {
michael@0 283 return (CK_BBOOL) 0;
michael@0 284 }
michael@0 285 if (item.size != sizeof(CK_BBOOL)) {
michael@0 286 *pError = CKR_ATTRIBUTE_VALUE_INVALID;
michael@0 287 return (CK_BBOOL) 0;
michael@0 288 }
michael@0 289 return *(CK_BBOOL *)item.data;
michael@0 290 }
michael@0 291
michael@0 292 /*
michael@0 293 * get an attribute which is type CK_BBOOL.
michael@0 294 */
michael@0 295 char *
michael@0 296 nss_ckcapi_GetStringAttribute
michael@0 297 (
michael@0 298 CK_ATTRIBUTE_TYPE type,
michael@0 299 CK_ATTRIBUTE *template,
michael@0 300 CK_ULONG templateSize,
michael@0 301 CK_RV *pError
michael@0 302 )
michael@0 303 {
michael@0 304 NSSItem item;
michael@0 305 char *str;
michael@0 306
michael@0 307 /* get the attribute */
michael@0 308 *pError = nss_ckcapi_GetAttribute(type, template, templateSize, &item);
michael@0 309 if (CKR_OK != *pError) {
michael@0 310 return (char *)NULL;
michael@0 311 }
michael@0 312 /* make sure it is null terminated */
michael@0 313 str = nss_ZNEWARRAY(NULL, char, item.size+1);
michael@0 314 if ((char *)NULL == str) {
michael@0 315 *pError = CKR_HOST_MEMORY;
michael@0 316 return (char *)NULL;
michael@0 317 }
michael@0 318
michael@0 319 nsslibc_memcpy(str, item.data, item.size);
michael@0 320 str[item.size] = 0;
michael@0 321
michael@0 322 return str;
michael@0 323 }
michael@0 324
michael@0 325 /*
michael@0 326 * Return the size in bytes of a wide string, including the terminating null
michael@0 327 * character
michael@0 328 */
michael@0 329 int
michael@0 330 nss_ckcapi_WideSize
michael@0 331 (
michael@0 332 LPCWSTR wide
michael@0 333 )
michael@0 334 {
michael@0 335 DWORD size;
michael@0 336
michael@0 337 if ((LPWSTR)NULL == wide) {
michael@0 338 return 0;
michael@0 339 }
michael@0 340 size = wcslen(wide)+1;
michael@0 341 return size*sizeof(WCHAR);
michael@0 342 }
michael@0 343
michael@0 344 /*
michael@0 345 * Covert a Unicode wide character string to a UTF8 string
michael@0 346 */
michael@0 347 char *
michael@0 348 nss_ckcapi_WideToUTF8
michael@0 349 (
michael@0 350 LPCWSTR wide
michael@0 351 )
michael@0 352 {
michael@0 353 DWORD size;
michael@0 354 char *buf;
michael@0 355
michael@0 356 if ((LPWSTR)NULL == wide) {
michael@0 357 return (char *)NULL;
michael@0 358 }
michael@0 359
michael@0 360 size = WideCharToMultiByte(CP_UTF8, 0, wide, -1, NULL, 0, NULL, 0);
michael@0 361 if (size == 0) {
michael@0 362 return (char *)NULL;
michael@0 363 }
michael@0 364 buf = nss_ZNEWARRAY(NULL, char, size);
michael@0 365 size = WideCharToMultiByte(CP_UTF8, 0, wide, -1, buf, size, NULL, 0);
michael@0 366 if (size == 0) {
michael@0 367 nss_ZFreeIf(buf);
michael@0 368 return (char *)NULL;
michael@0 369 }
michael@0 370 return buf;
michael@0 371 }
michael@0 372
michael@0 373 /*
michael@0 374 * Return a Wide String duplicated with nss allocated memory.
michael@0 375 */
michael@0 376 LPWSTR
michael@0 377 nss_ckcapi_WideDup
michael@0 378 (
michael@0 379 LPCWSTR wide
michael@0 380 )
michael@0 381 {
michael@0 382 DWORD len;
michael@0 383 LPWSTR buf;
michael@0 384
michael@0 385 if ((LPWSTR)NULL == wide) {
michael@0 386 return (LPWSTR)NULL;
michael@0 387 }
michael@0 388
michael@0 389 len = wcslen(wide)+1;
michael@0 390
michael@0 391 buf = nss_ZNEWARRAY(NULL, WCHAR, len);
michael@0 392 if ((LPWSTR) NULL == buf) {
michael@0 393 return buf;
michael@0 394 }
michael@0 395 nsslibc_memcpy(buf, wide, len*sizeof(WCHAR));
michael@0 396 return buf;
michael@0 397 }
michael@0 398
michael@0 399 /*
michael@0 400 * Covert a UTF8 string to Unicode wide character
michael@0 401 */
michael@0 402 LPWSTR
michael@0 403 nss_ckcapi_UTF8ToWide
michael@0 404 (
michael@0 405 char *buf
michael@0 406 )
michael@0 407 {
michael@0 408 DWORD size;
michael@0 409 LPWSTR wide;
michael@0 410
michael@0 411 if ((char *)NULL == buf) {
michael@0 412 return (LPWSTR) NULL;
michael@0 413 }
michael@0 414
michael@0 415 size = MultiByteToWideChar(CP_UTF8, 0, buf, -1, NULL, 0);
michael@0 416 if (size == 0) {
michael@0 417 return (LPWSTR) NULL;
michael@0 418 }
michael@0 419 wide = nss_ZNEWARRAY(NULL, WCHAR, size);
michael@0 420 size = MultiByteToWideChar(CP_UTF8, 0, buf, -1, wide, size);
michael@0 421 if (size == 0) {
michael@0 422 nss_ZFreeIf(wide);
michael@0 423 return (LPWSTR) NULL;
michael@0 424 }
michael@0 425 return wide;
michael@0 426 }
michael@0 427
michael@0 428
michael@0 429 /*
michael@0 430 * keep all the knowlege of how the internalObject is laid out in this function
michael@0 431 *
michael@0 432 * nss_ckcapi_FetchKeyContainer
michael@0 433 *
michael@0 434 * fetches the Provider container and info as well as a key handle for a
michael@0 435 * private key. If something other than a private key is passed in,
michael@0 436 * this function fails with CKR_KEY_TYPE_INCONSISTENT
michael@0 437 */
michael@0 438 NSS_EXTERN CK_RV
michael@0 439 nss_ckcapi_FetchKeyContainer
michael@0 440 (
michael@0 441 ckcapiInternalObject *iKey,
michael@0 442 HCRYPTPROV *hProv,
michael@0 443 DWORD *keySpec,
michael@0 444 HCRYPTKEY *hKey
michael@0 445 )
michael@0 446 {
michael@0 447 ckcapiCertObject *co;
michael@0 448 ckcapiKeyObject *ko;
michael@0 449 BOOL rc, dummy;
michael@0 450 DWORD msError;
michael@0 451
michael@0 452
michael@0 453 switch (iKey->type) {
michael@0 454 default:
michael@0 455 case ckcapiRaw:
michael@0 456 /* can't have raw private keys */
michael@0 457 return CKR_KEY_TYPE_INCONSISTENT;
michael@0 458 case ckcapiCert:
michael@0 459 if (iKey->objClass != CKO_PRIVATE_KEY) {
michael@0 460 /* Only private keys have private key provider handles */
michael@0 461 return CKR_KEY_TYPE_INCONSISTENT;
michael@0 462 }
michael@0 463 co = &iKey->u.cert;
michael@0 464
michael@0 465 /* OK, get the Provider */
michael@0 466 rc = CryptAcquireCertificatePrivateKey(co->certContext,
michael@0 467 CRYPT_ACQUIRE_CACHE_FLAG|CRYPT_ACQUIRE_COMPARE_KEY_FLAG, NULL, hProv,
michael@0 468 keySpec, &dummy);
michael@0 469 if (!rc) {
michael@0 470 goto loser;
michael@0 471 }
michael@0 472 break;
michael@0 473 case ckcapiBareKey:
michael@0 474 if (iKey->objClass != CKO_PRIVATE_KEY) {
michael@0 475 /* Only private keys have private key provider handles */
michael@0 476 return CKR_KEY_TYPE_INCONSISTENT;
michael@0 477 }
michael@0 478 ko = &iKey->u.key;
michael@0 479
michael@0 480 /* OK, get the Provider */
michael@0 481 if (0 == ko->hProv) {
michael@0 482 rc = CryptAcquireContext(hProv,
michael@0 483 ko->containerName,
michael@0 484 ko->provName,
michael@0 485 ko->provInfo.dwProvType , 0);
michael@0 486 if (!rc) {
michael@0 487 goto loser;
michael@0 488 }
michael@0 489 } else {
michael@0 490 *hProv = ko->hProv;
michael@0 491 }
michael@0 492 *keySpec = ko->provInfo.dwKeySpec;
michael@0 493 break;
michael@0 494 }
michael@0 495
michael@0 496 /* and get the crypto handle */
michael@0 497 rc = CryptGetUserKey(*hProv, *keySpec, hKey);
michael@0 498 if (!rc) {
michael@0 499 goto loser;
michael@0 500 }
michael@0 501 return CKR_OK;
michael@0 502 loser:
michael@0 503 /* map the microsoft error before leaving */
michael@0 504 msError = GetLastError();
michael@0 505 switch (msError) {
michael@0 506 case ERROR_INVALID_HANDLE:
michael@0 507 case ERROR_INVALID_PARAMETER:
michael@0 508 case NTE_BAD_KEY:
michael@0 509 case NTE_NO_KEY:
michael@0 510 case NTE_BAD_PUBLIC_KEY:
michael@0 511 case NTE_BAD_KEYSET:
michael@0 512 case NTE_KEYSET_NOT_DEF:
michael@0 513 return CKR_KEY_TYPE_INCONSISTENT;
michael@0 514 case NTE_BAD_UID:
michael@0 515 case NTE_KEYSET_ENTRY_BAD:
michael@0 516 return CKR_DEVICE_ERROR;
michael@0 517 }
michael@0 518 return CKR_GENERAL_ERROR;
michael@0 519 }
michael@0 520
michael@0 521
michael@0 522 /*
michael@0 523 * take a DER PUBLIC Key block and return the modulus and exponent
michael@0 524 */
michael@0 525 static void
michael@0 526 ckcapi_CertPopulateModulusExponent
michael@0 527 (
michael@0 528 ckcapiInternalObject *io
michael@0 529 )
michael@0 530 {
michael@0 531 ckcapiKeyParams *kp = &io->u.cert.key;
michael@0 532 PCCERT_CONTEXT certContext = io->u.cert.certContext;
michael@0 533 unsigned char *pkData =
michael@0 534 certContext->pCertInfo->SubjectPublicKeyInfo.PublicKey.pbData;
michael@0 535 unsigned int size=
michael@0 536 certContext->pCertInfo->SubjectPublicKeyInfo.PublicKey.cbData;
michael@0 537 unsigned int newSize;
michael@0 538 unsigned char *ptr, *newptr;
michael@0 539
michael@0 540 /* find the start of the modulus -- this will not give good results if
michael@0 541 * the key isn't an rsa key! */
michael@0 542 ptr = nss_ckcapi_DERUnwrap(pkData, size, &newSize, NULL);
michael@0 543 kp->modulus.data = nss_ckcapi_DERUnwrap(ptr, newSize,
michael@0 544 &kp->modulus.size, &newptr);
michael@0 545 /* changed from signed to unsigned int */
michael@0 546 if (0 == *(char *)kp->modulus.data) {
michael@0 547 kp->modulus.data = ((char *)kp->modulus.data)+1;
michael@0 548 kp->modulus.size = kp->modulus.size - 1;
michael@0 549 }
michael@0 550 /* changed from signed to unsigned int */
michael@0 551 kp->exponent.data = nss_ckcapi_DERUnwrap(newptr, (newptr-ptr)+newSize,
michael@0 552 &kp->exponent.size, NULL);
michael@0 553 if (0 == *(char *)kp->exponent.data) {
michael@0 554 kp->exponent.data = ((char *)kp->exponent.data)+1;
michael@0 555 kp->exponent.size = kp->exponent.size - 1;
michael@0 556 }
michael@0 557 return;
michael@0 558 }
michael@0 559
michael@0 560 typedef struct _CAPI_RSA_KEY_BLOB {
michael@0 561 PUBLICKEYSTRUC header;
michael@0 562 RSAPUBKEY rsa;
michael@0 563 char data[1];
michael@0 564 } CAPI_RSA_KEY_BLOB;
michael@0 565
michael@0 566 #define CAPI_MODULUS_OFFSET(modSize) 0
michael@0 567 #define CAPI_PRIME_1_OFFSET(modSize) (modSize)
michael@0 568 #define CAPI_PRIME_2_OFFSET(modSize) ((modSize)+(modSize)/2)
michael@0 569 #define CAPI_EXPONENT_1_OFFSET(modSize) ((modSize)*2)
michael@0 570 #define CAPI_EXPONENT_2_OFFSET(modSize) ((modSize)*2+(modSize)/2)
michael@0 571 #define CAPI_COEFFICIENT_OFFSET(modSize) ((modSize)*3)
michael@0 572 #define CAPI_PRIVATE_EXP_OFFSET(modSize) ((modSize)*3+(modSize)/2)
michael@0 573
michael@0 574 void
michael@0 575 ckcapi_FetchPublicKey
michael@0 576 (
michael@0 577 ckcapiInternalObject *io
michael@0 578 )
michael@0 579 {
michael@0 580 ckcapiKeyParams *kp;
michael@0 581 HCRYPTPROV hProv;
michael@0 582 DWORD keySpec;
michael@0 583 HCRYPTKEY hKey = 0;
michael@0 584 CK_RV error;
michael@0 585 DWORD bufLen;
michael@0 586 BOOL rc;
michael@0 587 unsigned long modulus;
michael@0 588 char *buf = NULL;
michael@0 589 CAPI_RSA_KEY_BLOB *blob;
michael@0 590
michael@0 591 error = nss_ckcapi_FetchKeyContainer(io, &hProv, &keySpec, &hKey);
michael@0 592 if (CKR_OK != error) {
michael@0 593 goto loser;
michael@0 594 }
michael@0 595 kp = (ckcapiCert == io->type) ? &io->u.cert.key : &io->u.key.key;
michael@0 596
michael@0 597 rc = CryptExportKey(hKey, 0, PUBLICKEYBLOB, 0, buf, &bufLen);
michael@0 598 if (!rc) {
michael@0 599 goto loser;
michael@0 600 }
michael@0 601 buf = nss_ZNEWARRAY(NULL, char, bufLen);
michael@0 602 rc = CryptExportKey(hKey, 0, PUBLICKEYBLOB, 0, buf, &bufLen);
michael@0 603 if (!rc) {
michael@0 604 goto loser;
michael@0 605 }
michael@0 606 /* validate the blob */
michael@0 607 blob = (CAPI_RSA_KEY_BLOB *)buf;
michael@0 608 if ((PUBLICKEYBLOB != blob->header.bType) ||
michael@0 609 (0x02 != blob->header.bVersion) ||
michael@0 610 (0x31415352 != blob->rsa.magic)) {
michael@0 611 goto loser;
michael@0 612 }
michael@0 613 modulus = blob->rsa.bitlen/8;
michael@0 614 kp->pubKey = buf;
michael@0 615 buf = NULL;
michael@0 616
michael@0 617 kp->modulus.data = &blob->data[CAPI_MODULUS_OFFSET(modulus)];
michael@0 618 kp->modulus.size = modulus;
michael@0 619 ckcapi_ReverseData(&kp->modulus);
michael@0 620 nss_ckcapi_IntToData(blob->rsa.pubexp, &kp->exponent,
michael@0 621 kp->publicExponentData, &error);
michael@0 622
michael@0 623 loser:
michael@0 624 nss_ZFreeIf(buf);
michael@0 625 if (0 != hKey) {
michael@0 626 CryptDestroyKey(hKey);
michael@0 627 }
michael@0 628 return;
michael@0 629 }
michael@0 630
michael@0 631 void
michael@0 632 ckcapi_FetchPrivateKey
michael@0 633 (
michael@0 634 ckcapiInternalObject *io
michael@0 635 )
michael@0 636 {
michael@0 637 ckcapiKeyParams *kp;
michael@0 638 HCRYPTPROV hProv;
michael@0 639 DWORD keySpec;
michael@0 640 HCRYPTKEY hKey = 0;
michael@0 641 CK_RV error;
michael@0 642 DWORD bufLen;
michael@0 643 BOOL rc;
michael@0 644 unsigned long modulus;
michael@0 645 char *buf = NULL;
michael@0 646 CAPI_RSA_KEY_BLOB *blob;
michael@0 647
michael@0 648 error = nss_ckcapi_FetchKeyContainer(io, &hProv, &keySpec, &hKey);
michael@0 649 if (CKR_OK != error) {
michael@0 650 goto loser;
michael@0 651 }
michael@0 652 kp = (ckcapiCert == io->type) ? &io->u.cert.key : &io->u.key.key;
michael@0 653
michael@0 654 rc = CryptExportKey(hKey, 0, PRIVATEKEYBLOB, 0, buf, &bufLen);
michael@0 655 if (!rc) {
michael@0 656 goto loser;
michael@0 657 }
michael@0 658 buf = nss_ZNEWARRAY(NULL, char, bufLen);
michael@0 659 rc = CryptExportKey(hKey, 0, PRIVATEKEYBLOB, 0, buf, &bufLen);
michael@0 660 if (!rc) {
michael@0 661 goto loser;
michael@0 662 }
michael@0 663 /* validate the blob */
michael@0 664 blob = (CAPI_RSA_KEY_BLOB *)buf;
michael@0 665 if ((PRIVATEKEYBLOB != blob->header.bType) ||
michael@0 666 (0x02 != blob->header.bVersion) ||
michael@0 667 (0x32415352 != blob->rsa.magic)) {
michael@0 668 goto loser;
michael@0 669 }
michael@0 670 modulus = blob->rsa.bitlen/8;
michael@0 671 kp->privateKey = buf;
michael@0 672 buf = NULL;
michael@0 673
michael@0 674 kp->privateExponent.data = &blob->data[CAPI_PRIVATE_EXP_OFFSET(modulus)];
michael@0 675 kp->privateExponent.size = modulus;
michael@0 676 ckcapi_ReverseData(&kp->privateExponent);
michael@0 677 kp->prime1.data = &blob->data[CAPI_PRIME_1_OFFSET(modulus)];
michael@0 678 kp->prime1.size = modulus/2;
michael@0 679 ckcapi_ReverseData(&kp->prime1);
michael@0 680 kp->prime2.data = &blob->data[CAPI_PRIME_2_OFFSET(modulus)];
michael@0 681 kp->prime2.size = modulus/2;
michael@0 682 ckcapi_ReverseData(&kp->prime2);
michael@0 683 kp->exponent1.data = &blob->data[CAPI_EXPONENT_1_OFFSET(modulus)];
michael@0 684 kp->exponent1.size = modulus/2;
michael@0 685 ckcapi_ReverseData(&kp->exponent1);
michael@0 686 kp->exponent2.data = &blob->data[CAPI_EXPONENT_2_OFFSET(modulus)];
michael@0 687 kp->exponent2.size = modulus/2;
michael@0 688 ckcapi_ReverseData(&kp->exponent2);
michael@0 689 kp->coefficient.data = &blob->data[CAPI_COEFFICIENT_OFFSET(modulus)];
michael@0 690 kp->coefficient.size = modulus/2;
michael@0 691 ckcapi_ReverseData(&kp->coefficient);
michael@0 692
michael@0 693 loser:
michael@0 694 nss_ZFreeIf(buf);
michael@0 695 if (0 != hKey) {
michael@0 696 CryptDestroyKey(hKey);
michael@0 697 }
michael@0 698 return;
michael@0 699 }
michael@0 700
michael@0 701
michael@0 702 void
michael@0 703 ckcapi_PopulateModulusExponent
michael@0 704 (
michael@0 705 ckcapiInternalObject *io
michael@0 706 )
michael@0 707 {
michael@0 708 if (ckcapiCert == io->type) {
michael@0 709 ckcapi_CertPopulateModulusExponent(io);
michael@0 710 } else {
michael@0 711 ckcapi_FetchPublicKey(io);
michael@0 712 }
michael@0 713 return;
michael@0 714 }
michael@0 715
michael@0 716 /*
michael@0 717 * fetch the friendly name attribute.
michael@0 718 * can only be called with ckcapiCert type objects!
michael@0 719 */
michael@0 720 void
michael@0 721 ckcapi_FetchLabel
michael@0 722 (
michael@0 723 ckcapiInternalObject *io
michael@0 724 )
michael@0 725 {
michael@0 726 ckcapiCertObject *co = &io->u.cert;
michael@0 727 char *label;
michael@0 728 PCCERT_CONTEXT certContext = io->u.cert.certContext;
michael@0 729 char labelDataUTF16[128];
michael@0 730 DWORD size = sizeof(labelDataUTF16);
michael@0 731 DWORD size8 = sizeof(co->labelData);
michael@0 732 BOOL rv;
michael@0 733
michael@0 734 rv = CertGetCertificateContextProperty(certContext,
michael@0 735 CERT_FRIENDLY_NAME_PROP_ID, labelDataUTF16, &size);
michael@0 736 if (rv) {
michael@0 737 co->labelData = nss_ckcapi_WideToUTF8((LPCWSTR)labelDataUTF16);
michael@0 738 if ((CHAR *)NULL == co->labelData) {
michael@0 739 rv = 0;
michael@0 740 } else {
michael@0 741 size = strlen(co->labelData);
michael@0 742 }
michael@0 743 }
michael@0 744 label = co->labelData;
michael@0 745 /* we are presuming a user cert, make sure it has a nickname, even if
michael@0 746 * Microsoft never gave it one */
michael@0 747 if (!rv && co->hasID) {
michael@0 748 DWORD mserror = GetLastError();
michael@0 749 #define DEFAULT_NICKNAME "no Microsoft nickname"
michael@0 750 label = DEFAULT_NICKNAME;
michael@0 751 size = sizeof(DEFAULT_NICKNAME);
michael@0 752 rv = 1;
michael@0 753 }
michael@0 754
michael@0 755 if (rv) {
michael@0 756 co->label.data = label;
michael@0 757 co->label.size = size;
michael@0 758 }
michael@0 759 return;
michael@0 760 }
michael@0 761
michael@0 762 void
michael@0 763 ckcapi_FetchSerial
michael@0 764 (
michael@0 765 ckcapiInternalObject *io
michael@0 766 )
michael@0 767 {
michael@0 768 ckcapiCertObject *co = &io->u.cert;
michael@0 769 PCCERT_CONTEXT certContext = io->u.cert.certContext;
michael@0 770 DWORD size = sizeof(co->derSerial);
michael@0 771
michael@0 772 BOOL rc = CryptEncodeObject(X509_ASN_ENCODING,
michael@0 773 X509_MULTI_BYTE_INTEGER,
michael@0 774 &certContext->pCertInfo->SerialNumber,
michael@0 775 co->derSerial,
michael@0 776 &size);
michael@0 777 if (rc) {
michael@0 778 co->serial.data = co->derSerial;
michael@0 779 co->serial.size = size;
michael@0 780 }
michael@0 781 return;
michael@0 782 }
michael@0 783
michael@0 784 /*
michael@0 785 * fetch the key ID.
michael@0 786 */
michael@0 787 void
michael@0 788 ckcapi_FetchID
michael@0 789 (
michael@0 790 ckcapiInternalObject *io
michael@0 791 )
michael@0 792 {
michael@0 793 PCCERT_CONTEXT certContext = io->u.cert.certContext;
michael@0 794 DWORD size = 0;
michael@0 795 BOOL rc;
michael@0 796
michael@0 797 rc = CertGetCertificateContextProperty(certContext,
michael@0 798 CERT_KEY_IDENTIFIER_PROP_ID, NULL, &size);
michael@0 799 if (!rc) {
michael@0 800 return;
michael@0 801 }
michael@0 802 io->idData = nss_ZNEWARRAY(NULL, char, size);
michael@0 803 if (io->idData == NULL) {
michael@0 804 return;
michael@0 805 }
michael@0 806
michael@0 807 rc = CertGetCertificateContextProperty(certContext,
michael@0 808 CERT_KEY_IDENTIFIER_PROP_ID, io->idData, &size);
michael@0 809 if (!rc) {
michael@0 810 nss_ZFreeIf(io->idData);
michael@0 811 io->idData = NULL;
michael@0 812 return;
michael@0 813 }
michael@0 814 io->id.data = io->idData;
michael@0 815 io->id.size = size;
michael@0 816 return;
michael@0 817 }
michael@0 818
michael@0 819 /*
michael@0 820 * fetch the hash key.
michael@0 821 */
michael@0 822 void
michael@0 823 ckcapi_CertFetchHashKey
michael@0 824 (
michael@0 825 ckcapiInternalObject *io
michael@0 826 )
michael@0 827 {
michael@0 828 ckcapiCertObject *co = &io->u.cert;
michael@0 829 PCCERT_CONTEXT certContext = io->u.cert.certContext;
michael@0 830 DWORD size = certContext->cbCertEncoded;
michael@0 831 DWORD max = sizeof(io->hashKeyData)-1;
michael@0 832 DWORD offset = 0;
michael@0 833
michael@0 834 /* make sure we don't over flow. NOTE: cutting the top of a cert is
michael@0 835 * not a big issue because the signature for will be unique for the cert */
michael@0 836 if (size > max) {
michael@0 837 offset = size - max;
michael@0 838 size = max;
michael@0 839 }
michael@0 840
michael@0 841 nsslibc_memcpy(io->hashKeyData,certContext->pbCertEncoded+offset, size);
michael@0 842 io->hashKeyData[size] = (char)(io->objClass & 0xff);
michael@0 843
michael@0 844 io->hashKey.data = io->hashKeyData;
michael@0 845 io->hashKey.size = size+1;
michael@0 846 return;
michael@0 847 }
michael@0 848
michael@0 849 /*
michael@0 850 * fetch the hash key.
michael@0 851 */
michael@0 852 void
michael@0 853 ckcapi_KeyFetchHashKey
michael@0 854 (
michael@0 855 ckcapiInternalObject *io
michael@0 856 )
michael@0 857 {
michael@0 858 ckcapiKeyObject *ko = &io->u.key;
michael@0 859 DWORD size;
michael@0 860 DWORD max = sizeof(io->hashKeyData)-2;
michael@0 861 DWORD offset = 0;
michael@0 862 DWORD provLen = strlen(ko->provName);
michael@0 863 DWORD containerLen = strlen(ko->containerName);
michael@0 864
michael@0 865
michael@0 866 size = provLen + containerLen;
michael@0 867
michael@0 868 /* make sure we don't overflow, try to keep things unique */
michael@0 869 if (size > max) {
michael@0 870 DWORD diff = ((size - max)+1)/2;
michael@0 871 provLen -= diff;
michael@0 872 containerLen -= diff;
michael@0 873 size = provLen+containerLen;
michael@0 874 }
michael@0 875
michael@0 876 nsslibc_memcpy(io->hashKeyData, ko->provName, provLen);
michael@0 877 nsslibc_memcpy(&io->hashKeyData[provLen],
michael@0 878 ko->containerName,
michael@0 879 containerLen);
michael@0 880 io->hashKeyData[size] = (char)(io->objClass & 0xff);
michael@0 881 io->hashKeyData[size+1] = (char)(ko->provInfo.dwKeySpec & 0xff);
michael@0 882
michael@0 883 io->hashKey.data = io->hashKeyData;
michael@0 884 io->hashKey.size = size+2;
michael@0 885 return;
michael@0 886 }
michael@0 887
michael@0 888 /*
michael@0 889 * fetch the hash key.
michael@0 890 */
michael@0 891 void
michael@0 892 ckcapi_FetchHashKey
michael@0 893 (
michael@0 894 ckcapiInternalObject *io
michael@0 895 )
michael@0 896 {
michael@0 897 if (ckcapiCert == io->type) {
michael@0 898 ckcapi_CertFetchHashKey(io);
michael@0 899 } else {
michael@0 900 ckcapi_KeyFetchHashKey(io);
michael@0 901 }
michael@0 902 return;
michael@0 903 }
michael@0 904
michael@0 905 const NSSItem *
michael@0 906 ckcapi_FetchCertAttribute
michael@0 907 (
michael@0 908 ckcapiInternalObject *io,
michael@0 909 CK_ATTRIBUTE_TYPE type
michael@0 910 )
michael@0 911 {
michael@0 912 PCCERT_CONTEXT certContext = io->u.cert.certContext;
michael@0 913 switch(type) {
michael@0 914 case CKA_CLASS:
michael@0 915 return &ckcapi_certClassItem;
michael@0 916 case CKA_TOKEN:
michael@0 917 return &ckcapi_trueItem;
michael@0 918 case CKA_MODIFIABLE:
michael@0 919 case CKA_PRIVATE:
michael@0 920 return &ckcapi_falseItem;
michael@0 921 case CKA_CERTIFICATE_TYPE:
michael@0 922 return &ckcapi_x509Item;
michael@0 923 case CKA_LABEL:
michael@0 924 if (0 == io->u.cert.label.size) {
michael@0 925 ckcapi_FetchLabel(io);
michael@0 926 }
michael@0 927 return &io->u.cert.label;
michael@0 928 case CKA_SUBJECT:
michael@0 929 if (0 == io->u.cert.subject.size) {
michael@0 930 io->u.cert.subject.data = certContext->pCertInfo->Subject.pbData;
michael@0 931 io->u.cert.subject.size = certContext->pCertInfo->Subject.cbData;
michael@0 932 }
michael@0 933 return &io->u.cert.subject;
michael@0 934 case CKA_ISSUER:
michael@0 935 if (0 == io->u.cert.issuer.size) {
michael@0 936 io->u.cert.issuer.data = certContext->pCertInfo->Issuer.pbData;
michael@0 937 io->u.cert.issuer.size = certContext->pCertInfo->Issuer.cbData;
michael@0 938 }
michael@0 939 return &io->u.cert.issuer;
michael@0 940 case CKA_SERIAL_NUMBER:
michael@0 941 if (0 == io->u.cert.serial.size) {
michael@0 942 /* not exactly right. This should be the encoded serial number, but
michael@0 943 * it's the decoded serial number! */
michael@0 944 ckcapi_FetchSerial(io);
michael@0 945 }
michael@0 946 return &io->u.cert.serial;
michael@0 947 case CKA_VALUE:
michael@0 948 if (0 == io->u.cert.derCert.size) {
michael@0 949 io->u.cert.derCert.data = io->u.cert.certContext->pbCertEncoded;
michael@0 950 io->u.cert.derCert.size = io->u.cert.certContext->cbCertEncoded;
michael@0 951 }
michael@0 952 return &io->u.cert.derCert;
michael@0 953 case CKA_ID:
michael@0 954 if (!io->u.cert.hasID) {
michael@0 955 return NULL;
michael@0 956 }
michael@0 957 if (0 == io->id.size) {
michael@0 958 ckcapi_FetchID(io);
michael@0 959 }
michael@0 960 return &io->id;
michael@0 961 default:
michael@0 962 break;
michael@0 963 }
michael@0 964 return NULL;
michael@0 965 }
michael@0 966
michael@0 967 const NSSItem *
michael@0 968 ckcapi_FetchPubKeyAttribute
michael@0 969 (
michael@0 970 ckcapiInternalObject *io,
michael@0 971 CK_ATTRIBUTE_TYPE type
michael@0 972 )
michael@0 973 {
michael@0 974 PRBool isCertType = (ckcapiCert == io->type);
michael@0 975 ckcapiKeyParams *kp = isCertType ? &io->u.cert.key : &io->u.key.key;
michael@0 976
michael@0 977 switch(type) {
michael@0 978 case CKA_CLASS:
michael@0 979 return &ckcapi_pubKeyClassItem;
michael@0 980 case CKA_TOKEN:
michael@0 981 case CKA_LOCAL:
michael@0 982 case CKA_ENCRYPT:
michael@0 983 case CKA_VERIFY:
michael@0 984 case CKA_VERIFY_RECOVER:
michael@0 985 return &ckcapi_trueItem;
michael@0 986 case CKA_PRIVATE:
michael@0 987 case CKA_MODIFIABLE:
michael@0 988 case CKA_DERIVE:
michael@0 989 case CKA_WRAP:
michael@0 990 return &ckcapi_falseItem;
michael@0 991 case CKA_KEY_TYPE:
michael@0 992 return &ckcapi_rsaItem;
michael@0 993 case CKA_LABEL:
michael@0 994 if (!isCertType) {
michael@0 995 return &ckcapi_emptyItem;
michael@0 996 }
michael@0 997 if (0 == io->u.cert.label.size) {
michael@0 998 ckcapi_FetchLabel(io);
michael@0 999 }
michael@0 1000 return &io->u.cert.label;
michael@0 1001 case CKA_SUBJECT:
michael@0 1002 if (!isCertType) {
michael@0 1003 return &ckcapi_emptyItem;
michael@0 1004 }
michael@0 1005 if (0 == io->u.cert.subject.size) {
michael@0 1006 PCCERT_CONTEXT certContext= io->u.cert.certContext;
michael@0 1007 io->u.cert.subject.data = certContext->pCertInfo->Subject.pbData;
michael@0 1008 io->u.cert.subject.size = certContext->pCertInfo->Subject.cbData;
michael@0 1009 }
michael@0 1010 return &io->u.cert.subject;
michael@0 1011 case CKA_MODULUS:
michael@0 1012 if (0 == kp->modulus.size) {
michael@0 1013 ckcapi_PopulateModulusExponent(io);
michael@0 1014 }
michael@0 1015 return &kp->modulus;
michael@0 1016 case CKA_PUBLIC_EXPONENT:
michael@0 1017 if (0 == kp->modulus.size) {
michael@0 1018 ckcapi_PopulateModulusExponent(io);
michael@0 1019 }
michael@0 1020 return &kp->exponent;
michael@0 1021 case CKA_ID:
michael@0 1022 if (0 == io->id.size) {
michael@0 1023 ckcapi_FetchID(io);
michael@0 1024 }
michael@0 1025 return &io->id;
michael@0 1026 default:
michael@0 1027 break;
michael@0 1028 }
michael@0 1029 return NULL;
michael@0 1030 }
michael@0 1031
michael@0 1032 const NSSItem *
michael@0 1033 ckcapi_FetchPrivKeyAttribute
michael@0 1034 (
michael@0 1035 ckcapiInternalObject *io,
michael@0 1036 CK_ATTRIBUTE_TYPE type
michael@0 1037 )
michael@0 1038 {
michael@0 1039 PRBool isCertType = (ckcapiCert == io->type);
michael@0 1040 ckcapiKeyParams *kp = isCertType ? &io->u.cert.key : &io->u.key.key;
michael@0 1041
michael@0 1042 switch(type) {
michael@0 1043 case CKA_CLASS:
michael@0 1044 return &ckcapi_privKeyClassItem;
michael@0 1045 case CKA_TOKEN:
michael@0 1046 case CKA_LOCAL:
michael@0 1047 case CKA_SIGN:
michael@0 1048 case CKA_DECRYPT:
michael@0 1049 case CKA_SIGN_RECOVER:
michael@0 1050 return &ckcapi_trueItem;
michael@0 1051 case CKA_SENSITIVE:
michael@0 1052 case CKA_PRIVATE: /* should move in the future */
michael@0 1053 case CKA_MODIFIABLE:
michael@0 1054 case CKA_DERIVE:
michael@0 1055 case CKA_UNWRAP:
michael@0 1056 case CKA_EXTRACTABLE: /* will probably move in the future */
michael@0 1057 case CKA_ALWAYS_SENSITIVE:
michael@0 1058 case CKA_NEVER_EXTRACTABLE:
michael@0 1059 return &ckcapi_falseItem;
michael@0 1060 case CKA_KEY_TYPE:
michael@0 1061 return &ckcapi_rsaItem;
michael@0 1062 case CKA_LABEL:
michael@0 1063 if (!isCertType) {
michael@0 1064 return &ckcapi_emptyItem;
michael@0 1065 }
michael@0 1066 if (0 == io->u.cert.label.size) {
michael@0 1067 ckcapi_FetchLabel(io);
michael@0 1068 }
michael@0 1069 return &io->u.cert.label;
michael@0 1070 case CKA_SUBJECT:
michael@0 1071 if (!isCertType) {
michael@0 1072 return &ckcapi_emptyItem;
michael@0 1073 }
michael@0 1074 if (0 == io->u.cert.subject.size) {
michael@0 1075 PCCERT_CONTEXT certContext= io->u.cert.certContext;
michael@0 1076 io->u.cert.subject.data = certContext->pCertInfo->Subject.pbData;
michael@0 1077 io->u.cert.subject.size = certContext->pCertInfo->Subject.cbData;
michael@0 1078 }
michael@0 1079 return &io->u.cert.subject;
michael@0 1080 case CKA_MODULUS:
michael@0 1081 if (0 == kp->modulus.size) {
michael@0 1082 ckcapi_PopulateModulusExponent(io);
michael@0 1083 }
michael@0 1084 return &kp->modulus;
michael@0 1085 case CKA_PUBLIC_EXPONENT:
michael@0 1086 if (0 == kp->modulus.size) {
michael@0 1087 ckcapi_PopulateModulusExponent(io);
michael@0 1088 }
michael@0 1089 return &kp->exponent;
michael@0 1090 case CKA_PRIVATE_EXPONENT:
michael@0 1091 if (0 == kp->privateExponent.size) {
michael@0 1092 ckcapi_FetchPrivateKey(io);
michael@0 1093 }
michael@0 1094 return &kp->privateExponent;
michael@0 1095 case CKA_PRIME_1:
michael@0 1096 if (0 == kp->privateExponent.size) {
michael@0 1097 ckcapi_FetchPrivateKey(io);
michael@0 1098 }
michael@0 1099 return &kp->prime1;
michael@0 1100 case CKA_PRIME_2:
michael@0 1101 if (0 == kp->privateExponent.size) {
michael@0 1102 ckcapi_FetchPrivateKey(io);
michael@0 1103 }
michael@0 1104 return &kp->prime2;
michael@0 1105 case CKA_EXPONENT_1:
michael@0 1106 if (0 == kp->privateExponent.size) {
michael@0 1107 ckcapi_FetchPrivateKey(io);
michael@0 1108 }
michael@0 1109 return &kp->exponent1;
michael@0 1110 case CKA_EXPONENT_2:
michael@0 1111 if (0 == kp->privateExponent.size) {
michael@0 1112 ckcapi_FetchPrivateKey(io);
michael@0 1113 }
michael@0 1114 return &kp->exponent2;
michael@0 1115 case CKA_COEFFICIENT:
michael@0 1116 if (0 == kp->privateExponent.size) {
michael@0 1117 ckcapi_FetchPrivateKey(io);
michael@0 1118 }
michael@0 1119 return &kp->coefficient;
michael@0 1120 case CKA_ID:
michael@0 1121 if (0 == io->id.size) {
michael@0 1122 ckcapi_FetchID(io);
michael@0 1123 }
michael@0 1124 return &io->id;
michael@0 1125 default:
michael@0 1126 return NULL;
michael@0 1127 }
michael@0 1128 }
michael@0 1129
michael@0 1130 const NSSItem *
michael@0 1131 nss_ckcapi_FetchAttribute
michael@0 1132 (
michael@0 1133 ckcapiInternalObject *io,
michael@0 1134 CK_ATTRIBUTE_TYPE type
michael@0 1135 )
michael@0 1136 {
michael@0 1137 CK_ULONG i;
michael@0 1138
michael@0 1139 if (io->type == ckcapiRaw) {
michael@0 1140 for( i = 0; i < io->u.raw.n; i++ ) {
michael@0 1141 if( type == io->u.raw.types[i] ) {
michael@0 1142 return &io->u.raw.items[i];
michael@0 1143 }
michael@0 1144 }
michael@0 1145 return NULL;
michael@0 1146 }
michael@0 1147 /* deal with the common attributes */
michael@0 1148 switch (io->objClass) {
michael@0 1149 case CKO_CERTIFICATE:
michael@0 1150 return ckcapi_FetchCertAttribute(io, type);
michael@0 1151 case CKO_PRIVATE_KEY:
michael@0 1152 return ckcapi_FetchPrivKeyAttribute(io, type);
michael@0 1153 case CKO_PUBLIC_KEY:
michael@0 1154 return ckcapi_FetchPubKeyAttribute(io, type);
michael@0 1155 }
michael@0 1156 return NULL;
michael@0 1157 }
michael@0 1158
michael@0 1159 /*
michael@0 1160 * check to see if the certificate already exists
michael@0 1161 */
michael@0 1162 static PRBool
michael@0 1163 ckcapi_cert_exists(
michael@0 1164 NSSItem *value,
michael@0 1165 ckcapiInternalObject **io
michael@0 1166 )
michael@0 1167 {
michael@0 1168 int count,i;
michael@0 1169 PRUint32 size = 0;
michael@0 1170 ckcapiInternalObject **listp = NULL;
michael@0 1171 CK_ATTRIBUTE myTemplate[2];
michael@0 1172 CK_OBJECT_CLASS cert_class = CKO_CERTIFICATE;
michael@0 1173 CK_ULONG templateCount = 2;
michael@0 1174 CK_RV error;
michael@0 1175 PRBool found = PR_FALSE;
michael@0 1176
michael@0 1177 myTemplate[0].type = CKA_CLASS;
michael@0 1178 myTemplate[0].pValue = &cert_class;
michael@0 1179 myTemplate[0].ulValueLen = sizeof(cert_class);
michael@0 1180 myTemplate[1].type = CKA_VALUE;
michael@0 1181 myTemplate[1].pValue = value->data;
michael@0 1182 myTemplate[1].ulValueLen = value->size;
michael@0 1183
michael@0 1184 count = nss_ckcapi_collect_all_certs(myTemplate, templateCount, &listp,
michael@0 1185 &size, 0, &error);
michael@0 1186
michael@0 1187 /* free them */
michael@0 1188 if (count > 1) {
michael@0 1189 *io = listp[0];
michael@0 1190 found = PR_TRUE;
michael@0 1191 }
michael@0 1192
michael@0 1193 for (i=1; i < count; i++) {
michael@0 1194 nss_ckcapi_DestroyInternalObject(listp[i]);
michael@0 1195 }
michael@0 1196 nss_ZFreeIf(listp);
michael@0 1197 return found;
michael@0 1198 }
michael@0 1199
michael@0 1200 static PRBool
michael@0 1201 ckcapi_cert_hasEmail
michael@0 1202 (
michael@0 1203 PCCERT_CONTEXT certContext
michael@0 1204 )
michael@0 1205 {
michael@0 1206 int count;
michael@0 1207
michael@0 1208 count = CertGetNameString(certContext, CERT_NAME_EMAIL_TYPE,
michael@0 1209 0, NULL, NULL, 0);
michael@0 1210
michael@0 1211 return count > 1 ? PR_TRUE : PR_FALSE;
michael@0 1212 }
michael@0 1213
michael@0 1214 static PRBool
michael@0 1215 ckcapi_cert_isRoot
michael@0 1216 (
michael@0 1217 PCCERT_CONTEXT certContext
michael@0 1218 )
michael@0 1219 {
michael@0 1220 return CertCompareCertificateName(certContext->dwCertEncodingType,
michael@0 1221 &certContext->pCertInfo->Issuer, &certContext->pCertInfo->Subject);
michael@0 1222 }
michael@0 1223
michael@0 1224 static PRBool
michael@0 1225 ckcapi_cert_isCA
michael@0 1226 (
michael@0 1227 PCCERT_CONTEXT certContext
michael@0 1228 )
michael@0 1229 {
michael@0 1230 PCERT_EXTENSION extension;
michael@0 1231 CERT_BASIC_CONSTRAINTS2_INFO basicInfo;
michael@0 1232 DWORD size = sizeof(basicInfo);
michael@0 1233 BOOL rc;
michael@0 1234
michael@0 1235 extension = CertFindExtension (szOID_BASIC_CONSTRAINTS,
michael@0 1236 certContext->pCertInfo->cExtension,
michael@0 1237 certContext->pCertInfo->rgExtension);
michael@0 1238 if ((PCERT_EXTENSION) NULL == extension ) {
michael@0 1239 return PR_FALSE;
michael@0 1240 }
michael@0 1241 rc = CryptDecodeObject(X509_ASN_ENCODING, szOID_BASIC_CONSTRAINTS2,
michael@0 1242 extension->Value.pbData, extension->Value.cbData,
michael@0 1243 0, &basicInfo, &size);
michael@0 1244 if (!rc) {
michael@0 1245 return PR_FALSE;
michael@0 1246 }
michael@0 1247 return (PRBool) basicInfo.fCA;
michael@0 1248 }
michael@0 1249
michael@0 1250 static CRYPT_KEY_PROV_INFO *
michael@0 1251 ckcapi_cert_getPrivateKeyInfo
michael@0 1252 (
michael@0 1253 PCCERT_CONTEXT certContext,
michael@0 1254 NSSItem *keyID
michael@0 1255 )
michael@0 1256 {
michael@0 1257 BOOL rc;
michael@0 1258 CRYPT_HASH_BLOB msKeyID;
michael@0 1259 DWORD size = 0;
michael@0 1260 CRYPT_KEY_PROV_INFO *prov = NULL;
michael@0 1261
michael@0 1262 msKeyID.cbData = keyID->size;
michael@0 1263 msKeyID.pbData = keyID->data;
michael@0 1264
michael@0 1265 rc = CryptGetKeyIdentifierProperty(
michael@0 1266 &msKeyID,
michael@0 1267 CERT_KEY_PROV_INFO_PROP_ID,
michael@0 1268 0, NULL, NULL, NULL, &size);
michael@0 1269 if (!rc) {
michael@0 1270 return (CRYPT_KEY_PROV_INFO *)NULL;
michael@0 1271 }
michael@0 1272 prov = (CRYPT_KEY_PROV_INFO *)nss_ZAlloc(NULL, size);
michael@0 1273 if ((CRYPT_KEY_PROV_INFO *)prov == NULL) {
michael@0 1274 return (CRYPT_KEY_PROV_INFO *) NULL;
michael@0 1275 }
michael@0 1276 rc = CryptGetKeyIdentifierProperty(
michael@0 1277 &msKeyID,
michael@0 1278 CERT_KEY_PROV_INFO_PROP_ID,
michael@0 1279 0, NULL, NULL, prov, &size);
michael@0 1280 if (!rc) {
michael@0 1281 nss_ZFreeIf(prov);
michael@0 1282 return (CRYPT_KEY_PROV_INFO *)NULL;
michael@0 1283 }
michael@0 1284
michael@0 1285 return prov;
michael@0 1286 }
michael@0 1287
michael@0 1288 static CRYPT_KEY_PROV_INFO *
michael@0 1289 ckcapi_cert_getProvInfo
michael@0 1290 (
michael@0 1291 ckcapiInternalObject *io
michael@0 1292 )
michael@0 1293 {
michael@0 1294 BOOL rc;
michael@0 1295 DWORD size = 0;
michael@0 1296 CRYPT_KEY_PROV_INFO *prov = NULL;
michael@0 1297
michael@0 1298 rc = CertGetCertificateContextProperty(
michael@0 1299 io->u.cert.certContext,
michael@0 1300 CERT_KEY_PROV_INFO_PROP_ID,
michael@0 1301 NULL, &size);
michael@0 1302 if (!rc) {
michael@0 1303 return (CRYPT_KEY_PROV_INFO *)NULL;
michael@0 1304 }
michael@0 1305 prov = (CRYPT_KEY_PROV_INFO *)nss_ZAlloc(NULL, size);
michael@0 1306 if ((CRYPT_KEY_PROV_INFO *)prov == NULL) {
michael@0 1307 return (CRYPT_KEY_PROV_INFO *) NULL;
michael@0 1308 }
michael@0 1309 rc = CertGetCertificateContextProperty(
michael@0 1310 io->u.cert.certContext,
michael@0 1311 CERT_KEY_PROV_INFO_PROP_ID,
michael@0 1312 prov, &size);
michael@0 1313 if (!rc) {
michael@0 1314 nss_ZFreeIf(prov);
michael@0 1315 return (CRYPT_KEY_PROV_INFO *)NULL;
michael@0 1316 }
michael@0 1317
michael@0 1318 return prov;
michael@0 1319 }
michael@0 1320
michael@0 1321 /* forward declaration */
michael@0 1322 static void
michael@0 1323 ckcapi_removeObjectFromHash
michael@0 1324 (
michael@0 1325 ckcapiInternalObject *io
michael@0 1326 );
michael@0 1327
michael@0 1328 /*
michael@0 1329 * Finalize - unneeded
michael@0 1330 * Destroy
michael@0 1331 * IsTokenObject - CK_TRUE
michael@0 1332 * GetAttributeCount
michael@0 1333 * GetAttributeTypes
michael@0 1334 * GetAttributeSize
michael@0 1335 * GetAttribute
michael@0 1336 * SetAttribute
michael@0 1337 * GetObjectSize
michael@0 1338 */
michael@0 1339
michael@0 1340 static CK_RV
michael@0 1341 ckcapi_mdObject_Destroy
michael@0 1342 (
michael@0 1343 NSSCKMDObject *mdObject,
michael@0 1344 NSSCKFWObject *fwObject,
michael@0 1345 NSSCKMDSession *mdSession,
michael@0 1346 NSSCKFWSession *fwSession,
michael@0 1347 NSSCKMDToken *mdToken,
michael@0 1348 NSSCKFWToken *fwToken,
michael@0 1349 NSSCKMDInstance *mdInstance,
michael@0 1350 NSSCKFWInstance *fwInstance
michael@0 1351 )
michael@0 1352 {
michael@0 1353 ckcapiInternalObject *io = (ckcapiInternalObject *)mdObject->etc;
michael@0 1354 CK_OBJECT_CLASS objClass;
michael@0 1355 BOOL rc;
michael@0 1356 DWORD provType;
michael@0 1357 DWORD msError;
michael@0 1358 PRBool isCertType = (PRBool)(ckcapiCert == io->type);
michael@0 1359 HCERTSTORE hStore = 0;
michael@0 1360
michael@0 1361 if (ckcapiRaw == io->type) {
michael@0 1362 /* there is not 'object write protected' error, use the next best thing */
michael@0 1363 return CKR_TOKEN_WRITE_PROTECTED;
michael@0 1364 }
michael@0 1365
michael@0 1366 objClass = io->objClass;
michael@0 1367 if (CKO_CERTIFICATE == objClass) {
michael@0 1368 PCCERT_CONTEXT certContext;
michael@0 1369
michael@0 1370 /* get the store */
michael@0 1371 hStore = CertOpenSystemStore(0, io->u.cert.certStore);
michael@0 1372 if (0 == hStore) {
michael@0 1373 rc = 0;
michael@0 1374 goto loser;
michael@0 1375 }
michael@0 1376 certContext = CertFindCertificateInStore(hStore, X509_ASN_ENCODING, 0,
michael@0 1377 CERT_FIND_EXISTING, io->u.cert.certContext, NULL);
michael@0 1378 if ((PCCERT_CONTEXT)NULL == certContext) {
michael@0 1379 rc = 0;
michael@0 1380 goto loser;
michael@0 1381 }
michael@0 1382 rc = CertDeleteCertificateFromStore(certContext);
michael@0 1383 } else {
michael@0 1384 char *provName = NULL;
michael@0 1385 char *containerName = NULL;
michael@0 1386 HCRYPTPROV hProv;
michael@0 1387 CRYPT_HASH_BLOB msKeyID;
michael@0 1388
michael@0 1389 if (0 == io->id.size) {
michael@0 1390 ckcapi_FetchID(io);
michael@0 1391 }
michael@0 1392
michael@0 1393 if (isCertType) {
michael@0 1394 CRYPT_KEY_PROV_INFO * provInfo = ckcapi_cert_getProvInfo(io);
michael@0 1395 provName = nss_ckcapi_WideToUTF8(provInfo->pwszProvName);
michael@0 1396 containerName = nss_ckcapi_WideToUTF8(provInfo->pwszContainerName);
michael@0 1397 provType = provInfo->dwProvType;
michael@0 1398 nss_ZFreeIf(provInfo);
michael@0 1399 } else {
michael@0 1400 provName = io->u.key.provName;
michael@0 1401 containerName = io->u.key.containerName;
michael@0 1402 provType = io->u.key.provInfo.dwProvType;
michael@0 1403 io->u.key.provName = NULL;
michael@0 1404 io->u.key.containerName = NULL;
michael@0 1405 }
michael@0 1406 /* first remove the key id pointer */
michael@0 1407 msKeyID.cbData = io->id.size;
michael@0 1408 msKeyID.pbData = io->id.data;
michael@0 1409 rc = CryptSetKeyIdentifierProperty(&msKeyID,
michael@0 1410 CERT_KEY_PROV_INFO_PROP_ID, CRYPT_KEYID_DELETE_FLAG, NULL, NULL, NULL);
michael@0 1411 if (rc) {
michael@0 1412 rc = CryptAcquireContext(&hProv, containerName, provName, provType,
michael@0 1413 CRYPT_DELETEKEYSET);
michael@0 1414 }
michael@0 1415 nss_ZFreeIf(provName);
michael@0 1416 nss_ZFreeIf(containerName);
michael@0 1417 }
michael@0 1418 loser:
michael@0 1419
michael@0 1420 if (hStore) {
michael@0 1421 CertCloseStore(hStore, 0);
michael@0 1422 }
michael@0 1423 if (!rc) {
michael@0 1424 msError = GetLastError();
michael@0 1425 return CKR_GENERAL_ERROR;
michael@0 1426 }
michael@0 1427
michael@0 1428 /* remove it from the hash */
michael@0 1429 ckcapi_removeObjectFromHash(io);
michael@0 1430
michael@0 1431 /* free the puppy.. */
michael@0 1432 nss_ckcapi_DestroyInternalObject(io);
michael@0 1433 return CKR_OK;
michael@0 1434 }
michael@0 1435
michael@0 1436 static CK_BBOOL
michael@0 1437 ckcapi_mdObject_IsTokenObject
michael@0 1438 (
michael@0 1439 NSSCKMDObject *mdObject,
michael@0 1440 NSSCKFWObject *fwObject,
michael@0 1441 NSSCKMDSession *mdSession,
michael@0 1442 NSSCKFWSession *fwSession,
michael@0 1443 NSSCKMDToken *mdToken,
michael@0 1444 NSSCKFWToken *fwToken,
michael@0 1445 NSSCKMDInstance *mdInstance,
michael@0 1446 NSSCKFWInstance *fwInstance
michael@0 1447 )
michael@0 1448 {
michael@0 1449 return CK_TRUE;
michael@0 1450 }
michael@0 1451
michael@0 1452 static CK_ULONG
michael@0 1453 ckcapi_mdObject_GetAttributeCount
michael@0 1454 (
michael@0 1455 NSSCKMDObject *mdObject,
michael@0 1456 NSSCKFWObject *fwObject,
michael@0 1457 NSSCKMDSession *mdSession,
michael@0 1458 NSSCKFWSession *fwSession,
michael@0 1459 NSSCKMDToken *mdToken,
michael@0 1460 NSSCKFWToken *fwToken,
michael@0 1461 NSSCKMDInstance *mdInstance,
michael@0 1462 NSSCKFWInstance *fwInstance,
michael@0 1463 CK_RV *pError
michael@0 1464 )
michael@0 1465 {
michael@0 1466 ckcapiInternalObject *io = (ckcapiInternalObject *)mdObject->etc;
michael@0 1467
michael@0 1468 if (ckcapiRaw == io->type) {
michael@0 1469 return io->u.raw.n;
michael@0 1470 }
michael@0 1471 switch (io->objClass) {
michael@0 1472 case CKO_CERTIFICATE:
michael@0 1473 return certAttrsCount;
michael@0 1474 case CKO_PUBLIC_KEY:
michael@0 1475 return pubKeyAttrsCount;
michael@0 1476 case CKO_PRIVATE_KEY:
michael@0 1477 return privKeyAttrsCount;
michael@0 1478 default:
michael@0 1479 break;
michael@0 1480 }
michael@0 1481 return 0;
michael@0 1482 }
michael@0 1483
michael@0 1484 static CK_RV
michael@0 1485 ckcapi_mdObject_GetAttributeTypes
michael@0 1486 (
michael@0 1487 NSSCKMDObject *mdObject,
michael@0 1488 NSSCKFWObject *fwObject,
michael@0 1489 NSSCKMDSession *mdSession,
michael@0 1490 NSSCKFWSession *fwSession,
michael@0 1491 NSSCKMDToken *mdToken,
michael@0 1492 NSSCKFWToken *fwToken,
michael@0 1493 NSSCKMDInstance *mdInstance,
michael@0 1494 NSSCKFWInstance *fwInstance,
michael@0 1495 CK_ATTRIBUTE_TYPE_PTR typeArray,
michael@0 1496 CK_ULONG ulCount
michael@0 1497 )
michael@0 1498 {
michael@0 1499 ckcapiInternalObject *io = (ckcapiInternalObject *)mdObject->etc;
michael@0 1500 CK_ULONG i;
michael@0 1501 CK_RV error = CKR_OK;
michael@0 1502 const CK_ATTRIBUTE_TYPE *attrs = NULL;
michael@0 1503 CK_ULONG size = ckcapi_mdObject_GetAttributeCount(
michael@0 1504 mdObject, fwObject, mdSession, fwSession,
michael@0 1505 mdToken, fwToken, mdInstance, fwInstance, &error);
michael@0 1506
michael@0 1507 if( size != ulCount ) {
michael@0 1508 return CKR_BUFFER_TOO_SMALL;
michael@0 1509 }
michael@0 1510 if (io->type == ckcapiRaw) {
michael@0 1511 attrs = io->u.raw.types;
michael@0 1512 } else switch(io->objClass) {
michael@0 1513 case CKO_CERTIFICATE:
michael@0 1514 attrs = certAttrs;
michael@0 1515 break;
michael@0 1516 case CKO_PUBLIC_KEY:
michael@0 1517 attrs = pubKeyAttrs;
michael@0 1518 break;
michael@0 1519 case CKO_PRIVATE_KEY:
michael@0 1520 attrs = privKeyAttrs;
michael@0 1521 break;
michael@0 1522 default:
michael@0 1523 return CKR_OK;
michael@0 1524 }
michael@0 1525
michael@0 1526 for( i = 0; i < size; i++) {
michael@0 1527 typeArray[i] = attrs[i];
michael@0 1528 }
michael@0 1529
michael@0 1530 return CKR_OK;
michael@0 1531 }
michael@0 1532
michael@0 1533 static CK_ULONG
michael@0 1534 ckcapi_mdObject_GetAttributeSize
michael@0 1535 (
michael@0 1536 NSSCKMDObject *mdObject,
michael@0 1537 NSSCKFWObject *fwObject,
michael@0 1538 NSSCKMDSession *mdSession,
michael@0 1539 NSSCKFWSession *fwSession,
michael@0 1540 NSSCKMDToken *mdToken,
michael@0 1541 NSSCKFWToken *fwToken,
michael@0 1542 NSSCKMDInstance *mdInstance,
michael@0 1543 NSSCKFWInstance *fwInstance,
michael@0 1544 CK_ATTRIBUTE_TYPE attribute,
michael@0 1545 CK_RV *pError
michael@0 1546 )
michael@0 1547 {
michael@0 1548 ckcapiInternalObject *io = (ckcapiInternalObject *)mdObject->etc;
michael@0 1549
michael@0 1550 const NSSItem *b;
michael@0 1551
michael@0 1552 b = nss_ckcapi_FetchAttribute(io, attribute);
michael@0 1553
michael@0 1554 if ((const NSSItem *)NULL == b) {
michael@0 1555 *pError = CKR_ATTRIBUTE_TYPE_INVALID;
michael@0 1556 return 0;
michael@0 1557 }
michael@0 1558 return b->size;
michael@0 1559 }
michael@0 1560
michael@0 1561 static CK_RV
michael@0 1562 ckcapi_mdObject_SetAttribute
michael@0 1563 (
michael@0 1564 NSSCKMDObject *mdObject,
michael@0 1565 NSSCKFWObject *fwObject,
michael@0 1566 NSSCKMDSession *mdSession,
michael@0 1567 NSSCKFWSession *fwSession,
michael@0 1568 NSSCKMDToken *mdToken,
michael@0 1569 NSSCKFWToken *fwToken,
michael@0 1570 NSSCKMDInstance *mdInstance,
michael@0 1571 NSSCKFWInstance *fwInstance,
michael@0 1572 CK_ATTRIBUTE_TYPE attribute,
michael@0 1573 NSSItem *value
michael@0 1574 )
michael@0 1575 {
michael@0 1576 return CKR_OK;
michael@0 1577 }
michael@0 1578
michael@0 1579 static NSSCKFWItem
michael@0 1580 ckcapi_mdObject_GetAttribute
michael@0 1581 (
michael@0 1582 NSSCKMDObject *mdObject,
michael@0 1583 NSSCKFWObject *fwObject,
michael@0 1584 NSSCKMDSession *mdSession,
michael@0 1585 NSSCKFWSession *fwSession,
michael@0 1586 NSSCKMDToken *mdToken,
michael@0 1587 NSSCKFWToken *fwToken,
michael@0 1588 NSSCKMDInstance *mdInstance,
michael@0 1589 NSSCKFWInstance *fwInstance,
michael@0 1590 CK_ATTRIBUTE_TYPE attribute,
michael@0 1591 CK_RV *pError
michael@0 1592 )
michael@0 1593 {
michael@0 1594 NSSCKFWItem mdItem;
michael@0 1595 ckcapiInternalObject *io = (ckcapiInternalObject *)mdObject->etc;
michael@0 1596
michael@0 1597 mdItem.needsFreeing = PR_FALSE;
michael@0 1598 mdItem.item = (NSSItem*)nss_ckcapi_FetchAttribute(io, attribute);
michael@0 1599
michael@0 1600 if ((NSSItem *)NULL == mdItem.item) {
michael@0 1601 *pError = CKR_ATTRIBUTE_TYPE_INVALID;
michael@0 1602 }
michael@0 1603
michael@0 1604 return mdItem;
michael@0 1605 }
michael@0 1606
michael@0 1607 static CK_ULONG
michael@0 1608 ckcapi_mdObject_GetObjectSize
michael@0 1609 (
michael@0 1610 NSSCKMDObject *mdObject,
michael@0 1611 NSSCKFWObject *fwObject,
michael@0 1612 NSSCKMDSession *mdSession,
michael@0 1613 NSSCKFWSession *fwSession,
michael@0 1614 NSSCKMDToken *mdToken,
michael@0 1615 NSSCKFWToken *fwToken,
michael@0 1616 NSSCKMDInstance *mdInstance,
michael@0 1617 NSSCKFWInstance *fwInstance,
michael@0 1618 CK_RV *pError
michael@0 1619 )
michael@0 1620 {
michael@0 1621 ckcapiInternalObject *io = (ckcapiInternalObject *)mdObject->etc;
michael@0 1622 CK_ULONG rv = 1;
michael@0 1623
michael@0 1624 /* size is irrelevant to this token */
michael@0 1625 return rv;
michael@0 1626 }
michael@0 1627
michael@0 1628 static const NSSCKMDObject
michael@0 1629 ckcapi_prototype_mdObject = {
michael@0 1630 (void *)NULL, /* etc */
michael@0 1631 NULL, /* Finalize */
michael@0 1632 ckcapi_mdObject_Destroy,
michael@0 1633 ckcapi_mdObject_IsTokenObject,
michael@0 1634 ckcapi_mdObject_GetAttributeCount,
michael@0 1635 ckcapi_mdObject_GetAttributeTypes,
michael@0 1636 ckcapi_mdObject_GetAttributeSize,
michael@0 1637 ckcapi_mdObject_GetAttribute,
michael@0 1638 NULL, /* FreeAttribute */
michael@0 1639 ckcapi_mdObject_SetAttribute,
michael@0 1640 ckcapi_mdObject_GetObjectSize,
michael@0 1641 (void *)NULL /* null terminator */
michael@0 1642 };
michael@0 1643
michael@0 1644 static nssHash *ckcapiInternalObjectHash = NULL;
michael@0 1645
michael@0 1646 NSS_IMPLEMENT NSSCKMDObject *
michael@0 1647 nss_ckcapi_CreateMDObject
michael@0 1648 (
michael@0 1649 NSSArena *arena,
michael@0 1650 ckcapiInternalObject *io,
michael@0 1651 CK_RV *pError
michael@0 1652 )
michael@0 1653 {
michael@0 1654 if ((nssHash *)NULL == ckcapiInternalObjectHash) {
michael@0 1655 ckcapiInternalObjectHash = nssHash_CreateItem(NULL, 10);
michael@0 1656 }
michael@0 1657 if (ckcapiCert == io->type) {
michael@0 1658 /* the hash key, not a cryptographic key */
michael@0 1659 NSSItem *key = &io->hashKey;
michael@0 1660 ckcapiInternalObject *old_o = NULL;
michael@0 1661
michael@0 1662 if (key->size == 0) {
michael@0 1663 ckcapi_FetchHashKey(io);
michael@0 1664 }
michael@0 1665 old_o = (ckcapiInternalObject *)
michael@0 1666 nssHash_Lookup(ckcapiInternalObjectHash, key);
michael@0 1667 if (!old_o) {
michael@0 1668 nssHash_Add(ckcapiInternalObjectHash, key, io);
michael@0 1669 } else if (old_o != io) {
michael@0 1670 nss_ckcapi_DestroyInternalObject(io);
michael@0 1671 io = old_o;
michael@0 1672 }
michael@0 1673 }
michael@0 1674
michael@0 1675 if ( (void*)NULL == io->mdObject.etc) {
michael@0 1676 (void) nsslibc_memcpy(&io->mdObject,&ckcapi_prototype_mdObject,
michael@0 1677 sizeof(ckcapi_prototype_mdObject));
michael@0 1678 io->mdObject.etc = (void *)io;
michael@0 1679 }
michael@0 1680 return &io->mdObject;
michael@0 1681 }
michael@0 1682
michael@0 1683 static void
michael@0 1684 ckcapi_removeObjectFromHash
michael@0 1685 (
michael@0 1686 ckcapiInternalObject *io
michael@0 1687 )
michael@0 1688 {
michael@0 1689 NSSItem *key = &io->hashKey;
michael@0 1690
michael@0 1691 if ((nssHash *)NULL == ckcapiInternalObjectHash) {
michael@0 1692 return;
michael@0 1693 }
michael@0 1694 if (key->size == 0) {
michael@0 1695 ckcapi_FetchHashKey(io);
michael@0 1696 }
michael@0 1697 nssHash_Remove(ckcapiInternalObjectHash, key);
michael@0 1698 return;
michael@0 1699 }
michael@0 1700
michael@0 1701 void
michael@0 1702 nss_ckcapi_DestroyInternalObject
michael@0 1703 (
michael@0 1704 ckcapiInternalObject *io
michael@0 1705 )
michael@0 1706 {
michael@0 1707 switch (io->type) {
michael@0 1708 case ckcapiRaw:
michael@0 1709 return;
michael@0 1710 case ckcapiCert:
michael@0 1711 CertFreeCertificateContext(io->u.cert.certContext);
michael@0 1712 nss_ZFreeIf(io->u.cert.labelData);
michael@0 1713 nss_ZFreeIf(io->u.cert.key.privateKey);
michael@0 1714 nss_ZFreeIf(io->u.cert.key.pubKey);
michael@0 1715 nss_ZFreeIf(io->idData);
michael@0 1716 break;
michael@0 1717 case ckcapiBareKey:
michael@0 1718 nss_ZFreeIf(io->u.key.provInfo.pwszContainerName);
michael@0 1719 nss_ZFreeIf(io->u.key.provInfo.pwszProvName);
michael@0 1720 nss_ZFreeIf(io->u.key.provName);
michael@0 1721 nss_ZFreeIf(io->u.key.containerName);
michael@0 1722 nss_ZFreeIf(io->u.key.key.privateKey);
michael@0 1723 nss_ZFreeIf(io->u.key.key.pubKey);
michael@0 1724 if (0 != io->u.key.hProv) {
michael@0 1725 CryptReleaseContext(io->u.key.hProv, 0);
michael@0 1726 }
michael@0 1727 nss_ZFreeIf(io->idData);
michael@0 1728 break;
michael@0 1729 }
michael@0 1730 nss_ZFreeIf(io);
michael@0 1731 return;
michael@0 1732 }
michael@0 1733
michael@0 1734 static ckcapiInternalObject *
michael@0 1735 nss_ckcapi_CreateCertificate
michael@0 1736 (
michael@0 1737 NSSCKFWSession *fwSession,
michael@0 1738 CK_ATTRIBUTE_PTR pTemplate,
michael@0 1739 CK_ULONG ulAttributeCount,
michael@0 1740 CK_RV *pError
michael@0 1741 )
michael@0 1742 {
michael@0 1743 NSSItem value;
michael@0 1744 NSSItem keyID;
michael@0 1745 char *storeStr;
michael@0 1746 ckcapiInternalObject *io = NULL;
michael@0 1747 PCCERT_CONTEXT certContext = NULL;
michael@0 1748 PCCERT_CONTEXT storedCertContext = NULL;
michael@0 1749 CRYPT_KEY_PROV_INFO *prov_info = NULL;
michael@0 1750 char *nickname = NULL;
michael@0 1751 HCERTSTORE hStore = 0;
michael@0 1752 DWORD msError = 0;
michael@0 1753 PRBool hasID;
michael@0 1754 CK_RV dummy;
michael@0 1755 BOOL rc;
michael@0 1756
michael@0 1757 *pError = nss_ckcapi_GetAttribute(CKA_VALUE, pTemplate,
michael@0 1758 ulAttributeCount, &value);
michael@0 1759
michael@0 1760 if (CKR_OK != *pError) {
michael@0 1761 return (ckcapiInternalObject *)NULL;
michael@0 1762 }
michael@0 1763
michael@0 1764 *pError = nss_ckcapi_GetAttribute(CKA_ID, pTemplate,
michael@0 1765 ulAttributeCount, &keyID);
michael@0 1766
michael@0 1767 if (CKR_OK != *pError) {
michael@0 1768 return (ckcapiInternalObject *)NULL;
michael@0 1769 }
michael@0 1770
michael@0 1771 if (ckcapi_cert_exists(&value, &io)) {
michael@0 1772 return io;
michael@0 1773 }
michael@0 1774
michael@0 1775 /* OK, we are creating a new one, figure out what store it belongs to..
michael@0 1776 * first get a certContext handle.. */
michael@0 1777 certContext = CertCreateCertificateContext(X509_ASN_ENCODING,
michael@0 1778 value.data, value.size);
michael@0 1779 if ((PCCERT_CONTEXT) NULL == certContext) {
michael@0 1780 msError = GetLastError();
michael@0 1781 *pError = CKR_ATTRIBUTE_VALUE_INVALID;
michael@0 1782 goto loser;
michael@0 1783 }
michael@0 1784
michael@0 1785 /* do we have a private key laying around... */
michael@0 1786 prov_info = ckcapi_cert_getPrivateKeyInfo(certContext, &keyID);
michael@0 1787 if (prov_info) {
michael@0 1788 CRYPT_DATA_BLOB msKeyID;
michael@0 1789 storeStr = "My";
michael@0 1790 hasID = PR_TRUE;
michael@0 1791 rc = CertSetCertificateContextProperty(certContext,
michael@0 1792 CERT_KEY_PROV_INFO_PROP_ID,
michael@0 1793 0, prov_info);
michael@0 1794 nss_ZFreeIf(prov_info);
michael@0 1795 if (!rc) {
michael@0 1796 msError = GetLastError();
michael@0 1797 *pError = CKR_DEVICE_ERROR;
michael@0 1798 goto loser;
michael@0 1799 }
michael@0 1800 msKeyID.cbData = keyID.size;
michael@0 1801 msKeyID.pbData = keyID.data;
michael@0 1802 rc = CertSetCertificateContextProperty(certContext,
michael@0 1803 CERT_KEY_IDENTIFIER_PROP_ID,
michael@0 1804 0, &msKeyID);
michael@0 1805 if (!rc) {
michael@0 1806 msError = GetLastError();
michael@0 1807 *pError = CKR_DEVICE_ERROR;
michael@0 1808 goto loser;
michael@0 1809 }
michael@0 1810
michael@0 1811 /* does it look like a CA */
michael@0 1812 } else if (ckcapi_cert_isCA(certContext)) {
michael@0 1813 storeStr = ckcapi_cert_isRoot(certContext) ? "CA" : "Root";
michael@0 1814 /* does it look like an S/MIME cert */
michael@0 1815 } else if (ckcapi_cert_hasEmail(certContext)) {
michael@0 1816 storeStr = "AddressBook";
michael@0 1817 } else {
michael@0 1818 /* just pick a store */
michael@0 1819 storeStr = "CA";
michael@0 1820 }
michael@0 1821
michael@0 1822 /* get the nickname, not an error if we can't find it */
michael@0 1823 nickname = nss_ckcapi_GetStringAttribute(CKA_LABEL, pTemplate,
michael@0 1824 ulAttributeCount, &dummy);
michael@0 1825 if (nickname) {
michael@0 1826 LPWSTR nicknameUTF16 = NULL;
michael@0 1827 CRYPT_DATA_BLOB nicknameBlob;
michael@0 1828
michael@0 1829 nicknameUTF16 = nss_ckcapi_UTF8ToWide(nickname);
michael@0 1830 nss_ZFreeIf(nickname);
michael@0 1831 nickname = NULL;
michael@0 1832 if ((LPWSTR)NULL == nicknameUTF16) {
michael@0 1833 *pError = CKR_HOST_MEMORY;
michael@0 1834 goto loser;
michael@0 1835 }
michael@0 1836 nicknameBlob.cbData = nss_ckcapi_WideSize(nicknameUTF16);
michael@0 1837 nicknameBlob.pbData = (BYTE *)nicknameUTF16;
michael@0 1838 rc = CertSetCertificateContextProperty(certContext,
michael@0 1839 CERT_FRIENDLY_NAME_PROP_ID, 0, &nicknameBlob);
michael@0 1840 nss_ZFreeIf(nicknameUTF16);
michael@0 1841 if (!rc) {
michael@0 1842 msError = GetLastError();
michael@0 1843 *pError = CKR_DEVICE_ERROR;
michael@0 1844 goto loser;
michael@0 1845 }
michael@0 1846 }
michael@0 1847
michael@0 1848 hStore = CertOpenSystemStore((HCRYPTPROV) NULL, storeStr);
michael@0 1849 if (0 == hStore) {
michael@0 1850 msError = GetLastError();
michael@0 1851 *pError = CKR_DEVICE_ERROR;
michael@0 1852 goto loser;
michael@0 1853 }
michael@0 1854
michael@0 1855 rc = CertAddCertificateContextToStore(hStore, certContext,
michael@0 1856 CERT_STORE_ADD_REPLACE_EXISTING_INHERIT_PROPERTIES, &storedCertContext);
michael@0 1857 CertFreeCertificateContext(certContext);
michael@0 1858 certContext = NULL;
michael@0 1859 CertCloseStore(hStore, 0);
michael@0 1860 hStore = 0;
michael@0 1861 if (!rc) {
michael@0 1862 msError = GetLastError();
michael@0 1863 *pError = CKR_DEVICE_ERROR;
michael@0 1864 goto loser;
michael@0 1865 }
michael@0 1866
michael@0 1867 io = nss_ZNEW(NULL, ckcapiInternalObject);
michael@0 1868 if ((ckcapiInternalObject *)NULL == io) {
michael@0 1869 *pError = CKR_HOST_MEMORY;
michael@0 1870 goto loser;
michael@0 1871 }
michael@0 1872 io->type = ckcapiCert;
michael@0 1873 io->objClass = CKO_CERTIFICATE;
michael@0 1874 io->u.cert.certContext = storedCertContext;
michael@0 1875 io->u.cert.hasID = hasID;
michael@0 1876 return io;
michael@0 1877
michael@0 1878 loser:
michael@0 1879 if (certContext) {
michael@0 1880 CertFreeCertificateContext(certContext);
michael@0 1881 certContext = NULL;
michael@0 1882 }
michael@0 1883 if (storedCertContext) {
michael@0 1884 CertFreeCertificateContext(storedCertContext);
michael@0 1885 storedCertContext = NULL;
michael@0 1886 }
michael@0 1887 if (0 != hStore) {
michael@0 1888 CertCloseStore(hStore, 0);
michael@0 1889 }
michael@0 1890 return (ckcapiInternalObject *)NULL;
michael@0 1891
michael@0 1892 }
michael@0 1893
michael@0 1894 static char *
michael@0 1895 ckcapi_getDefaultProvider
michael@0 1896 (
michael@0 1897 CK_RV *pError
michael@0 1898 )
michael@0 1899 {
michael@0 1900 char *name = NULL;
michael@0 1901 BOOL rc;
michael@0 1902 DWORD nameLength = 0;
michael@0 1903
michael@0 1904 rc = CryptGetDefaultProvider(PROV_RSA_FULL, NULL, CRYPT_USER_DEFAULT, NULL,
michael@0 1905 &nameLength);
michael@0 1906 if (!rc) {
michael@0 1907 return (char *)NULL;
michael@0 1908 }
michael@0 1909
michael@0 1910 name = nss_ZNEWARRAY(NULL, char, nameLength);
michael@0 1911 if ((char *)NULL == name ) {
michael@0 1912 return (char *)NULL;
michael@0 1913 }
michael@0 1914 rc = CryptGetDefaultProvider(PROV_RSA_FULL, NULL, CRYPT_USER_DEFAULT, name,
michael@0 1915 &nameLength);
michael@0 1916 if (!rc) {
michael@0 1917 nss_ZFreeIf(name);
michael@0 1918 return (char *)NULL;
michael@0 1919 }
michael@0 1920
michael@0 1921 return name;
michael@0 1922 }
michael@0 1923
michael@0 1924 static char *
michael@0 1925 ckcapi_getContainer
michael@0 1926 (
michael@0 1927 CK_RV *pError,
michael@0 1928 NSSItem *id
michael@0 1929 )
michael@0 1930 {
michael@0 1931 RPC_STATUS rstat;
michael@0 1932 UUID uuid;
michael@0 1933 char *uuidStr;
michael@0 1934 char *container;
michael@0 1935
michael@0 1936 rstat = UuidCreate(&uuid);
michael@0 1937 rstat = UuidToString(&uuid, &uuidStr);
michael@0 1938
michael@0 1939 /* convert it from rcp memory to our own */
michael@0 1940 container = nssUTF8_Duplicate(uuidStr, NULL);
michael@0 1941 RpcStringFree(&uuidStr);
michael@0 1942
michael@0 1943 return container;
michael@0 1944 }
michael@0 1945
michael@0 1946 static CK_RV
michael@0 1947 ckcapi_buildPrivateKeyBlob
michael@0 1948 (
michael@0 1949 NSSItem *keyBlob,
michael@0 1950 NSSItem *modulus,
michael@0 1951 NSSItem *publicExponent,
michael@0 1952 NSSItem *privateExponent,
michael@0 1953 NSSItem *prime1,
michael@0 1954 NSSItem *prime2,
michael@0 1955 NSSItem *exponent1,
michael@0 1956 NSSItem *exponent2,
michael@0 1957 NSSItem *coefficient,
michael@0 1958 PRBool isKeyExchange
michael@0 1959 )
michael@0 1960 {
michael@0 1961 CAPI_RSA_KEY_BLOB *keyBlobData = NULL;
michael@0 1962 unsigned char *target;
michael@0 1963 unsigned long modSize = modulus->size;
michael@0 1964 unsigned long dataSize;
michael@0 1965 CK_RV error = CKR_OK;
michael@0 1966
michael@0 1967 /* validate extras */
michael@0 1968 if (privateExponent->size != modSize) {
michael@0 1969 error = CKR_ATTRIBUTE_VALUE_INVALID;
michael@0 1970 goto loser;
michael@0 1971 }
michael@0 1972 if (prime1->size != modSize/2) {
michael@0 1973 error = CKR_ATTRIBUTE_VALUE_INVALID;
michael@0 1974 goto loser;
michael@0 1975 }
michael@0 1976 if (prime2->size != modSize/2) {
michael@0 1977 error = CKR_ATTRIBUTE_VALUE_INVALID;
michael@0 1978 goto loser;
michael@0 1979 }
michael@0 1980 if (exponent1->size != modSize/2) {
michael@0 1981 error = CKR_ATTRIBUTE_VALUE_INVALID;
michael@0 1982 goto loser;
michael@0 1983 }
michael@0 1984 if (exponent2->size != modSize/2) {
michael@0 1985 error = CKR_ATTRIBUTE_VALUE_INVALID;
michael@0 1986 goto loser;
michael@0 1987 }
michael@0 1988 if (coefficient->size != modSize/2) {
michael@0 1989 error = CKR_ATTRIBUTE_VALUE_INVALID;
michael@0 1990 goto loser;
michael@0 1991 }
michael@0 1992 dataSize = (modSize*4)+(modSize/2) + sizeof(CAPI_RSA_KEY_BLOB);
michael@0 1993 keyBlobData = (CAPI_RSA_KEY_BLOB *)nss_ZAlloc(NULL, dataSize);
michael@0 1994 if ((CAPI_RSA_KEY_BLOB *)NULL == keyBlobData) {
michael@0 1995 error = CKR_HOST_MEMORY;
michael@0 1996 goto loser;
michael@0 1997 }
michael@0 1998
michael@0 1999 keyBlobData->header.bType = PRIVATEKEYBLOB;
michael@0 2000 keyBlobData->header.bVersion = 0x02;
michael@0 2001 keyBlobData->header.reserved = 0x00;
michael@0 2002 keyBlobData->header.aiKeyAlg = isKeyExchange ? CALG_RSA_KEYX:CALG_RSA_SIGN;
michael@0 2003 keyBlobData->rsa.magic = 0x32415352;
michael@0 2004 keyBlobData->rsa.bitlen = modSize * 8;
michael@0 2005 keyBlobData->rsa.pubexp = nss_ckcapi_DataToInt(publicExponent,&error);
michael@0 2006 if (CKR_OK != error) {
michael@0 2007 goto loser;
michael@0 2008 }
michael@0 2009
michael@0 2010 target = &keyBlobData->data[CAPI_MODULUS_OFFSET(modSize)];
michael@0 2011 nsslibc_memcpy(target, modulus->data, modulus->size);
michael@0 2012 modulus->data = target;
michael@0 2013 ckcapi_ReverseData(modulus);
michael@0 2014
michael@0 2015 target = &keyBlobData->data[CAPI_PRIVATE_EXP_OFFSET(modSize)];
michael@0 2016 nsslibc_memcpy(target, privateExponent->data, privateExponent->size);
michael@0 2017 privateExponent->data = target;
michael@0 2018 ckcapi_ReverseData(privateExponent);
michael@0 2019
michael@0 2020 target = &keyBlobData->data[CAPI_PRIME_1_OFFSET(modSize)];
michael@0 2021 nsslibc_memcpy(target, prime1->data, prime1->size);
michael@0 2022 prime1->data = target;
michael@0 2023 ckcapi_ReverseData(prime1);
michael@0 2024
michael@0 2025 target = &keyBlobData->data[CAPI_PRIME_2_OFFSET(modSize)];
michael@0 2026 nsslibc_memcpy(target, prime2->data, prime2->size);
michael@0 2027 prime2->data = target;
michael@0 2028 ckcapi_ReverseData(prime2);
michael@0 2029
michael@0 2030 target = &keyBlobData->data[CAPI_EXPONENT_1_OFFSET(modSize)];
michael@0 2031 nsslibc_memcpy(target, exponent1->data, exponent1->size);
michael@0 2032 exponent1->data = target;
michael@0 2033 ckcapi_ReverseData(exponent1);
michael@0 2034
michael@0 2035 target = &keyBlobData->data[CAPI_EXPONENT_2_OFFSET(modSize)];
michael@0 2036 nsslibc_memcpy(target, exponent2->data, exponent2->size);
michael@0 2037 exponent2->data = target;
michael@0 2038 ckcapi_ReverseData(exponent2);
michael@0 2039
michael@0 2040 target = &keyBlobData->data[CAPI_COEFFICIENT_OFFSET(modSize)];
michael@0 2041 nsslibc_memcpy(target, coefficient->data, coefficient->size);
michael@0 2042 coefficient->data = target;
michael@0 2043 ckcapi_ReverseData(coefficient);
michael@0 2044
michael@0 2045 keyBlob->data = keyBlobData;
michael@0 2046 keyBlob->size = dataSize;
michael@0 2047
michael@0 2048 return CKR_OK;
michael@0 2049
michael@0 2050 loser:
michael@0 2051 nss_ZFreeIf(keyBlobData);
michael@0 2052 return error;
michael@0 2053 }
michael@0 2054
michael@0 2055 static ckcapiInternalObject *
michael@0 2056 nss_ckcapi_CreatePrivateKey
michael@0 2057 (
michael@0 2058 NSSCKFWSession *fwSession,
michael@0 2059 CK_ATTRIBUTE_PTR pTemplate,
michael@0 2060 CK_ULONG ulAttributeCount,
michael@0 2061 CK_RV *pError
michael@0 2062 )
michael@0 2063 {
michael@0 2064 NSSItem modulus;
michael@0 2065 NSSItem publicExponent;
michael@0 2066 NSSItem privateExponent;
michael@0 2067 NSSItem exponent1;
michael@0 2068 NSSItem exponent2;
michael@0 2069 NSSItem prime1;
michael@0 2070 NSSItem prime2;
michael@0 2071 NSSItem coefficient;
michael@0 2072 NSSItem keyID;
michael@0 2073 NSSItem keyBlob;
michael@0 2074 ckcapiInternalObject *io = NULL;
michael@0 2075 char *providerName = NULL;
michael@0 2076 char *containerName = NULL;
michael@0 2077 char *idData = NULL;
michael@0 2078 CRYPT_KEY_PROV_INFO provInfo;
michael@0 2079 CRYPT_HASH_BLOB msKeyID;
michael@0 2080 CK_KEY_TYPE keyType;
michael@0 2081 HCRYPTPROV hProv = 0;
michael@0 2082 HCRYPTKEY hKey = 0;
michael@0 2083 PRBool decrypt;
michael@0 2084 DWORD keySpec;
michael@0 2085 DWORD msError;
michael@0 2086 BOOL rc;
michael@0 2087
michael@0 2088 keyType = nss_ckcapi_GetULongAttribute
michael@0 2089 (CKA_KEY_TYPE, pTemplate, ulAttributeCount, pError);
michael@0 2090 if (CKR_OK != *pError) {
michael@0 2091 return (ckcapiInternalObject *)NULL;
michael@0 2092 }
michael@0 2093 if (CKK_RSA != keyType) {
michael@0 2094 *pError = CKR_ATTRIBUTE_VALUE_INVALID;
michael@0 2095 return (ckcapiInternalObject *)NULL;
michael@0 2096 }
michael@0 2097
michael@0 2098 decrypt = nss_ckcapi_GetBoolAttribute(CKA_DECRYPT,
michael@0 2099 pTemplate, ulAttributeCount, pError);
michael@0 2100 if (CKR_TEMPLATE_INCOMPLETE == *pError) {
michael@0 2101 decrypt = PR_TRUE; /* default to true */
michael@0 2102 }
michael@0 2103 decrypt = decrypt || nss_ckcapi_GetBoolAttribute(CKA_UNWRAP,
michael@0 2104 pTemplate, ulAttributeCount, pError);
michael@0 2105 if (CKR_TEMPLATE_INCOMPLETE == *pError) {
michael@0 2106 decrypt = PR_TRUE; /* default to true */
michael@0 2107 }
michael@0 2108 keySpec = decrypt ? AT_KEYEXCHANGE : AT_SIGNATURE;
michael@0 2109
michael@0 2110 *pError = nss_ckcapi_GetAttribute(CKA_MODULUS, pTemplate,
michael@0 2111 ulAttributeCount, &modulus);
michael@0 2112 if (CKR_OK != *pError) {
michael@0 2113 return (ckcapiInternalObject *)NULL;
michael@0 2114 }
michael@0 2115 *pError = nss_ckcapi_GetAttribute(CKA_PUBLIC_EXPONENT, pTemplate,
michael@0 2116 ulAttributeCount, &publicExponent);
michael@0 2117 if (CKR_OK != *pError) {
michael@0 2118 return (ckcapiInternalObject *)NULL;
michael@0 2119 }
michael@0 2120 *pError = nss_ckcapi_GetAttribute(CKA_PRIVATE_EXPONENT, pTemplate,
michael@0 2121 ulAttributeCount, &privateExponent);
michael@0 2122 if (CKR_OK != *pError) {
michael@0 2123 return (ckcapiInternalObject *)NULL;
michael@0 2124 }
michael@0 2125 *pError = nss_ckcapi_GetAttribute(CKA_PRIME_1, pTemplate,
michael@0 2126 ulAttributeCount, &prime1);
michael@0 2127 if (CKR_OK != *pError) {
michael@0 2128 return (ckcapiInternalObject *)NULL;
michael@0 2129 }
michael@0 2130 *pError = nss_ckcapi_GetAttribute(CKA_PRIME_2, pTemplate,
michael@0 2131 ulAttributeCount, &prime2);
michael@0 2132 if (CKR_OK != *pError) {
michael@0 2133 return (ckcapiInternalObject *)NULL;
michael@0 2134 }
michael@0 2135 *pError = nss_ckcapi_GetAttribute(CKA_EXPONENT_1, pTemplate,
michael@0 2136 ulAttributeCount, &exponent1);
michael@0 2137 if (CKR_OK != *pError) {
michael@0 2138 return (ckcapiInternalObject *)NULL;
michael@0 2139 }
michael@0 2140 *pError = nss_ckcapi_GetAttribute(CKA_EXPONENT_2, pTemplate,
michael@0 2141 ulAttributeCount, &exponent2);
michael@0 2142 if (CKR_OK != *pError) {
michael@0 2143 return (ckcapiInternalObject *)NULL;
michael@0 2144 }
michael@0 2145 *pError = nss_ckcapi_GetAttribute(CKA_COEFFICIENT, pTemplate,
michael@0 2146 ulAttributeCount, &coefficient);
michael@0 2147 if (CKR_OK != *pError) {
michael@0 2148 return (ckcapiInternalObject *)NULL;
michael@0 2149 }
michael@0 2150 *pError = nss_ckcapi_GetAttribute(CKA_ID, pTemplate,
michael@0 2151 ulAttributeCount, &keyID);
michael@0 2152 if (CKR_OK != *pError) {
michael@0 2153 return (ckcapiInternalObject *)NULL;
michael@0 2154 }
michael@0 2155 providerName = ckcapi_getDefaultProvider(pError);
michael@0 2156 if ((char *)NULL == providerName ) {
michael@0 2157 return (ckcapiInternalObject *)NULL;
michael@0 2158 }
michael@0 2159 containerName = ckcapi_getContainer(pError, &keyID);
michael@0 2160 if ((char *)NULL == containerName) {
michael@0 2161 goto loser;
michael@0 2162 }
michael@0 2163 rc = CryptAcquireContext(&hProv, containerName, providerName,
michael@0 2164 PROV_RSA_FULL, CRYPT_NEWKEYSET);
michael@0 2165 if (!rc) {
michael@0 2166 msError = GetLastError();
michael@0 2167 *pError = CKR_DEVICE_ERROR;
michael@0 2168 goto loser;
michael@0 2169 }
michael@0 2170
michael@0 2171 *pError = ckcapi_buildPrivateKeyBlob(
michael@0 2172 &keyBlob,
michael@0 2173 &modulus,
michael@0 2174 &publicExponent,
michael@0 2175 &privateExponent,
michael@0 2176 &prime1,
michael@0 2177 &prime2,
michael@0 2178 &exponent1,
michael@0 2179 &exponent2,
michael@0 2180 &coefficient,
michael@0 2181 decrypt);
michael@0 2182 if (CKR_OK != *pError) {
michael@0 2183 goto loser;
michael@0 2184 }
michael@0 2185
michael@0 2186 rc = CryptImportKey(hProv, keyBlob.data, keyBlob.size,
michael@0 2187 0, CRYPT_EXPORTABLE, &hKey);
michael@0 2188 if (!rc) {
michael@0 2189 msError = GetLastError();
michael@0 2190 *pError = CKR_DEVICE_ERROR;
michael@0 2191 goto loser;
michael@0 2192 }
michael@0 2193
michael@0 2194 idData = nss_ZNEWARRAY(NULL, char, keyID.size);
michael@0 2195 if ((void *)NULL == idData) {
michael@0 2196 *pError = CKR_HOST_MEMORY;
michael@0 2197 goto loser;
michael@0 2198 }
michael@0 2199 nsslibc_memcpy(idData, keyID.data, keyID.size);
michael@0 2200
michael@0 2201 provInfo.pwszContainerName = nss_ckcapi_UTF8ToWide(containerName);
michael@0 2202 provInfo.pwszProvName = nss_ckcapi_UTF8ToWide(providerName);
michael@0 2203 provInfo.dwProvType = PROV_RSA_FULL;
michael@0 2204 provInfo.dwFlags = 0;
michael@0 2205 provInfo.cProvParam = 0;
michael@0 2206 provInfo.rgProvParam = NULL;
michael@0 2207 provInfo.dwKeySpec = keySpec;
michael@0 2208
michael@0 2209 msKeyID.cbData = keyID.size;
michael@0 2210 msKeyID.pbData = keyID.data;
michael@0 2211
michael@0 2212 rc = CryptSetKeyIdentifierProperty(&msKeyID, CERT_KEY_PROV_INFO_PROP_ID,
michael@0 2213 0, NULL, NULL, &provInfo);
michael@0 2214 if (!rc) {
michael@0 2215 goto loser;
michael@0 2216 }
michael@0 2217
michael@0 2218 /* handle error here */
michael@0 2219 io = nss_ZNEW(NULL, ckcapiInternalObject);
michael@0 2220 if ((ckcapiInternalObject *)NULL == io) {
michael@0 2221 *pError = CKR_HOST_MEMORY;
michael@0 2222 goto loser;
michael@0 2223 }
michael@0 2224 io->type = ckcapiBareKey;
michael@0 2225 io->objClass = CKO_PRIVATE_KEY;
michael@0 2226 io->u.key.provInfo = provInfo;
michael@0 2227 io->u.key.provName = providerName;
michael@0 2228 io->u.key.containerName = containerName;
michael@0 2229 io->u.key.hProv = hProv; /* save the handle */
michael@0 2230 io->idData = idData;
michael@0 2231 io->id.data = idData;
michael@0 2232 io->id.size = keyID.size;
michael@0 2233 /* done with the key handle */
michael@0 2234 CryptDestroyKey(hKey);
michael@0 2235 return io;
michael@0 2236
michael@0 2237 loser:
michael@0 2238 nss_ZFreeIf(containerName);
michael@0 2239 nss_ZFreeIf(providerName);
michael@0 2240 nss_ZFreeIf(idData);
michael@0 2241 if (0 != hProv) {
michael@0 2242 CryptReleaseContext(hProv, 0);
michael@0 2243 }
michael@0 2244 if (0 != hKey) {
michael@0 2245 CryptDestroyKey(hKey);
michael@0 2246 }
michael@0 2247 return (ckcapiInternalObject *)NULL;
michael@0 2248 }
michael@0 2249
michael@0 2250
michael@0 2251 NSS_EXTERN NSSCKMDObject *
michael@0 2252 nss_ckcapi_CreateObject
michael@0 2253 (
michael@0 2254 NSSCKFWSession *fwSession,
michael@0 2255 CK_ATTRIBUTE_PTR pTemplate,
michael@0 2256 CK_ULONG ulAttributeCount,
michael@0 2257 CK_RV *pError
michael@0 2258 )
michael@0 2259 {
michael@0 2260 CK_OBJECT_CLASS objClass;
michael@0 2261 ckcapiInternalObject *io = NULL;
michael@0 2262 CK_BBOOL isToken;
michael@0 2263
michael@0 2264 /*
michael@0 2265 * only create token objects
michael@0 2266 */
michael@0 2267 isToken = nss_ckcapi_GetBoolAttribute(CKA_TOKEN, pTemplate,
michael@0 2268 ulAttributeCount, pError);
michael@0 2269 if (CKR_OK != *pError) {
michael@0 2270 return (NSSCKMDObject *) NULL;
michael@0 2271 }
michael@0 2272 if (!isToken) {
michael@0 2273 *pError = CKR_ATTRIBUTE_VALUE_INVALID;
michael@0 2274 return (NSSCKMDObject *) NULL;
michael@0 2275 }
michael@0 2276
michael@0 2277 /*
michael@0 2278 * only create keys and certs.
michael@0 2279 */
michael@0 2280 objClass = nss_ckcapi_GetULongAttribute(CKA_CLASS, pTemplate,
michael@0 2281 ulAttributeCount, pError);
michael@0 2282 if (CKR_OK != *pError) {
michael@0 2283 return (NSSCKMDObject *) NULL;
michael@0 2284 }
michael@0 2285 #ifdef notdef
michael@0 2286 if (objClass == CKO_PUBLIC_KEY) {
michael@0 2287 return CKR_OK; /* fake public key creation, happens as a side effect of
michael@0 2288 * private key creation */
michael@0 2289 }
michael@0 2290 #endif
michael@0 2291 if (objClass == CKO_CERTIFICATE) {
michael@0 2292 io = nss_ckcapi_CreateCertificate(fwSession, pTemplate,
michael@0 2293 ulAttributeCount, pError);
michael@0 2294 } else if (objClass == CKO_PRIVATE_KEY) {
michael@0 2295 io = nss_ckcapi_CreatePrivateKey(fwSession, pTemplate,
michael@0 2296 ulAttributeCount, pError);
michael@0 2297 } else {
michael@0 2298 *pError = CKR_ATTRIBUTE_VALUE_INVALID;
michael@0 2299 }
michael@0 2300
michael@0 2301 if ((ckcapiInternalObject *)NULL == io) {
michael@0 2302 return (NSSCKMDObject *) NULL;
michael@0 2303 }
michael@0 2304 return nss_ckcapi_CreateMDObject(NULL, io, pError);
michael@0 2305 }

mercurial