components/coolkey/patches/04-object.cpp.patch
branchs11u3-sru
changeset 6535 8f23248b161c
equal deleted inserted replaced
6529:50a81baffe58 6535:8f23248b161c
       
     1 Upstream fixes already included in the latest community updates to coolkey v1.1.0
       
     2 
       
     3 Addresses various bugs found in PKCS11 object handling.
       
     4 
       
     5 --- ORIGINAL/./src/coolkey/object.cpp	2016-06-24 16:07:19.782779440 -0400
       
     6 +++ ././src/coolkey/object.cpp	2016-06-27 13:43:35.548673450 -0400
       
     7 @@ -21,15 +21,48 @@
       
     8  #include "PKCS11Exception.h"
       
     9  #include "object.h"
       
    10  #include <algorithm>
       
    11 +#include <string.h>
       
    12  
       
    13  using std::find_if;
       
    14  
       
    15 +const CKYByte rsaOID[] = {0x2A,0x86,0x48,0x86,0xF7,0x0D, 0x01, 0x01,0x1};
       
    16 +const CKYByte eccOID[] = {0x2a,0x86,0x48,0xce,0x3d,0x02,0x01};
       
    17 +
       
    18 +#ifdef DEBUG
       
    19 +void dump(CKYBuffer *buf)
       
    20 +{
       
    21 +    CKYSize i;
       
    22 +    CKYSize size = CKYBuffer_Size(buf);
       
    23 +#define ROW_LENGTH 60
       
    24 +    char string[ROW_LENGTH+1];
       
    25 +    char *bp = &string[0];
       
    26 +    CKYByte c;
       
    27 +
       
    28 +    for (i=0; i < size; i++) {
       
    29 +        if (i && ((i % (ROW_LENGTH-1)) == 0) ) {
       
    30 +            *bp = 0;
       
    31 +            printf(" %s\n",string);
       
    32 +            bp = &string[0];
       
    33 +        }
       
    34 +        c = CKYBuffer_GetChar(buf, i);
       
    35 +        printf("%02x ",c);
       
    36 +        *bp++ =  (c < ' ') ? '.' : ((c & 0x80) ? '*' : c);
       
    37 +    }
       
    38 +    *bp = 0;
       
    39 +    for (i= (i % (ROW_LENGTH-1)); i && (i < ROW_LENGTH); i++) {
       
    40 +        printf("   ");
       
    41 +    }
       
    42 +    printf(" %s\n",string);
       
    43 +    fflush(stdout);
       
    44 +}
       
    45 +#endif
       
    46 +
       
    47  
       
    48  bool AttributeMatch::operator()(const PKCS11Attribute& cmp) 
       
    49  {
       
    50      return (attr->type == cmp.getType()) &&
       
    51 -	CKYBuffer_DataIsEqual(cmp.getValue(), 
       
    52 -			(const CKYByte *)attr->pValue, attr->ulValueLen);
       
    53 +        CKYBuffer_DataIsEqual(cmp.getValue(), 
       
    54 +                        (const CKYByte *)attr->pValue, attr->ulValueLen);
       
    55  }
       
    56  
       
    57  class AttributeTypeMatch
       
    58 @@ -44,14 +77,14 @@
       
    59  };
       
    60  
       
    61  PKCS11Object::PKCS11Object(unsigned long muscleObjID_,CK_OBJECT_HANDLE handle_)
       
    62 -    : muscleObjID(muscleObjID_), handle(handle_), label(NULL), name(NULL)
       
    63 +    : muscleObjID(muscleObjID_), handle(handle_), label(NULL), name(NULL), keyType(unknown)
       
    64  { 
       
    65      CKYBuffer_InitEmpty(&pubKey);
       
    66  }
       
    67  
       
    68  PKCS11Object::PKCS11Object(unsigned long muscleObjID_, const CKYBuffer *data,
       
    69      CK_OBJECT_HANDLE handle_) :  muscleObjID(muscleObjID_), handle(handle_),
       
    70 -			label(NULL), name(NULL)
       
    71 +                        label(NULL), name(NULL), keyType(unknown)
       
    72  {
       
    73      CKYBuffer_InitEmpty(&pubKey);
       
    74  
       
    75 @@ -62,9 +95,98 @@
       
    76              "PKCS #11 actual object id does not match stated id");
       
    77      }
       
    78      if (type == 0) {
       
    79 -	parseOldObject(data);
       
    80 +        parseOldObject(data);
       
    81      } else if (type == 1) {
       
    82 -	parseNewObject(data);
       
    83 +        parseNewObject(data);
       
    84 +    }
       
    85 +}
       
    86 +
       
    87 +SecretKey::SecretKey(unsigned long muscleObjID_, CK_OBJECT_HANDLE handle_, CKYBuffer *secretKeyBuffer, CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulAttributeCount)
       
    88 +     : PKCS11Object(muscleObjID_, handle_)
       
    89 +{
       
    90 +    static CK_OBJECT_CLASS objClass = CKO_SECRET_KEY;
       
    91 +    static CK_KEY_TYPE keyType = CKK_GENERIC_SECRET;
       
    92 +    static CK_BBOOL value = 0x1;
       
    93 +
       
    94 +    if ( secretKeyBuffer == NULL)
       
    95 +        return;
       
    96 +
       
    97 +    /* Rifle through the input template */
       
    98 +
       
    99 +    CK_ATTRIBUTE_TYPE type;
       
   100 +    CK_ATTRIBUTE attr;
       
   101 +    CK_ULONG valueLength = 0;
       
   102 +
       
   103 +    for(int i = 0; i <  (int) ulAttributeCount; i++) {
       
   104 +       attr = pTemplate[i];
       
   105 +       type =  attr.type;
       
   106 +
       
   107 +       if ( type == CKA_VALUE_LEN) {
       
   108 +           //CK_ULONG ulValueLen = attr.ulValueLen;
       
   109 +           valueLength = *((CK_ULONG *)attr.pValue);
       
   110 +       } else {
       
   111 +
       
   112 +           CKYBuffer val;
       
   113 +           CKYBuffer_InitFromData(&val,(const CK_BYTE *) attr.pValue, attr.ulValueLen);
       
   114 +           setAttribute( type, &val);
       
   115 +           CKYBuffer_FreeData(&val);
       
   116 +       }
       
   117 +    }
       
   118 +
       
   119 +    adjustToKeyValueLength( secretKeyBuffer, valueLength ); 
       
   120 +
       
   121 +    /* Fall backs. */
       
   122 +
       
   123 +    if(!attributeExists(CKA_CLASS))
       
   124 +        setAttributeULong(CKA_CLASS, objClass);
       
   125 +
       
   126 +    if(!attributeExists(CKA_KEY_TYPE))
       
   127 +        setAttributeULong(CKA_KEY_TYPE, keyType);
       
   128 +
       
   129 +    if(!attributeExists(CKA_TOKEN))
       
   130 +        setAttributeBool(CKA_TOKEN, value);
       
   131 +      
       
   132 +    if(!attributeExists(CKA_DERIVE)) 
       
   133 +        setAttributeBool(CKA_DERIVE, value);
       
   134 +
       
   135 +    /* Actual value */
       
   136 +    setAttribute(CKA_VALUE, secretKeyBuffer);
       
   137 +
       
   138 +}
       
   139 +
       
   140 +void SecretKey::adjustToKeyValueLength(CKYBuffer * secretKeyBuffer,CK_ULONG valueLength)
       
   141 +{
       
   142 +    const CK_LONG MAX_DIFF = 200; /* Put some bounds on this value */
       
   143 +
       
   144 +    if ( !secretKeyBuffer ) {
       
   145 +        return;
       
   146 +    }
       
   147 +
       
   148 +    CKYBuffer scratch;
       
   149 +    CK_ULONG actual_length = CKYBuffer_Size(secretKeyBuffer);
       
   150 +
       
   151 +    CK_LONG diff = 0;
       
   152 +    diff = (CK_LONG) valueLength - actual_length;
       
   153 +
       
   154 +    if ( diff == 0 ) {
       
   155 +        return;
       
   156 +    }
       
   157 +
       
   158 +    if ( diff > 0 && diff < MAX_DIFF ) { /*check for silly values */
       
   159 +        /* prepend with zeroes */
       
   160 +        CKYBuffer_InitFromLen(&scratch, diff);
       
   161 +        CKYBuffer_AppendCopy(&scratch, secretKeyBuffer);
       
   162 +
       
   163 +        CKYBuffer_FreeData(secretKeyBuffer);
       
   164 +        CKYBuffer_InitFromCopy(secretKeyBuffer, &scratch);
       
   165 +        CKYBuffer_FreeData(&scratch);
       
   166 +
       
   167 +    } else if (diff < 0 ) {
       
   168 +        /* truncate most significant bytes */
       
   169 +        CKYBuffer_InitFromData(&scratch, CKYBuffer_Data(secretKeyBuffer)-diff, valueLength);
       
   170 +        CKYBuffer_FreeData(secretKeyBuffer);
       
   171 +        CKYBuffer_InitFromCopy(secretKeyBuffer, &scratch);
       
   172 +        CKYBuffer_FreeData(&scratch);
       
   173      }
       
   174  }
       
   175  
       
   176 @@ -94,29 +216,29 @@
       
   177          attrib.setType(CKYBuffer_GetLong(data, idx));
       
   178          idx += 4;
       
   179          unsigned int attrLen = CKYBuffer_GetShort(data, idx);
       
   180 -		idx += 2;
       
   181 +                idx += 2;
       
   182          if( attrLen > CKYBuffer_Size(data) 
       
   183 -			|| (idx + attrLen > CKYBuffer_Size(data)) ) {
       
   184 +                        || (idx + attrLen > CKYBuffer_Size(data)) ) {
       
   185              throw PKCS11Exception(CKR_DEVICE_ERROR,
       
   186                  "Invalid attribute length %d\n", attrLen);
       
   187          }
       
   188 -	/* these two types are ints, read them back from 
       
   189 -	 * the card in host order */
       
   190 -	if ((attrib.getType() == CKA_CLASS) || 
       
   191 -	    (attrib.getType() == CKA_CERTIFICATE_TYPE) ||
       
   192 -	    (attrib.getType() == CKA_KEY_TYPE)) {
       
   193 -	    /* ulongs are 4 bytes on the token, even if they are 8 or
       
   194 -	     * more in the pkcs11 module */
       
   195 -	    if (attrLen != 4) {
       
   196 +        /* these two types are ints, read them back from 
       
   197 +         * the card in host order */
       
   198 +        if ((attrib.getType() == CKA_CLASS) || 
       
   199 +            (attrib.getType() == CKA_CERTIFICATE_TYPE) ||
       
   200 +            (attrib.getType() == CKA_KEY_TYPE)) {
       
   201 +            /* ulongs are 4 bytes on the token, even if they are 8 or
       
   202 +             * more in the pkcs11 module */
       
   203 +            if (attrLen != 4) {
       
   204                  throw PKCS11Exception(CKR_DEVICE_ERROR,
       
   205                  "Invalid attribute length %d\n", attrLen);
       
   206 -	    }
       
   207 -	    CK_ULONG value = makeLEUInt(data,idx);
       
   208 +            }
       
   209 +            CK_ULONG value = makeLEUInt(data,idx);
       
   210  
       
   211 -	    attrib.setValue((const CKYByte *)&value, sizeof(CK_ULONG));
       
   212 -	} else {
       
   213 -	    attrib.setValue(CKYBuffer_Data(data)+idx, attrLen);
       
   214 -	}
       
   215 +            attrib.setValue((const CKYByte *)&value, sizeof(CK_ULONG));
       
   216 +        } else {
       
   217 +            attrib.setValue(CKYBuffer_Data(data)+idx, attrLen);
       
   218 +        }
       
   219          idx += attrLen;
       
   220          attributes.push_back(attrib);
       
   221      }
       
   222 @@ -176,33 +298,33 @@
       
   223      unsigned long i;
       
   224  
       
   225      if (!attributeExists(CKA_ID)) {
       
   226 -	PKCS11Attribute attrib;
       
   227 -	attrib.setType(CKA_ID);
       
   228 -	attrib.setValue(&cka_id, 1);
       
   229 +        PKCS11Attribute attrib;
       
   230 +        attrib.setType(CKA_ID);
       
   231 +        attrib.setValue(&cka_id, 1);
       
   232          attributes.push_back(attrib);
       
   233      }
       
   234      /* unpack the class */
       
   235      if (!attributeExists(CKA_CLASS)) {
       
   236 -	PKCS11Attribute attrib;
       
   237 -	attrib.setType(CKA_CLASS);
       
   238 -	attrib.setValue((CKYByte *)&objectType, sizeof(CK_ULONG));
       
   239 +        PKCS11Attribute attrib;
       
   240 +        attrib.setType(CKA_CLASS);
       
   241 +        attrib.setValue((CKYByte *)&objectType, sizeof(CK_ULONG));
       
   242          attributes.push_back(attrib);
       
   243      }
       
   244  
       
   245      /* unpack the boolean flags. Note, the default mask is based on
       
   246       * the class specified in fixedAttrs, not on the real class */
       
   247      for (i=1; i < sizeof(unsigned long)*8; i++) {
       
   248 -	unsigned long iMask = 1<< i;
       
   249 -	if ((mask & iMask) == 0) {
       
   250 -	   continue;
       
   251 -	}
       
   252 -	if (attributeExists(boolType[i])) {
       
   253 -	    continue;
       
   254 -	}
       
   255 -	PKCS11Attribute attrib;
       
   256 -	CKYByte bVal = (fixedAttrs & iMask) != 0;
       
   257 -	attrib.setType(boolType[i]);
       
   258 -	attrib.setValue(&bVal, 1);
       
   259 +        unsigned long iMask = 1<< i;
       
   260 +        if ((mask & iMask) == 0) {
       
   261 +           continue;
       
   262 +        }
       
   263 +        if (attributeExists(boolType[i])) {
       
   264 +            continue;
       
   265 +        }
       
   266 +        PKCS11Attribute attrib;
       
   267 +        CKYByte bVal = (fixedAttrs & iMask) != 0;
       
   268 +        attrib.setType(boolType[i]);
       
   269 +        attrib.setValue(&bVal, 1);
       
   270          attributes.push_back(attrib);
       
   271      }
       
   272  }
       
   273 @@ -223,40 +345,40 @@
       
   274      // load up the explicit attributes first
       
   275      for (j=0, offset = 11; j < attributeCount && offset < size; j++) {
       
   276          PKCS11Attribute attrib;
       
   277 -	CKYByte attributeDataType = CKYBuffer_GetChar(data, offset+4);
       
   278 -	unsigned int attrLen = 0;
       
   279 +        CKYByte attributeDataType = CKYBuffer_GetChar(data, offset+4);
       
   280 +        unsigned int attrLen = 0;
       
   281          attrib.setType(CKYBuffer_GetLong(data, offset));
       
   282          offset += 5;
       
   283  
       
   284 -	switch(attributeDataType) {
       
   285 -	case DATATYPE_STRING:
       
   286 -	    attrLen = CKYBuffer_GetShort(data, offset);
       
   287 -	    offset += 2;
       
   288 +        switch(attributeDataType) {
       
   289 +        case DATATYPE_STRING:
       
   290 +            attrLen = CKYBuffer_GetShort(data, offset);
       
   291 +            offset += 2;
       
   292              if (attrLen > CKYBuffer_Size(data) 
       
   293 -			|| (offset + attrLen > CKYBuffer_Size(data)) ) {
       
   294 -            	throw PKCS11Exception(CKR_DEVICE_ERROR,
       
   295 -            	    "Invalid attribute length %d\n", attrLen);
       
   296 +                        || (offset + attrLen > CKYBuffer_Size(data)) ) {
       
   297 +                    throw PKCS11Exception(CKR_DEVICE_ERROR,
       
   298 +                        "Invalid attribute length %d\n", attrLen);
       
   299               }
       
   300 -	    attrib.setValue(CKYBuffer_Data(data)+offset, attrLen);
       
   301 -	    break;
       
   302 -	case DATATYPE_BOOL_FALSE:
       
   303 -	case DATATYPE_BOOL_TRUE:
       
   304 -	    {
       
   305 -		CKYByte bval = attributeDataType & 1;
       
   306 -		attrib.setValue(&bval, 1);
       
   307 -	    }
       
   308 -	    break;
       
   309 -	case DATATYPE_INTEGER:
       
   310 -	    {
       
   311 -		CK_ULONG value = CKYBuffer_GetLong(data, offset);
       
   312 -		attrLen = 4;
       
   313 -		attrib.setValue((const CKYByte *)&value, sizeof(CK_ULONG));
       
   314 -	    }
       
   315 -	    break;
       
   316 -	default:
       
   317 -	    throw PKCS11Exception(CKR_DEVICE_ERROR, 
       
   318 -		"Invalid attribute Data Type %d\n", attributeDataType);
       
   319 -	}
       
   320 +            attrib.setValue(CKYBuffer_Data(data)+offset, attrLen);
       
   321 +            break;
       
   322 +        case DATATYPE_BOOL_FALSE:
       
   323 +        case DATATYPE_BOOL_TRUE:
       
   324 +            {
       
   325 +                CKYByte bval = attributeDataType & 1;
       
   326 +                attrib.setValue(&bval, 1);
       
   327 +            }
       
   328 +            break;
       
   329 +        case DATATYPE_INTEGER:
       
   330 +            {
       
   331 +                CK_ULONG value = CKYBuffer_GetLong(data, offset);
       
   332 +                attrLen = 4;
       
   333 +                attrib.setValue((const CKYByte *)&value, sizeof(CK_ULONG));
       
   334 +            }
       
   335 +            break;
       
   336 +        default:
       
   337 +            throw PKCS11Exception(CKR_DEVICE_ERROR, 
       
   338 +                "Invalid attribute Data Type %d\n", attributeDataType);
       
   339 +        }
       
   340          offset += attrLen;
       
   341          attributes.push_back(attrib);
       
   342      }
       
   343 @@ -273,9 +395,10 @@
       
   344  };
       
   345  #endif
       
   346  
       
   347 +// XXX - Need to use a correct signature. This is necessary only on SPARC
       
   348  bool
       
   349 -PKCS11Object::matchesTemplate(const CK_ATTRIBUTE_PTR pTemplate, 
       
   350 -						CK_ULONG ulCount)
       
   351 +PKCS11Object::matchesTemplate(CK_ATTRIBUTE_PTR pTemplate, 
       
   352 +                                                CK_ULONG ulCount)
       
   353      const
       
   354  {
       
   355      unsigned int i;
       
   356 @@ -284,10 +407,10 @@
       
   357  
       
   358  #if defined( NSS_HIDE_NONSTANDARD_OBJECTS )
       
   359      if (!ulCount) {
       
   360 -	// exclude MOZ reader objects from searches for all objects.
       
   361 -	// To find an MOZ reader object, one must search for it by 
       
   362 -	// some matching attribute, such as class.
       
   363 -	iterator iter = find_if(attributes.begin(), attributes.end(),
       
   364 +        // exclude MOZ reader objects from searches for all objects.
       
   365 +        // To find an MOZ reader object, one must search for it by 
       
   366 +        // some matching attribute, such as class.
       
   367 +        iterator iter = find_if(attributes.begin(), attributes.end(),
       
   368                                  AttributeMatch(&rdr_template[0]));
       
   369          return (iter == attributes.end()) ? true : false;
       
   370      }
       
   371 @@ -324,7 +447,7 @@
       
   372              AttributeTypeMatch(type));
       
   373  
       
   374      if( iter == attributes.end() ) {
       
   375 -	return NULL;
       
   376 +        return NULL;
       
   377      }
       
   378      return iter->getValue();
       
   379  }
       
   380 @@ -348,8 +471,9 @@
       
   381          if( iter == attributes.end() ) {
       
   382              // no attribute of this type
       
   383              attrTypeInvalid = true;
       
   384 -            log->log("GetAttributeValue: invalid type 0x%08x on object %x\n",
       
   385 -                pTemplate[i].type, muscleObjID);
       
   386 +            if ( log )
       
   387 +                log->log("GetAttributeValue: invalid type 0x%08x on object %x\n",
       
   388 +                    pTemplate[i].type, muscleObjID);
       
   389              pTemplate[i].ulValueLen = (CK_ULONG)-1;
       
   390              continue;
       
   391          }
       
   392 @@ -370,7 +494,7 @@
       
   393          // the buffer is large enough. return the value and set the exact
       
   394          // length.
       
   395          memcpy(pTemplate[i].pValue, CKYBuffer_Data(iter->getValue()), 
       
   396 -					CKYBuffer_Size(iter->getValue()));
       
   397 +                                        CKYBuffer_Size(iter->getValue()));
       
   398          pTemplate[i].ulValueLen = CKYBuffer_Size(iter->getValue());
       
   399      }
       
   400  
       
   401 @@ -396,7 +520,7 @@
       
   402  {
       
   403      // clean up old one
       
   404      if (label) {
       
   405 -	delete label;
       
   406 +	delete [] label;
       
   407  	label = NULL;
       
   408      }
       
   409      // find matching attribute
       
   410 @@ -405,14 +529,14 @@
       
   411  
       
   412      // none found 
       
   413      if( iter == attributes.end() ) {
       
   414 -	return "";
       
   415 +        return "";
       
   416      }
       
   417  
       
   418      int size = CKYBuffer_Size(iter->getValue());
       
   419  
       
   420      label = new char [ size + 1 ];
       
   421      if (!label) {
       
   422 -	return "";
       
   423 +        return "";
       
   424      }
       
   425      memcpy(label, CKYBuffer_Data(iter->getValue()), size);
       
   426      label[size] = 0;
       
   427 @@ -430,13 +554,13 @@
       
   428  
       
   429      // none found */
       
   430      if( iter == attributes.end() ) {
       
   431 -	return (CK_OBJECT_CLASS) -1;
       
   432 +        return (CK_OBJECT_CLASS) -1;
       
   433      }
       
   434  
       
   435      int size = CKYBuffer_Size(iter->getValue());
       
   436  
       
   437      if (size != sizeof(objClass)) {
       
   438 -	return (CK_OBJECT_CLASS) -1;
       
   439 +        return (CK_OBJECT_CLASS) -1;
       
   440      }
       
   441  
       
   442      memcpy(&objClass, CKYBuffer_Data(iter->getValue()), size);
       
   443 @@ -452,7 +576,7 @@
       
   444      iter = find_if(attributes.begin(), attributes.end(),
       
   445          AttributeTypeMatch(type));
       
   446      if( iter != attributes.end() )  {
       
   447 -	iter->setValue( CKYBuffer_Data(value), CKYBuffer_Size(value));
       
   448 +        iter->setValue( CKYBuffer_Data(value), CKYBuffer_Size(value));
       
   449      } else {
       
   450          attributes.push_back(PKCS11Attribute(type, value));
       
   451      }
       
   452 @@ -504,6 +628,16 @@
       
   453      unsigned char tag;
       
   454      unsigned int used_length= 0;
       
   455  
       
   456 +    *data_length = 0; /* make sure data_length is zero on failure */
       
   457 +
       
   458 +    if(!buf) {
       
   459 +        return NULL;
       
   460 +    }
       
   461 +    /* there must be at least 2 bytes */
       
   462 +    if (length < 2) {
       
   463 +	return NULL;
       
   464 +    }
       
   465 +
       
   466      tag = buf[used_length++];
       
   467  
       
   468      /* blow out when we come to the end */
       
   469 @@ -516,15 +650,22 @@
       
   470      if (*data_length&0x80) {
       
   471          int  len_count = *data_length & 0x7f;
       
   472  
       
   473 +	if (len_count+used_length > length) {
       
   474 +	    return NULL;
       
   475 +	}
       
   476 +
       
   477          *data_length = 0;
       
   478  
       
   479          while (len_count-- > 0) {
       
   480              *data_length = (*data_length << 8) | buf[used_length++];
       
   481          }
       
   482      }
       
   483 +    /* paranoia, can't happen */
       
   484 +    if (length < used_length) {
       
   485 +	return NULL;
       
   486 +    }
       
   487  
       
   488      if (*data_length > (length-used_length) ) {
       
   489 -        *data_length = length-used_length;
       
   490          return NULL;
       
   491      }
       
   492      if (includeTag) *data_length += used_length;
       
   493 @@ -537,16 +678,158 @@
       
   494  {
       
   495      /* for RSA, bit string always has byte number of bits */
       
   496      if (buf[0] != 0) {
       
   497 -	return NULL;
       
   498 +        return NULL;
       
   499      }
       
   500      if (len < 1) {
       
   501 -	return NULL;
       
   502 +        return NULL;
       
   503      }
       
   504      *retLen = len -1;
       
   505      return buf+1;
       
   506  }
       
   507  
       
   508  static SECStatus
       
   509 +GetECKeyFieldItems(const CKYByte *spki_data,unsigned int spki_length,
       
   510 +        CCItem *point, CCItem *params)
       
   511 +{
       
   512 +    const CKYByte *buf = spki_data;
       
   513 +    unsigned int buf_length = spki_length;
       
   514 +    const CKYByte *algid;
       
   515 +    unsigned int algidlen;
       
   516 +    const CKYByte *dummy;
       
   517 +    unsigned int dummylen;
       
   518 +
       
   519 +    if (!point || !params || !buf)
       
   520 +        return SECFailure;
       
   521 +
       
   522 +    point->data = NULL;
       
   523 +    point->len = 0;
       
   524 +    params->data = NULL;
       
   525 +    params->len = 0;
       
   526 +
       
   527 +    /* unwrap the algorithm id */
       
   528 +    dummy = dataStart(buf,buf_length,&dummylen,false);
       
   529 +    if (dummy == NULL) return SECFailure;
       
   530 +    buf_length -= (dummy-buf) + dummylen;
       
   531 +    buf = dummy + dummylen;
       
   532 +    /* unwrpped value is in dummy */
       
   533 +    algid = dummy;
       
   534 +    algidlen = dummylen;
       
   535 +    /* skip past algid oid */
       
   536 +    dummy = dataStart(algid, algidlen, &dummylen, false);
       
   537 +    if (dummy == NULL) return SECFailure;
       
   538 +    algidlen -= (dummy-algid) + dummylen;
       
   539 +    algid = dummy + dummylen;
       
   540 +    params->data = algid;
       
   541 +    params->len = algidlen;
       
   542 +
       
   543 +       /* unwrap the public key info */
       
   544 +    buf = dataStart(buf,buf_length,&buf_length,false);
       
   545 +    if (buf == NULL) return SECFailure;
       
   546 +    buf = unwrapBitString(buf,buf_length,&buf_length);
       
   547 +    if (buf == NULL) return SECFailure;
       
   548 +
       
   549 +    point->data = buf;
       
   550 +    point->len = buf_length;
       
   551 +
       
   552 +    if(point->data == NULL) return SECFailure;
       
   553 +
       
   554 +    return SECSuccess;
       
   555 +}
       
   556 +
       
   557 +static bool
       
   558 +GetKeyOIDMatches(const CKYByte *spki_data, unsigned int length, const CKYByte *oid_data)
       
   559 +{
       
   560 +    bool ret = TRUE;
       
   561 +
       
   562 +    if( spki_data == NULL || oid_data == NULL) {
       
   563 +        return FALSE;
       
   564 +    }
       
   565 +
       
   566 +    for ( int i = 0 ; i < (int) length ; i++) {
       
   567 +        if (spki_data[i] != oid_data[i]) {
       
   568 +            ret = FALSE;
       
   569 +            break;
       
   570 +        }
       
   571 +            
       
   572 +    }
       
   573 +
       
   574 +    return ret;
       
   575 +}
       
   576 +
       
   577 +static SECStatus
       
   578 +GetKeyAlgorithmId(const CKYByte *spki_data, unsigned int spki_length,
       
   579 +       CCItem *algorithmId)
       
   580 +{
       
   581 +
       
   582 +    const CKYByte *buf = spki_data;
       
   583 +    unsigned int buf_length = spki_length;
       
   584 +
       
   585 +    if ( algorithmId == NULL) return SECFailure;
       
   586 +
       
   587 +    /* objtain the algorithm id */
       
   588 +    algorithmId->data = dataStart(buf,buf_length,&algorithmId->len,false);
       
   589 +    if (algorithmId->data == NULL) return SECFailure;
       
   590 +
       
   591 +    return SECSuccess;
       
   592 +
       
   593 +}
       
   594 +
       
   595 +static PKCS11Object::KeyType
       
   596 +GetKeyTypeFromSPKI(const CKYBuffer *key)
       
   597 +{
       
   598 +    CCItem algIdItem;
       
   599 +    SECStatus ret = GetKeyAlgorithmId(CKYBuffer_Data(key), 
       
   600 +                                      CKYBuffer_Size(key),&algIdItem);
       
   601 +    PKCS11Object::KeyType foundType = PKCS11Object::unknown;
       
   602 +
       
   603 +    if ( ret != SECSuccess ) {
       
   604 +        throw PKCS11Exception(CKR_FUNCTION_FAILED,
       
   605 +            "Failed to decode key algorithm ID.");
       
   606 +    }
       
   607 +
       
   608 +    unsigned int length = 0;
       
   609 +    const CKYByte *keyData = NULL;
       
   610 +
       
   611 +    /* Get actual oid buffer */
       
   612 +
       
   613 +    keyData = dataStart(algIdItem.data,algIdItem.len,&length, false);
       
   614 +    if (keyData == NULL) {
       
   615 +        throw PKCS11Exception(CKR_FUNCTION_FAILED,
       
   616 +            "Failed to decode key algorithm ID.");
       
   617 +    }
       
   618 +
       
   619 +    bool match = FALSE;
       
   620 +    
       
   621 +    /* Check for outrageous length */
       
   622 +
       
   623 +    if ( length <= 3 || length >= algIdItem.len) {
       
   624 +        throw PKCS11Exception(CKR_FUNCTION_FAILED,
       
   625 +            "Failed to decode key algorithm ID.");
       
   626 +    }
       
   627 +    /* check for RSA */
       
   628 + 
       
   629 +    match = GetKeyOIDMatches(keyData, length, rsaOID);
       
   630 +   
       
   631 +    if ( match == TRUE ) {
       
   632 +       foundType = PKCS11Object::rsa;
       
   633 +    } else { 
       
   634 +      /* check for ECC */
       
   635 +       match = GetKeyOIDMatches(keyData, length, eccOID);
       
   636 +
       
   637 +       if ( match == TRUE ) {
       
   638 +         foundType = PKCS11Object::ecc;
       
   639 +       }
       
   640 +
       
   641 +    }
       
   642 +
       
   643 +    if ( foundType == PKCS11Object::unknown) {
       
   644 +        throw PKCS11Exception(CKR_FUNCTION_FAILED,
       
   645 +            "Failed to decode key algorithm ID.");
       
   646 +    }
       
   647 +    return foundType;
       
   648 +}
       
   649 +
       
   650 +static SECStatus
       
   651  GetKeyFieldItems(const CKYByte *spki_data,unsigned int spki_length,
       
   652          CCItem *modulus, CCItem *exponent)
       
   653  {
       
   654 @@ -591,7 +874,7 @@
       
   655      CCItem modulusItem, exponentItem;
       
   656  
       
   657      rv = GetKeyFieldItems(CKYBuffer_Data(spki), CKYBuffer_Size(spki), 
       
   658 -	&modulusItem, &exponentItem);
       
   659 +        &modulusItem, &exponentItem);
       
   660  
       
   661      if( rv != SECSuccess ) {
       
   662          throw PKCS11Exception(CKR_FUNCTION_FAILED,
       
   663 @@ -602,6 +885,29 @@
       
   664      CKYBuffer_Replace(exponent, 0, exponentItem.data, exponentItem.len);
       
   665  }
       
   666  
       
   667 +static void
       
   668 +GetECKeyFields(const CKYBuffer *spki, CKYBuffer *point, CKYBuffer *params)
       
   669 +{
       
   670 +    SECStatus rv;
       
   671 +    CCItem pointItem, paramsItem;
       
   672 +
       
   673 +    if (spki == NULL || point == NULL || params == NULL) {
       
   674 +        throw PKCS11Exception(CKR_FUNCTION_FAILED,
       
   675 +             "Failed to decode certificate Subject Public KeyInfo!");
       
   676 +    }
       
   677 +    
       
   678 +    rv = GetECKeyFieldItems(CKYBuffer_Data(spki), CKYBuffer_Size(spki),
       
   679 +        &pointItem, &paramsItem);
       
   680 +
       
   681 +    if( rv != SECSuccess ) {
       
   682 +        throw PKCS11Exception(CKR_FUNCTION_FAILED,
       
   683 +            "Failed to decode certificate Subject Public Key Info!");
       
   684 +    }
       
   685 +
       
   686 +    CKYBuffer_Replace(point, 0, pointItem.data, pointItem.len);
       
   687 +    CKYBuffer_Replace(params, 0, paramsItem.data, paramsItem.len);
       
   688 +}
       
   689 +
       
   690  Key::Key(unsigned long muscleObjID, const CKYBuffer *data,
       
   691      CK_OBJECT_HANDLE handle) : PKCS11Object(muscleObjID, data, handle)
       
   692  {
       
   693 @@ -611,22 +917,41 @@
       
   694      CKYBuffer_InitEmpty(&empty);
       
   695  
       
   696      if ((objClass == CKO_PUBLIC_KEY) || (objClass == CKO_PRIVATE_KEY)) {
       
   697 -	/* only CKK_RSA is supported */
       
   698 -	setAttributeULong(CKA_KEY_TYPE, CKK_RSA);
       
   699 +        //we may know already what type of key this is.
       
   700 +        if (attributeExists(CKA_KEY_TYPE)) {
       
   701 +            CK_ULONG type = 0;
       
   702 +            CK_ATTRIBUTE aTemplate = {CKA_KEY_TYPE, &type, sizeof(CK_ULONG)};
       
   703 +    
       
   704 +            getAttributeValue(&aTemplate, 1, NULL);
       
   705 +
       
   706 +            if (type == 0x3) {
       
   707 +                setKeyType(ecc);
       
   708 +                setAttributeULong(CKA_KEY_TYPE, CKK_EC);
       
   709 +            } else {  
       
   710 +                setKeyType(rsa);
       
   711 +                setAttributeULong(CKA_KEY_TYPE, CKK_RSA);
       
   712 +            }
       
   713 +        } else {
       
   714 +           /* default to rsa */
       
   715 +           setKeyType(rsa);
       
   716 +           setAttributeULong(CKA_KEY_TYPE, CKK_RSA); 
       
   717 +        }
       
   718 +
       
   719 +    // Could be RSA or ECC
       
   720      } else if (objClass == CKO_SECRET_KEY) {
       
   721 -	if (!attributeExists(CKA_LABEL)) {
       
   722 -	    setAttribute(CKA_LABEL, &empty);
       
   723 -	}
       
   724 -	if (!attributeExists(CKA_KEY_TYPE)) {
       
   725 -	    /* default to DES3 */
       
   726 -	    setAttributeULong(CKA_KEY_TYPE, CKK_DES3);
       
   727 -	}
       
   728 +        if (!attributeExists(CKA_LABEL)) {
       
   729 +            setAttribute(CKA_LABEL, &empty);
       
   730 +        }
       
   731 +        if (!attributeExists(CKA_KEY_TYPE)) {
       
   732 +            /* default to DES3 */
       
   733 +            setAttributeULong(CKA_KEY_TYPE, CKK_DES3);
       
   734 +        }
       
   735      }
       
   736      if (!attributeExists(CKA_START_DATE)) {
       
   737 -	setAttribute(CKA_START_DATE, &empty);
       
   738 +        setAttribute(CKA_START_DATE, &empty);
       
   739      }
       
   740      if (!attributeExists(CKA_END_DATE)) {
       
   741 -	setAttribute(CKA_END_DATE, &empty);
       
   742 +        setAttribute(CKA_END_DATE, &empty);
       
   743      }
       
   744  }
       
   745  
       
   746 @@ -635,32 +960,59 @@
       
   747  {
       
   748      // infer key attributes from cert
       
   749      bool modulusExists, exponentExists;
       
   750 -    CKYBuffer modulus; CKYBuffer_InitEmpty(&modulus);
       
   751 -    CKYBuffer exponent; CKYBuffer_InitEmpty(&exponent);
       
   752 +    bool pointExists, paramsExists;
       
   753 +
       
   754 +    PKCS11Object::KeyType keyType;
       
   755 +    const CKYBuffer *key = cert.getPubKey();
       
   756  
       
   757      if (!attributeExists(CKA_LABEL)) {
       
   758 -	setAttribute(CKA_LABEL, cert.getAttribute(CKA_LABEL));
       
   759 +        setAttribute(CKA_LABEL, cert.getAttribute(CKA_LABEL));
       
   760      }
       
   761 +
       
   762 +    CKYBuffer param1; CKYBuffer_InitEmpty(&param1);
       
   763 +    CKYBuffer param2; CKYBuffer_InitEmpty(&param2);
       
   764      try {
       
   765 - 	modulusExists = attributeExists(CKA_MODULUS);
       
   766 -	exponentExists = attributeExists(CKA_PUBLIC_EXPONENT);
       
   767 -	if (!modulusExists || !exponentExists) {
       
   768 -	    const CKYBuffer *key = cert.getPubKey();
       
   769 -	    GetKeyFields(key, &modulus, &exponent);
       
   770 -	    if (!modulusExists) {
       
   771 -		setAttribute(CKA_MODULUS, &modulus);
       
   772 -	    }
       
   773 -	    if (!exponentExists) {
       
   774 -		setAttribute(CKA_PUBLIC_EXPONENT, &exponent);
       
   775 -	    }
       
   776 -	}
       
   777 +        keyType = GetKeyTypeFromSPKI(key);
       
   778 +        setKeyType(keyType);
       
   779 +
       
   780 +        switch (keyType) {
       
   781 +        case rsa:
       
   782 +            modulusExists = attributeExists(CKA_MODULUS);
       
   783 +            exponentExists = attributeExists(CKA_PUBLIC_EXPONENT);
       
   784 +            if (!modulusExists || !exponentExists) {
       
   785 +                GetKeyFields(key, &param1, &param2);
       
   786 +                if (!modulusExists) {
       
   787 +                        setAttribute(CKA_MODULUS, &param1);
       
   788 +                }
       
   789 +                if (!exponentExists) {
       
   790 +                      setAttribute(CKA_PUBLIC_EXPONENT, &param2);
       
   791 +                }
       
   792 +            }
       
   793 +            break;
       
   794 +        case ecc:
       
   795 +            pointExists = attributeExists(CKA_EC_POINT);
       
   796 +            paramsExists = attributeExists(CKA_EC_PARAMS);
       
   797 +
       
   798 +            if (!pointExists || !paramsExists) {
       
   799 +                GetECKeyFields(key, &param1, &param2);
       
   800 +                if (!pointExists) {
       
   801 +                   setAttribute(CKA_EC_POINT, &param1);
       
   802 +                }
       
   803 +                if (!paramsExists) {
       
   804 +                    setAttribute(CKA_EC_PARAMS, &param2);
       
   805 +                }
       
   806 +            }
       
   807 +            break;
       
   808 +        default:
       
   809 +            break;
       
   810 +        }
       
   811      } catch (PKCS11Exception &e) {
       
   812 -	CKYBuffer_FreeData(&modulus);
       
   813 -	CKYBuffer_FreeData(&exponent);
       
   814 -	throw e;
       
   815 +        CKYBuffer_FreeData(&param1);
       
   816 +        CKYBuffer_FreeData(&param2);
       
   817 +        throw e;
       
   818      }
       
   819 -    CKYBuffer_FreeData(&modulus);
       
   820 -    CKYBuffer_FreeData(&exponent);
       
   821 +    CKYBuffer_FreeData(&param1);
       
   822 +    CKYBuffer_FreeData(&param2);
       
   823  }
       
   824  
       
   825  static SECStatus
       
   826 @@ -732,14 +1084,14 @@
       
   827  
       
   828  static void
       
   829  GetCertFields(const CKYBuffer *derCert, CKYBuffer *derSerial, 
       
   830 -	    CKYBuffer *derSubject, CKYBuffer *derIssuer, CKYBuffer *subjectKey)
       
   831 +            CKYBuffer *derSubject, CKYBuffer *derIssuer, CKYBuffer *subjectKey)
       
   832  {
       
   833      SECStatus rv;
       
   834      CCItem issuerItem, serialItem, derSerialItem, subjectItem,
       
   835          validityItem, subjectKeyItem;
       
   836  
       
   837      rv = GetCertFieldItems(CKYBuffer_Data(derCert), CKYBuffer_Size(derCert), 
       
   838 -	&issuerItem, &serialItem, &derSerialItem, &subjectItem, &validityItem,
       
   839 +        &issuerItem, &serialItem, &derSerialItem, &subjectItem, &validityItem,
       
   840          &subjectKeyItem);
       
   841  
       
   842      if( rv != SECSuccess ) {
       
   843 @@ -764,50 +1116,50 @@
       
   844      CK_ULONG certTypeValue = CKC_X_509;
       
   845  
       
   846      CKYBuffer_InitFromData(&certType, (CKYByte *)&certTypeValue, 
       
   847 -						sizeof(certTypeValue));
       
   848 +                                                sizeof(certTypeValue));
       
   849      CKYBuffer_Resize(&pubKey,0);
       
   850  
       
   851      try {
       
   852 - 	setAttribute(CKA_CERTIFICATE_TYPE, &certType);
       
   853 +         setAttribute(CKA_CERTIFICATE_TYPE, &certType);
       
   854  
       
   855 -	if (!attributeExists(CKA_VALUE)) {
       
   856 -	    if (derCert) {
       
   857 -		 setAttribute(CKA_VALUE, derCert);
       
   858 -	    } else  {
       
   859 -		throw PKCS11Exception(CKR_DEVICE_ERROR, 
       
   860 -		    "Missing certificate data from token");
       
   861 -	    }
       
   862 -	}
       
   863 +        if (!attributeExists(CKA_VALUE)) {
       
   864 +            if (derCert) {
       
   865 +                 setAttribute(CKA_VALUE, derCert);
       
   866 +            } else  {
       
   867 +                throw PKCS11Exception(CKR_DEVICE_ERROR, 
       
   868 +                    "Missing certificate data from token");
       
   869 +            }
       
   870 +        }
       
   871  
       
   872 -	if (!derCert) {
       
   873 -	    derCert = getAttribute(CKA_VALUE);
       
   874 -	    if (!derCert) {
       
   875 -		// paranoia, should never happen since we verify the
       
   876 -		// attribute exists above
       
   877 -		throw PKCS11Exception(CKR_DEVICE_ERROR, 
       
   878 -		     "Missing certificate data from token");
       
   879 -	    }
       
   880 -	}
       
   881 +        if (!derCert) {
       
   882 +            derCert = getAttribute(CKA_VALUE);
       
   883 +            if (!derCert) {
       
   884 +                // paranoia, should never happen since we verify the
       
   885 +                // attribute exists above
       
   886 +                throw PKCS11Exception(CKR_DEVICE_ERROR, 
       
   887 +                     "Missing certificate data from token");
       
   888 +            }
       
   889 +        }
       
   890  
       
   891 -	// infer cert attributes
       
   892 +        // infer cert attributes
       
   893  
       
   894 -	GetCertFields(derCert, &derSerial, &derSubject, &derIssuer, &pubKey);
       
   895 +        GetCertFields(derCert, &derSerial, &derSubject, &derIssuer, &pubKey);
       
   896  
       
   897 -	if (!attributeExists(CKA_SERIAL_NUMBER)) {
       
   898 -	    setAttribute(CKA_SERIAL_NUMBER, &derSerial);
       
   899 -	}
       
   900 -	if (!attributeExists(CKA_SUBJECT)) {
       
   901 -	    setAttribute(CKA_SUBJECT, &derSubject);
       
   902 -	}
       
   903 -	if (!attributeExists(CKA_ISSUER)) {
       
   904 -	    setAttribute(CKA_ISSUER, &derIssuer);
       
   905 -	}
       
   906 +        if (!attributeExists(CKA_SERIAL_NUMBER)) {
       
   907 +            setAttribute(CKA_SERIAL_NUMBER, &derSerial);
       
   908 +        }
       
   909 +        if (!attributeExists(CKA_SUBJECT)) {
       
   910 +            setAttribute(CKA_SUBJECT, &derSubject);
       
   911 +        }
       
   912 +        if (!attributeExists(CKA_ISSUER)) {
       
   913 +            setAttribute(CKA_ISSUER, &derIssuer);
       
   914 +        }
       
   915     } catch (PKCS11Exception &e) {
       
   916 -	CKYBuffer_FreeData(&certType);
       
   917 -	CKYBuffer_FreeData(&derSerial);
       
   918 -	CKYBuffer_FreeData(&derSubject);
       
   919 -	CKYBuffer_FreeData(&derIssuer);
       
   920 -	throw e;
       
   921 +        CKYBuffer_FreeData(&certType);
       
   922 +        CKYBuffer_FreeData(&derSerial);
       
   923 +        CKYBuffer_FreeData(&derSubject);
       
   924 +        CKYBuffer_FreeData(&derIssuer);
       
   925 +        throw e;
       
   926      }
       
   927      CKYBuffer_FreeData(&certType);
       
   928      CKYBuffer_FreeData(&derSerial);
       
   929 @@ -817,7 +1169,7 @@
       
   930  
       
   931  Reader::Reader(unsigned long muscleObjID, CK_OBJECT_HANDLE handle, 
       
   932      const char *reader, const CKYBuffer *cardATR, bool isCoolkey) : 
       
   933 -	PKCS11Object(muscleObjID, handle)
       
   934 +        PKCS11Object(muscleObjID, handle)
       
   935  {
       
   936      setAttributeULong(CKA_CLASS, CKO_MOZ_READER);
       
   937      setAttribute(CKA_LABEL, reader);
       
   938 @@ -828,9 +1180,10 @@
       
   939      setAttribute(CKA_MOZ_ATR, cardATR);
       
   940  }
       
   941  
       
   942 -CACPrivKey::CACPrivKey(CKYByte instance, const PKCS11Object &cert) : 
       
   943 -	PKCS11Object( ((int)'k') << 24 | ((int)instance+'0') << 16,
       
   944 -			 instance | 0x400)
       
   945 +
       
   946 +CACPrivKey::CACPrivKey(CKYByte instance, const PKCS11Object &cert,bool isPIV) : 
       
   947 +        PKCS11Object( ((int)'k') << 24 | ((int)instance+'0') << 16,
       
   948 +                         instance | 0x400)
       
   949  {
       
   950      CKYBuffer id;
       
   951      CKYBuffer empty;
       
   952 @@ -838,8 +1191,10 @@
       
   953  
       
   954      /* So we know what the key is supposed to be used for based on
       
   955       * the instance */
       
   956 -    if (instance == 2) {
       
   957 -	decrypt = TRUE;
       
   958 +    /* instance 2 is usually a decryption cert. >2 are usually old decryption 
       
   959 +     * certs */
       
   960 +    if (instance == 2 || (instance > (isPIV ? 3 : 2))) {
       
   961 +        decrypt = TRUE;
       
   962      }
       
   963  
       
   964      CKYBuffer_InitEmpty(&empty);
       
   965 @@ -858,33 +1213,52 @@
       
   966      setAttributeBool(CKA_LOCAL, TRUE);
       
   967      setAttributeULong(CKA_KEY_TYPE, CKK_RSA);
       
   968  
       
   969 -    setAttributeBool(CKA_DECRYPT, decrypt);
       
   970      setAttributeBool(CKA_SIGN, !decrypt);
       
   971      setAttributeBool(CKA_SIGN_RECOVER, !decrypt);
       
   972      setAttributeBool(CKA_UNWRAP, FALSE);
       
   973      setAttributeBool(CKA_SENSITIVE, TRUE);
       
   974      setAttributeBool(CKA_EXTRACTABLE, FALSE);
       
   975  
       
   976 -    CKYBuffer modulus; CKYBuffer_InitEmpty(&modulus);
       
   977 -    CKYBuffer exponent; CKYBuffer_InitEmpty(&exponent);
       
   978 +    CKYBuffer param1; CKYBuffer_InitEmpty(&param1);
       
   979 +    CKYBuffer param2; CKYBuffer_InitEmpty(&param2);
       
   980  
       
   981      try {
       
   982 -	const CKYBuffer *key = cert.getPubKey();
       
   983 -	GetKeyFields(key, &modulus, &exponent);
       
   984 -	setAttribute(CKA_MODULUS, &modulus);
       
   985 -	setAttribute(CKA_PUBLIC_EXPONENT, &exponent);
       
   986 -    } catch (PKCS11Exception &e) {
       
   987 -	CKYBuffer_FreeData(&modulus);
       
   988 -	CKYBuffer_FreeData(&exponent);
       
   989 -	throw e;
       
   990 -    }
       
   991 -    CKYBuffer_FreeData(&modulus);
       
   992 -    CKYBuffer_FreeData(&exponent);
       
   993 +        const CKYBuffer *key = cert.getPubKey();
       
   994 +        keyType = GetKeyTypeFromSPKI(key);
       
   995 +        setKeyType(keyType);
       
   996 +
       
   997 +        switch (keyType) {
       
   998 +        case rsa:
       
   999 +            GetKeyFields(key, &param1, &param2);
       
  1000 +            setAttribute(CKA_MODULUS, &param1);
       
  1001 +            setAttribute(CKA_PUBLIC_EXPONENT, &param2);
       
  1002 +	    setAttributeULong(CKA_KEY_TYPE, CKK_RSA);
       
  1003 +	    setAttributeBool(CKA_DECRYPT, decrypt);
       
  1004 +	    setAttributeBool(CKA_DERIVE, FALSE);
       
  1005 +            break;
       
  1006 +        case ecc:
       
  1007 +            GetECKeyFields(key, &param1, &param2);
       
  1008 +            setAttribute(CKA_EC_POINT, &param1);
       
  1009 +            setAttribute(CKA_EC_PARAMS, &param2);
       
  1010 +	    setAttributeULong(CKA_KEY_TYPE, CKK_EC);
       
  1011 +	    setAttributeBool(CKA_DECRYPT, FALSE);
       
  1012 +	    setAttributeBool(CKA_DERIVE, decrypt);
       
  1013 +            break;
       
  1014 +        default:
       
  1015 +            break;
       
  1016 +        }
       
  1017 +     } catch (PKCS11Exception &e) {
       
  1018 +        CKYBuffer_FreeData(&param1);
       
  1019 +        CKYBuffer_FreeData(&param2);
       
  1020 +        throw e;
       
  1021 +     }
       
  1022 +     CKYBuffer_FreeData(&param1);
       
  1023 +     CKYBuffer_FreeData(&param2);
       
  1024  }
       
  1025  
       
  1026 -CACPubKey::CACPubKey(CKYByte instance, const PKCS11Object &cert) : 
       
  1027 -	PKCS11Object( ((int)'k') << 24 | ((int)(instance+'5')) << 16,
       
  1028 -		       instance | 0x500)
       
  1029 +CACPubKey::CACPubKey(CKYByte instance, const PKCS11Object &cert, bool isPIV) : 
       
  1030 +        PKCS11Object( ((int)'k') << 24 | ((int)(instance+'a')) << 16,
       
  1031 +                       instance | 0x500)
       
  1032  {
       
  1033      CKYBuffer id;
       
  1034      CKYBuffer empty;
       
  1035 @@ -892,8 +1266,8 @@
       
  1036  
       
  1037      /* So we know what the key is supposed to be used for based on
       
  1038       * the instance */
       
  1039 -    if (instance == 2) {
       
  1040 -	encrypt = TRUE;
       
  1041 +    if (instance == 2 || (instance > (isPIV ? 3 : 2))) {
       
  1042 +        encrypt = TRUE;
       
  1043      }
       
  1044  
       
  1045      CKYBuffer_InitEmpty(&empty);
       
  1046 @@ -910,34 +1284,72 @@
       
  1047      setAttribute(CKA_END_DATE, &empty);
       
  1048      setAttributeBool(CKA_DERIVE, FALSE);
       
  1049      setAttributeBool(CKA_LOCAL, TRUE);
       
  1050 -    setAttributeULong(CKA_KEY_TYPE, CKK_RSA);
       
  1051  
       
  1052      setAttributeBool(CKA_ENCRYPT, encrypt);
       
  1053      setAttributeBool(CKA_VERIFY, !encrypt);
       
  1054      setAttributeBool(CKA_VERIFY_RECOVER, !encrypt);
       
  1055      setAttributeBool(CKA_WRAP, FALSE);
       
  1056  
       
  1057 -    CKYBuffer modulus; CKYBuffer_InitEmpty(&modulus);
       
  1058 -    CKYBuffer exponent; CKYBuffer_InitEmpty(&exponent);
       
  1059 +    CKYBuffer param1; CKYBuffer_InitEmpty(&param1);
       
  1060 +    CKYBuffer param2; CKYBuffer_InitEmpty(&param2);
       
  1061  
       
  1062      try {
       
  1063 -	const CKYBuffer *key = cert.getPubKey();
       
  1064 -	GetKeyFields(key, &modulus, &exponent);
       
  1065 -	setAttribute(CKA_MODULUS, &modulus);
       
  1066 -	setAttribute(CKA_PUBLIC_EXPONENT, &exponent);
       
  1067 -    } catch (PKCS11Exception &e) {
       
  1068 -	CKYBuffer_FreeData(&modulus);
       
  1069 -	CKYBuffer_FreeData(&exponent);
       
  1070 -	throw e;
       
  1071 -    }
       
  1072 -    CKYBuffer_FreeData(&modulus);
       
  1073 -    CKYBuffer_FreeData(&exponent);
       
  1074 +        const CKYBuffer *key = cert.getPubKey();
       
  1075 +        keyType = GetKeyTypeFromSPKI(key);
       
  1076 +        setKeyType(keyType);
       
  1077 +
       
  1078 +        switch (keyType) {
       
  1079 +        case rsa:
       
  1080 +            GetKeyFields(key, &param1, &param2);
       
  1081 +            setAttribute(CKA_MODULUS, &param1);
       
  1082 +            setAttribute(CKA_PUBLIC_EXPONENT, &param2);
       
  1083 +	    setAttributeULong(CKA_KEY_TYPE, CKK_RSA);
       
  1084 +            break;
       
  1085 +        case ecc:
       
  1086 +            GetECKeyFields(key, &param1, &param2);
       
  1087 +            setAttribute(CKA_EC_POINT, &param1);
       
  1088 +            setAttribute(CKA_EC_PARAMS, &param2);
       
  1089 +	    setAttributeULong(CKA_KEY_TYPE, CKK_EC);
       
  1090 +    	    setAttributeBool(CKA_VERIFY_RECOVER, FALSE);
       
  1091 +    	    setAttributeBool(CKA_ENCRYPT, FALSE);
       
  1092 +    	    setAttributeBool(CKA_DERIVE, encrypt);
       
  1093 +            break;
       
  1094 +        default:
       
  1095 +            break;
       
  1096 +        }
       
  1097 +     } catch (PKCS11Exception &e) {
       
  1098 +        CKYBuffer_FreeData(&param1);
       
  1099 +        CKYBuffer_FreeData(&param2);
       
  1100 +        throw e;
       
  1101 +     }
       
  1102 +     CKYBuffer_FreeData(&param1);
       
  1103 +     CKYBuffer_FreeData(&param2);
       
  1104  }
       
  1105  
       
  1106  static const char *CAC_Label[] = {
       
  1107 -	"CAC ID Certificate",
       
  1108 -	"CAC Email Signature Certificate",
       
  1109 -	"CAC Email Encryption Certificate",
       
  1110 +        "CAC ID Certificate",
       
  1111 +        "CAC Email Signature Certificate",
       
  1112 +        "CAC Email Encryption Certificate",
       
  1113 +        "CAC Cert 3",
       
  1114 +        "CAC Cert 4",
       
  1115 +        "CAC Cert 5",
       
  1116 +        "CAC Cert 6",
       
  1117 +        "CAC Cert 7",
       
  1118 +        "CAC Cert 8",
       
  1119 +        "CAC Cert 9",
       
  1120 +};
       
  1121 +
       
  1122 +static const char *PIV_Label[] = {
       
  1123 +        "PIV ID Certificate",
       
  1124 +        "PIV Email Signature Certificate",
       
  1125 +        "PIV Email Encryption Certificate",
       
  1126 +        "PIV Card Authentication Certificate",
       
  1127 +        "PIV Cert 4",
       
  1128 +        "PIV Cert 5",
       
  1129 +        "PIV Cert 6",
       
  1130 +        "PIV Cert 7",
       
  1131 +        "PIV Cert 8",
       
  1132 +        "PIV Cert 9",
       
  1133  };
       
  1134  
       
  1135  static const unsigned char CN_DATA[] = { 0x55, 0x4, 0x3 };
       
  1136 @@ -954,39 +1366,43 @@
       
  1137      if (buf == NULL) return SECFailure;
       
  1138  
       
  1139      while (buf_length) {
       
  1140 -	const CKYByte *name;
       
  1141 -	unsigned int name_length;
       
  1142 -	const CKYByte *oid;
       
  1143 -	unsigned int oid_length;
       
  1144 -
       
  1145 -	/* unwrap the set */
       
  1146 -	name = dataStart(buf, buf_length, &name_length, false);
       
  1147 +        const CKYByte *name;
       
  1148 +        unsigned int name_length;
       
  1149 +        const CKYByte *oid;
       
  1150 +        unsigned int oid_length;
       
  1151 +
       
  1152 +        /* unwrap the set */
       
  1153 +        name = dataStart(buf, buf_length, &name_length, false);
       
  1154 +	if (name == NULL) return SECFailure;
       
  1155  
       
  1156          /* advance to next set */
       
  1157 -	buf_length -= (name-buf) + name_length;
       
  1158 -	buf = name + name_length; 
       
  1159 +        buf_length -= (name-buf) + name_length;
       
  1160 +        buf = name + name_length; 
       
  1161  
       
  1162 -	/* unwrap the Sequence */
       
  1163 -	name = dataStart(name, name_length, &name_length, false);
       
  1164 +        /* unwrap the Sequence */
       
  1165 +        name = dataStart(name, name_length, &name_length, false);
       
  1166 +	if (name == NULL) return SECFailure;
       
  1167  
       
  1168          /* unwrap the oid */
       
  1169 -	oid = dataStart(name, name_length, &oid_length, false);
       
  1170 +        oid = dataStart(name, name_length, &oid_length, false);
       
  1171 +	if (oid == NULL) return SECFailure;
       
  1172  
       
  1173 -	/* test the oid */
       
  1174 -	if (oid_length != CN_LENGTH) {
       
  1175 -	    continue;
       
  1176 -	}
       
  1177 -	if (memcmp(oid, CN_DATA, CN_LENGTH) != 0) {
       
  1178 -	    continue;
       
  1179 -	}
       
  1180 +        /* test the oid */
       
  1181 +        if (oid_length != CN_LENGTH) {
       
  1182 +            continue;
       
  1183 +        }
       
  1184 +        if (memcmp(oid, CN_DATA, CN_LENGTH) != 0) {
       
  1185 +            continue;
       
  1186 +        }
       
  1187  
       
  1188 -	/* advance to CN */
       
  1189 -	name_length -= (oid-name) + oid_length;
       
  1190 -	name = oid + oid_length;
       
  1191 -
       
  1192 -	/* unwrap the CN */
       
  1193 -	cn->data = dataStart(name, name_length, &cn->len, false);
       
  1194 -	return SECSuccess;
       
  1195 +        /* advance to CN */
       
  1196 +        name_length -= (oid-name) + oid_length;
       
  1197 +        name = oid + oid_length;
       
  1198 +
       
  1199 +        /* unwrap the CN */
       
  1200 +        cn->data = dataStart(name, name_length, &cn->len, false);
       
  1201 +	if (cn->data == NULL) return SECFailure;
       
  1202 +        return SECSuccess;
       
  1203      }
       
  1204      return SECFailure;
       
  1205  }
       
  1206 @@ -1001,30 +1417,23 @@
       
  1207      rv = GetCN(CKYBuffer_Data(dn), CKYBuffer_Size(dn) , &cn);
       
  1208  
       
  1209      if( rv != SECSuccess ) {
       
  1210 -	return NULL;
       
  1211 +        return NULL;
       
  1212      }
       
  1213      string = new char [ cn.len + 1 ];
       
  1214      if (string == NULL) {
       
  1215 -	return NULL;
       
  1216 +        return NULL;
       
  1217      }
       
  1218      memcpy(string, cn.data, cn.len);
       
  1219      string[cn.len] = 0;
       
  1220      return string;
       
  1221  }
       
  1222  
       
  1223 -CACCert::CACCert(CKYByte instance, const CKYBuffer *derCert) : 
       
  1224 -	PKCS11Object( ((int)'c') << 24 | ((int)instance+'0') << 16, 
       
  1225 -			instance | 0x600)
       
  1226 +CACCert::CACCert(CKYByte instance, const CKYBuffer *derCert, bool isPIV) : 
       
  1227 +        PKCS11Object( ((int)'c') << 24 | ((int)instance+'0') << 16, 
       
  1228 +                        instance | 0x600)
       
  1229  {
       
  1230      CKYBuffer id;
       
  1231      CKYBuffer empty;
       
  1232 -    CK_BBOOL decrypt = FALSE;
       
  1233 -
       
  1234 -    /* So we know what the key is supposed to be used for based on
       
  1235 -     * the instance */
       
  1236 -    if (instance == 2) {
       
  1237 -	decrypt = TRUE;
       
  1238 -    }
       
  1239  
       
  1240      CKYBuffer_InitEmpty(&empty);
       
  1241      setAttributeULong(CKA_CLASS, CKO_CERTIFICATE);
       
  1242 @@ -1036,7 +1445,7 @@
       
  1243      setAttribute(CKA_ID, &id);
       
  1244      CKYBuffer_FreeData(&id);
       
  1245      setAttributeULong(CKA_CERTIFICATE_TYPE, CKC_X_509);
       
  1246 -    setAttribute(CKA_LABEL, CAC_Label[instance]);
       
  1247 +    setAttribute(CKA_LABEL, isPIV ? PIV_Label[instance] : CAC_Label[instance]);
       
  1248  
       
  1249      CKYBuffer derSerial; CKYBuffer_InitEmpty(&derSerial);
       
  1250      CKYBuffer derSubject; CKYBuffer_InitEmpty(&derSubject);
       
  1251 @@ -1045,19 +1454,19 @@
       
  1252      CKYBuffer_Resize(&pubKey,0);
       
  1253  
       
  1254      try {
       
  1255 -	setAttribute(CKA_VALUE, derCert);
       
  1256 -	// infer cert attributes
       
  1257 +        setAttribute(CKA_VALUE, derCert);
       
  1258 +        // infer cert attributes
       
  1259  
       
  1260 -	GetCertFields(derCert, &derSerial, &derSubject, &derIssuer, &pubKey);
       
  1261 +        GetCertFields(derCert, &derSerial, &derSubject, &derIssuer, &pubKey);
       
  1262  
       
  1263 -	setAttribute(CKA_SERIAL_NUMBER, &derSerial);
       
  1264 -	setAttribute(CKA_SUBJECT, &derSubject);
       
  1265 -	setAttribute(CKA_ISSUER, &derIssuer);
       
  1266 +        setAttribute(CKA_SERIAL_NUMBER, &derSerial);
       
  1267 +        setAttribute(CKA_SUBJECT, &derSubject);
       
  1268 +        setAttribute(CKA_ISSUER, &derIssuer);
       
  1269     } catch (PKCS11Exception &e) {
       
  1270 -	CKYBuffer_FreeData(&derSerial);
       
  1271 -	CKYBuffer_FreeData(&derSubject);
       
  1272 -	CKYBuffer_FreeData(&derIssuer);
       
  1273 -	throw e;
       
  1274 +        CKYBuffer_FreeData(&derSerial);
       
  1275 +        CKYBuffer_FreeData(&derSubject);
       
  1276 +        CKYBuffer_FreeData(&derIssuer);
       
  1277 +        throw e;
       
  1278      }
       
  1279  
       
  1280      name = GetUserName(&derSubject); /* adopt */
       
  1281 @@ -1065,3 +1474,100 @@
       
  1282      CKYBuffer_FreeData(&derSubject);
       
  1283      CKYBuffer_FreeData(&derIssuer);
       
  1284  }
       
  1285 +
       
  1286 +DEREncodedSignature::DEREncodedSignature(const CKYBuffer *derSig)
       
  1287 +{
       
  1288 +
       
  1289 +    CKYBuffer_InitEmpty(&derEncodedSignature);
       
  1290 +    CKYBuffer_InitFromCopy(&derEncodedSignature, derSig);
       
  1291 +}
       
  1292 +
       
  1293 +DEREncodedSignature::~DEREncodedSignature()
       
  1294 +{
       
  1295 +    CKYBuffer_FreeData(&derEncodedSignature);
       
  1296 +}
       
  1297 +
       
  1298 +int DEREncodedSignature::getRawSignature(CKYBuffer *rawSig, 
       
  1299 +					  unsigned int keySize)
       
  1300 +{
       
  1301 +    const CKYByte *buf = NULL;
       
  1302 +
       
  1303 +    if (rawSig == NULL) {
       
  1304 +        return -1;
       
  1305 +    }
       
  1306 +
       
  1307 +    if (CKYBuffer_Size(&derEncodedSignature) == 0) {
       
  1308 +        return -1;
       
  1309 +    }
       
  1310 +
       
  1311 +    CKYBuffer_Zero(rawSig);
       
  1312 +
       
  1313 +    unsigned int seq_length = 0;
       
  1314 +    unsigned int expected_sig_len = ( (keySize + 7) / 8 ) * 2 ;
       
  1315 +    unsigned int expected_piece_size = expected_sig_len / 2 ;
       
  1316 +
       
  1317 +    /* unwrap the sequence */
       
  1318 +    buf = dataStart(CKYBuffer_Data(&derEncodedSignature), CKYBuffer_Size(&derEncodedSignature),&seq_length, false);
       
  1319 +
       
  1320 +    if (buf == NULL) return -1;
       
  1321 +
       
  1322 +    // unwrap first multi byte integer
       
  1323 +   
       
  1324 +    unsigned int int_length = 0;
       
  1325 +    const CKYByte *int1Buf = NULL;
       
  1326 +    const CKYByte *int2Buf = NULL;
       
  1327 +
       
  1328 +    int1Buf = dataStart(buf, seq_length, &int_length, false );
       
  1329 +
       
  1330 +    if (int1Buf == NULL) return -1;
       
  1331 +    //advance to next entry
       
  1332 +
       
  1333 +    if (int_length > expected_piece_size) {
       
  1334 +
       
  1335 +      unsigned int diff = int_length - expected_piece_size ;
       
  1336 +
       
  1337 +      /* Make sure we are chopping off zeroes 
       
  1338 +         Otherwise give up. */
       
  1339 +
       
  1340 +      for (int i = 0 ; i < (int) diff ; i++) {
       
  1341 +          if ( int1Buf[i] != 0) 
       
  1342 +              return -1;
       
  1343 +      }
       
  1344 +
       
  1345 +      int_length -= diff;
       
  1346 +      int1Buf += diff;
       
  1347 +
       
  1348 +    }
       
  1349 +
       
  1350 +    seq_length -= (int1Buf -buf) + int_length;
       
  1351 +    buf = int1Buf +  int_length;
       
  1352 +
       
  1353 +    // unwrap second multi byte integer
       
  1354 +
       
  1355 +    unsigned int second_int_length = 0;
       
  1356 +
       
  1357 +    int2Buf = dataStart(buf, seq_length, &second_int_length, false);
       
  1358 +
       
  1359 +    if (int2Buf == NULL) return -1;
       
  1360 +
       
  1361 +
       
  1362 +    if (second_int_length > expected_piece_size) {
       
  1363 +        unsigned int diff = second_int_length - expected_piece_size ;
       
  1364 +
       
  1365 +        /* Make sure we are chopping off zeroes 
       
  1366 +           Otherwise give up. */
       
  1367 +
       
  1368 +        for (int i = 0 ;  i < (int)  diff ; i++) {
       
  1369 +            if ( int2Buf[i] != 0) 
       
  1370 +                return -1;
       
  1371 +        }
       
  1372 +      
       
  1373 +        second_int_length -= diff;
       
  1374 +        int2Buf += diff;
       
  1375 +    }
       
  1376 +
       
  1377 +    CKYBuffer_AppendData(rawSig, int1Buf, int_length);
       
  1378 +    CKYBuffer_AppendData(rawSig, int2Buf, second_int_length);
       
  1379 +
       
  1380 +    return CKYSUCCESS;
       
  1381 +}