6399N/AUpstream fixes already included in the latest community updates to coolkey v1.1.0
6399N/A
6399N/AAddresses various bugs found in PKCS11 object handling.
6399N/A
6399N/A--- ORIGINAL/./src/coolkey/object.cpp 2016-06-24 16:07:19.782779440 -0400
6399N/A+++ ././src/coolkey/object.cpp 2016-06-27 13:43:35.548673450 -0400
6399N/A@@ -21,15 +21,48 @@
6399N/A #include "PKCS11Exception.h"
6399N/A #include "object.h"
6399N/A #include <algorithm>
6399N/A+#include <string.h>
6399N/A
6399N/A using std::find_if;
6399N/A
6399N/A+const CKYByte rsaOID[] = {0x2A,0x86,0x48,0x86,0xF7,0x0D, 0x01, 0x01,0x1};
6399N/A+const CKYByte eccOID[] = {0x2a,0x86,0x48,0xce,0x3d,0x02,0x01};
6399N/A+
6399N/A+#ifdef DEBUG
6399N/A+void dump(CKYBuffer *buf)
6399N/A+{
6399N/A+ CKYSize i;
6399N/A+ CKYSize size = CKYBuffer_Size(buf);
6399N/A+#define ROW_LENGTH 60
6399N/A+ char string[ROW_LENGTH+1];
6399N/A+ char *bp = &string[0];
6399N/A+ CKYByte c;
6399N/A+
6399N/A+ for (i=0; i < size; i++) {
6399N/A+ if (i && ((i % (ROW_LENGTH-1)) == 0) ) {
6399N/A+ *bp = 0;
6399N/A+ printf(" %s\n",string);
6399N/A+ bp = &string[0];
6399N/A+ }
6399N/A+ c = CKYBuffer_GetChar(buf, i);
6399N/A+ printf("%02x ",c);
6399N/A+ *bp++ = (c < ' ') ? '.' : ((c & 0x80) ? '*' : c);
6399N/A+ }
6399N/A+ *bp = 0;
6399N/A+ for (i= (i % (ROW_LENGTH-1)); i && (i < ROW_LENGTH); i++) {
6399N/A+ printf(" ");
6399N/A+ }
6399N/A+ printf(" %s\n",string);
6399N/A+ fflush(stdout);
6399N/A+}
6399N/A+#endif
6399N/A+
6399N/A
6399N/A bool AttributeMatch::operator()(const PKCS11Attribute& cmp)
6399N/A {
6399N/A return (attr->type == cmp.getType()) &&
6399N/A- CKYBuffer_DataIsEqual(cmp.getValue(),
6399N/A- (const CKYByte *)attr->pValue, attr->ulValueLen);
6399N/A+ CKYBuffer_DataIsEqual(cmp.getValue(),
6399N/A+ (const CKYByte *)attr->pValue, attr->ulValueLen);
6399N/A }
6399N/A
6399N/A class AttributeTypeMatch
6399N/A@@ -44,14 +77,14 @@
6399N/A };
6399N/A
6399N/A PKCS11Object::PKCS11Object(unsigned long muscleObjID_,CK_OBJECT_HANDLE handle_)
6399N/A- : muscleObjID(muscleObjID_), handle(handle_), label(NULL), name(NULL)
6399N/A+ : muscleObjID(muscleObjID_), handle(handle_), label(NULL), name(NULL), keyType(unknown)
6399N/A {
6399N/A CKYBuffer_InitEmpty(&pubKey);
6399N/A }
6399N/A
6399N/A PKCS11Object::PKCS11Object(unsigned long muscleObjID_, const CKYBuffer *data,
6399N/A CK_OBJECT_HANDLE handle_) : muscleObjID(muscleObjID_), handle(handle_),
6399N/A- label(NULL), name(NULL)
6399N/A+ label(NULL), name(NULL), keyType(unknown)
6399N/A {
6399N/A CKYBuffer_InitEmpty(&pubKey);
6399N/A
6399N/A@@ -62,9 +95,98 @@
6399N/A "PKCS #11 actual object id does not match stated id");
6399N/A }
6399N/A if (type == 0) {
6399N/A- parseOldObject(data);
6399N/A+ parseOldObject(data);
6399N/A } else if (type == 1) {
6399N/A- parseNewObject(data);
6399N/A+ parseNewObject(data);
6399N/A+ }
6399N/A+}
6399N/A+
6399N/A+SecretKey::SecretKey(unsigned long muscleObjID_, CK_OBJECT_HANDLE handle_, CKYBuffer *secretKeyBuffer, CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulAttributeCount)
6399N/A+ : PKCS11Object(muscleObjID_, handle_)
6399N/A+{
6399N/A+ static CK_OBJECT_CLASS objClass = CKO_SECRET_KEY;
6399N/A+ static CK_KEY_TYPE keyType = CKK_GENERIC_SECRET;
6399N/A+ static CK_BBOOL value = 0x1;
6399N/A+
6399N/A+ if ( secretKeyBuffer == NULL)
6399N/A+ return;
6399N/A+
6399N/A+ /* Rifle through the input template */
6399N/A+
6399N/A+ CK_ATTRIBUTE_TYPE type;
6399N/A+ CK_ATTRIBUTE attr;
6399N/A+ CK_ULONG valueLength = 0;
6399N/A+
6399N/A+ for(int i = 0; i < (int) ulAttributeCount; i++) {
6399N/A+ attr = pTemplate[i];
6399N/A+ type = attr.type;
6399N/A+
6399N/A+ if ( type == CKA_VALUE_LEN) {
6399N/A+ //CK_ULONG ulValueLen = attr.ulValueLen;
6399N/A+ valueLength = *((CK_ULONG *)attr.pValue);
6399N/A+ } else {
6399N/A+
6399N/A+ CKYBuffer val;
6399N/A+ CKYBuffer_InitFromData(&val,(const CK_BYTE *) attr.pValue, attr.ulValueLen);
6399N/A+ setAttribute( type, &val);
6399N/A+ CKYBuffer_FreeData(&val);
6399N/A+ }
6399N/A+ }
6399N/A+
6399N/A+ adjustToKeyValueLength( secretKeyBuffer, valueLength );
6399N/A+
6399N/A+ /* Fall backs. */
6399N/A+
6399N/A+ if(!attributeExists(CKA_CLASS))
6399N/A+ setAttributeULong(CKA_CLASS, objClass);
6399N/A+
6399N/A+ if(!attributeExists(CKA_KEY_TYPE))
6399N/A+ setAttributeULong(CKA_KEY_TYPE, keyType);
6399N/A+
6399N/A+ if(!attributeExists(CKA_TOKEN))
6399N/A+ setAttributeBool(CKA_TOKEN, value);
6399N/A+
6399N/A+ if(!attributeExists(CKA_DERIVE))
6399N/A+ setAttributeBool(CKA_DERIVE, value);
6399N/A+
6399N/A+ /* Actual value */
6399N/A+ setAttribute(CKA_VALUE, secretKeyBuffer);
6399N/A+
6399N/A+}
6399N/A+
6399N/A+void SecretKey::adjustToKeyValueLength(CKYBuffer * secretKeyBuffer,CK_ULONG valueLength)
6399N/A+{
6399N/A+ const CK_LONG MAX_DIFF = 200; /* Put some bounds on this value */
6399N/A+
6399N/A+ if ( !secretKeyBuffer ) {
6399N/A+ return;
6399N/A+ }
6399N/A+
6399N/A+ CKYBuffer scratch;
6399N/A+ CK_ULONG actual_length = CKYBuffer_Size(secretKeyBuffer);
6399N/A+
6399N/A+ CK_LONG diff = 0;
6399N/A+ diff = (CK_LONG) valueLength - actual_length;
6399N/A+
6399N/A+ if ( diff == 0 ) {
6399N/A+ return;
6399N/A+ }
6399N/A+
6399N/A+ if ( diff > 0 && diff < MAX_DIFF ) { /*check for silly values */
6399N/A+ /* prepend with zeroes */
6399N/A+ CKYBuffer_InitFromLen(&scratch, diff);
6399N/A+ CKYBuffer_AppendCopy(&scratch, secretKeyBuffer);
6399N/A+
6399N/A+ CKYBuffer_FreeData(secretKeyBuffer);
6399N/A+ CKYBuffer_InitFromCopy(secretKeyBuffer, &scratch);
6399N/A+ CKYBuffer_FreeData(&scratch);
6399N/A+
6399N/A+ } else if (diff < 0 ) {
6399N/A+ /* truncate most significant bytes */
6399N/A+ CKYBuffer_InitFromData(&scratch, CKYBuffer_Data(secretKeyBuffer)-diff, valueLength);
6399N/A+ CKYBuffer_FreeData(secretKeyBuffer);
6399N/A+ CKYBuffer_InitFromCopy(secretKeyBuffer, &scratch);
6399N/A+ CKYBuffer_FreeData(&scratch);
6399N/A }
6399N/A }
6399N/A
6399N/A@@ -94,29 +216,29 @@
6399N/A attrib.setType(CKYBuffer_GetLong(data, idx));
6399N/A idx += 4;
6399N/A unsigned int attrLen = CKYBuffer_GetShort(data, idx);
6399N/A- idx += 2;
6399N/A+ idx += 2;
6399N/A if( attrLen > CKYBuffer_Size(data)
6399N/A- || (idx + attrLen > CKYBuffer_Size(data)) ) {
6399N/A+ || (idx + attrLen > CKYBuffer_Size(data)) ) {
6399N/A throw PKCS11Exception(CKR_DEVICE_ERROR,
6399N/A "Invalid attribute length %d\n", attrLen);
6399N/A }
6399N/A- /* these two types are ints, read them back from
6399N/A- * the card in host order */
6399N/A- if ((attrib.getType() == CKA_CLASS) ||
6399N/A- (attrib.getType() == CKA_CERTIFICATE_TYPE) ||
6399N/A- (attrib.getType() == CKA_KEY_TYPE)) {
6399N/A- /* ulongs are 4 bytes on the token, even if they are 8 or
6399N/A- * more in the pkcs11 module */
6399N/A- if (attrLen != 4) {
6399N/A+ /* these two types are ints, read them back from
6399N/A+ * the card in host order */
6399N/A+ if ((attrib.getType() == CKA_CLASS) ||
6399N/A+ (attrib.getType() == CKA_CERTIFICATE_TYPE) ||
6399N/A+ (attrib.getType() == CKA_KEY_TYPE)) {
6399N/A+ /* ulongs are 4 bytes on the token, even if they are 8 or
6399N/A+ * more in the pkcs11 module */
6399N/A+ if (attrLen != 4) {
6399N/A throw PKCS11Exception(CKR_DEVICE_ERROR,
6399N/A "Invalid attribute length %d\n", attrLen);
6399N/A- }
6399N/A- CK_ULONG value = makeLEUInt(data,idx);
6399N/A+ }
6399N/A+ CK_ULONG value = makeLEUInt(data,idx);
6399N/A
6399N/A- attrib.setValue((const CKYByte *)&value, sizeof(CK_ULONG));
6399N/A- } else {
6399N/A- attrib.setValue(CKYBuffer_Data(data)+idx, attrLen);
6399N/A- }
6399N/A+ attrib.setValue((const CKYByte *)&value, sizeof(CK_ULONG));
6399N/A+ } else {
6399N/A+ attrib.setValue(CKYBuffer_Data(data)+idx, attrLen);
6399N/A+ }
6399N/A idx += attrLen;
6399N/A attributes.push_back(attrib);
6399N/A }
6399N/A@@ -176,33 +298,33 @@
6399N/A unsigned long i;
6399N/A
6399N/A if (!attributeExists(CKA_ID)) {
6399N/A- PKCS11Attribute attrib;
6399N/A- attrib.setType(CKA_ID);
6399N/A- attrib.setValue(&cka_id, 1);
6399N/A+ PKCS11Attribute attrib;
6399N/A+ attrib.setType(CKA_ID);
6399N/A+ attrib.setValue(&cka_id, 1);
6399N/A attributes.push_back(attrib);
6399N/A }
6399N/A /* unpack the class */
6399N/A if (!attributeExists(CKA_CLASS)) {
6399N/A- PKCS11Attribute attrib;
6399N/A- attrib.setType(CKA_CLASS);
6399N/A- attrib.setValue((CKYByte *)&objectType, sizeof(CK_ULONG));
6399N/A+ PKCS11Attribute attrib;
6399N/A+ attrib.setType(CKA_CLASS);
6399N/A+ attrib.setValue((CKYByte *)&objectType, sizeof(CK_ULONG));
6399N/A attributes.push_back(attrib);
6399N/A }
6399N/A
6399N/A /* unpack the boolean flags. Note, the default mask is based on
6399N/A * the class specified in fixedAttrs, not on the real class */
6399N/A for (i=1; i < sizeof(unsigned long)*8; i++) {
6399N/A- unsigned long iMask = 1<< i;
6399N/A- if ((mask & iMask) == 0) {
6399N/A- continue;
6399N/A- }
6399N/A- if (attributeExists(boolType[i])) {
6399N/A- continue;
6399N/A- }
6399N/A- PKCS11Attribute attrib;
6399N/A- CKYByte bVal = (fixedAttrs & iMask) != 0;
6399N/A- attrib.setType(boolType[i]);
6399N/A- attrib.setValue(&bVal, 1);
6399N/A+ unsigned long iMask = 1<< i;
6399N/A+ if ((mask & iMask) == 0) {
6399N/A+ continue;
6399N/A+ }
6399N/A+ if (attributeExists(boolType[i])) {
6399N/A+ continue;
6399N/A+ }
6399N/A+ PKCS11Attribute attrib;
6399N/A+ CKYByte bVal = (fixedAttrs & iMask) != 0;
6399N/A+ attrib.setType(boolType[i]);
6399N/A+ attrib.setValue(&bVal, 1);
6399N/A attributes.push_back(attrib);
6399N/A }
6399N/A }
6399N/A@@ -223,40 +345,40 @@
6399N/A // load up the explicit attributes first
6399N/A for (j=0, offset = 11; j < attributeCount && offset < size; j++) {
6399N/A PKCS11Attribute attrib;
6399N/A- CKYByte attributeDataType = CKYBuffer_GetChar(data, offset+4);
6399N/A- unsigned int attrLen = 0;
6399N/A+ CKYByte attributeDataType = CKYBuffer_GetChar(data, offset+4);
6399N/A+ unsigned int attrLen = 0;
6399N/A attrib.setType(CKYBuffer_GetLong(data, offset));
6399N/A offset += 5;
6399N/A
6399N/A- switch(attributeDataType) {
6399N/A- case DATATYPE_STRING:
6399N/A- attrLen = CKYBuffer_GetShort(data, offset);
6399N/A- offset += 2;
6399N/A+ switch(attributeDataType) {
6399N/A+ case DATATYPE_STRING:
6399N/A+ attrLen = CKYBuffer_GetShort(data, offset);
6399N/A+ offset += 2;
6399N/A if (attrLen > CKYBuffer_Size(data)
6399N/A- || (offset + attrLen > CKYBuffer_Size(data)) ) {
6399N/A- throw PKCS11Exception(CKR_DEVICE_ERROR,
6399N/A- "Invalid attribute length %d\n", attrLen);
6399N/A+ || (offset + attrLen > CKYBuffer_Size(data)) ) {
6399N/A+ throw PKCS11Exception(CKR_DEVICE_ERROR,
6399N/A+ "Invalid attribute length %d\n", attrLen);
6399N/A }
6399N/A- attrib.setValue(CKYBuffer_Data(data)+offset, attrLen);
6399N/A- break;
6399N/A- case DATATYPE_BOOL_FALSE:
6399N/A- case DATATYPE_BOOL_TRUE:
6399N/A- {
6399N/A- CKYByte bval = attributeDataType & 1;
6399N/A- attrib.setValue(&bval, 1);
6399N/A- }
6399N/A- break;
6399N/A- case DATATYPE_INTEGER:
6399N/A- {
6399N/A- CK_ULONG value = CKYBuffer_GetLong(data, offset);
6399N/A- attrLen = 4;
6399N/A- attrib.setValue((const CKYByte *)&value, sizeof(CK_ULONG));
6399N/A- }
6399N/A- break;
6399N/A- default:
6399N/A- throw PKCS11Exception(CKR_DEVICE_ERROR,
6399N/A- "Invalid attribute Data Type %d\n", attributeDataType);
6399N/A- }
6399N/A+ attrib.setValue(CKYBuffer_Data(data)+offset, attrLen);
6399N/A+ break;
6399N/A+ case DATATYPE_BOOL_FALSE:
6399N/A+ case DATATYPE_BOOL_TRUE:
6399N/A+ {
6399N/A+ CKYByte bval = attributeDataType & 1;
6399N/A+ attrib.setValue(&bval, 1);
6399N/A+ }
6399N/A+ break;
6399N/A+ case DATATYPE_INTEGER:
6399N/A+ {
6399N/A+ CK_ULONG value = CKYBuffer_GetLong(data, offset);
6399N/A+ attrLen = 4;
6399N/A+ attrib.setValue((const CKYByte *)&value, sizeof(CK_ULONG));
6399N/A+ }
6399N/A+ break;
6399N/A+ default:
6399N/A+ throw PKCS11Exception(CKR_DEVICE_ERROR,
6399N/A+ "Invalid attribute Data Type %d\n", attributeDataType);
6399N/A+ }
6399N/A offset += attrLen;
6399N/A attributes.push_back(attrib);
6399N/A }
6399N/A@@ -273,9 +395,10 @@
6399N/A };
6399N/A #endif
6399N/A
6399N/A+// XXX - Need to use a correct signature. This is necessary only on SPARC
6399N/A bool
6399N/A-PKCS11Object::matchesTemplate(const CK_ATTRIBUTE_PTR pTemplate,
6399N/A- CK_ULONG ulCount)
6399N/A+PKCS11Object::matchesTemplate(CK_ATTRIBUTE_PTR pTemplate,
6399N/A+ CK_ULONG ulCount)
6399N/A const
6399N/A {
6399N/A unsigned int i;
6399N/A@@ -284,10 +407,10 @@
6399N/A
6399N/A #if defined( NSS_HIDE_NONSTANDARD_OBJECTS )
6399N/A if (!ulCount) {
6399N/A- // exclude MOZ reader objects from searches for all objects.
6399N/A- // To find an MOZ reader object, one must search for it by
6399N/A- // some matching attribute, such as class.
6399N/A- iterator iter = find_if(attributes.begin(), attributes.end(),
6399N/A+ // exclude MOZ reader objects from searches for all objects.
6399N/A+ // To find an MOZ reader object, one must search for it by
6399N/A+ // some matching attribute, such as class.
6399N/A+ iterator iter = find_if(attributes.begin(), attributes.end(),
6399N/A AttributeMatch(&rdr_template[0]));
6399N/A return (iter == attributes.end()) ? true : false;
6399N/A }
6399N/A@@ -324,7 +447,7 @@
6399N/A AttributeTypeMatch(type));
6399N/A
6399N/A if( iter == attributes.end() ) {
6399N/A- return NULL;
6399N/A+ return NULL;
6399N/A }
6399N/A return iter->getValue();
6399N/A }
6399N/A@@ -348,8 +471,9 @@
6399N/A if( iter == attributes.end() ) {
6399N/A // no attribute of this type
6399N/A attrTypeInvalid = true;
6399N/A- log->log("GetAttributeValue: invalid type 0x%08x on object %x\n",
6399N/A- pTemplate[i].type, muscleObjID);
6399N/A+ if ( log )
6399N/A+ log->log("GetAttributeValue: invalid type 0x%08x on object %x\n",
6399N/A+ pTemplate[i].type, muscleObjID);
6399N/A pTemplate[i].ulValueLen = (CK_ULONG)-1;
6399N/A continue;
6399N/A }
6399N/A@@ -370,7 +494,7 @@
6399N/A // the buffer is large enough. return the value and set the exact
6399N/A // length.
6399N/A memcpy(pTemplate[i].pValue, CKYBuffer_Data(iter->getValue()),
6399N/A- CKYBuffer_Size(iter->getValue()));
6399N/A+ CKYBuffer_Size(iter->getValue()));
6399N/A pTemplate[i].ulValueLen = CKYBuffer_Size(iter->getValue());
6399N/A }
6399N/A
6399N/A@@ -396,7 +520,7 @@
6399N/A {
6399N/A // clean up old one
6399N/A if (label) {
6399N/A- delete label;
6399N/A+ delete [] label;
6399N/A label = NULL;
6399N/A }
6399N/A // find matching attribute
6399N/A@@ -405,14 +529,14 @@
6399N/A
6399N/A // none found
6399N/A if( iter == attributes.end() ) {
6399N/A- return "";
6399N/A+ return "";
6399N/A }
6399N/A
6399N/A int size = CKYBuffer_Size(iter->getValue());
6399N/A
6399N/A label = new char [ size + 1 ];
6399N/A if (!label) {
6399N/A- return "";
6399N/A+ return "";
6399N/A }
6399N/A memcpy(label, CKYBuffer_Data(iter->getValue()), size);
6399N/A label[size] = 0;
6399N/A@@ -430,13 +554,13 @@
6399N/A
6399N/A // none found */
6399N/A if( iter == attributes.end() ) {
6399N/A- return (CK_OBJECT_CLASS) -1;
6399N/A+ return (CK_OBJECT_CLASS) -1;
6399N/A }
6399N/A
6399N/A int size = CKYBuffer_Size(iter->getValue());
6399N/A
6399N/A if (size != sizeof(objClass)) {
6399N/A- return (CK_OBJECT_CLASS) -1;
6399N/A+ return (CK_OBJECT_CLASS) -1;
6399N/A }
6399N/A
6399N/A memcpy(&objClass, CKYBuffer_Data(iter->getValue()), size);
6399N/A@@ -452,7 +576,7 @@
6399N/A iter = find_if(attributes.begin(), attributes.end(),
6399N/A AttributeTypeMatch(type));
6399N/A if( iter != attributes.end() ) {
6399N/A- iter->setValue( CKYBuffer_Data(value), CKYBuffer_Size(value));
6399N/A+ iter->setValue( CKYBuffer_Data(value), CKYBuffer_Size(value));
6399N/A } else {
6399N/A attributes.push_back(PKCS11Attribute(type, value));
6399N/A }
6399N/A@@ -504,6 +628,16 @@
6399N/A unsigned char tag;
6399N/A unsigned int used_length= 0;
6399N/A
6399N/A+ *data_length = 0; /* make sure data_length is zero on failure */
6399N/A+
6399N/A+ if(!buf) {
6399N/A+ return NULL;
6399N/A+ }
6399N/A+ /* there must be at least 2 bytes */
6399N/A+ if (length < 2) {
6399N/A+ return NULL;
6399N/A+ }
6399N/A+
6399N/A tag = buf[used_length++];
6399N/A
6399N/A /* blow out when we come to the end */
6399N/A@@ -516,15 +650,22 @@
6399N/A if (*data_length&0x80) {
6399N/A int len_count = *data_length & 0x7f;
6399N/A
6399N/A+ if (len_count+used_length > length) {
6399N/A+ return NULL;
6399N/A+ }
6399N/A+
6399N/A *data_length = 0;
6399N/A
6399N/A while (len_count-- > 0) {
6399N/A *data_length = (*data_length << 8) | buf[used_length++];
6399N/A }
6399N/A }
6399N/A+ /* paranoia, can't happen */
6399N/A+ if (length < used_length) {
6399N/A+ return NULL;
6399N/A+ }
6399N/A
6399N/A if (*data_length > (length-used_length) ) {
6399N/A- *data_length = length-used_length;
6399N/A return NULL;
6399N/A }
6399N/A if (includeTag) *data_length += used_length;
6399N/A@@ -537,16 +678,158 @@
6399N/A {
6399N/A /* for RSA, bit string always has byte number of bits */
6399N/A if (buf[0] != 0) {
6399N/A- return NULL;
6399N/A+ return NULL;
6399N/A }
6399N/A if (len < 1) {
6399N/A- return NULL;
6399N/A+ return NULL;
6399N/A }
6399N/A *retLen = len -1;
6399N/A return buf+1;
6399N/A }
6399N/A
6399N/A static SECStatus
6399N/A+GetECKeyFieldItems(const CKYByte *spki_data,unsigned int spki_length,
6399N/A+ CCItem *point, CCItem *params)
6399N/A+{
6399N/A+ const CKYByte *buf = spki_data;
6399N/A+ unsigned int buf_length = spki_length;
6399N/A+ const CKYByte *algid;
6399N/A+ unsigned int algidlen;
6399N/A+ const CKYByte *dummy;
6399N/A+ unsigned int dummylen;
6399N/A+
6399N/A+ if (!point || !params || !buf)
6399N/A+ return SECFailure;
6399N/A+
6399N/A+ point->data = NULL;
6399N/A+ point->len = 0;
6399N/A+ params->data = NULL;
6399N/A+ params->len = 0;
6399N/A+
6399N/A+ /* unwrap the algorithm id */
6399N/A+ dummy = dataStart(buf,buf_length,&dummylen,false);
6399N/A+ if (dummy == NULL) return SECFailure;
6399N/A+ buf_length -= (dummy-buf) + dummylen;
6399N/A+ buf = dummy + dummylen;
6399N/A+ /* unwrpped value is in dummy */
6399N/A+ algid = dummy;
6399N/A+ algidlen = dummylen;
6399N/A+ /* skip past algid oid */
6399N/A+ dummy = dataStart(algid, algidlen, &dummylen, false);
6399N/A+ if (dummy == NULL) return SECFailure;
6399N/A+ algidlen -= (dummy-algid) + dummylen;
6399N/A+ algid = dummy + dummylen;
6399N/A+ params->data = algid;
6399N/A+ params->len = algidlen;
6399N/A+
6399N/A+ /* unwrap the public key info */
6399N/A+ buf = dataStart(buf,buf_length,&buf_length,false);
6399N/A+ if (buf == NULL) return SECFailure;
6399N/A+ buf = unwrapBitString(buf,buf_length,&buf_length);
6399N/A+ if (buf == NULL) return SECFailure;
6399N/A+
6399N/A+ point->data = buf;
6399N/A+ point->len = buf_length;
6399N/A+
6399N/A+ if(point->data == NULL) return SECFailure;
6399N/A+
6399N/A+ return SECSuccess;
6399N/A+}
6399N/A+
6399N/A+static bool
6399N/A+GetKeyOIDMatches(const CKYByte *spki_data, unsigned int length, const CKYByte *oid_data)
6399N/A+{
6399N/A+ bool ret = TRUE;
6399N/A+
6399N/A+ if( spki_data == NULL || oid_data == NULL) {
6399N/A+ return FALSE;
6399N/A+ }
6399N/A+
6399N/A+ for ( int i = 0 ; i < (int) length ; i++) {
6399N/A+ if (spki_data[i] != oid_data[i]) {
6399N/A+ ret = FALSE;
6399N/A+ break;
6399N/A+ }
6399N/A+
6399N/A+ }
6399N/A+
6399N/A+ return ret;
6399N/A+}
6399N/A+
6399N/A+static SECStatus
6399N/A+GetKeyAlgorithmId(const CKYByte *spki_data, unsigned int spki_length,
6399N/A+ CCItem *algorithmId)
6399N/A+{
6399N/A+
6399N/A+ const CKYByte *buf = spki_data;
6399N/A+ unsigned int buf_length = spki_length;
6399N/A+
6399N/A+ if ( algorithmId == NULL) return SECFailure;
6399N/A+
6399N/A+ /* objtain the algorithm id */
6399N/A+ algorithmId->data = dataStart(buf,buf_length,&algorithmId->len,false);
6399N/A+ if (algorithmId->data == NULL) return SECFailure;
6399N/A+
6399N/A+ return SECSuccess;
6399N/A+
6399N/A+}
6399N/A+
6399N/A+static PKCS11Object::KeyType
6399N/A+GetKeyTypeFromSPKI(const CKYBuffer *key)
6399N/A+{
6399N/A+ CCItem algIdItem;
6399N/A+ SECStatus ret = GetKeyAlgorithmId(CKYBuffer_Data(key),
6399N/A+ CKYBuffer_Size(key),&algIdItem);
6399N/A+ PKCS11Object::KeyType foundType = PKCS11Object::unknown;
6399N/A+
6399N/A+ if ( ret != SECSuccess ) {
6399N/A+ throw PKCS11Exception(CKR_FUNCTION_FAILED,
6399N/A+ "Failed to decode key algorithm ID.");
6399N/A+ }
6399N/A+
6399N/A+ unsigned int length = 0;
6399N/A+ const CKYByte *keyData = NULL;
6399N/A+
6399N/A+ /* Get actual oid buffer */
6399N/A+
6399N/A+ keyData = dataStart(algIdItem.data,algIdItem.len,&length, false);
6399N/A+ if (keyData == NULL) {
6399N/A+ throw PKCS11Exception(CKR_FUNCTION_FAILED,
6399N/A+ "Failed to decode key algorithm ID.");
6399N/A+ }
6399N/A+
6399N/A+ bool match = FALSE;
6399N/A+
6399N/A+ /* Check for outrageous length */
6399N/A+
6399N/A+ if ( length <= 3 || length >= algIdItem.len) {
6399N/A+ throw PKCS11Exception(CKR_FUNCTION_FAILED,
6399N/A+ "Failed to decode key algorithm ID.");
6399N/A+ }
6399N/A+ /* check for RSA */
6399N/A+
6399N/A+ match = GetKeyOIDMatches(keyData, length, rsaOID);
6399N/A+
6399N/A+ if ( match == TRUE ) {
6399N/A+ foundType = PKCS11Object::rsa;
6399N/A+ } else {
6399N/A+ /* check for ECC */
6399N/A+ match = GetKeyOIDMatches(keyData, length, eccOID);
6399N/A+
6399N/A+ if ( match == TRUE ) {
6399N/A+ foundType = PKCS11Object::ecc;
6399N/A+ }
6399N/A+
6399N/A+ }
6399N/A+
6399N/A+ if ( foundType == PKCS11Object::unknown) {
6399N/A+ throw PKCS11Exception(CKR_FUNCTION_FAILED,
6399N/A+ "Failed to decode key algorithm ID.");
6399N/A+ }
6399N/A+ return foundType;
6399N/A+}
6399N/A+
6399N/A+static SECStatus
6399N/A GetKeyFieldItems(const CKYByte *spki_data,unsigned int spki_length,
6399N/A CCItem *modulus, CCItem *exponent)
6399N/A {
6399N/A@@ -591,7 +874,7 @@
6399N/A CCItem modulusItem, exponentItem;
6399N/A
6399N/A rv = GetKeyFieldItems(CKYBuffer_Data(spki), CKYBuffer_Size(spki),
6399N/A- &modulusItem, &exponentItem);
6399N/A+ &modulusItem, &exponentItem);
6399N/A
6399N/A if( rv != SECSuccess ) {
6399N/A throw PKCS11Exception(CKR_FUNCTION_FAILED,
6399N/A@@ -602,6 +885,29 @@
6399N/A CKYBuffer_Replace(exponent, 0, exponentItem.data, exponentItem.len);
6399N/A }
6399N/A
6399N/A+static void
6399N/A+GetECKeyFields(const CKYBuffer *spki, CKYBuffer *point, CKYBuffer *params)
6399N/A+{
6399N/A+ SECStatus rv;
6399N/A+ CCItem pointItem, paramsItem;
6399N/A+
6399N/A+ if (spki == NULL || point == NULL || params == NULL) {
6399N/A+ throw PKCS11Exception(CKR_FUNCTION_FAILED,
6399N/A+ "Failed to decode certificate Subject Public KeyInfo!");
6399N/A+ }
6399N/A+
6399N/A+ rv = GetECKeyFieldItems(CKYBuffer_Data(spki), CKYBuffer_Size(spki),
6399N/A+ &pointItem, &paramsItem);
6399N/A+
6399N/A+ if( rv != SECSuccess ) {
6399N/A+ throw PKCS11Exception(CKR_FUNCTION_FAILED,
6399N/A+ "Failed to decode certificate Subject Public Key Info!");
6399N/A+ }
6399N/A+
6399N/A+ CKYBuffer_Replace(point, 0, pointItem.data, pointItem.len);
6399N/A+ CKYBuffer_Replace(params, 0, paramsItem.data, paramsItem.len);
6399N/A+}
6399N/A+
6399N/A Key::Key(unsigned long muscleObjID, const CKYBuffer *data,
6399N/A CK_OBJECT_HANDLE handle) : PKCS11Object(muscleObjID, data, handle)
6399N/A {
6399N/A@@ -611,22 +917,41 @@
6399N/A CKYBuffer_InitEmpty(&empty);
6399N/A
6399N/A if ((objClass == CKO_PUBLIC_KEY) || (objClass == CKO_PRIVATE_KEY)) {
6399N/A- /* only CKK_RSA is supported */
6399N/A- setAttributeULong(CKA_KEY_TYPE, CKK_RSA);
6399N/A+ //we may know already what type of key this is.
6399N/A+ if (attributeExists(CKA_KEY_TYPE)) {
6399N/A+ CK_ULONG type = 0;
6399N/A+ CK_ATTRIBUTE aTemplate = {CKA_KEY_TYPE, &type, sizeof(CK_ULONG)};
6399N/A+
6399N/A+ getAttributeValue(&aTemplate, 1, NULL);
6399N/A+
6399N/A+ if (type == 0x3) {
6399N/A+ setKeyType(ecc);
6399N/A+ setAttributeULong(CKA_KEY_TYPE, CKK_EC);
6399N/A+ } else {
6399N/A+ setKeyType(rsa);
6399N/A+ setAttributeULong(CKA_KEY_TYPE, CKK_RSA);
6399N/A+ }
6399N/A+ } else {
6399N/A+ /* default to rsa */
6399N/A+ setKeyType(rsa);
6399N/A+ setAttributeULong(CKA_KEY_TYPE, CKK_RSA);
6399N/A+ }
6399N/A+
6399N/A+ // Could be RSA or ECC
6399N/A } else if (objClass == CKO_SECRET_KEY) {
6399N/A- if (!attributeExists(CKA_LABEL)) {
6399N/A- setAttribute(CKA_LABEL, &empty);
6399N/A- }
6399N/A- if (!attributeExists(CKA_KEY_TYPE)) {
6399N/A- /* default to DES3 */
6399N/A- setAttributeULong(CKA_KEY_TYPE, CKK_DES3);
6399N/A- }
6399N/A+ if (!attributeExists(CKA_LABEL)) {
6399N/A+ setAttribute(CKA_LABEL, &empty);
6399N/A+ }
6399N/A+ if (!attributeExists(CKA_KEY_TYPE)) {
6399N/A+ /* default to DES3 */
6399N/A+ setAttributeULong(CKA_KEY_TYPE, CKK_DES3);
6399N/A+ }
6399N/A }
6399N/A if (!attributeExists(CKA_START_DATE)) {
6399N/A- setAttribute(CKA_START_DATE, &empty);
6399N/A+ setAttribute(CKA_START_DATE, &empty);
6399N/A }
6399N/A if (!attributeExists(CKA_END_DATE)) {
6399N/A- setAttribute(CKA_END_DATE, &empty);
6399N/A+ setAttribute(CKA_END_DATE, &empty);
6399N/A }
6399N/A }
6399N/A
6399N/A@@ -635,32 +960,59 @@
6399N/A {
6399N/A // infer key attributes from cert
6399N/A bool modulusExists, exponentExists;
6399N/A- CKYBuffer modulus; CKYBuffer_InitEmpty(&modulus);
6399N/A- CKYBuffer exponent; CKYBuffer_InitEmpty(&exponent);
6399N/A+ bool pointExists, paramsExists;
6399N/A+
6399N/A+ PKCS11Object::KeyType keyType;
6399N/A+ const CKYBuffer *key = cert.getPubKey();
6399N/A
6399N/A if (!attributeExists(CKA_LABEL)) {
6399N/A- setAttribute(CKA_LABEL, cert.getAttribute(CKA_LABEL));
6399N/A+ setAttribute(CKA_LABEL, cert.getAttribute(CKA_LABEL));
6399N/A }
6399N/A+
6399N/A+ CKYBuffer param1; CKYBuffer_InitEmpty(&param1);
6399N/A+ CKYBuffer param2; CKYBuffer_InitEmpty(&param2);
6399N/A try {
6399N/A- modulusExists = attributeExists(CKA_MODULUS);
6399N/A- exponentExists = attributeExists(CKA_PUBLIC_EXPONENT);
6399N/A- if (!modulusExists || !exponentExists) {
6399N/A- const CKYBuffer *key = cert.getPubKey();
6399N/A- GetKeyFields(key, &modulus, &exponent);
6399N/A- if (!modulusExists) {
6399N/A- setAttribute(CKA_MODULUS, &modulus);
6399N/A- }
6399N/A- if (!exponentExists) {
6399N/A- setAttribute(CKA_PUBLIC_EXPONENT, &exponent);
6399N/A- }
6399N/A- }
6399N/A+ keyType = GetKeyTypeFromSPKI(key);
6399N/A+ setKeyType(keyType);
6399N/A+
6399N/A+ switch (keyType) {
6399N/A+ case rsa:
6399N/A+ modulusExists = attributeExists(CKA_MODULUS);
6399N/A+ exponentExists = attributeExists(CKA_PUBLIC_EXPONENT);
6399N/A+ if (!modulusExists || !exponentExists) {
6399N/A+ GetKeyFields(key, &param1, &param2);
6399N/A+ if (!modulusExists) {
6399N/A+ setAttribute(CKA_MODULUS, &param1);
6399N/A+ }
6399N/A+ if (!exponentExists) {
6399N/A+ setAttribute(CKA_PUBLIC_EXPONENT, &param2);
6399N/A+ }
6399N/A+ }
6399N/A+ break;
6399N/A+ case ecc:
6399N/A+ pointExists = attributeExists(CKA_EC_POINT);
6399N/A+ paramsExists = attributeExists(CKA_EC_PARAMS);
6399N/A+
6399N/A+ if (!pointExists || !paramsExists) {
6399N/A+ GetECKeyFields(key, &param1, &param2);
6399N/A+ if (!pointExists) {
6399N/A+ setAttribute(CKA_EC_POINT, &param1);
6399N/A+ }
6399N/A+ if (!paramsExists) {
6399N/A+ setAttribute(CKA_EC_PARAMS, &param2);
6399N/A+ }
6399N/A+ }
6399N/A+ break;
6399N/A+ default:
6399N/A+ break;
6399N/A+ }
6399N/A } catch (PKCS11Exception &e) {
6399N/A- CKYBuffer_FreeData(&modulus);
6399N/A- CKYBuffer_FreeData(&exponent);
6399N/A- throw e;
6399N/A+ CKYBuffer_FreeData(&param1);
6399N/A+ CKYBuffer_FreeData(&param2);
6399N/A+ throw e;
6399N/A }
6399N/A- CKYBuffer_FreeData(&modulus);
6399N/A- CKYBuffer_FreeData(&exponent);
6399N/A+ CKYBuffer_FreeData(&param1);
6399N/A+ CKYBuffer_FreeData(&param2);
6399N/A }
6399N/A
6399N/A static SECStatus
6399N/A@@ -732,14 +1084,14 @@
6399N/A
6399N/A static void
6399N/A GetCertFields(const CKYBuffer *derCert, CKYBuffer *derSerial,
6399N/A- CKYBuffer *derSubject, CKYBuffer *derIssuer, CKYBuffer *subjectKey)
6399N/A+ CKYBuffer *derSubject, CKYBuffer *derIssuer, CKYBuffer *subjectKey)
6399N/A {
6399N/A SECStatus rv;
6399N/A CCItem issuerItem, serialItem, derSerialItem, subjectItem,
6399N/A validityItem, subjectKeyItem;
6399N/A
6399N/A rv = GetCertFieldItems(CKYBuffer_Data(derCert), CKYBuffer_Size(derCert),
6399N/A- &issuerItem, &serialItem, &derSerialItem, &subjectItem, &validityItem,
6399N/A+ &issuerItem, &serialItem, &derSerialItem, &subjectItem, &validityItem,
6399N/A &subjectKeyItem);
6399N/A
6399N/A if( rv != SECSuccess ) {
6399N/A@@ -764,50 +1116,50 @@
6399N/A CK_ULONG certTypeValue = CKC_X_509;
6399N/A
6399N/A CKYBuffer_InitFromData(&certType, (CKYByte *)&certTypeValue,
6399N/A- sizeof(certTypeValue));
6399N/A+ sizeof(certTypeValue));
6399N/A CKYBuffer_Resize(&pubKey,0);
6399N/A
6399N/A try {
6399N/A- setAttribute(CKA_CERTIFICATE_TYPE, &certType);
6399N/A+ setAttribute(CKA_CERTIFICATE_TYPE, &certType);
6399N/A
6399N/A- if (!attributeExists(CKA_VALUE)) {
6399N/A- if (derCert) {
6399N/A- setAttribute(CKA_VALUE, derCert);
6399N/A- } else {
6399N/A- throw PKCS11Exception(CKR_DEVICE_ERROR,
6399N/A- "Missing certificate data from token");
6399N/A- }
6399N/A- }
6399N/A+ if (!attributeExists(CKA_VALUE)) {
6399N/A+ if (derCert) {
6399N/A+ setAttribute(CKA_VALUE, derCert);
6399N/A+ } else {
6399N/A+ throw PKCS11Exception(CKR_DEVICE_ERROR,
6399N/A+ "Missing certificate data from token");
6399N/A+ }
6399N/A+ }
6399N/A
6399N/A- if (!derCert) {
6399N/A- derCert = getAttribute(CKA_VALUE);
6399N/A- if (!derCert) {
6399N/A- // paranoia, should never happen since we verify the
6399N/A- // attribute exists above
6399N/A- throw PKCS11Exception(CKR_DEVICE_ERROR,
6399N/A- "Missing certificate data from token");
6399N/A- }
6399N/A- }
6399N/A+ if (!derCert) {
6399N/A+ derCert = getAttribute(CKA_VALUE);
6399N/A+ if (!derCert) {
6399N/A+ // paranoia, should never happen since we verify the
6399N/A+ // attribute exists above
6399N/A+ throw PKCS11Exception(CKR_DEVICE_ERROR,
6399N/A+ "Missing certificate data from token");
6399N/A+ }
6399N/A+ }
6399N/A
6399N/A- // infer cert attributes
6399N/A+ // infer cert attributes
6399N/A
6399N/A- GetCertFields(derCert, &derSerial, &derSubject, &derIssuer, &pubKey);
6399N/A+ GetCertFields(derCert, &derSerial, &derSubject, &derIssuer, &pubKey);
6399N/A
6399N/A- if (!attributeExists(CKA_SERIAL_NUMBER)) {
6399N/A- setAttribute(CKA_SERIAL_NUMBER, &derSerial);
6399N/A- }
6399N/A- if (!attributeExists(CKA_SUBJECT)) {
6399N/A- setAttribute(CKA_SUBJECT, &derSubject);
6399N/A- }
6399N/A- if (!attributeExists(CKA_ISSUER)) {
6399N/A- setAttribute(CKA_ISSUER, &derIssuer);
6399N/A- }
6399N/A+ if (!attributeExists(CKA_SERIAL_NUMBER)) {
6399N/A+ setAttribute(CKA_SERIAL_NUMBER, &derSerial);
6399N/A+ }
6399N/A+ if (!attributeExists(CKA_SUBJECT)) {
6399N/A+ setAttribute(CKA_SUBJECT, &derSubject);
6399N/A+ }
6399N/A+ if (!attributeExists(CKA_ISSUER)) {
6399N/A+ setAttribute(CKA_ISSUER, &derIssuer);
6399N/A+ }
6399N/A } catch (PKCS11Exception &e) {
6399N/A- CKYBuffer_FreeData(&certType);
6399N/A- CKYBuffer_FreeData(&derSerial);
6399N/A- CKYBuffer_FreeData(&derSubject);
6399N/A- CKYBuffer_FreeData(&derIssuer);
6399N/A- throw e;
6399N/A+ CKYBuffer_FreeData(&certType);
6399N/A+ CKYBuffer_FreeData(&derSerial);
6399N/A+ CKYBuffer_FreeData(&derSubject);
6399N/A+ CKYBuffer_FreeData(&derIssuer);
6399N/A+ throw e;
6399N/A }
6399N/A CKYBuffer_FreeData(&certType);
6399N/A CKYBuffer_FreeData(&derSerial);
6399N/A@@ -817,7 +1169,7 @@
6399N/A
6399N/A Reader::Reader(unsigned long muscleObjID, CK_OBJECT_HANDLE handle,
6399N/A const char *reader, const CKYBuffer *cardATR, bool isCoolkey) :
6399N/A- PKCS11Object(muscleObjID, handle)
6399N/A+ PKCS11Object(muscleObjID, handle)
6399N/A {
6399N/A setAttributeULong(CKA_CLASS, CKO_MOZ_READER);
6399N/A setAttribute(CKA_LABEL, reader);
6399N/A@@ -828,9 +1180,10 @@
6399N/A setAttribute(CKA_MOZ_ATR, cardATR);
6399N/A }
6399N/A
6399N/A-CACPrivKey::CACPrivKey(CKYByte instance, const PKCS11Object &cert) :
6399N/A- PKCS11Object( ((int)'k') << 24 | ((int)instance+'0') << 16,
6399N/A- instance | 0x400)
6399N/A+
6399N/A+CACPrivKey::CACPrivKey(CKYByte instance, const PKCS11Object &cert,bool isPIV) :
6399N/A+ PKCS11Object( ((int)'k') << 24 | ((int)instance+'0') << 16,
6399N/A+ instance | 0x400)
6399N/A {
6399N/A CKYBuffer id;
6399N/A CKYBuffer empty;
6399N/A@@ -838,8 +1191,10 @@
6399N/A
6399N/A /* So we know what the key is supposed to be used for based on
6399N/A * the instance */
6399N/A- if (instance == 2) {
6399N/A- decrypt = TRUE;
6399N/A+ /* instance 2 is usually a decryption cert. >2 are usually old decryption
6399N/A+ * certs */
6399N/A+ if (instance == 2 || (instance > (isPIV ? 3 : 2))) {
6399N/A+ decrypt = TRUE;
6399N/A }
6399N/A
6399N/A CKYBuffer_InitEmpty(&empty);
6399N/A@@ -858,33 +1213,52 @@
6399N/A setAttributeBool(CKA_LOCAL, TRUE);
6399N/A setAttributeULong(CKA_KEY_TYPE, CKK_RSA);
6399N/A
6399N/A- setAttributeBool(CKA_DECRYPT, decrypt);
6399N/A setAttributeBool(CKA_SIGN, !decrypt);
6399N/A setAttributeBool(CKA_SIGN_RECOVER, !decrypt);
6399N/A setAttributeBool(CKA_UNWRAP, FALSE);
6399N/A setAttributeBool(CKA_SENSITIVE, TRUE);
6399N/A setAttributeBool(CKA_EXTRACTABLE, FALSE);
6399N/A
6399N/A- CKYBuffer modulus; CKYBuffer_InitEmpty(&modulus);
6399N/A- CKYBuffer exponent; CKYBuffer_InitEmpty(&exponent);
6399N/A+ CKYBuffer param1; CKYBuffer_InitEmpty(&param1);
6399N/A+ CKYBuffer param2; CKYBuffer_InitEmpty(&param2);
6399N/A
6399N/A try {
6399N/A- const CKYBuffer *key = cert.getPubKey();
6399N/A- GetKeyFields(key, &modulus, &exponent);
6399N/A- setAttribute(CKA_MODULUS, &modulus);
6399N/A- setAttribute(CKA_PUBLIC_EXPONENT, &exponent);
6399N/A- } catch (PKCS11Exception &e) {
6399N/A- CKYBuffer_FreeData(&modulus);
6399N/A- CKYBuffer_FreeData(&exponent);
6399N/A- throw e;
6399N/A- }
6399N/A- CKYBuffer_FreeData(&modulus);
6399N/A- CKYBuffer_FreeData(&exponent);
6399N/A+ const CKYBuffer *key = cert.getPubKey();
6399N/A+ keyType = GetKeyTypeFromSPKI(key);
6399N/A+ setKeyType(keyType);
6399N/A+
6399N/A+ switch (keyType) {
6399N/A+ case rsa:
6399N/A+ GetKeyFields(key, &param1, &param2);
6399N/A+ setAttribute(CKA_MODULUS, &param1);
6399N/A+ setAttribute(CKA_PUBLIC_EXPONENT, &param2);
6399N/A+ setAttributeULong(CKA_KEY_TYPE, CKK_RSA);
6399N/A+ setAttributeBool(CKA_DECRYPT, decrypt);
6399N/A+ setAttributeBool(CKA_DERIVE, FALSE);
6399N/A+ break;
6399N/A+ case ecc:
6399N/A+ GetECKeyFields(key, &param1, &param2);
6399N/A+ setAttribute(CKA_EC_POINT, &param1);
6399N/A+ setAttribute(CKA_EC_PARAMS, &param2);
6399N/A+ setAttributeULong(CKA_KEY_TYPE, CKK_EC);
6399N/A+ setAttributeBool(CKA_DECRYPT, FALSE);
6399N/A+ setAttributeBool(CKA_DERIVE, decrypt);
6399N/A+ break;
6399N/A+ default:
6399N/A+ break;
6399N/A+ }
6399N/A+ } catch (PKCS11Exception &e) {
6399N/A+ CKYBuffer_FreeData(&param1);
6399N/A+ CKYBuffer_FreeData(&param2);
6399N/A+ throw e;
6399N/A+ }
6399N/A+ CKYBuffer_FreeData(&param1);
6399N/A+ CKYBuffer_FreeData(&param2);
6399N/A }
6399N/A
6399N/A-CACPubKey::CACPubKey(CKYByte instance, const PKCS11Object &cert) :
6399N/A- PKCS11Object( ((int)'k') << 24 | ((int)(instance+'5')) << 16,
6399N/A- instance | 0x500)
6399N/A+CACPubKey::CACPubKey(CKYByte instance, const PKCS11Object &cert, bool isPIV) :
6399N/A+ PKCS11Object( ((int)'k') << 24 | ((int)(instance+'a')) << 16,
6399N/A+ instance | 0x500)
6399N/A {
6399N/A CKYBuffer id;
6399N/A CKYBuffer empty;
6399N/A@@ -892,8 +1266,8 @@
6399N/A
6399N/A /* So we know what the key is supposed to be used for based on
6399N/A * the instance */
6399N/A- if (instance == 2) {
6399N/A- encrypt = TRUE;
6399N/A+ if (instance == 2 || (instance > (isPIV ? 3 : 2))) {
6399N/A+ encrypt = TRUE;
6399N/A }
6399N/A
6399N/A CKYBuffer_InitEmpty(&empty);
6399N/A@@ -910,34 +1284,72 @@
6399N/A setAttribute(CKA_END_DATE, &empty);
6399N/A setAttributeBool(CKA_DERIVE, FALSE);
6399N/A setAttributeBool(CKA_LOCAL, TRUE);
6399N/A- setAttributeULong(CKA_KEY_TYPE, CKK_RSA);
6399N/A
6399N/A setAttributeBool(CKA_ENCRYPT, encrypt);
6399N/A setAttributeBool(CKA_VERIFY, !encrypt);
6399N/A setAttributeBool(CKA_VERIFY_RECOVER, !encrypt);
6399N/A setAttributeBool(CKA_WRAP, FALSE);
6399N/A
6399N/A- CKYBuffer modulus; CKYBuffer_InitEmpty(&modulus);
6399N/A- CKYBuffer exponent; CKYBuffer_InitEmpty(&exponent);
6399N/A+ CKYBuffer param1; CKYBuffer_InitEmpty(&param1);
6399N/A+ CKYBuffer param2; CKYBuffer_InitEmpty(&param2);
6399N/A
6399N/A try {
6399N/A- const CKYBuffer *key = cert.getPubKey();
6399N/A- GetKeyFields(key, &modulus, &exponent);
6399N/A- setAttribute(CKA_MODULUS, &modulus);
6399N/A- setAttribute(CKA_PUBLIC_EXPONENT, &exponent);
6399N/A- } catch (PKCS11Exception &e) {
6399N/A- CKYBuffer_FreeData(&modulus);
6399N/A- CKYBuffer_FreeData(&exponent);
6399N/A- throw e;
6399N/A- }
6399N/A- CKYBuffer_FreeData(&modulus);
6399N/A- CKYBuffer_FreeData(&exponent);
6399N/A+ const CKYBuffer *key = cert.getPubKey();
6399N/A+ keyType = GetKeyTypeFromSPKI(key);
6399N/A+ setKeyType(keyType);
6399N/A+
6399N/A+ switch (keyType) {
6399N/A+ case rsa:
6399N/A+ GetKeyFields(key, &param1, &param2);
6399N/A+ setAttribute(CKA_MODULUS, &param1);
6399N/A+ setAttribute(CKA_PUBLIC_EXPONENT, &param2);
6399N/A+ setAttributeULong(CKA_KEY_TYPE, CKK_RSA);
6399N/A+ break;
6399N/A+ case ecc:
6399N/A+ GetECKeyFields(key, &param1, &param2);
6399N/A+ setAttribute(CKA_EC_POINT, &param1);
6399N/A+ setAttribute(CKA_EC_PARAMS, &param2);
6399N/A+ setAttributeULong(CKA_KEY_TYPE, CKK_EC);
6399N/A+ setAttributeBool(CKA_VERIFY_RECOVER, FALSE);
6399N/A+ setAttributeBool(CKA_ENCRYPT, FALSE);
6399N/A+ setAttributeBool(CKA_DERIVE, encrypt);
6399N/A+ break;
6399N/A+ default:
6399N/A+ break;
6399N/A+ }
6399N/A+ } catch (PKCS11Exception &e) {
6399N/A+ CKYBuffer_FreeData(&param1);
6399N/A+ CKYBuffer_FreeData(&param2);
6399N/A+ throw e;
6399N/A+ }
6399N/A+ CKYBuffer_FreeData(&param1);
6399N/A+ CKYBuffer_FreeData(&param2);
6399N/A }
6399N/A
6399N/A static const char *CAC_Label[] = {
6399N/A- "CAC ID Certificate",
6399N/A- "CAC Email Signature Certificate",
6399N/A- "CAC Email Encryption Certificate",
6399N/A+ "CAC ID Certificate",
6399N/A+ "CAC Email Signature Certificate",
6399N/A+ "CAC Email Encryption Certificate",
6399N/A+ "CAC Cert 3",
6399N/A+ "CAC Cert 4",
6399N/A+ "CAC Cert 5",
6399N/A+ "CAC Cert 6",
6399N/A+ "CAC Cert 7",
6399N/A+ "CAC Cert 8",
6399N/A+ "CAC Cert 9",
6399N/A+};
6399N/A+
6399N/A+static const char *PIV_Label[] = {
6399N/A+ "PIV ID Certificate",
6399N/A+ "PIV Email Signature Certificate",
6399N/A+ "PIV Email Encryption Certificate",
6399N/A+ "PIV Card Authentication Certificate",
6399N/A+ "PIV Cert 4",
6399N/A+ "PIV Cert 5",
6399N/A+ "PIV Cert 6",
6399N/A+ "PIV Cert 7",
6399N/A+ "PIV Cert 8",
6399N/A+ "PIV Cert 9",
6399N/A };
6399N/A
6399N/A static const unsigned char CN_DATA[] = { 0x55, 0x4, 0x3 };
6399N/A@@ -954,39 +1366,43 @@
6399N/A if (buf == NULL) return SECFailure;
6399N/A
6399N/A while (buf_length) {
6399N/A- const CKYByte *name;
6399N/A- unsigned int name_length;
6399N/A- const CKYByte *oid;
6399N/A- unsigned int oid_length;
6399N/A-
6399N/A- /* unwrap the set */
6399N/A- name = dataStart(buf, buf_length, &name_length, false);
6399N/A+ const CKYByte *name;
6399N/A+ unsigned int name_length;
6399N/A+ const CKYByte *oid;
6399N/A+ unsigned int oid_length;
6399N/A+
6399N/A+ /* unwrap the set */
6399N/A+ name = dataStart(buf, buf_length, &name_length, false);
6399N/A+ if (name == NULL) return SECFailure;
6399N/A
6399N/A /* advance to next set */
6399N/A- buf_length -= (name-buf) + name_length;
6399N/A- buf = name + name_length;
6399N/A+ buf_length -= (name-buf) + name_length;
6399N/A+ buf = name + name_length;
6399N/A
6399N/A- /* unwrap the Sequence */
6399N/A- name = dataStart(name, name_length, &name_length, false);
6399N/A+ /* unwrap the Sequence */
6399N/A+ name = dataStart(name, name_length, &name_length, false);
6399N/A+ if (name == NULL) return SECFailure;
6399N/A
6399N/A /* unwrap the oid */
6399N/A- oid = dataStart(name, name_length, &oid_length, false);
6399N/A+ oid = dataStart(name, name_length, &oid_length, false);
6399N/A+ if (oid == NULL) return SECFailure;
6399N/A
6399N/A- /* test the oid */
6399N/A- if (oid_length != CN_LENGTH) {
6399N/A- continue;
6399N/A- }
6399N/A- if (memcmp(oid, CN_DATA, CN_LENGTH) != 0) {
6399N/A- continue;
6399N/A- }
6399N/A+ /* test the oid */
6399N/A+ if (oid_length != CN_LENGTH) {
6399N/A+ continue;
6399N/A+ }
6399N/A+ if (memcmp(oid, CN_DATA, CN_LENGTH) != 0) {
6399N/A+ continue;
6399N/A+ }
6399N/A
6399N/A- /* advance to CN */
6399N/A- name_length -= (oid-name) + oid_length;
6399N/A- name = oid + oid_length;
6399N/A-
6399N/A- /* unwrap the CN */
6399N/A- cn->data = dataStart(name, name_length, &cn->len, false);
6399N/A- return SECSuccess;
6399N/A+ /* advance to CN */
6399N/A+ name_length -= (oid-name) + oid_length;
6399N/A+ name = oid + oid_length;
6399N/A+
6399N/A+ /* unwrap the CN */
6399N/A+ cn->data = dataStart(name, name_length, &cn->len, false);
6399N/A+ if (cn->data == NULL) return SECFailure;
6399N/A+ return SECSuccess;
6399N/A }
6399N/A return SECFailure;
6399N/A }
6399N/A@@ -1001,30 +1417,23 @@
6399N/A rv = GetCN(CKYBuffer_Data(dn), CKYBuffer_Size(dn) , &cn);
6399N/A
6399N/A if( rv != SECSuccess ) {
6399N/A- return NULL;
6399N/A+ return NULL;
6399N/A }
6399N/A string = new char [ cn.len + 1 ];
6399N/A if (string == NULL) {
6399N/A- return NULL;
6399N/A+ return NULL;
6399N/A }
6399N/A memcpy(string, cn.data, cn.len);
6399N/A string[cn.len] = 0;
6399N/A return string;
6399N/A }
6399N/A
6399N/A-CACCert::CACCert(CKYByte instance, const CKYBuffer *derCert) :
6399N/A- PKCS11Object( ((int)'c') << 24 | ((int)instance+'0') << 16,
6399N/A- instance | 0x600)
6399N/A+CACCert::CACCert(CKYByte instance, const CKYBuffer *derCert, bool isPIV) :
6399N/A+ PKCS11Object( ((int)'c') << 24 | ((int)instance+'0') << 16,
6399N/A+ instance | 0x600)
6399N/A {
6399N/A CKYBuffer id;
6399N/A CKYBuffer empty;
6399N/A- CK_BBOOL decrypt = FALSE;
6399N/A-
6399N/A- /* So we know what the key is supposed to be used for based on
6399N/A- * the instance */
6399N/A- if (instance == 2) {
6399N/A- decrypt = TRUE;
6399N/A- }
6399N/A
6399N/A CKYBuffer_InitEmpty(&empty);
6399N/A setAttributeULong(CKA_CLASS, CKO_CERTIFICATE);
6399N/A@@ -1036,7 +1445,7 @@
6399N/A setAttribute(CKA_ID, &id);
6399N/A CKYBuffer_FreeData(&id);
6399N/A setAttributeULong(CKA_CERTIFICATE_TYPE, CKC_X_509);
6399N/A- setAttribute(CKA_LABEL, CAC_Label[instance]);
6399N/A+ setAttribute(CKA_LABEL, isPIV ? PIV_Label[instance] : CAC_Label[instance]);
6399N/A
6399N/A CKYBuffer derSerial; CKYBuffer_InitEmpty(&derSerial);
6399N/A CKYBuffer derSubject; CKYBuffer_InitEmpty(&derSubject);
6399N/A@@ -1045,19 +1454,19 @@
6399N/A CKYBuffer_Resize(&pubKey,0);
6399N/A
6399N/A try {
6399N/A- setAttribute(CKA_VALUE, derCert);
6399N/A- // infer cert attributes
6399N/A+ setAttribute(CKA_VALUE, derCert);
6399N/A+ // infer cert attributes
6399N/A
6399N/A- GetCertFields(derCert, &derSerial, &derSubject, &derIssuer, &pubKey);
6399N/A+ GetCertFields(derCert, &derSerial, &derSubject, &derIssuer, &pubKey);
6399N/A
6399N/A- setAttribute(CKA_SERIAL_NUMBER, &derSerial);
6399N/A- setAttribute(CKA_SUBJECT, &derSubject);
6399N/A- setAttribute(CKA_ISSUER, &derIssuer);
6399N/A+ setAttribute(CKA_SERIAL_NUMBER, &derSerial);
6399N/A+ setAttribute(CKA_SUBJECT, &derSubject);
6399N/A+ setAttribute(CKA_ISSUER, &derIssuer);
6399N/A } catch (PKCS11Exception &e) {
6399N/A- CKYBuffer_FreeData(&derSerial);
6399N/A- CKYBuffer_FreeData(&derSubject);
6399N/A- CKYBuffer_FreeData(&derIssuer);
6399N/A- throw e;
6399N/A+ CKYBuffer_FreeData(&derSerial);
6399N/A+ CKYBuffer_FreeData(&derSubject);
6399N/A+ CKYBuffer_FreeData(&derIssuer);
6399N/A+ throw e;
6399N/A }
6399N/A
6399N/A name = GetUserName(&derSubject); /* adopt */
6399N/A@@ -1065,3 +1474,100 @@
6399N/A CKYBuffer_FreeData(&derSubject);
6399N/A CKYBuffer_FreeData(&derIssuer);
6399N/A }
6399N/A+
6399N/A+DEREncodedSignature::DEREncodedSignature(const CKYBuffer *derSig)
6399N/A+{
6399N/A+
6399N/A+ CKYBuffer_InitEmpty(&derEncodedSignature);
6399N/A+ CKYBuffer_InitFromCopy(&derEncodedSignature, derSig);
6399N/A+}
6399N/A+
6399N/A+DEREncodedSignature::~DEREncodedSignature()
6399N/A+{
6399N/A+ CKYBuffer_FreeData(&derEncodedSignature);
6399N/A+}
6399N/A+
6399N/A+int DEREncodedSignature::getRawSignature(CKYBuffer *rawSig,
6399N/A+ unsigned int keySize)
6399N/A+{
6399N/A+ const CKYByte *buf = NULL;
6399N/A+
6399N/A+ if (rawSig == NULL) {
6399N/A+ return -1;
6399N/A+ }
6399N/A+
6399N/A+ if (CKYBuffer_Size(&derEncodedSignature) == 0) {
6399N/A+ return -1;
6399N/A+ }
6399N/A+
6399N/A+ CKYBuffer_Zero(rawSig);
6399N/A+
6399N/A+ unsigned int seq_length = 0;
6399N/A+ unsigned int expected_sig_len = ( (keySize + 7) / 8 ) * 2 ;
6399N/A+ unsigned int expected_piece_size = expected_sig_len / 2 ;
6399N/A+
6399N/A+ /* unwrap the sequence */
6399N/A+ buf = dataStart(CKYBuffer_Data(&derEncodedSignature), CKYBuffer_Size(&derEncodedSignature),&seq_length, false);
6399N/A+
6399N/A+ if (buf == NULL) return -1;
6399N/A+
6399N/A+ // unwrap first multi byte integer
6399N/A+
6399N/A+ unsigned int int_length = 0;
6399N/A+ const CKYByte *int1Buf = NULL;
6399N/A+ const CKYByte *int2Buf = NULL;
6399N/A+
6399N/A+ int1Buf = dataStart(buf, seq_length, &int_length, false );
6399N/A+
6399N/A+ if (int1Buf == NULL) return -1;
6399N/A+ //advance to next entry
6399N/A+
6399N/A+ if (int_length > expected_piece_size) {
6399N/A+
6399N/A+ unsigned int diff = int_length - expected_piece_size ;
6399N/A+
6399N/A+ /* Make sure we are chopping off zeroes
6399N/A+ Otherwise give up. */
6399N/A+
6399N/A+ for (int i = 0 ; i < (int) diff ; i++) {
6399N/A+ if ( int1Buf[i] != 0)
6399N/A+ return -1;
6399N/A+ }
6399N/A+
6399N/A+ int_length -= diff;
6399N/A+ int1Buf += diff;
6399N/A+
6399N/A+ }
6399N/A+
6399N/A+ seq_length -= (int1Buf -buf) + int_length;
6399N/A+ buf = int1Buf + int_length;
6399N/A+
6399N/A+ // unwrap second multi byte integer
6399N/A+
6399N/A+ unsigned int second_int_length = 0;
6399N/A+
6399N/A+ int2Buf = dataStart(buf, seq_length, &second_int_length, false);
6399N/A+
6399N/A+ if (int2Buf == NULL) return -1;
6399N/A+
6399N/A+
6399N/A+ if (second_int_length > expected_piece_size) {
6399N/A+ unsigned int diff = second_int_length - expected_piece_size ;
6399N/A+
6399N/A+ /* Make sure we are chopping off zeroes
6399N/A+ Otherwise give up. */
6399N/A+
6399N/A+ for (int i = 0 ; i < (int) diff ; i++) {
6399N/A+ if ( int2Buf[i] != 0)
6399N/A+ return -1;
6399N/A+ }
6399N/A+
6399N/A+ second_int_length -= diff;
6399N/A+ int2Buf += diff;
6399N/A+ }
6399N/A+
6399N/A+ CKYBuffer_AppendData(rawSig, int1Buf, int_length);
6399N/A+ CKYBuffer_AppendData(rawSig, int2Buf, second_int_length);
6399N/A+
6399N/A+ return CKYSUCCESS;
6399N/A+}