void CL_certCrlDecodeComponents( const CssmData &signedItem, // DER-encoded cert or CRL CssmOwnedData &tbsBlob, // still DER-encoded CssmOwnedData &algId, // ditto CssmOwnedData &rawSig) // raw bits (not an encoded AsnBits) { /* BER-decode into temp memory */ NSS_SignedCertOrCRL nssObj; SecNssCoder coder; PRErrorCode prtn; memset(&nssObj, 0, sizeof(nssObj)); prtn = coder.decode(signedItem.data(), signedItem.length(), kSecAsn1SignedCertOrCRLTemplate, &nssObj); if(prtn) { CssmError::throwMe(CSSMERR_CL_UNKNOWN_FORMAT); } /* tbsBlob and algId are raw ASN_ANY including tags, which we pass * back to caller intact */ tbsBlob.copy(nssObj.tbsBlob.Data, nssObj.tbsBlob.Length); algId.copy(nssObj.signatureAlgorithm.Data, nssObj.signatureAlgorithm.Length); /* signature is a bit string which we do in fact decode */ rawSig.copy(nssObj.signature.Data, (nssObj.signature.Length + 7) / 8); }
static bool getFieldIssuerStd( 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.derIssuer); 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; }
/*** *** 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; }
/* * 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; }