/*** *** Issuer Name, Subject Name (encoded, NON-normalized version) *** Format = CSSM_DATA containing the DER encoding of the name ***/ static bool getFieldSubjectStd( DecodedItem &item, unsigned index, // which occurrence (0 = first) uint32 &numFields, // RETURNED CssmOwnedData &fieldValue) // RETURNED { if(index != 0) { return false; } const DecodedCert &cert = dynamic_cast<const DecodedCert &>(item); fieldValue.copy(cert.mCert.tbs.derSubject); numFields = 1; return true; }
/*** *** Signature *** Format = raw bytes *** read-only ***/ static bool getField_Signature ( DecodedItem &item, unsigned index, // which occurrence (0 = first) uint32 &numFields, // RETURNED CssmOwnedData &fieldValue) // RETURNED { const DecodedCert &cert = dynamic_cast<const DecodedCert &>(item); const CSSM_DATA &sigBits = cert.mCert.signature; if(!tbsGetCheck(sigBits.Data, index)) { return false; } fieldValue.copy(sigBits.Data, (sigBits.Length + 7) / 8); numFields = 1; return true; }
/*** *** Serial Number *** Format = DER-encoded int, variable length ***/ static bool getField_SerialNumber ( DecodedItem &item, unsigned index, // which occurrence (0 = first) uint32 &numFields, // RETURNED CssmOwnedData &fieldValue) // RETURNED { const DecodedCert &cert = dynamic_cast<const DecodedCert &>(item); const CSSM_DATA &sn = cert.mCert.tbs.serialNumber; if(!tbsGetCheck(sn.Data, index)) { return false; } fieldValue.copy(sn.Data, sn.Length); numFields = 1; return true; }
/*** *** key info from CSSM_KEY *** Format = CSSM_KEY ***/ static bool getField_PublicKeyStruct ( DecodedItem &item, unsigned index, // which occurrence (0 = first) uint32 &numFields, // RETURNED CssmOwnedData &fieldValue) // RETURNED { const DecodedCert &cert = dynamic_cast<const DecodedCert &>(item); if(!tbsGetCheck(cert.mCert.tbs.subjectPublicKeyInfo.subjectPublicKey.Data, index)) { return false; } CSSM_KEY_PTR cssmKey = cert.extractCSSMKey(fieldValue.allocator); fieldValue.set(reinterpret_cast<uint8 *>(cssmKey), sizeof(CSSM_KEY)); numFields = 1; return true; }
/*** *** Version *** Format = DER-encoded int (max of four bytes in this case) ***/ static bool getField_Version ( DecodedItem &item, unsigned index, // which occurrence (0 = first) uint32 &numFields, // RETURNED CssmOwnedData &fieldValue) // RETURNED { const DecodedCert &cert = dynamic_cast<const DecodedCert &>(item); const CSSM_DATA &vers = cert.mCert.tbs.version; if(!tbsGetCheck(vers.Data, index)) { /* not present, optional */ return false; } fieldValue.copy(vers.Data, vers.Length); numFields = 1; return true; }
static bool getField_IssuerUniqueId ( DecodedItem &item, unsigned index, // which occurrence (0 = first) uint32 &numFields, // RETURNED CssmOwnedData &fieldValue) // RETURNED { const DecodedCert &cert = dynamic_cast<const DecodedCert &>(item); const CSSM_DATA &srcBits = cert.mCert.tbs.issuerID; if(!tbsGetCheck(srcBits.Data, index)) { return false; } /* That CSSM_DATA is a decoded BITSTRING; its length is in bits */ CSSM_DATA tmp = srcBits; tmp.Length = (tmp.Length + 7) / 8; fieldValue.copy(tmp.Data, tmp.Length); numFields = 1; return true; }
static void freeField_PublicKeyStruct ( CssmOwnedData &fieldValue) { CSSM_KEY_PTR cssmKey = (CSSM_KEY_PTR)fieldValue.data(); CL_freeCSSMKey(cssmKey, fieldValue.allocator, false); }
/* * Infer DescriptiveData (i.e., comment) from a SecKeyRef's PrintName * attribute. */ void impExpOpensshInferDescData( SecKeyRef keyRef, CssmOwnedData &descData) { OSStatus ortn; SecKeychainAttributeInfo attrInfo; SecKeychainAttrType attrType = kSecKeyPrintName; attrInfo.count = 1; attrInfo.tag = &attrType; attrInfo.format = NULL; SecKeychainAttributeList *attrList = NULL; ortn = SecKeychainItemCopyAttributesAndData( (SecKeychainItemRef)keyRef, &attrInfo, NULL, // itemClass &attrList, NULL, // don't need the data NULL); if(ortn) { SecSSHDbg("SecKeychainItemCopyAttributesAndData returned %ld", (unsigned long)ortn); return; } /* subsequent errors to errOut: */ SecKeychainAttribute *attr = attrList->attr; /* * On a previous import, we would have set this to something like * "OpenSSHv2 Public Key: comment". * We want to strip off everything up to the actual comment. */ unsigned toStrip = 0; /* min length of attribute value for this code to be meaningful */ unsigned len = strlen(SSHv2_PUB_KEY_NAME) + 1; char *printNameStr = NULL; if(len < attr->length) { printNameStr = (char *)malloc(attr->length + 1); memmove(printNameStr, attr->data, attr->length); printNameStr[attr->length] = '\0'; if(strstr(printNameStr, SSHv2_PUB_KEY_NAME) == printNameStr) { toStrip = strlen(SSHv2_PUB_KEY_NAME); } else if(strstr(printNameStr, SSHv1_PUB_KEY_NAME) == printNameStr) { toStrip = strlen(SSHv1_PUB_KEY_NAME); } else if(strstr(printNameStr, SSHv1_PRIV_KEY_NAME) == printNameStr) { toStrip = strlen(SSHv1_PRIV_KEY_NAME); } if(toStrip) { /* only strip if we have ": " after toStrip bytes */ if((printNameStr[toStrip] == ':') && (printNameStr[toStrip+1] == ' ')) { toStrip += 2; } } } if(printNameStr) { free(printNameStr); } len = attr->length; unsigned char *attrVal; if(len < toStrip) { SecSSHDbg("impExpOpensshInferDescData: string parse screwup"); goto errOut; } if(len > toStrip) { /* Normal case of stripping off leading header */ len -= toStrip; } else { /* * If equal, then the attr value *is* "OpenSSHv2 Public Key: " with * no comment. Not sure how that could happen, but let's be careful. */ toStrip = 0; } attrVal = ((unsigned char *)attr->data) + toStrip; descData.copy(attrVal, len); errOut: SecKeychainItemFreeAttributesAndData(attrList, NULL); return; }