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.

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

mercurial