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; }
RTDECL(int) RTAsn1DynType_DecodeAsn1(PRTASN1CURSOR pCursor, uint32_t fFlags, PRTASN1DYNTYPE pDynType, const char *pszErrorTag) { RT_ZERO(*pDynType); Assert(!(fFlags & RTASN1CURSOR_GET_F_IMPLICIT)); RT_NOREF_PV(fFlags); uint32_t cbSavedLeft = pCursor->cbLeft; uint8_t const *pbSavedCur = pCursor->pbCur; int rc = RTAsn1CursorReadHdr(pCursor, &pDynType->u.Core, pszErrorTag); if (RT_SUCCESS(rc)) { pDynType->enmType = RTASN1TYPE_CORE; if (pDynType->u.Core.fClass == (ASN1_TAGCLASS_UNIVERSAL | ASN1_TAGFLAG_PRIMITIVE)) { switch (pDynType->u.Core.uTag) { case ASN1_TAG_BOOLEAN: pDynType->enmType = RTASN1TYPE_BOOLEAN; break; case ASN1_TAG_INTEGER: pDynType->enmType = RTASN1TYPE_INTEGER; break; //case ASN1_TAG_ENUMERATED: // pDynType->enmType = RTASN1TYPE_ENUMERATED; // break; //case ASN1_TAG_REAL: // pDynType->enmType = RTASN1TYPE_REAL; // break; case ASN1_TAG_BIT_STRING: pDynType->enmType = RTASN1TYPE_BIT_STRING; break; case ASN1_TAG_OCTET_STRING: pDynType->enmType = RTASN1TYPE_OCTET_STRING; break; case ASN1_TAG_NULL: pDynType->enmType = RTASN1TYPE_NULL; break; case ASN1_TAG_SEQUENCE: RT_ZERO(*pDynType); return RTAsn1CursorSetInfo(pCursor, VERR_ASN1_DYNTYPE_BAD_TAG, "ASN.1 SEQUENCE shall be constructed."); case ASN1_TAG_SET: RT_ZERO(*pDynType); return RTAsn1CursorSetInfo(pCursor, VERR_ASN1_DYNTYPE_BAD_TAG, "ASN.1 SET shall be constructed."); case ASN1_TAG_OID: pDynType->enmType = RTASN1TYPE_OBJID; break; //case ASN1_TAG_RELATIVE_OID: // pDynType->enmType = RTASN1TYPE_RELATIVE_OBJID; // break; case ASN1_TAG_UTC_TIME: case ASN1_TAG_GENERALIZED_TIME: pDynType->enmType = RTASN1TYPE_TIME; break; case ASN1_TAG_UTF8_STRING: case ASN1_TAG_NUMERIC_STRING: case ASN1_TAG_PRINTABLE_STRING: case ASN1_TAG_T61_STRING: case ASN1_TAG_VIDEOTEX_STRING: case ASN1_TAG_IA5_STRING: case ASN1_TAG_GRAPHIC_STRING: case ASN1_TAG_VISIBLE_STRING: case ASN1_TAG_UNIVERSAL_STRING: case ASN1_TAG_GENERAL_STRING: case ASN1_TAG_BMP_STRING: pDynType->enmType = RTASN1TYPE_STRING; break; //case ASN1_TAG_CHARACTER_STRING: // pDynType->enmType = RTASN1TYPE_CHARACTER_STRING; // break; default: RT_ZERO(*pDynType); return RTAsn1CursorSetInfo(pCursor, VERR_ASN1_DYNTYPE_TAG_NOT_IMPL, "Primitive tag %u (%#x) not implemented.", pDynType->u.Core.uTag, pDynType->u.Core.uTag); } } else if (pDynType->u.Core.fClass == (ASN1_TAGCLASS_UNIVERSAL | ASN1_TAGFLAG_CONSTRUCTED)) switch (pDynType->u.Core.uTag) { case ASN1_TAG_BOOLEAN: RT_ZERO(*pDynType); return RTAsn1CursorSetInfo(pCursor, VERR_ASN1_DYNTYPE_BAD_TAG, "ASN.1 BOOLEAN shall be primitive."); case ASN1_TAG_INTEGER: RT_ZERO(*pDynType); return RTAsn1CursorSetInfo(pCursor, VERR_ASN1_DYNTYPE_BAD_TAG, "ASN.1 BOOLEAN shall be primitive."); case ASN1_TAG_ENUMERATED: RT_ZERO(*pDynType); return RTAsn1CursorSetInfo(pCursor, VERR_ASN1_DYNTYPE_BAD_TAG, "ASN.1 ENUMERATED shall be primitive."); case ASN1_TAG_REAL: RT_ZERO(*pDynType); return RTAsn1CursorSetInfo(pCursor, VERR_ASN1_DYNTYPE_BAD_TAG, "ASN.1 REAL shall be primitive."); case ASN1_TAG_BIT_STRING: pDynType->enmType = RTASN1TYPE_BIT_STRING; break; case ASN1_TAG_OCTET_STRING: pDynType->enmType = RTASN1TYPE_OCTET_STRING; break; case ASN1_TAG_NULL: RT_ZERO(*pDynType); return RTAsn1CursorSetInfo(pCursor, VERR_ASN1_DYNTYPE_BAD_TAG, "ASN.1 NULL shall be primitive."); case ASN1_TAG_SEQUENCE: #if 0 pDynType->enmType = RTASN1TYPE_SEQUENCE_CORE; pDynType->u.SeqCore.Asn1Core.fFlags |= RTASN1CORE_F_PRIMITE_TAG_STRUCT; RTAsn1CursorSkip(pCursor, pDynType->u.Core.cb); return VINF_SUCCESS; #else pDynType->enmType = RTASN1TYPE_CORE; #endif break; case ASN1_TAG_SET: #if 0 pDynType->enmType = RTASN1TYPE_SET_CORE; pDynType->u.SeqCore.Asn1Core.fFlags |= RTASN1CORE_F_PRIMITE_TAG_STRUCT; RTAsn1CursorSkip(pCursor, pDynType->u.Core.cb); return VINF_SUCCESS; #else pDynType->enmType = RTASN1TYPE_CORE; #endif break; case ASN1_TAG_OID: RT_ZERO(*pDynType); return RTAsn1CursorSetInfo(pCursor, VERR_ASN1_DYNTYPE_BAD_TAG, "ASN.1 OBJECT ID shall be primitive."); case ASN1_TAG_RELATIVE_OID: RT_ZERO(*pDynType); return RTAsn1CursorSetInfo(pCursor, VERR_ASN1_DYNTYPE_BAD_TAG, "ASN.1 RELATIVE OID shall be primitive."); case ASN1_TAG_UTF8_STRING: case ASN1_TAG_NUMERIC_STRING: case ASN1_TAG_PRINTABLE_STRING: case ASN1_TAG_T61_STRING: case ASN1_TAG_VIDEOTEX_STRING: case ASN1_TAG_IA5_STRING: case ASN1_TAG_GRAPHIC_STRING: case ASN1_TAG_VISIBLE_STRING: case ASN1_TAG_UNIVERSAL_STRING: case ASN1_TAG_GENERAL_STRING: case ASN1_TAG_BMP_STRING: pDynType->enmType = RTASN1TYPE_STRING; break; //case ASN1_TAG_CHARACTER_STRING: // pDynType->enmType = RTASN1TYPE_CHARACTER_STRING; // break; default: RT_ZERO(*pDynType); return RTAsn1CursorSetInfo(pCursor, VERR_ASN1_DYNTYPE_TAG_NOT_IMPL, "Constructed tag %u (%#x) not implemented.", pDynType->u.Core.uTag, pDynType->u.Core.uTag); } else { RTAsn1CursorSkip(pCursor, pDynType->u.Core.cb); return VINF_SUCCESS; } /* * Restore the cursor and redo with specific type. */ pCursor->pbCur = pbSavedCur; pCursor->cbLeft = cbSavedLeft; switch (pDynType->enmType) { case RTASN1TYPE_INTEGER: rc = RTAsn1Integer_DecodeAsn1(pCursor, 0, &pDynType->u.Integer, pszErrorTag); break; case RTASN1TYPE_BOOLEAN: rc = RTAsn1Boolean_DecodeAsn1(pCursor, 0, &pDynType->u.Boolean, pszErrorTag); break; case RTASN1TYPE_OBJID: rc = RTAsn1ObjId_DecodeAsn1(pCursor, 0, &pDynType->u.ObjId, pszErrorTag); break; case RTASN1TYPE_BIT_STRING: rc = RTAsn1BitString_DecodeAsn1(pCursor, 0, &pDynType->u.BitString, pszErrorTag); break; case RTASN1TYPE_OCTET_STRING: rc = RTAsn1OctetString_DecodeAsn1(pCursor, 0, &pDynType->u.OctetString, pszErrorTag); break; case RTASN1TYPE_NULL: rc = RTAsn1Null_DecodeAsn1(pCursor, 0, &pDynType->u.Asn1Null, pszErrorTag); break; case RTASN1TYPE_TIME: rc = RTAsn1Time_DecodeAsn1(pCursor, 0, &pDynType->u.Time, pszErrorTag); break; case RTASN1TYPE_STRING: rc = RTAsn1String_DecodeAsn1(pCursor, 0, &pDynType->u.String, pszErrorTag); break; case RTASN1TYPE_CORE: rc = RTAsn1Core_DecodeAsn1(pCursor, 0, &pDynType->u.Core, pszErrorTag); break; default: AssertFailedReturn(VERR_INTERNAL_ERROR_4); } if (RT_SUCCESS(rc)) return rc; } RT_ZERO(*pDynType); return rc; }