security/nss/lib/ckfw/nssmkey/mobject.c

Thu, 22 Jan 2015 13:21:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 22 Jan 2015 13:21:57 +0100
branch
TOR_BUG_9701
changeset 15
b8a032363ba2
permissions
-rw-r--r--

Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6

     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 "ckmk.h"
     6 #include "nssbase.h"
     8 #include "secdert.h" /* for DER_INTEGER */
     9 #include "string.h"
    11 /* asn1 encoder (to build pkcs#8 blobs) */
    12 #include <seccomon.h>
    13 #include <secitem.h>
    14 #include <blapit.h>
    15 #include <secoid.h>
    16 #include <secasn1.h>
    18 /* for importing the keys */
    19 #include <CoreFoundation/CoreFoundation.h>
    20 #include <security/SecImportExport.h>
    22 /*
    23  * nssmkey/mobject.c
    24  *
    25  * This file implements the NSSCKMDObject object for the
    26  * "nssmkey" cryptoki module.
    27  */
    29 const CK_ATTRIBUTE_TYPE certAttrs[] = {
    30     CKA_CLASS,
    31     CKA_TOKEN,
    32     CKA_PRIVATE,
    33     CKA_MODIFIABLE,
    34     CKA_LABEL,
    35     CKA_CERTIFICATE_TYPE,
    36     CKA_SUBJECT,
    37     CKA_ISSUER,
    38     CKA_SERIAL_NUMBER,
    39     CKA_VALUE
    40 };
    41 const PRUint32 certAttrsCount = NSS_CKMK_ARRAY_SIZE(certAttrs);
    43 /* private keys, for now only support RSA */
    44 const CK_ATTRIBUTE_TYPE privKeyAttrs[] = {
    45     CKA_CLASS,
    46     CKA_TOKEN,
    47     CKA_PRIVATE,
    48     CKA_MODIFIABLE,
    49     CKA_LABEL,
    50     CKA_KEY_TYPE,
    51     CKA_DERIVE,
    52     CKA_LOCAL,
    53     CKA_SUBJECT,
    54     CKA_SENSITIVE,
    55     CKA_DECRYPT,
    56     CKA_SIGN,
    57     CKA_SIGN_RECOVER,
    58     CKA_UNWRAP,
    59     CKA_EXTRACTABLE,
    60     CKA_ALWAYS_SENSITIVE,
    61     CKA_NEVER_EXTRACTABLE,
    62     CKA_MODULUS,
    63     CKA_PUBLIC_EXPONENT,
    64 };
    65 const PRUint32 privKeyAttrsCount = NSS_CKMK_ARRAY_SIZE(privKeyAttrs);
    67 /* public keys, for now only support RSA */
    68 const CK_ATTRIBUTE_TYPE pubKeyAttrs[] = {
    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_ENCRYPT,
    79     CKA_VERIFY,
    80     CKA_VERIFY_RECOVER,
    81     CKA_WRAP,
    82     CKA_MODULUS,
    83     CKA_PUBLIC_EXPONENT,
    84 };
    85 const PRUint32 pubKeyAttrsCount = NSS_CKMK_ARRAY_SIZE(pubKeyAttrs);
    86 static const CK_BBOOL ck_true = CK_TRUE;
    87 static const CK_BBOOL ck_false = CK_FALSE;
    88 static const CK_CERTIFICATE_TYPE ckc_x509 = CKC_X_509;
    89 static const CK_KEY_TYPE ckk_rsa = CKK_RSA;
    90 static const CK_OBJECT_CLASS cko_certificate = CKO_CERTIFICATE;
    91 static const CK_OBJECT_CLASS cko_private_key = CKO_PRIVATE_KEY;
    92 static const CK_OBJECT_CLASS cko_public_key = CKO_PUBLIC_KEY;
    93 static const NSSItem ckmk_trueItem = { 
    94   (void *)&ck_true, (PRUint32)sizeof(CK_BBOOL) };
    95 static const NSSItem ckmk_falseItem = { 
    96   (void *)&ck_false, (PRUint32)sizeof(CK_BBOOL) };
    97 static const NSSItem ckmk_x509Item = { 
    98   (void *)&ckc_x509, (PRUint32)sizeof(CK_CERTIFICATE_TYPE) };
    99 static const NSSItem ckmk_rsaItem = { 
   100   (void *)&ckk_rsa, (PRUint32)sizeof(CK_KEY_TYPE) };
   101 static const NSSItem ckmk_certClassItem = { 
   102   (void *)&cko_certificate, (PRUint32)sizeof(CK_OBJECT_CLASS) };
   103 static const NSSItem ckmk_privKeyClassItem = {
   104   (void *)&cko_private_key, (PRUint32)sizeof(CK_OBJECT_CLASS) };
   105 static const NSSItem ckmk_pubKeyClassItem = {
   106   (void *)&cko_public_key, (PRUint32)sizeof(CK_OBJECT_CLASS) };
   107 static const NSSItem ckmk_emptyItem = { 
   108   (void *)&ck_true, 0};
   110 /*
   111  * these are utilities. The chould be moved to a new utilities file.
   112  */
   113 #ifdef DEBUG
   114 static void
   115 itemdump(char *str, void *data, int size, CK_RV error) 
   116 {
   117   unsigned char *ptr = (unsigned char *)data;
   118   int i;
   119   fprintf(stderr,str);
   120   for (i=0; i < size; i++) {
   121     fprintf(stderr,"%02x ",(unsigned int) ptr[i]);
   122   }
   123   fprintf(stderr," (error = %d)\n", (int ) error);
   124 }
   125 #endif
   127 /*
   128  * unwrap a single DER value
   129  * now that we have util linked in, we should probably use
   130  * the ANS1_Decoder for this work...
   131  */
   132 unsigned char *
   133 nss_ckmk_DERUnwrap
   134 (
   135   unsigned char *src, 
   136   int size, 
   137   int *outSize, 
   138   unsigned char **next
   139 )
   140 {
   141   unsigned char *start = src;
   142   unsigned int len = 0;
   144   /* initialize error condition return values */
   145   *outSize = 0;
   146   if (next) {
   147     *next = src;
   148   }
   150   if (size < 2) {
   151     return start;
   152   }
   153   src ++ ; /* skip the tag -- should check it against an expected value! */
   154   len = (unsigned) *src++;
   155   if (len & 0x80) {
   156     int count = len & 0x7f;
   157     len =0;
   159     if (count+2 > size) {
   160       return start;
   161     }
   162     while (count-- > 0) {
   163       len = (len << 8) | (unsigned) *src++;
   164     }
   165   }
   166   if (len + (src-start) > (unsigned int)size) {
   167     return start;
   168   }
   169   if (next) {
   170     *next = src+len;
   171   }
   172   *outSize = len;
   174   return src;
   175 }
   177 /*
   178  * get an attribute from a template. Value is returned in NSS item.
   179  * data for the item is owned by the template.
   180  */
   181 CK_RV
   182 nss_ckmk_GetAttribute
   183 (
   184   CK_ATTRIBUTE_TYPE type,
   185   CK_ATTRIBUTE *template,
   186   CK_ULONG templateSize, 
   187   NSSItem *item
   188 )
   189 {
   190   CK_ULONG i;
   192   for (i=0; i < templateSize; i++) {
   193     if (template[i].type == type) {
   194       item->data = template[i].pValue;
   195       item->size = template[i].ulValueLen;
   196       return CKR_OK;
   197     }
   198   }
   199   return CKR_TEMPLATE_INCOMPLETE;
   200 }
   202 /*
   203  * get an attribute which is type CK_ULONG.
   204  */
   205 CK_ULONG
   206 nss_ckmk_GetULongAttribute
   207 (
   208   CK_ATTRIBUTE_TYPE type,
   209   CK_ATTRIBUTE *template,
   210   CK_ULONG templateSize, 
   211   CK_RV *pError
   212 )
   213 {
   214   NSSItem item;
   216   *pError = nss_ckmk_GetAttribute(type, template, templateSize, &item);
   217   if (CKR_OK != *pError) {
   218     return (CK_ULONG) 0;
   219   }
   220   if (item.size != sizeof(CK_ULONG)) {
   221     *pError = CKR_ATTRIBUTE_VALUE_INVALID;
   222     return (CK_ULONG) 0;
   223   }
   224   return *(CK_ULONG *)item.data;
   225 }
   227 /*
   228  * get an attribute which is type CK_BBOOL.
   229  */
   230 CK_BBOOL
   231 nss_ckmk_GetBoolAttribute
   232 (
   233   CK_ATTRIBUTE_TYPE type,
   234   CK_ATTRIBUTE *template,
   235   CK_ULONG templateSize, 
   236   CK_BBOOL defaultBool
   237 )
   238 {
   239   NSSItem item;
   240   CK_RV error;
   242   error = nss_ckmk_GetAttribute(type, template, templateSize, &item);
   243   if (CKR_OK != error) {
   244     return defaultBool;
   245   }
   246   if (item.size != sizeof(CK_BBOOL)) {
   247     return defaultBool;
   248   }
   249   return *(CK_BBOOL *)item.data;
   250 }
   252 /*
   253  * get an attribute as a NULL terminated string. Caller is responsible to
   254  * free the string.
   255  */
   256 char *
   257 nss_ckmk_GetStringAttribute
   258 (
   259   CK_ATTRIBUTE_TYPE type,
   260   CK_ATTRIBUTE *template,
   261   CK_ULONG templateSize, 
   262   CK_RV *pError
   263 )
   264 {
   265   NSSItem item;
   266   char *str;
   268   /* get the attribute */
   269   *pError = nss_ckmk_GetAttribute(type, template, templateSize, &item);
   270   if (CKR_OK != *pError) {
   271     return (char *)NULL;
   272   }
   273   /* make sure it is null terminated */
   274   str = nss_ZNEWARRAY(NULL, char, item.size+1);
   275   if ((char *)NULL == str) {
   276     *pError = CKR_HOST_MEMORY;
   277     return (char *)NULL;
   278   }
   280   nsslibc_memcpy(str, item.data, item.size);
   281   str[item.size] = 0;
   283   return str;
   284 }
   286 /*
   287  * Apple doesn't seem to have a public interface to the DER encoder,
   288  * wip out a quick one for integers only (anything more complicated,
   289  * we should use one of the 3 in lib/util). -- especially since we
   290  * now link with it.
   291  */
   292 static CK_RV
   293 ckmk_encodeInt(NSSItem *dest, void *src, int srcLen)
   294 {                 
   295   int dataLen = srcLen;
   296   int lenLen = 1;
   297   int encLen;
   298   int isSigned = 0;
   299   int offset = 0;
   300   unsigned char *data = NULL;
   301   int i;
   303   if (*(unsigned char *)src & 0x80) {
   304     dataLen++;
   305     isSigned = 1;
   306   }
   308   /* calculate the length of the length specifier */
   309   /* (NOTE: destroys dataLen value) */ 
   310   if (dataLen > 0x7f) {
   311     do {
   312       lenLen++;
   313       dataLen >>= 8;
   314     } while (dataLen);
   315   }
   317   /* calculate our total length */
   318   dataLen = isSigned + srcLen;
   319   encLen = 1 + lenLen + dataLen;
   320   data  = nss_ZNEWARRAY(NULL, unsigned char, encLen);
   321   if ((unsigned char *)NULL == data) {
   322     return CKR_HOST_MEMORY;
   323   }
   324   data[0] = DER_INTEGER;
   325   if (1 == lenLen) {
   326     data[1] = dataLen;
   327   } else {
   328     data[1] = 0x80 + lenLen;
   329     for (i=0; i < lenLen; i++) {
   330       data[i+1] = ((dataLen >> ((lenLen-i-1)*8)) & 0xff);
   331     }
   332   }
   333   offset = lenLen+1;
   335   if (isSigned) {
   336     data[offset++] = 0;
   337   }
   338   nsslibc_memcpy(&data[offset], src, srcLen);
   339   dest->data = data;
   340   dest->size = encLen;
   341   return CKR_OK;
   342 }
   345 /*
   346  * Get a Keyring attribute. If content is set to true, then we get the
   347  * content, not the attribute.
   348  */
   349 static CK_RV
   350 ckmk_GetCommonAttribute
   351 (
   352   ckmkInternalObject *io,
   353   SecItemAttr itemAttr,
   354   PRBool content,
   355   NSSItem *item,
   356   char *dbString
   357 )
   358 {
   359   SecKeychainAttributeList *attrList = NULL;
   360   SecKeychainAttributeInfo attrInfo;
   361   PRUint32 len = 0;
   362   PRUint32 dataLen = 0;
   363   PRUint32 attrFormat = 0;
   364   void *dataVal = 0;
   365   void *out = NULL;
   366   CK_RV error = CKR_OK;
   367   OSStatus macErr;
   369   attrInfo.count = 1;
   370   attrInfo.tag = &itemAttr;
   371   attrInfo.format = &attrFormat;
   373   macErr = SecKeychainItemCopyAttributesAndData(io->u.item.itemRef, 
   374                                 &attrInfo, NULL, &attrList, &len, &out);
   375   if (noErr != macErr) {
   376     CKMK_MACERR(dbString, macErr);
   377     return CKR_ATTRIBUTE_TYPE_INVALID;
   378   }
   379   dataLen = content ? len : attrList->attr->length;
   380   dataVal = content ? out : attrList->attr->data;
   382   /* Apple's documentation says this value is DER Encoded, but it clearly isn't
   383    * der encode it before we ship it back off to NSS
   384    */
   385   if ( kSecSerialNumberItemAttr == itemAttr ) {
   386     error = ckmk_encodeInt(item, dataVal, dataLen);
   387     goto loser; /* logically 'done' if error == CKR_OK */
   388   }
   389   item->data = nss_ZNEWARRAY(NULL, char, dataLen);
   390   if (NULL == item->data) {
   391     error = CKR_HOST_MEMORY;
   392     goto loser;
   393   }
   394   nsslibc_memcpy(item->data, dataVal, dataLen);
   395   item->size = dataLen;
   397 loser:
   398   SecKeychainItemFreeAttributesAndData(attrList, out);
   399   return error;
   400 }
   402 /*
   403  * change an attribute (does not operate on the content).
   404  */
   405 static CK_RV
   406 ckmk_updateAttribute
   407 (
   408   SecKeychainItemRef itemRef,
   409   SecItemAttr itemAttr,
   410   void *data,
   411   PRUint32 len,
   412   char *dbString
   413 )
   414 {
   415   SecKeychainAttributeList attrList;
   416   SecKeychainAttribute     attrAttr;
   417   OSStatus macErr;
   418   CK_RV error = CKR_OK;
   420   attrList.count = 1;
   421   attrList.attr = &attrAttr;
   422   attrAttr.tag = itemAttr;
   423   attrAttr.data = data;
   424   attrAttr.length = len;
   425   macErr = SecKeychainItemModifyAttributesAndData(itemRef, &attrList, 0, NULL);
   426   if (noErr != macErr) {
   427     CKMK_MACERR(dbString, macErr);
   428     error = CKR_ATTRIBUTE_TYPE_INVALID;
   429   }
   430   return error;
   431 }
   433 /*
   434  * get an attribute (does not operate on the content)
   435  */
   436 static CK_RV
   437 ckmk_GetDataAttribute
   438 (
   439   ckmkInternalObject *io,
   440   SecItemAttr itemAttr,
   441   NSSItem *item,
   442   char *dbString
   443 )
   444 {
   445   return ckmk_GetCommonAttribute(io, itemAttr, PR_FALSE, item, dbString);
   446 }
   448 /*
   449  * get an attribute we know is a BOOL.
   450  */
   451 static CK_RV
   452 ckmk_GetBoolAttribute
   453 (
   454   ckmkInternalObject *io,
   455   SecItemAttr itemAttr,
   456   NSSItem *item,
   457   char *dbString
   458 )
   459 {
   460   SecKeychainAttribute attr;
   461   SecKeychainAttributeList attrList;
   462   CK_BBOOL *boolp = NULL;
   463   PRUint32 len = 0;;
   464   void *out = NULL;
   465   CK_RV error = CKR_OK;
   466   OSStatus macErr;
   468   attr.tag = itemAttr;
   469   attr.length = 0;
   470   attr.data = NULL;
   471   attrList.count = 1;
   472   attrList.attr = &attr;
   474   boolp = nss_ZNEW(NULL, CK_BBOOL);
   475   if ((CK_BBOOL *)NULL == boolp) {
   476     error = CKR_HOST_MEMORY;
   477     goto loser;
   478   }
   480   macErr = SecKeychainItemCopyContent(io->u.item.itemRef, NULL, 
   481                                       &attrList, &len, &out);
   482   if (noErr != macErr) {
   483     CKMK_MACERR(dbString, macErr);
   484     error = CKR_ATTRIBUTE_TYPE_INVALID;
   485     goto loser;
   486   }
   487   if (sizeof(PRUint32) != attr.length) {
   488     error = CKR_ATTRIBUTE_TYPE_INVALID;
   489     goto loser;
   490   }
   491   *boolp = *(PRUint32 *)attr.data ? 1 : 0;
   492   item->data =  boolp;
   493   boolp = NULL;
   494   item->size = sizeof(CK_BBOOL);
   496 loser:
   497   nss_ZFreeIf(boolp);
   498   SecKeychainItemFreeContent(&attrList, out);
   499   return error;
   500 }
   503 /*
   504  * macros for fetching attributes into a cache and returning the
   505  * appropriate value. These operate inside switch statements
   506  */
   507 #define CKMK_HANDLE_ITEM(func, io, type, loc, item, error, str) \
   508     if (0 == (item)->loc.size) { \
   509       error = func(io, type, &(item)->loc, str); \
   510     } \
   511     return (CKR_OK == (error)) ? &(item)->loc : NULL;
   513 #define CKMK_HANDLE_OPT_ITEM(func, io, type, loc, item, error, str) \
   514     if (0 == (item)->loc.size) { \
   515       (void) func(io, type, &(item)->loc, str); \
   516     } \
   517     return &(item)->loc ;
   519 #define CKMK_HANDLE_BOOL_ITEM(io, type, loc, item, error, str) \
   520     CKMK_HANDLE_ITEM(ckmk_GetBoolAttribute, io, type, loc, item, error, str)
   521 #define CKMK_HANDLE_DATA_ITEM(io, type, loc, item, error, str) \
   522     CKMK_HANDLE_ITEM(ckmk_GetDataAttribute, io, type, loc, item, error, str)
   523 #define CKMK_HANDLE_OPT_DATA_ITEM(io, type, loc, item, error, str) \
   524     CKMK_HANDLE_OPT_ITEM(ckmk_GetDataAttribute, io, type, loc, item, error, str)
   526 /*
   527  * fetch the unique identifier for each object type.
   528  */
   529 static void
   530 ckmk_FetchHashKey
   531 (
   532   ckmkInternalObject *io
   533 )
   534 {
   535   NSSItem *key = &io->hashKey;
   537   if (io->objClass == CKO_CERTIFICATE) {
   538     ckmk_GetCommonAttribute(io, kSecCertEncodingItemAttr, 
   539                             PR_TRUE, key, "Fetching HashKey (cert)");
   540   } else {
   541     ckmk_GetCommonAttribute(io, kSecKeyLabel,
   542                             PR_FALSE, key, "Fetching HashKey (key)");
   543   }
   544 }
   546 /*
   547  * Apple mucks with the actual subject and issuer, so go fetch
   548  * the real ones ourselves.
   549  */
   550 static void 
   551 ckmk_fetchCert
   552 (
   553   ckmkInternalObject *io
   554 )
   555 {
   556   CK_RV error;
   557   unsigned char * cert, *next;
   558   int certSize, thisEntrySize;
   560   error = ckmk_GetCommonAttribute(io, kSecCertEncodingItemAttr, PR_TRUE, 
   561                         &io->u.item.derCert, "Fetching Value (cert)");
   562   if (CKR_OK != error) {
   563     return;
   564   }
   565   /* unwrap the cert bundle */
   566   cert  = nss_ckmk_DERUnwrap((unsigned char *)io->u.item.derCert.data,
   567                             io->u.item.derCert.size,
   568                             &certSize, NULL);
   569   /* unwrap the cert itself */
   570   /* cert == certdata */
   571   cert = nss_ckmk_DERUnwrap(cert, certSize, &certSize, NULL);
   573   /* skip the optional version */
   574   if ((cert[0] & 0xa0) == 0xa0) {
   575     nss_ckmk_DERUnwrap(cert, certSize, &thisEntrySize, &next);
   576     certSize -= next - cert;
   577     cert = next;
   578   }
   579   /* skip the serial number */
   580   nss_ckmk_DERUnwrap(cert, certSize, &thisEntrySize, &next);
   581   certSize -= next - cert;
   582   cert = next;
   584   /* skip the OID */
   585   nss_ckmk_DERUnwrap(cert, certSize, &thisEntrySize, &next);
   586   certSize -= next - cert;
   587   cert = next;
   589   /* save the (wrapped) issuer */
   590   io->u.item.issuer.data = cert;
   591   nss_ckmk_DERUnwrap(cert, certSize, &thisEntrySize, &next);
   592   io->u.item.issuer.size = next - cert;
   593   certSize -= io->u.item.issuer.size;
   594   cert = next;
   596   /* skip the OID */
   597   nss_ckmk_DERUnwrap(cert, certSize, &thisEntrySize, &next);
   598   certSize -= next - cert;
   599   cert = next;
   601   /* save the (wrapped) subject */
   602   io->u.item.subject.data = cert;
   603   nss_ckmk_DERUnwrap(cert, certSize, &thisEntrySize, &next);
   604   io->u.item.subject.size = next - cert;
   605   certSize -= io->u.item.subject.size;
   606   cert = next;
   607 }
   609 static void 
   610 ckmk_fetchModulus
   611 (
   612   ckmkInternalObject *io
   613 )
   614 {
   615   NSSItem item;
   616   PRInt32 modLen;
   617   CK_RV error;
   619   /* we can't reliably get the modulus for private keys through CSSM (sigh).
   620    * For NSS this is OK because we really only use this to get the modulus
   621    * length (unless we are trying to get a public key from a private keys, 
   622    * something CSSM ALSO does not do!).
   623    */
   624   error = ckmk_GetDataAttribute(io, kSecKeyKeySizeInBits, &item, 
   625                         "Key Fetch Modulus");
   626   if (CKR_OK != error) {
   627     return;
   628   }
   630   modLen = *(PRInt32 *)item.data;
   631   modLen = modLen/8; /* convert from bits to bytes */
   633   nss_ZFreeIf(item.data);
   634   io->u.item.modulus.data = nss_ZNEWARRAY(NULL, char, modLen);
   635   if (NULL == io->u.item.modulus.data) {
   636     return;
   637   }
   638   *(char *)io->u.item.modulus.data = 0x80; /* fake NSS out or it will 
   639                                               * drop the first byte */
   640   io->u.item.modulus.size = modLen;
   641   return;
   642 }
   644 const NSSItem *
   645 ckmk_FetchCertAttribute
   646 (
   647   ckmkInternalObject *io,
   648   CK_ATTRIBUTE_TYPE type,
   649   CK_RV *pError
   650 )
   651 {
   652   ckmkItemObject *item = &io->u.item;
   653   *pError = CKR_OK;
   654   switch(type) {
   655   case CKA_CLASS:
   656     return &ckmk_certClassItem;
   657   case CKA_TOKEN:
   658   case CKA_MODIFIABLE:
   659     return &ckmk_trueItem;
   660   case CKA_PRIVATE:
   661     return &ckmk_falseItem;
   662   case CKA_CERTIFICATE_TYPE:
   663     return &ckmk_x509Item;
   664   case CKA_LABEL:
   665     CKMK_HANDLE_OPT_DATA_ITEM(io, kSecLabelItemAttr, label, item, *pError,
   666                               "Cert:Label attr")
   667   case CKA_SUBJECT:
   668     /* OK, well apple does provide an subject and issuer attribute, but they
   669      * decided to cannonicalize that value. Probably a good move for them,
   670      * but makes it useless for most users of PKCS #11.. Get the real subject
   671      * from the certificate */
   672     if (0 == item->derCert.size) {
   673       ckmk_fetchCert(io);
   674     }
   675     return &item->subject;
   676   case CKA_ISSUER:
   677     if (0 == item->derCert.size) {
   678       ckmk_fetchCert(io);
   679     }
   680     return &item->issuer;
   681   case CKA_SERIAL_NUMBER:
   682     CKMK_HANDLE_DATA_ITEM(io, kSecSerialNumberItemAttr, serial, item, *pError,
   683                           "Cert:Serial Number attr")
   684   case CKA_VALUE:
   685     if (0 == item->derCert.size) {
   686       ckmk_fetchCert(io);
   687     }
   688     return &item->derCert;
   689   case CKA_ID:
   690     CKMK_HANDLE_OPT_DATA_ITEM(io, kSecPublicKeyHashItemAttr, id, item, *pError,
   691                               "Cert:ID attr")
   692   default:
   693     *pError = CKR_ATTRIBUTE_TYPE_INVALID;
   694     break;
   695   }
   696   return NULL;
   697 }
   699 const NSSItem *
   700 ckmk_FetchPubKeyAttribute
   701 (
   702   ckmkInternalObject *io, 
   703   CK_ATTRIBUTE_TYPE type,
   704   CK_RV *pError
   705 )
   706 {
   707   ckmkItemObject *item = &io->u.item;
   708   *pError = CKR_OK;
   710   switch(type) {
   711   case CKA_CLASS:
   712     return &ckmk_pubKeyClassItem;
   713   case CKA_TOKEN:
   714   case CKA_LOCAL:
   715     return &ckmk_trueItem;
   716   case CKA_KEY_TYPE:
   717     return &ckmk_rsaItem;
   718   case CKA_LABEL:
   719     CKMK_HANDLE_OPT_DATA_ITEM(io, kSecKeyPrintName, label, item, *pError,
   720                               "PubKey:Label attr")
   721   case CKA_ENCRYPT:
   722     CKMK_HANDLE_BOOL_ITEM(io, kSecKeyEncrypt, encrypt, item, *pError,
   723                               "PubKey:Encrypt attr")
   724   case CKA_VERIFY:
   725     CKMK_HANDLE_BOOL_ITEM(io, kSecKeyVerify, verify, item, *pError,
   726                               "PubKey:Verify attr")
   727   case CKA_VERIFY_RECOVER:
   728     CKMK_HANDLE_BOOL_ITEM(io, kSecKeyVerifyRecover, verifyRecover, 
   729                           item, *pError, "PubKey:VerifyRecover attr")
   730   case CKA_PRIVATE:
   731     CKMK_HANDLE_BOOL_ITEM(io, kSecKeyPrivate, private, item, *pError,
   732                               "PubKey:Private attr")
   733   case CKA_MODIFIABLE:
   734     CKMK_HANDLE_BOOL_ITEM(io, kSecKeyModifiable, modify, item, *pError,
   735                               "PubKey:Modify attr")
   736   case CKA_DERIVE:
   737     CKMK_HANDLE_BOOL_ITEM(io, kSecKeyDerive, derive, item, *pError,
   738                               "PubKey:Derive attr")
   739   case CKA_WRAP:
   740     CKMK_HANDLE_BOOL_ITEM(io, kSecKeyWrap, wrap, item, *pError,
   741                               "PubKey:Wrap attr")
   742   case CKA_SUBJECT:
   743     CKMK_HANDLE_OPT_DATA_ITEM(io, kSecSubjectItemAttr, subject, item, *pError,
   744                               "PubKey:Subect attr")
   745   case CKA_MODULUS:
   746     return &ckmk_emptyItem;
   747   case CKA_PUBLIC_EXPONENT:
   748     return &ckmk_emptyItem;
   749   case CKA_ID:
   750     CKMK_HANDLE_OPT_DATA_ITEM(io, kSecKeyLabel, id, item, *pError,
   751                               "PubKey:ID attr")
   752   default:
   753     *pError = CKR_ATTRIBUTE_TYPE_INVALID;
   754     break;
   755   }
   756   return NULL;
   757 }
   759 const NSSItem *
   760 ckmk_FetchPrivKeyAttribute
   761 (
   762   ckmkInternalObject *io, 
   763   CK_ATTRIBUTE_TYPE type,
   764   CK_RV *pError
   765 )
   766 {
   767   ckmkItemObject *item = &io->u.item;
   768   *pError = CKR_OK;
   770   switch(type) {
   771   case CKA_CLASS:
   772     return &ckmk_privKeyClassItem;
   773   case CKA_TOKEN:
   774   case CKA_LOCAL:
   775     return &ckmk_trueItem;
   776   case CKA_SENSITIVE:
   777   case CKA_EXTRACTABLE: /* will probably move in the future */
   778   case CKA_ALWAYS_SENSITIVE:
   779   case CKA_NEVER_EXTRACTABLE:
   780     return &ckmk_falseItem;
   781   case CKA_KEY_TYPE:
   782     return &ckmk_rsaItem;
   783   case CKA_LABEL:
   784     CKMK_HANDLE_OPT_DATA_ITEM(io, kSecKeyPrintName, label, item, *pError,
   785                               "PrivateKey:Label attr")
   786   case CKA_DECRYPT:
   787     CKMK_HANDLE_BOOL_ITEM(io, kSecKeyDecrypt, decrypt, item, *pError,
   788                               "PrivateKey:Decrypt attr") 
   789   case CKA_SIGN:
   790     CKMK_HANDLE_BOOL_ITEM(io, kSecKeySign, sign, item, *pError,
   791                               "PrivateKey:Sign attr") 
   792   case CKA_SIGN_RECOVER:
   793     CKMK_HANDLE_BOOL_ITEM(io, kSecKeySignRecover, signRecover, item, *pError,
   794                               "PrivateKey:Sign Recover attr") 
   795   case CKA_PRIVATE:
   796     CKMK_HANDLE_BOOL_ITEM(io, kSecKeyPrivate, private, item, *pError,
   797                               "PrivateKey:Private attr") 
   798   case CKA_MODIFIABLE:
   799     CKMK_HANDLE_BOOL_ITEM(io, kSecKeyModifiable, modify, item, *pError,
   800                               "PrivateKey:Modify attr") 
   801   case CKA_DERIVE:
   802     CKMK_HANDLE_BOOL_ITEM(io, kSecKeyDerive, derive, item, *pError,
   803                               "PrivateKey:Derive attr")
   804   case CKA_UNWRAP:
   805     CKMK_HANDLE_BOOL_ITEM(io, kSecKeyUnwrap, unwrap, item, *pError,
   806                               "PrivateKey:Unwrap attr") 
   807   case CKA_SUBJECT:
   808     CKMK_HANDLE_OPT_DATA_ITEM(io, kSecSubjectItemAttr, subject, item, *pError,
   809                               "PrivateKey:Subject attr")
   810   case CKA_MODULUS:
   811     if (0 == item->modulus.size) {
   812       ckmk_fetchModulus(io);
   813     }
   814     return &item->modulus;
   815   case CKA_PUBLIC_EXPONENT:
   816     return &ckmk_emptyItem;
   817 #ifdef notdef
   818   /* the following are sensitive attributes. We could implement them for 
   819    * sensitive keys using the key export function, but it's better to
   820    * just support wrap through this token. That will more reliably allow us
   821    * to export any private key that is truly exportable.
   822    */
   823   case CKA_PRIVATE_EXPONENT:
   824     CKMK_HANDLE_DATA_ITEM(io, kSecPrivateExponentItemAttr, privateExponent, 
   825                           item, *pError)
   826   case CKA_PRIME_1:
   827     CKMK_HANDLE_DATA_ITEM(io, kSecPrime1ItemAttr, prime1, item, *pError)
   828   case CKA_PRIME_2:
   829     CKMK_HANDLE_DATA_ITEM(io, kSecPrime2ItemAttr, prime2, item, *pError)
   830   case CKA_EXPONENT_1:
   831     CKMK_HANDLE_DATA_ITEM(io, kSecExponent1ItemAttr, exponent1, item, *pError)
   832   case CKA_EXPONENT_2:
   833     CKMK_HANDLE_DATA_ITEM(io, kSecExponent2ItemAttr, exponent2, item, *pError)
   834   case CKA_COEFFICIENT:
   835     CKMK_HANDLE_DATA_ITEM(io, kSecCoefficientItemAttr, coefficient, 
   836                           item, *pError)
   837 #endif
   838   case CKA_ID:
   839     CKMK_HANDLE_OPT_DATA_ITEM(io, kSecKeyLabel, id, item, *pError,
   840                               "PrivateKey:ID attr")
   841   default:
   842     *pError = CKR_ATTRIBUTE_TYPE_INVALID;
   843     return NULL;
   844   }
   845 }
   847 const NSSItem *
   848 nss_ckmk_FetchAttribute
   849 (
   850   ckmkInternalObject *io, 
   851   CK_ATTRIBUTE_TYPE type,
   852   CK_RV *pError
   853 )
   854 {
   855   CK_ULONG i;
   856   const NSSItem * value = NULL;
   858   if (io->type == ckmkRaw) {
   859     for( i = 0; i < io->u.raw.n; i++ ) {
   860       if( type == io->u.raw.types[i] ) {
   861         return &io->u.raw.items[i];
   862       }
   863     }
   864     *pError = CKR_ATTRIBUTE_TYPE_INVALID;
   865     return NULL;
   866   }
   867   /* deal with the common attributes */
   868   switch (io->objClass) {
   869   case CKO_CERTIFICATE:
   870    value = ckmk_FetchCertAttribute(io, type, pError); 
   871    break;
   872   case CKO_PRIVATE_KEY:
   873    value = ckmk_FetchPrivKeyAttribute(io, type, pError); 
   874    break;
   875   case CKO_PUBLIC_KEY:
   876    value = ckmk_FetchPubKeyAttribute(io, type, pError); 
   877    break;
   878   default:
   879     *pError = CKR_OBJECT_HANDLE_INVALID;
   880     return NULL;
   881  }
   883 #ifdef DEBUG
   884   if (CKA_ID == type) {
   885     itemdump("id: ", value->data, value->size, *pError);
   886   }
   887 #endif
   888   return value;
   889 }
   891 static void 
   892 ckmk_removeObjectFromHash
   893 (
   894   ckmkInternalObject *io
   895 );
   897 /*
   898  *
   899  * These are the MSObject functions we need to implement
   900  *
   901  * Finalize - unneeded (actually we should clean up the hashtables)
   902  * Destroy 
   903  * IsTokenObject - CK_TRUE
   904  * GetAttributeCount
   905  * GetAttributeTypes
   906  * GetAttributeSize
   907  * GetAttribute
   908  * SetAttribute
   909  * GetObjectSize
   910  */
   912 static CK_RV
   913 ckmk_mdObject_Destroy
   914 (
   915   NSSCKMDObject *mdObject,
   916   NSSCKFWObject *fwObject,
   917   NSSCKMDSession *mdSession,
   918   NSSCKFWSession *fwSession,
   919   NSSCKMDToken *mdToken,
   920   NSSCKFWToken *fwToken,
   921   NSSCKMDInstance *mdInstance,
   922   NSSCKFWInstance *fwInstance
   923 )
   924 {
   925   ckmkInternalObject *io = (ckmkInternalObject *)mdObject->etc;
   926   OSStatus macErr;
   928   if (ckmkRaw == io->type) {
   929     /* there is not 'object write protected' error, use the next best thing */
   930     return CKR_TOKEN_WRITE_PROTECTED;
   931   }
   933   /* This API is done well. The following 4 lines are the complete apple
   934    * specific part of this implementation */
   935   macErr = SecKeychainItemDelete(io->u.item.itemRef);
   936   if (noErr != macErr) {
   937     CKMK_MACERR("Delete object", macErr);
   938   }
   940   /* remove it from the hash */
   941   ckmk_removeObjectFromHash(io);
   943   /* free the puppy.. */
   944   nss_ckmk_DestroyInternalObject(io);
   946   return CKR_OK;
   947 }
   949 static CK_BBOOL
   950 ckmk_mdObject_IsTokenObject
   951 (
   952   NSSCKMDObject *mdObject,
   953   NSSCKFWObject *fwObject,
   954   NSSCKMDSession *mdSession,
   955   NSSCKFWSession *fwSession,
   956   NSSCKMDToken *mdToken,
   957   NSSCKFWToken *fwToken,
   958   NSSCKMDInstance *mdInstance,
   959   NSSCKFWInstance *fwInstance
   960 )
   961 {
   962   return CK_TRUE;
   963 }
   965 static CK_ULONG
   966 ckmk_mdObject_GetAttributeCount
   967 (
   968   NSSCKMDObject *mdObject,
   969   NSSCKFWObject *fwObject,
   970   NSSCKMDSession *mdSession,
   971   NSSCKFWSession *fwSession,
   972   NSSCKMDToken *mdToken,
   973   NSSCKFWToken *fwToken,
   974   NSSCKMDInstance *mdInstance,
   975   NSSCKFWInstance *fwInstance,
   976   CK_RV *pError
   977 )
   978 {
   979   ckmkInternalObject *io = (ckmkInternalObject *)mdObject->etc;
   981   if (ckmkRaw == io->type) {
   982      return io->u.raw.n;
   983   }
   984   switch (io->objClass) {
   985   case CKO_CERTIFICATE:
   986     return certAttrsCount;
   987   case CKO_PUBLIC_KEY:
   988     return pubKeyAttrsCount;
   989   case CKO_PRIVATE_KEY:
   990     return privKeyAttrsCount;
   991   default:
   992     break;
   993   }
   994   return 0;
   995 }
   997 static CK_RV
   998 ckmk_mdObject_GetAttributeTypes
   999 (
  1000   NSSCKMDObject *mdObject,
  1001   NSSCKFWObject *fwObject,
  1002   NSSCKMDSession *mdSession,
  1003   NSSCKFWSession *fwSession,
  1004   NSSCKMDToken *mdToken,
  1005   NSSCKFWToken *fwToken,
  1006   NSSCKMDInstance *mdInstance,
  1007   NSSCKFWInstance *fwInstance,
  1008   CK_ATTRIBUTE_TYPE_PTR typeArray,
  1009   CK_ULONG ulCount
  1012   ckmkInternalObject *io = (ckmkInternalObject *)mdObject->etc;
  1013   CK_ULONG i;
  1014   CK_RV error = CKR_OK;
  1015   const CK_ATTRIBUTE_TYPE *attrs = NULL;
  1016   CK_ULONG size = ckmk_mdObject_GetAttributeCount(
  1017                         mdObject, fwObject, mdSession, fwSession, 
  1018                         mdToken, fwToken, mdInstance, fwInstance, &error);
  1020   if( size != ulCount ) {
  1021     return CKR_BUFFER_TOO_SMALL;
  1023   if (io->type == ckmkRaw) {
  1024     attrs = io->u.raw.types;
  1025   } else switch(io->objClass) {
  1026     case CKO_CERTIFICATE:
  1027       attrs = certAttrs;
  1028       break;
  1029     case CKO_PUBLIC_KEY:
  1030       attrs = pubKeyAttrs;
  1031       break;
  1032     case CKO_PRIVATE_KEY:
  1033       attrs = privKeyAttrs;
  1034       break;
  1035     default:
  1036       return CKR_OK;
  1039   for( i = 0; i < size; i++) {
  1040     typeArray[i] = attrs[i];
  1043   return CKR_OK;
  1046 static CK_ULONG
  1047 ckmk_mdObject_GetAttributeSize
  1049   NSSCKMDObject *mdObject,
  1050   NSSCKFWObject *fwObject,
  1051   NSSCKMDSession *mdSession,
  1052   NSSCKFWSession *fwSession,
  1053   NSSCKMDToken *mdToken,
  1054   NSSCKFWToken *fwToken,
  1055   NSSCKMDInstance *mdInstance,
  1056   NSSCKFWInstance *fwInstance,
  1057   CK_ATTRIBUTE_TYPE attribute,
  1058   CK_RV *pError
  1061   ckmkInternalObject *io = (ckmkInternalObject *)mdObject->etc;
  1063   const NSSItem *b;
  1065   b = nss_ckmk_FetchAttribute(io, attribute, pError);
  1067   if ((const NSSItem *)NULL == b) {
  1068     return 0;
  1070   return b->size;
  1073 static CK_RV
  1074 ckmk_mdObject_SetAttribute
  1076   NSSCKMDObject *mdObject,
  1077   NSSCKFWObject *fwObject,
  1078   NSSCKMDSession *mdSession,
  1079   NSSCKFWSession *fwSession,
  1080   NSSCKMDToken *mdToken,
  1081   NSSCKFWToken *fwToken,
  1082   NSSCKMDInstance *mdInstance,
  1083   NSSCKFWInstance *fwInstance,
  1084   CK_ATTRIBUTE_TYPE attribute,
  1085   NSSItem           *value
  1088   ckmkInternalObject *io = (ckmkInternalObject *)mdObject->etc;
  1089   SecKeychainItemRef itemRef;
  1091   if (io->type == ckmkRaw) {
  1092     return CKR_TOKEN_WRITE_PROTECTED;
  1094   itemRef = io->u.item.itemRef;
  1096   switch (io->objClass) {
  1097   case CKO_PRIVATE_KEY:
  1098   case CKO_PUBLIC_KEY:
  1099     switch (attribute) {
  1100     case CKA_ID:
  1101       ckmk_updateAttribute(itemRef, kSecKeyLabel, 
  1102                               value->data, value->size, "Set Attr Key ID");
  1103 #ifdef DEBUG
  1104       itemdump("key id: ", value->data, value->size, CKR_OK);
  1105 #endif
  1106       break;
  1107     case CKA_LABEL:
  1108       ckmk_updateAttribute(itemRef, kSecKeyPrintName, value->data, 
  1109                               value->size, "Set Attr Key Label");
  1110       break;
  1111     default:
  1112       break;
  1114     break;
  1116   case CKO_CERTIFICATE:
  1117     switch (attribute) {
  1118     case CKA_ID:
  1119       ckmk_updateAttribute(itemRef, kSecPublicKeyHashItemAttr, 
  1120                               value->data, value->size, "Set Attr Cert ID");
  1121       break;
  1122     case CKA_LABEL:
  1123       ckmk_updateAttribute(itemRef, kSecLabelItemAttr, value->data, 
  1124                               value->size, "Set Attr Cert Label");
  1125       break;
  1126     default:
  1127       break;
  1129     break;
  1131    default:
  1132     break;
  1134   return CKR_OK;
  1137 static NSSCKFWItem
  1138 ckmk_mdObject_GetAttribute
  1140   NSSCKMDObject *mdObject,
  1141   NSSCKFWObject *fwObject,
  1142   NSSCKMDSession *mdSession,
  1143   NSSCKFWSession *fwSession,
  1144   NSSCKMDToken *mdToken,
  1145   NSSCKFWToken *fwToken,
  1146   NSSCKMDInstance *mdInstance,
  1147   NSSCKFWInstance *fwInstance,
  1148   CK_ATTRIBUTE_TYPE attribute,
  1149   CK_RV *pError
  1152   NSSCKFWItem mdItem;
  1153   ckmkInternalObject *io = (ckmkInternalObject *)mdObject->etc;
  1155   mdItem.needsFreeing = PR_FALSE;
  1156   mdItem.item = (NSSItem*)nss_ckmk_FetchAttribute(io, attribute, pError);
  1159   return mdItem;
  1162 static CK_ULONG
  1163 ckmk_mdObject_GetObjectSize
  1165   NSSCKMDObject *mdObject,
  1166   NSSCKFWObject *fwObject,
  1167   NSSCKMDSession *mdSession,
  1168   NSSCKFWSession *fwSession,
  1169   NSSCKMDToken *mdToken,
  1170   NSSCKFWToken *fwToken,
  1171   NSSCKMDInstance *mdInstance,
  1172   NSSCKFWInstance *fwInstance,
  1173   CK_RV *pError
  1176   CK_ULONG rv = 1;
  1178   /* size is irrelevant to this token */
  1179   return rv;
  1182 static const NSSCKMDObject
  1183 ckmk_prototype_mdObject = {
  1184   (void *)NULL, /* etc */
  1185   NULL, /* Finalize */
  1186   ckmk_mdObject_Destroy,
  1187   ckmk_mdObject_IsTokenObject,
  1188   ckmk_mdObject_GetAttributeCount,
  1189   ckmk_mdObject_GetAttributeTypes,
  1190   ckmk_mdObject_GetAttributeSize,
  1191   ckmk_mdObject_GetAttribute,
  1192   NULL, /* FreeAttribute */
  1193   ckmk_mdObject_SetAttribute,
  1194   ckmk_mdObject_GetObjectSize,
  1195   (void *)NULL /* null terminator */
  1196 };
  1198 static nssHash *ckmkInternalObjectHash = NULL;
  1200 NSS_IMPLEMENT NSSCKMDObject *
  1201 nss_ckmk_CreateMDObject
  1203   NSSArena *arena,
  1204   ckmkInternalObject *io,
  1205   CK_RV *pError
  1208   if ((nssHash *)NULL == ckmkInternalObjectHash) {
  1209     ckmkInternalObjectHash = nssHash_CreateItem(NULL, 10);
  1211   if (ckmkItem == io->type) {
  1212     /* the hash key, not a cryptographic key */
  1213     NSSItem *key = &io->hashKey;
  1214     ckmkInternalObject *old_o = NULL;
  1216     if (key->size == 0) {
  1217       ckmk_FetchHashKey(io);
  1219     old_o = (ckmkInternalObject *) 
  1220               nssHash_Lookup(ckmkInternalObjectHash, key);
  1221     if (!old_o) {
  1222       nssHash_Add(ckmkInternalObjectHash, key, io);
  1223     } else if (old_o != io) {
  1224       nss_ckmk_DestroyInternalObject(io);
  1225       io = old_o;
  1229   if ( (void*)NULL == io->mdObject.etc) {
  1230     (void) nsslibc_memcpy(&io->mdObject,&ckmk_prototype_mdObject,
  1231                                         sizeof(ckmk_prototype_mdObject));
  1232     io->mdObject.etc = (void *)io;
  1234   return &io->mdObject;
  1237 static void
  1238 ckmk_removeObjectFromHash
  1240   ckmkInternalObject *io
  1243   NSSItem *key = &io->hashKey;
  1245   if ((nssHash *)NULL == ckmkInternalObjectHash) {
  1246     return;
  1248   if (key->size == 0) {
  1249     ckmk_FetchHashKey(io);
  1251   nssHash_Remove(ckmkInternalObjectHash, key);
  1252   return;
  1256 void
  1257 nss_ckmk_DestroyInternalObject
  1259   ckmkInternalObject *io
  1262   switch (io->type) {
  1263   case ckmkRaw:
  1264     return;
  1265   case ckmkItem:
  1266     nss_ZFreeIf(io->u.item.modify.data);
  1267     nss_ZFreeIf(io->u.item.private.data);
  1268     nss_ZFreeIf(io->u.item.encrypt.data);
  1269     nss_ZFreeIf(io->u.item.decrypt.data);
  1270     nss_ZFreeIf(io->u.item.derive.data);
  1271     nss_ZFreeIf(io->u.item.sign.data);
  1272     nss_ZFreeIf(io->u.item.signRecover.data);
  1273     nss_ZFreeIf(io->u.item.verify.data);
  1274     nss_ZFreeIf(io->u.item.verifyRecover.data);
  1275     nss_ZFreeIf(io->u.item.wrap.data);
  1276     nss_ZFreeIf(io->u.item.unwrap.data);
  1277     nss_ZFreeIf(io->u.item.label.data);
  1278     /*nss_ZFreeIf(io->u.item.subject.data); */
  1279     /*nss_ZFreeIf(io->u.item.issuer.data); */
  1280     nss_ZFreeIf(io->u.item.serial.data);
  1281     nss_ZFreeIf(io->u.item.modulus.data);
  1282     nss_ZFreeIf(io->u.item.exponent.data);
  1283     nss_ZFreeIf(io->u.item.privateExponent.data);
  1284     nss_ZFreeIf(io->u.item.prime1.data);
  1285     nss_ZFreeIf(io->u.item.prime2.data);
  1286     nss_ZFreeIf(io->u.item.exponent1.data);
  1287     nss_ZFreeIf(io->u.item.exponent2.data);
  1288     nss_ZFreeIf(io->u.item.coefficient.data);
  1289     break;
  1291   nss_ZFreeIf(io);
  1292   return;
  1296 static ckmkInternalObject *
  1297 nss_ckmk_NewInternalObject
  1299   CK_OBJECT_CLASS objClass,
  1300   SecKeychainItemRef itemRef,
  1301   SecItemClass itemClass,
  1302   CK_RV *pError
  1305   ckmkInternalObject *io = nss_ZNEW(NULL, ckmkInternalObject);
  1307   if ((ckmkInternalObject *)NULL == io) {
  1308     *pError = CKR_HOST_MEMORY;
  1309     return io;
  1311   io->type = ckmkItem;
  1312   io->objClass = objClass;
  1313   io->u.item.itemRef = itemRef;
  1314   io->u.item.itemClass = itemClass;
  1315   return io;
  1318 /*
  1319  * Apple doesn't alway have a default keyChain set by the OS, use the 
  1320  * SearchList to try to find one.
  1321  */
  1322 static CK_RV
  1323 ckmk_GetSafeDefaultKeychain
  1325   SecKeychainRef *keychainRef
  1328   OSStatus macErr;
  1329   CFArrayRef searchList = 0;
  1330   CK_RV error = CKR_OK;
  1332   macErr = SecKeychainCopyDefault(keychainRef);
  1333   if (noErr != macErr) {
  1334     int searchCount = 0;
  1335     if (errSecNoDefaultKeychain != macErr) {
  1336       CKMK_MACERR("Getting default key chain", macErr);
  1337       error = CKR_GENERAL_ERROR;
  1338       goto loser;
  1340     /* ok, we don't have a default key chain, find one */
  1341     macErr = SecKeychainCopySearchList(&searchList);
  1342     if (noErr != macErr) {
  1343       CKMK_MACERR("failed to find a keyring searchList", macErr);
  1344       error = CKR_DEVICE_REMOVED;
  1345       goto loser;
  1347     searchCount = CFArrayGetCount(searchList);
  1348     if (searchCount < 1) {
  1349       error = CKR_DEVICE_REMOVED;
  1350       goto loser;
  1352     *keychainRef = 
  1353         (SecKeychainRef)CFRetain(CFArrayGetValueAtIndex(searchList, 0));
  1354     if (0 == *keychainRef) {
  1355       error = CKR_DEVICE_REMOVED;
  1356       goto loser;
  1358     /* should we set it as default? */
  1360 loser:
  1361   if (0 != searchList) {
  1362     CFRelease(searchList);
  1364   return error;
  1366 static ckmkInternalObject *
  1367 nss_ckmk_CreateCertificate
  1369   NSSCKFWSession *fwSession,
  1370   CK_ATTRIBUTE_PTR pTemplate,
  1371   CK_ULONG ulAttributeCount,
  1372   CK_RV *pError
  1375   NSSItem value;
  1376   ckmkInternalObject *io = NULL; 
  1377   OSStatus macErr;
  1378   SecCertificateRef certRef;
  1379   SecKeychainItemRef itemRef;
  1380   SecKeychainRef keychainRef;
  1381   CSSM_DATA certData;
  1383   *pError = nss_ckmk_GetAttribute(CKA_VALUE, pTemplate, 
  1384                                   ulAttributeCount, &value);
  1385   if (CKR_OK != *pError) {
  1386     goto loser;
  1389   certData.Data = value.data;
  1390   certData.Length = value.size;
  1391   macErr = SecCertificateCreateFromData(&certData, CSSM_CERT_X_509v3, 
  1392                               CSSM_CERT_ENCODING_BER, &certRef);
  1393   if (noErr != macErr) {
  1394     CKMK_MACERR("Create cert from data Failed", macErr);
  1395     *pError = CKR_GENERAL_ERROR; /* need to map macErr */
  1396     goto loser;
  1399   *pError = ckmk_GetSafeDefaultKeychain(&keychainRef);
  1400   if (CKR_OK != *pError) {
  1401     goto loser;
  1404   macErr = SecCertificateAddToKeychain( certRef, keychainRef);
  1405   itemRef = (SecKeychainItemRef) certRef;
  1406   if (errSecDuplicateItem != macErr) {
  1407     NSSItem keyID = { NULL, 0 };
  1408     char *nickname = NULL;
  1409     CK_RV dummy;
  1411     if (noErr != macErr) {
  1412       CKMK_MACERR("Add cert to keychain Failed", macErr);
  1413       *pError = CKR_GENERAL_ERROR; /* need to map macErr */
  1414       goto loser;
  1416     /* these two are optional */
  1417     nickname = nss_ckmk_GetStringAttribute(CKA_LABEL, pTemplate, 
  1418                                   ulAttributeCount, &dummy);
  1419     /* we've added a new one, update the attributes in the key ring */
  1420     if (nickname) {
  1421       ckmk_updateAttribute(itemRef, kSecLabelItemAttr, nickname, 
  1422                               strlen(nickname)+1, "Modify Cert Label");
  1423       nss_ZFreeIf(nickname);
  1425     dummy = nss_ckmk_GetAttribute(CKA_ID, pTemplate, 
  1426                                   ulAttributeCount, &keyID);
  1427     if (CKR_OK == dummy) {
  1428       dummy = ckmk_updateAttribute(itemRef, kSecPublicKeyHashItemAttr, 
  1429                               keyID.data, keyID.size, "Modify Cert ID");
  1433   io = nss_ckmk_NewInternalObject(CKO_CERTIFICATE, itemRef, 
  1434                                   kSecCertificateItemClass, pError);
  1435   if ((ckmkInternalObject *)NULL != io) {
  1436     itemRef = 0;
  1439 loser:
  1440   if (0 != itemRef) {
  1441     CFRelease(itemRef);
  1443   if (0 != keychainRef) {
  1444     CFRelease(keychainRef);
  1447   return io;
  1450 /*
  1451  * PKCS #8 attributes
  1452  */
  1453 struct ckmk_AttributeStr {
  1454     SECItem attrType;
  1455     SECItem *attrValue;
  1456 };
  1457 typedef struct ckmk_AttributeStr ckmk_Attribute;
  1459 /*
  1460 ** A PKCS#8 private key info object
  1461 */
  1462 struct PrivateKeyInfoStr {
  1463     PLArenaPool *arena;
  1464     SECItem version;
  1465     SECAlgorithmID algorithm;
  1466     SECItem privateKey;
  1467     ckmk_Attribute **attributes;
  1468 };
  1469 typedef struct PrivateKeyInfoStr PrivateKeyInfo;
  1471 const SEC_ASN1Template ckmk_RSAPrivateKeyTemplate[] = {
  1472     { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(RSAPrivateKey) },
  1473     { SEC_ASN1_INTEGER, offsetof(RSAPrivateKey,version) },
  1474     { SEC_ASN1_INTEGER, offsetof(RSAPrivateKey,modulus) },
  1475     { SEC_ASN1_INTEGER, offsetof(RSAPrivateKey,publicExponent) },
  1476     { SEC_ASN1_INTEGER, offsetof(RSAPrivateKey,privateExponent) },
  1477     { SEC_ASN1_INTEGER, offsetof(RSAPrivateKey,prime1) },
  1478     { SEC_ASN1_INTEGER, offsetof(RSAPrivateKey,prime2) },
  1479     { SEC_ASN1_INTEGER, offsetof(RSAPrivateKey,exponent1) },
  1480     { SEC_ASN1_INTEGER, offsetof(RSAPrivateKey,exponent2) },
  1481     { SEC_ASN1_INTEGER, offsetof(RSAPrivateKey,coefficient) },
  1482     { 0 }                                                                     
  1483 }; 
  1485 const SEC_ASN1Template ckmk_AttributeTemplate[] = {
  1486     { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(ckmk_Attribute) },
  1487     { SEC_ASN1_OBJECT_ID, offsetof(ckmk_Attribute, attrType) },
  1488     { SEC_ASN1_SET_OF, offsetof(ckmk_Attribute, attrValue), 
  1489         SEC_AnyTemplate },
  1490     { 0 }
  1491 };
  1493 const SEC_ASN1Template ckmk_SetOfAttributeTemplate[] = {
  1494     { SEC_ASN1_SET_OF, 0, ckmk_AttributeTemplate },
  1495 };
  1497 SEC_ASN1_MKSUB(SECOID_AlgorithmIDTemplate)
  1499 /* ASN1 Templates for new decoder/encoder */
  1500 const SEC_ASN1Template ckmk_PrivateKeyInfoTemplate[] = {
  1501     { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(PrivateKeyInfo) },
  1502     { SEC_ASN1_INTEGER, offsetof(PrivateKeyInfo,version) },
  1503     { SEC_ASN1_INLINE | SEC_ASN1_XTRN, offsetof(PrivateKeyInfo,algorithm),
  1504         SEC_ASN1_SUB(SECOID_AlgorithmIDTemplate) },
  1505     { SEC_ASN1_OCTET_STRING, offsetof(PrivateKeyInfo,privateKey) },
  1506     { SEC_ASN1_OPTIONAL | SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | 0,
  1507         offsetof(PrivateKeyInfo, attributes), ckmk_SetOfAttributeTemplate },
  1508     { 0 }
  1509 };
  1511 #define CKMK_PRIVATE_KEY_INFO_VERSION 0
  1512 static CK_RV
  1513 ckmk_CreateRSAKeyBlob
  1515   RSAPrivateKey *lk,
  1516   NSSItem *keyBlob
  1519   PrivateKeyInfo *pki = NULL;
  1520   PLArenaPool *arena = NULL;
  1521   SECOidTag algorithm = SEC_OID_UNKNOWN;
  1522   void *dummy;
  1523   SECStatus rv;
  1524   SECItem *encodedKey = NULL;
  1525   CK_RV error = CKR_OK;
  1527   arena = PORT_NewArena(2048);         /* XXX different size? */
  1528   if(!arena) {
  1529     error = CKR_HOST_MEMORY;
  1530     goto loser;
  1533   pki = (PrivateKeyInfo*)PORT_ArenaZAlloc(arena, sizeof(PrivateKeyInfo));
  1534   if(!pki) {
  1535     error = CKR_HOST_MEMORY;
  1536     goto loser;
  1538   pki->arena = arena;
  1540   dummy = SEC_ASN1EncodeItem(arena, &pki->privateKey, lk,
  1541                              ckmk_RSAPrivateKeyTemplate);
  1542   algorithm = SEC_OID_PKCS1_RSA_ENCRYPTION;
  1544   if (!dummy) {
  1545     error = CKR_DEVICE_ERROR; /* should map NSS SECError */
  1546     goto loser;
  1549   rv = SECOID_SetAlgorithmID(arena, &pki->algorithm, algorithm, 
  1550                              (SECItem*)NULL);
  1551   if (rv != SECSuccess) {
  1552     error = CKR_DEVICE_ERROR; /* should map NSS SECError */
  1553     goto loser;
  1556   dummy = SEC_ASN1EncodeInteger(arena, &pki->version, 
  1557                                 CKMK_PRIVATE_KEY_INFO_VERSION);
  1558   if (!dummy) {
  1559     error = CKR_DEVICE_ERROR; /* should map NSS SECError */
  1560     goto loser;
  1563   encodedKey = SEC_ASN1EncodeItem(NULL, NULL, pki, 
  1564                                   ckmk_PrivateKeyInfoTemplate);
  1565   if (!encodedKey) {
  1566     error = CKR_DEVICE_ERROR;
  1567     goto loser;
  1570   keyBlob->data = nss_ZNEWARRAY(NULL, char, encodedKey->len);
  1571   if (NULL == keyBlob->data) {
  1572     error = CKR_HOST_MEMORY;
  1573     goto loser;
  1575   nsslibc_memcpy(keyBlob->data, encodedKey->data, encodedKey->len);
  1576   keyBlob->size = encodedKey->len;
  1578 loser:
  1579   if(arena) {
  1580     PORT_FreeArena(arena, PR_TRUE);
  1582   if (encodedKey) {
  1583     SECITEM_FreeItem(encodedKey, PR_TRUE);
  1586   return error;
  1588 /*
  1589  * There MUST be a better way to do this. For now, find the key based on the
  1590  * default name Apple gives it once we import.
  1591  */
  1592 #define IMPORTED_NAME "Imported Private Key"
  1593 static CK_RV
  1594 ckmk_FindImportedKey
  1596   SecKeychainRef keychainRef,
  1597   SecItemClass itemClass,
  1598   SecKeychainItemRef *outItemRef
  1601   OSStatus macErr;
  1602   SecKeychainSearchRef searchRef = 0;
  1603   SecKeychainItemRef newItemRef;
  1605   macErr = SecKeychainSearchCreateFromAttributes(keychainRef, itemClass,
  1606            NULL, &searchRef);
  1607   if (noErr != macErr) {
  1608     CKMK_MACERR("Can't search for Key", macErr);
  1609     return CKR_GENERAL_ERROR;
  1611   while (noErr == SecKeychainSearchCopyNext(searchRef, &newItemRef)) {
  1612     SecKeychainAttributeList *attrList = NULL;
  1613     SecKeychainAttributeInfo attrInfo;
  1614     SecItemAttr itemAttr = kSecKeyPrintName;
  1615     PRUint32 attrFormat = 0;
  1616     OSStatus macErr;
  1618     attrInfo.count = 1;
  1619     attrInfo.tag = &itemAttr;
  1620     attrInfo.format = &attrFormat;
  1622     macErr = SecKeychainItemCopyAttributesAndData(newItemRef,
  1623                                 &attrInfo, NULL, &attrList, NULL, NULL);
  1624     if (noErr == macErr) {
  1625       if (nsslibc_memcmp(attrList->attr->data, IMPORTED_NAME, 
  1626                          attrList->attr->length, NULL) == 0) {
  1627         *outItemRef = newItemRef;
  1628         CFRelease (searchRef);
  1629         SecKeychainItemFreeAttributesAndData(attrList, NULL);
  1630         return CKR_OK;
  1632       SecKeychainItemFreeAttributesAndData(attrList, NULL);
  1634     CFRelease(newItemRef);
  1636   CFRelease (searchRef);
  1637   return CKR_GENERAL_ERROR; /* we can come up with something better! */
  1640 static ckmkInternalObject *
  1641 nss_ckmk_CreatePrivateKey
  1643   NSSCKFWSession *fwSession,
  1644   CK_ATTRIBUTE_PTR pTemplate,
  1645   CK_ULONG ulAttributeCount,
  1646   CK_RV *pError
  1649   NSSItem attribute;
  1650   RSAPrivateKey lk;
  1651   NSSItem keyID;
  1652   char *nickname = NULL;
  1653   ckmkInternalObject *io = NULL;
  1654   CK_KEY_TYPE keyType;
  1655   OSStatus macErr;
  1656   SecKeychainItemRef itemRef = 0;
  1657   NSSItem keyBlob = { NULL, 0 };
  1658   CFDataRef dataRef = 0;
  1659   SecExternalFormat inputFormat = kSecFormatBSAFE; 
  1660   /*SecExternalFormat inputFormat = kSecFormatOpenSSL;  */
  1661   SecExternalItemType itemType = kSecItemTypePrivateKey;
  1662   SecKeyImportExportParameters keyParams ;
  1663   SecKeychainRef targetKeychain = 0;
  1664   unsigned char zero = 0;
  1665   CK_RV error;
  1667   keyParams.version = SEC_KEY_IMPORT_EXPORT_PARAMS_VERSION;
  1668   keyParams.flags = 0;
  1669   keyParams.passphrase = 0;
  1670   keyParams.alertTitle = 0;
  1671   keyParams.alertPrompt = 0;
  1672   keyParams.accessRef = 0; /* default */
  1673   keyParams.keyUsage = 0; /* will get filled in */
  1674   keyParams.keyAttributes = CSSM_KEYATTR_PERMANENT; /* will get filled in */
  1675   keyType = nss_ckmk_GetULongAttribute
  1676                   (CKA_KEY_TYPE, pTemplate, ulAttributeCount, pError);
  1677   if (CKR_OK != *pError) {
  1678     return (ckmkInternalObject *)NULL;
  1680   if (CKK_RSA != keyType) {
  1681     *pError = CKR_ATTRIBUTE_VALUE_INVALID;
  1682     return (ckmkInternalObject *)NULL;
  1684   if (nss_ckmk_GetBoolAttribute(CKA_DECRYPT, 
  1685                                 pTemplate, ulAttributeCount, CK_TRUE)) {
  1686     keyParams.keyUsage |= CSSM_KEYUSE_DECRYPT;
  1688   if (nss_ckmk_GetBoolAttribute(CKA_UNWRAP, 
  1689                                 pTemplate, ulAttributeCount, CK_TRUE)) {
  1690     keyParams.keyUsage |=  CSSM_KEYUSE_UNWRAP;
  1692   if (nss_ckmk_GetBoolAttribute(CKA_SIGN, 
  1693                                 pTemplate, ulAttributeCount, CK_TRUE)) {
  1694     keyParams.keyUsage |= CSSM_KEYUSE_SIGN;
  1696   if (nss_ckmk_GetBoolAttribute(CKA_DERIVE, 
  1697                                 pTemplate, ulAttributeCount, CK_FALSE)) {
  1698     keyParams.keyUsage |= CSSM_KEYUSE_DERIVE;
  1700   if (nss_ckmk_GetBoolAttribute(CKA_SENSITIVE, 
  1701                                 pTemplate, ulAttributeCount, CK_TRUE)) {
  1702     keyParams.keyAttributes |= CSSM_KEYATTR_SENSITIVE; 
  1704   if (nss_ckmk_GetBoolAttribute(CKA_EXTRACTABLE, 
  1705                                 pTemplate, ulAttributeCount, CK_TRUE)) {
  1706     keyParams.keyAttributes |= CSSM_KEYATTR_EXTRACTABLE;
  1709   lk.version.type = siUnsignedInteger;
  1710   lk.version.data = &zero;
  1711   lk.version.len = 1;
  1713   *pError = nss_ckmk_GetAttribute(CKA_MODULUS, pTemplate, 
  1714                                   ulAttributeCount, &attribute);
  1715   if (CKR_OK != *pError) {
  1716     return (ckmkInternalObject *)NULL;
  1718   lk.modulus.type = siUnsignedInteger;
  1719   lk.modulus.data = attribute.data;
  1720   lk.modulus.len = attribute.size;
  1722   *pError = nss_ckmk_GetAttribute(CKA_PUBLIC_EXPONENT, pTemplate, 
  1723                                   ulAttributeCount, &attribute);
  1724   if (CKR_OK != *pError) {
  1725     return (ckmkInternalObject *)NULL;
  1727   lk.publicExponent.type = siUnsignedInteger;
  1728   lk.publicExponent.data = attribute.data;
  1729   lk.publicExponent.len = attribute.size;
  1731   *pError = nss_ckmk_GetAttribute(CKA_PRIVATE_EXPONENT, pTemplate, 
  1732                                   ulAttributeCount, &attribute);
  1733   if (CKR_OK != *pError) {
  1734     return (ckmkInternalObject *)NULL;
  1736   lk.privateExponent.type = siUnsignedInteger;
  1737   lk.privateExponent.data = attribute.data;
  1738   lk.privateExponent.len = attribute.size;
  1740   *pError = nss_ckmk_GetAttribute(CKA_PRIME_1, pTemplate, 
  1741                                   ulAttributeCount, &attribute);
  1742   if (CKR_OK != *pError) {
  1743     return (ckmkInternalObject *)NULL;
  1745   lk.prime1.type = siUnsignedInteger;
  1746   lk.prime1.data = attribute.data;
  1747   lk.prime1.len = attribute.size;
  1749   *pError = nss_ckmk_GetAttribute(CKA_PRIME_2, pTemplate, 
  1750                                   ulAttributeCount, &attribute);
  1751   if (CKR_OK != *pError) {
  1752     return (ckmkInternalObject *)NULL;
  1754   lk.prime2.type = siUnsignedInteger;
  1755   lk.prime2.data = attribute.data;
  1756   lk.prime2.len = attribute.size;
  1758   *pError = nss_ckmk_GetAttribute(CKA_EXPONENT_1, pTemplate, 
  1759                                   ulAttributeCount, &attribute);
  1760   if (CKR_OK != *pError) {
  1761     return (ckmkInternalObject *)NULL;
  1763   lk.exponent1.type = siUnsignedInteger;
  1764   lk.exponent1.data = attribute.data;
  1765   lk.exponent1.len = attribute.size;
  1767   *pError = nss_ckmk_GetAttribute(CKA_EXPONENT_2, pTemplate, 
  1768                                   ulAttributeCount, &attribute);
  1769   if (CKR_OK != *pError) {
  1770     return (ckmkInternalObject *)NULL;
  1772   lk.exponent2.type = siUnsignedInteger;
  1773   lk.exponent2.data = attribute.data;
  1774   lk.exponent2.len = attribute.size;
  1776   *pError = nss_ckmk_GetAttribute(CKA_COEFFICIENT, pTemplate, 
  1777                                   ulAttributeCount, &attribute);
  1778   if (CKR_OK != *pError) {
  1779     return (ckmkInternalObject *)NULL;
  1781   lk.coefficient.type = siUnsignedInteger;
  1782   lk.coefficient.data = attribute.data;
  1783   lk.coefficient.len = attribute.size;
  1785   /* ASN1 Encode the pkcs8 structure... look at softoken to see how this
  1786    * is done... */
  1787   error = ckmk_CreateRSAKeyBlob(&lk, &keyBlob);
  1788   if (CKR_OK != error) {
  1789     goto loser;
  1792   dataRef = CFDataCreate(NULL, (UInt8 *)keyBlob.data, keyBlob.size);
  1793   if (0 == dataRef) {
  1794     *pError = CKR_HOST_MEMORY;
  1795     goto loser;
  1798   *pError == ckmk_GetSafeDefaultKeychain(&targetKeychain);
  1799   if (CKR_OK != *pError) {
  1800     goto loser;
  1804   /* the itemArray that is returned is useless. the item does not
  1805    * is 'not on the key chain' so none of the modify calls work on it.
  1806    * It also has a key that isn't the same key as the one in the actual
  1807    * key chain. In short it isn't the item we want, and it gives us zero
  1808    * information about the item we want, so don't even bother with it...
  1809    */
  1810   macErr = SecKeychainItemImport(dataRef, NULL, &inputFormat, &itemType, 0,
  1811         &keyParams, targetKeychain, NULL);
  1812   if (noErr != macErr) {
  1813     CKMK_MACERR("Import Private Key", macErr);
  1814     *pError = CKR_GENERAL_ERROR;
  1815     goto loser;
  1818   *pError = ckmk_FindImportedKey(targetKeychain, 
  1819                                  CSSM_DL_DB_RECORD_PRIVATE_KEY,
  1820                                  &itemRef);
  1821   if (CKR_OK != *pError) {
  1822 #ifdef DEBUG
  1823     fprintf(stderr,"couldn't find key in keychain \n");
  1824 #endif
  1825     goto loser;
  1829   /* set the CKA_ID and  the CKA_LABEL */
  1830   error = nss_ckmk_GetAttribute(CKA_ID, pTemplate, 
  1831                                   ulAttributeCount, &keyID);
  1832   if (CKR_OK == error) {
  1833     error = ckmk_updateAttribute(itemRef, kSecKeyLabel, 
  1834                               keyID.data, keyID.size, "Modify Key ID");
  1835 #ifdef DEBUG
  1836     itemdump("key id: ", keyID.data, keyID.size, error);
  1837 #endif
  1839   nickname = nss_ckmk_GetStringAttribute(CKA_LABEL, pTemplate, 
  1840                                   ulAttributeCount, &error);
  1841   if (nickname) {
  1842     ckmk_updateAttribute(itemRef, kSecKeyPrintName, nickname, 
  1843                               strlen(nickname)+1, "Modify Key Label");
  1844   } else {
  1845 #define DEFAULT_NICKNAME "NSS Imported Key"
  1846     ckmk_updateAttribute(itemRef, kSecKeyPrintName, DEFAULT_NICKNAME, 
  1847                               sizeof(DEFAULT_NICKNAME), "Modify Key Label");
  1850   io = nss_ckmk_NewInternalObject(CKO_PRIVATE_KEY, itemRef, 
  1851                                   CSSM_DL_DB_RECORD_PRIVATE_KEY, pError);
  1852   if ((ckmkInternalObject *)NULL == io) {
  1853     CFRelease(itemRef);
  1856   return io;
  1858 loser:
  1859   /* free the key blob */
  1860   if (keyBlob.data) {
  1861     nss_ZFreeIf(keyBlob.data);
  1863   if (0 != targetKeychain) {
  1864     CFRelease(targetKeychain);
  1866   if (0 != dataRef) {
  1867     CFRelease(dataRef);
  1869   return io;
  1873 NSS_EXTERN NSSCKMDObject *
  1874 nss_ckmk_CreateObject
  1876   NSSCKFWSession *fwSession,
  1877   CK_ATTRIBUTE_PTR pTemplate,
  1878   CK_ULONG ulAttributeCount,
  1879   CK_RV *pError
  1882   CK_OBJECT_CLASS objClass;
  1883   ckmkInternalObject *io;
  1884   CK_BBOOL isToken;
  1886   /*
  1887    * only create token objects
  1888    */
  1889   isToken = nss_ckmk_GetBoolAttribute(CKA_TOKEN, pTemplate, 
  1890                                       ulAttributeCount, CK_FALSE);
  1891   if (!isToken) {
  1892     *pError = CKR_ATTRIBUTE_VALUE_INVALID;
  1893     return (NSSCKMDObject *) NULL;
  1896   /*
  1897    * only create keys and certs.
  1898    */
  1899   objClass = nss_ckmk_GetULongAttribute(CKA_CLASS, pTemplate, 
  1900                                         ulAttributeCount, pError);
  1901   if (CKR_OK != *pError) {
  1902     return (NSSCKMDObject *) NULL;
  1904 #ifdef notdef
  1905   if (objClass == CKO_PUBLIC_KEY) {
  1906     return CKR_OK; /* fake public key creation, happens as a side effect of
  1907                     * private key creation */
  1909 #endif
  1910   if (objClass == CKO_CERTIFICATE) {
  1911     io = nss_ckmk_CreateCertificate(fwSession, pTemplate, 
  1912                                     ulAttributeCount, pError);
  1913   } else if (objClass == CKO_PRIVATE_KEY) {
  1914     io = nss_ckmk_CreatePrivateKey(fwSession, pTemplate, 
  1915                                    ulAttributeCount, pError);
  1916   } else {
  1917     *pError = CKR_ATTRIBUTE_VALUE_INVALID;
  1920   if ((ckmkInternalObject *)NULL == io) {
  1921     return (NSSCKMDObject *) NULL;
  1923   return nss_ckmk_CreateMDObject(NULL, io, pError);

mercurial