PageRenderTime 129ms CodeModel.GetById 2ms app.highlight 108ms RepoModel.GetById 1ms app.codeStats 0ms

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

http://github.com/zpao/v8monkey
C | 2343 lines | 1963 code | 200 blank | 180 comment | 332 complexity | 7efbd9cfff44089c2b6669fa99323158 MD5 | raw file

Large files files are truncated, but you can click here to view the full file

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

Large files files are truncated, but you can click here to view the full file