/** Decode the content of the octet string value if known. */ static int rtCrSpcSerializedObject_DecodeMore(PRTASN1CURSOR pCursor, uint32_t fFlags, PRTCRSPCSERIALIZEDOBJECT pThis, const char *pszErrorTag) { RT_NOREF_PV(fFlags); RT_NOREF_PV(pszErrorTag); int rc; RTASN1CURSOR SubCursor; if (RTUuidCompareStr(pThis->Uuid.Asn1Core.uData.pUuid, RTCRSPCSERIALIZEDOBJECT_UUID_STR) == 0) { rc = RTAsn1MemAllocZ(&pThis->SerializedData.EncapsulatedAllocation, (void **)&pThis->u.pData, sizeof(*pThis->u.pData)); if (RT_SUCCESS(rc)) { pThis->SerializedData.pEncapsulated = (PRTASN1CORE)pThis->u.pData; pThis->enmType = RTCRSPCSERIALIZEDOBJECTTYPE_ATTRIBUTES; rc = RTAsn1CursorInitSubFromCore(pCursor, &pThis->SerializedData.Asn1Core, &SubCursor, "SerializedData"); if (RT_SUCCESS(rc)) rc = RTCrSpcSerializedObjectAttributes_DecodeAsn1(&SubCursor, 0, pThis->u.pData, "SD"); } } else return VINF_SUCCESS; if (RT_SUCCESS(rc)) rc = RTAsn1CursorCheckEnd(&SubCursor); return rc; }
RTDECL(int) RTAsn1ObjId_DecodeAsn1(PRTASN1CURSOR pCursor, uint32_t fFlags, PRTASN1OBJID pThis, const char *pszErrorTag) { int rc = RTAsn1CursorReadHdr(pCursor, &pThis->Asn1Core, pszErrorTag); if (RT_SUCCESS(rc)) { rc = RTAsn1CursorMatchTagClassFlags(pCursor, &pThis->Asn1Core, ASN1_TAG_OID, ASN1_TAGCLASS_UNIVERSAL | ASN1_TAGFLAG_PRIMITIVE, fFlags, pszErrorTag, "OID"); if (RT_SUCCESS(rc)) { /* * Validate and count things first. */ uint8_t cComponents = 0; /* gcc maybe-crap */ uint8_t cchObjId = 0; /* ditto */ rc = rtAsn1ObjId_PreParse(pCursor->pbCur, pThis->Asn1Core.cb, pCursor, pszErrorTag, &cComponents, &cchObjId); if (RT_SUCCESS(rc)) { /* * Allocate memory for the components array, either out of the * string buffer or off the heap. */ pThis->cComponents = cComponents; RTAsn1CursorInitAllocation(pCursor, &pThis->Allocation); #if 0 /** @todo breaks with arrays of ObjIds or structs containing them. They get resized and repositioned in memory, thus invalidating the pointer. Add recall-pointers callback, or just waste memory? Or maybe make all arrays pointer-arrays? */ if (cComponents * sizeof(uint32_t) <= sizeof(pThis->szObjId) - cchObjId - 1) pThis->pauComponents = (uint32_t *)&pThis->szObjId[sizeof(pThis->szObjId) - cComponents * sizeof(uint32_t)]; else #endif rc = RTAsn1MemAllocZ(&pThis->Allocation, (void **)&pThis->pauComponents, cComponents * sizeof(pThis->pauComponents[0])); if (RT_SUCCESS(rc)) { uint32_t *pauComponents = (uint32_t *)pThis->pauComponents; /* * Deal with the two first components first since they are * encoded in a weird way to save a byte. */ uint8_t const *pbContent = pCursor->pbCur; uint32_t cbContent = pThis->Asn1Core.cb; uint32_t uValue; rc = rtAsn1ObjId_ReadComponent(pbContent, cbContent, &uValue); AssertRC(rc); if (RT_SUCCESS(rc)) { pbContent += rc; cbContent -= rc; if (uValue < 80) { pauComponents[0] = uValue / 40; pauComponents[1] = uValue % 40; } else { pauComponents[0] = 2; pauComponents[1] = uValue - 2*40; } char *pszObjId = &pThis->szObjId[0]; *pszObjId++ = g_achDigits[pauComponents[0]]; size_t cbObjIdLeft = cchObjId + 1 - 1; rc = rtAsn1ObjId_InternalFormatComponent(pauComponents[1], &pszObjId, &cbObjIdLeft); AssertRC(rc); if (RT_SUCCESS(rc)) { /* * The other components are encoded in less complicated manner. */ for (uint32_t i = 2; i < cComponents; i++) { rc = rtAsn1ObjId_ReadComponent(pbContent, cbContent, &uValue); AssertRCBreak(rc); pbContent += rc; cbContent -= rc; pauComponents[i] = uValue; rc = rtAsn1ObjId_InternalFormatComponent(uValue, &pszObjId, &cbObjIdLeft); AssertRCBreak(rc); } if (RT_SUCCESS(rc)) { Assert(cbObjIdLeft == 1); *pszObjId = '\0'; RTAsn1CursorSkip(pCursor, pThis->Asn1Core.cb); pThis->Asn1Core.fFlags |= RTASN1CORE_F_PRIMITE_TAG_STRUCT; pThis->Asn1Core.pOps = &g_RTAsn1ObjId_Vtable; return VINF_SUCCESS; } } } } } } } RT_ZERO(*pThis); return rc; }
static int rtCrPkcs7ContentInfo_DecodeExtra(PRTASN1CURSOR pCursor, uint32_t fFlags, PRTCRPKCS7CONTENTINFO pThis, const char *pszErrorTag) { pThis->u.pCore = NULL; /* * Figure the type. */ RTCRPKCS7CONTENTINFOCHOICE enmChoice; size_t cbContent = 0; if (RTAsn1ObjId_CompareWithString(&pThis->ContentType, RTCRPKCS7SIGNEDDATA_OID) == 0) { enmChoice = RTCRPKCS7CONTENTINFOCHOICE_SIGNED_DATA; cbContent = sizeof(*pThis->u.pSignedData); } else if (RTAsn1ObjId_CompareWithString(&pThis->ContentType, RTCRSPCINDIRECTDATACONTENT_OID) == 0) { enmChoice = RTCRPKCS7CONTENTINFOCHOICE_SPC_INDIRECT_DATA_CONTENT; cbContent = sizeof(*pThis->u.pIndirectDataContent); } else if (RTAsn1ObjId_CompareWithString(&pThis->ContentType, RTCRTSPTSTINFO_OID) == 0) { enmChoice = RTCRPKCS7CONTENTINFOCHOICE_TSP_TST_INFO; cbContent = sizeof(*pThis->u.pTstInfo); } else { enmChoice = RTCRPKCS7CONTENTINFOCHOICE_UNKNOWN; cbContent = 0; } int rc = VINF_SUCCESS; if (enmChoice != RTCRPKCS7CONTENTINFOCHOICE_UNKNOWN) { /* * Detect CMS octet string and open the content cursor. * Current we don't have work with any contet which is octet string, * they're all sequences, which make detection so much simpler. */ PRTASN1OCTETSTRING pOctetString = &pThis->Content; RTASN1CURSOR ContentCursor; rc = RTAsn1CursorInitSubFromCore(pCursor, &pThis->Content.Asn1Core, &ContentCursor, "Content"); if ( RT_SUCCESS(rc) && RTAsn1CursorIsNextEx(&ContentCursor, ASN1_TAG_OCTET_STRING, ASN1_TAGFLAG_PRIMITIVE | ASN1_TAGCLASS_UNIVERSAL)) { rc = RTAsn1MemAllocZ(&pThis->Content.EncapsulatedAllocation, (void **)&pThis->Content.pEncapsulated, sizeof(*pOctetString)); if (RT_SUCCESS(rc)) { pThis->pCmsContent = pOctetString = (PRTASN1OCTETSTRING)pThis->Content.pEncapsulated; rc = RTAsn1OctetString_DecodeAsn1(&ContentCursor, 0, pOctetString, "CmsContent"); if (RT_SUCCESS(rc)) rc = RTAsn1CursorCheckEnd(&ContentCursor); if (RT_SUCCESS(rc)) rc = RTAsn1CursorInitSubFromCore(pCursor, &pOctetString->Asn1Core, &ContentCursor, "CmsContent"); } } if (RT_SUCCESS(rc)) { /* * Allocate memory for the decoded content. */ rc = RTAsn1MemAllocZ(&pOctetString->EncapsulatedAllocation, (void **)&pOctetString->pEncapsulated, cbContent); if (RT_SUCCESS(rc)) { pThis->u.pCore = pOctetString->pEncapsulated; /* * Decode it. */ switch (enmChoice) { case RTCRPKCS7CONTENTINFOCHOICE_SIGNED_DATA: rc = RTCrPkcs7SignedData_DecodeAsn1(&ContentCursor, 0, pThis->u.pSignedData, "SignedData"); break; case RTCRPKCS7CONTENTINFOCHOICE_SPC_INDIRECT_DATA_CONTENT: rc = RTCrSpcIndirectDataContent_DecodeAsn1(&ContentCursor, 0, pThis->u.pIndirectDataContent, "IndirectDataContent"); break; case RTCRPKCS7CONTENTINFOCHOICE_TSP_TST_INFO: rc = RTCrTspTstInfo_DecodeAsn1(&ContentCursor, 0, pThis->u.pTstInfo, "TstInfo"); break; default: AssertFailed(); rc = VERR_IPE_NOT_REACHED_DEFAULT_CASE; break; } if (RT_SUCCESS(rc)) rc = RTAsn1CursorCheckEnd(&ContentCursor); if (RT_SUCCESS(rc)) return VINF_SUCCESS; RTAsn1MemFree(&pOctetString->EncapsulatedAllocation, pOctetString->pEncapsulated); pOctetString->pEncapsulated = NULL; pThis->u.pCore = NULL; } } } return rc; }
/* * One X.509 Extension. */ RTDECL(int) RTCrX509Extension_ExtnValue_DecodeAsn1(PRTASN1CURSOR pCursor, uint32_t fFlags, PRTCRX509EXTENSION pThis, const char *pszErrorTag) { pThis->enmValue = RTCRX509EXTENSIONVALUE_UNKNOWN; /* * Decode the encapsulated extension bytes if know the format. */ RTASN1CURSOR ValueCursor; int rc = RTAsn1CursorInitSubFromCore(pCursor, &pThis->ExtnValue.Asn1Core, &ValueCursor, "ExtnValue"); if (RT_FAILURE(rc)) return rc; pCursor = &ValueCursor; if (RTAsn1ObjId_CompareWithString(&pThis->ExtnId, RTCRX509_ID_CE_AUTHORITY_KEY_IDENTIFIER_OID) == 0) { /* 4.2.1.1 Authority Key Identifier */ PRTCRX509AUTHORITYKEYIDENTIFIER pThat; rc = RTAsn1MemAllocZ(&pThis->ExtnValue.EncapsulatedAllocation, (void **)&pThat, sizeof(*pThat)); if (RT_SUCCESS(rc)) { pThis->ExtnValue.pEncapsulated = &pThat->SeqCore.Asn1Core; pThis->enmValue = RTCRX509EXTENSIONVALUE_AUTHORITY_KEY_IDENTIFIER; rc = RTCrX509AuthorityKeyIdentifier_DecodeAsn1(&ValueCursor, 0, pThat, "AuthorityKeyIdentifier"); } } else if (RTAsn1ObjId_CompareWithString(&pThis->ExtnId, RTCRX509_ID_CE_OLD_AUTHORITY_KEY_IDENTIFIER_OID) == 0) { /* Old and obsolete version of the above, still found in microsoft certificates. */ PRTCRX509OLDAUTHORITYKEYIDENTIFIER pThat; rc = RTAsn1MemAllocZ(&pThis->ExtnValue.EncapsulatedAllocation, (void **)&pThat, sizeof(*pThat)); if (RT_SUCCESS(rc)) { pThis->ExtnValue.pEncapsulated = &pThat->SeqCore.Asn1Core; pThis->enmValue = RTCRX509EXTENSIONVALUE_OLD_AUTHORITY_KEY_IDENTIFIER; rc = RTCrX509OldAuthorityKeyIdentifier_DecodeAsn1(&ValueCursor, 0, pThat, "OldAuthorityKeyIdentifier"); } } else if (RTAsn1ObjId_CompareWithString(&pThis->ExtnId, RTCRX509_ID_CE_SUBJECT_KEY_IDENTIFIER_OID) == 0) { /* 4.2.1.2 Subject Key Identifier */ PRTASN1OCTETSTRING pThat; rc = RTAsn1MemAllocZ(&pThis->ExtnValue.EncapsulatedAllocation, (void **)&pThat, sizeof(*pThat)); if (RT_SUCCESS(rc)) { pThis->ExtnValue.pEncapsulated = &pThat->Asn1Core; pThis->enmValue = RTCRX509EXTENSIONVALUE_OCTET_STRING; rc = RTAsn1CursorGetOctetString(&ValueCursor, 0, pThat, "SubjectKeyIdentifier"); } } else if (RTAsn1ObjId_CompareWithString(&pThis->ExtnId, RTCRX509_ID_CE_KEY_USAGE_OID) == 0) { /* 4.2.1.3 Key Usage */ PRTASN1BITSTRING pThat; rc = RTAsn1MemAllocZ(&pThis->ExtnValue.EncapsulatedAllocation, (void **)&pThat, sizeof(*pThat)); if (RT_SUCCESS(rc)) { pThis->ExtnValue.pEncapsulated = &pThat->Asn1Core; pThis->enmValue = RTCRX509EXTENSIONVALUE_BIT_STRING; rc = RTAsn1CursorGetBitStringEx(&ValueCursor, 0, 9, pThat, "KeyUsage"); } } else if (RTAsn1ObjId_CompareWithString(&pThis->ExtnId, RTCRX509_ID_CE_CERTIFICATE_POLICIES_OID) == 0) { /* 4.2.1.4 Certificate Policies */ PRTCRX509CERTIFICATEPOLICIES pThat; rc = RTAsn1MemAllocZ(&pThis->ExtnValue.EncapsulatedAllocation, (void **)&pThat, sizeof(*pThat)); if (RT_SUCCESS(rc)) { pThis->ExtnValue.pEncapsulated = &pThat->SeqCore.Asn1Core; pThis->enmValue = RTCRX509EXTENSIONVALUE_CERTIFICATE_POLICIES; rc = RTCrX509CertificatePolicies_DecodeAsn1(&ValueCursor, 0, pThat, "CertPolicies"); } } else if (RTAsn1ObjId_CompareWithString(&pThis->ExtnId, RTCRX509_ID_CE_POLICY_MAPPINGS_OID) == 0) { /* 4.2.1.5 Policy Mappings */ PRTCRX509POLICYMAPPINGS pThat; rc = RTAsn1MemAllocZ(&pThis->ExtnValue.EncapsulatedAllocation, (void **)&pThat, sizeof(*pThat)); if (RT_SUCCESS(rc)) { pThis->ExtnValue.pEncapsulated = &pThat->SeqCore.Asn1Core; pThis->enmValue = RTCRX509EXTENSIONVALUE_POLICY_MAPPINGS; rc = RTCrX509PolicyMappings_DecodeAsn1(&ValueCursor, 0, pThat, "PolicyMapppings"); } } else if ( RTAsn1ObjId_CompareWithString(&pThis->ExtnId, RTCRX509_ID_CE_SUBJECT_ALT_NAME_OID) == 0 || RTAsn1ObjId_CompareWithString(&pThis->ExtnId, RTCRX509_ID_CE_ISSUER_ALT_NAME_OID) == 0) { /* 4.2.1.6 Subject Alternative Name / 4.2.1.7 Issuer Alternative Name */ PRTCRX509GENERALNAMES pThat; rc = RTAsn1MemAllocZ(&pThis->ExtnValue.EncapsulatedAllocation, (void **)&pThat, sizeof(*pThat)); if (RT_SUCCESS(rc)) { pThis->ExtnValue.pEncapsulated = &pThat->SeqCore.Asn1Core; pThis->enmValue = RTCRX509EXTENSIONVALUE_GENERAL_NAMES; rc = RTCrX509GeneralNames_DecodeAsn1(&ValueCursor, 0, pThat, "AltName"); } } else if (RTAsn1ObjId_CompareWithString(&pThis->ExtnId, RTCRX509_ID_CE_BASIC_CONSTRAINTS_OID) == 0) { /* 4.2.1.9 Basic Constraints */ PRTCRX509BASICCONSTRAINTS pThat; rc = RTAsn1MemAllocZ(&pThis->ExtnValue.EncapsulatedAllocation, (void **)&pThat, sizeof(*pThat)); if (RT_SUCCESS(rc)) { pThis->ExtnValue.pEncapsulated = &pThat->SeqCore.Asn1Core; pThis->enmValue = RTCRX509EXTENSIONVALUE_BASIC_CONSTRAINTS; rc = RTCrX509BasicConstraints_DecodeAsn1(&ValueCursor, 0, pThat, "BasicConstraints"); } } else if (RTAsn1ObjId_CompareWithString(&pThis->ExtnId, RTCRX509_ID_CE_NAME_CONSTRAINTS_OID) == 0) { /* 4.2.1.10 Name Constraints */ PRTCRX509NAMECONSTRAINTS pThat; rc = RTAsn1MemAllocZ(&pThis->ExtnValue.EncapsulatedAllocation, (void **)&pThat, sizeof(*pThat)); if (RT_SUCCESS(rc)) { pThis->ExtnValue.pEncapsulated = &pThat->SeqCore.Asn1Core; pThis->enmValue = RTCRX509EXTENSIONVALUE_NAME_CONSTRAINTS; rc = RTCrX509NameConstraints_DecodeAsn1(&ValueCursor, 0, pThat, "NameConstraints"); } } else if (RTAsn1ObjId_CompareWithString(&pThis->ExtnId, RTCRX509_ID_CE_POLICY_CONSTRAINTS_OID) == 0) { /* 4.2.1.11 Policy Constraints */ PRTCRX509POLICYCONSTRAINTS pThat; rc = RTAsn1MemAllocZ(&pThis->ExtnValue.EncapsulatedAllocation, (void **)&pThat, sizeof(*pThat)); if (RT_SUCCESS(rc)) { pThis->ExtnValue.pEncapsulated = &pThat->SeqCore.Asn1Core; pThis->enmValue = RTCRX509EXTENSIONVALUE_POLICY_CONSTRAINTS; rc = RTCrX509PolicyConstraints_DecodeAsn1(&ValueCursor, 0, pThat, "PolicyConstraints"); } } else if (RTAsn1ObjId_CompareWithString(&pThis->ExtnId, RTCRX509_ID_CE_EXT_KEY_USAGE_OID) == 0) { /* 4.2.1.12 Extended Key Usage */ PRTASN1SEQOFOBJIDS pThat; rc = RTAsn1MemAllocZ(&pThis->ExtnValue.EncapsulatedAllocation, (void **)&pThat, sizeof(*pThat)); if (RT_SUCCESS(rc)) { pThis->ExtnValue.pEncapsulated = &pThat->SeqCore.Asn1Core; pThis->enmValue = RTCRX509EXTENSIONVALUE_SEQ_OF_OBJ_IDS; rc = RTAsn1SeqOfObjIds_DecodeAsn1(&ValueCursor, 0, pThat, "ExKeyUsage"); } } else if (RTAsn1ObjId_CompareWithString(&pThis->ExtnId, RTCRX509_ID_CE_EXT_KEY_USAGE_OID) == 0) { /* 4.2.1.14 Inhibit anyPolicy */ PRTASN1INTEGER pThat; rc = RTAsn1MemAllocZ(&pThis->ExtnValue.EncapsulatedAllocation, (void **)&pThat, sizeof(*pThat)); if (RT_SUCCESS(rc)) { pThis->ExtnValue.pEncapsulated = &pThat->Asn1Core; pThis->enmValue = RTCRX509EXTENSIONVALUE_INTEGER; rc = RTAsn1CursorGetInteger(&ValueCursor, 0, pThat, "InhibitAnyPolicy"); } } else return VINF_SUCCESS; if (RT_SUCCESS(rc)) rc = RTAsn1CursorCheckEnd(&ValueCursor); if (RT_SUCCESS(rc)) return VINF_SUCCESS; return rc; }