13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync/* $Id$ */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync/** @file
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * IPRT - Crypto - PKCS \#7, Decoder for ASN.1.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync/*
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * Copyright (C) 2006-2014 Oracle Corporation
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync *
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * available from http://www.virtualbox.org. This file is free software;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * you can redistribute it and/or modify it under the terms of the GNU
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * General Public License (GPL) as published by the Free Software
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync *
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * The contents of this file may alternatively be used under the terms
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * of the Common Development and Distribution License Version 1.0
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * VirtualBox OSE distribution, in which case the provisions of the
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * CDDL are applicable instead of those of the GPL.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync *
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * You may elect to license modified versions of this file under the
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * terms and conditions of either the GPL or the CDDL or both.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync/*******************************************************************************
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync* Header Files *
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync*******************************************************************************/
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync#include "internal/iprt.h"
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync#include <iprt/crypto/pkcs7.h>
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync#include <iprt/err.h>
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync#include <iprt/string.h>
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync#include <iprt/crypto/spc.h>
4ee2f4fc8e99dc69ba5d63fd7dd3f52a38d0501evboxsync#include <iprt/crypto/tsp.h>
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync#include "pkcs7-internal.h"
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync/*
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * PKCS #7 ContentInfo
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync */
4ee2f4fc8e99dc69ba5d63fd7dd3f52a38d0501evboxsynctypedef enum RTCRPKCS7CONTENTINFOCHOICE
4ee2f4fc8e99dc69ba5d63fd7dd3f52a38d0501evboxsync{
4ee2f4fc8e99dc69ba5d63fd7dd3f52a38d0501evboxsync RTCRPKCS7CONTENTINFOCHOICE_INVALID = 0,
4ee2f4fc8e99dc69ba5d63fd7dd3f52a38d0501evboxsync RTCRPKCS7CONTENTINFOCHOICE_UNKNOWN,
4ee2f4fc8e99dc69ba5d63fd7dd3f52a38d0501evboxsync RTCRPKCS7CONTENTINFOCHOICE_SIGNED_DATA,
4ee2f4fc8e99dc69ba5d63fd7dd3f52a38d0501evboxsync RTCRPKCS7CONTENTINFOCHOICE_SPC_INDIRECT_DATA_CONTENT,
4ee2f4fc8e99dc69ba5d63fd7dd3f52a38d0501evboxsync RTCRPKCS7CONTENTINFOCHOICE_TSP_TST_INFO,
4ee2f4fc8e99dc69ba5d63fd7dd3f52a38d0501evboxsync RTCRPKCS7CONTENTINFOCHOICE_END,
4ee2f4fc8e99dc69ba5d63fd7dd3f52a38d0501evboxsync RTCRPKCS7CONTENTINFOCHOICE_32BIT_HACK = 0x7fffffff
4ee2f4fc8e99dc69ba5d63fd7dd3f52a38d0501evboxsync} RTCRPKCS7CONTENTINFOCHOICE;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsyncstatic int rtCrPkcs7ContentInfo_DecodeExtra(PRTASN1CURSOR pCursor, uint32_t fFlags, PRTCRPKCS7CONTENTINFO pThis,
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync const char *pszErrorTag)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync{
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync pThis->u.pCore = NULL;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
4ee2f4fc8e99dc69ba5d63fd7dd3f52a38d0501evboxsync /*
4ee2f4fc8e99dc69ba5d63fd7dd3f52a38d0501evboxsync * Figure the type.
4ee2f4fc8e99dc69ba5d63fd7dd3f52a38d0501evboxsync */
4ee2f4fc8e99dc69ba5d63fd7dd3f52a38d0501evboxsync RTCRPKCS7CONTENTINFOCHOICE enmChoice;
4ee2f4fc8e99dc69ba5d63fd7dd3f52a38d0501evboxsync size_t cbContent = 0;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if (RTAsn1ObjId_CompareWithString(&pThis->ContentType, RTCRPKCS7SIGNEDDATA_OID) == 0)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync {
4ee2f4fc8e99dc69ba5d63fd7dd3f52a38d0501evboxsync enmChoice = RTCRPKCS7CONTENTINFOCHOICE_SIGNED_DATA;
4ee2f4fc8e99dc69ba5d63fd7dd3f52a38d0501evboxsync cbContent = sizeof(*pThis->u.pSignedData);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync }
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync else if (RTAsn1ObjId_CompareWithString(&pThis->ContentType, RTCRSPCINDIRECTDATACONTENT_OID) == 0)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync {
4ee2f4fc8e99dc69ba5d63fd7dd3f52a38d0501evboxsync enmChoice = RTCRPKCS7CONTENTINFOCHOICE_SPC_INDIRECT_DATA_CONTENT;
4ee2f4fc8e99dc69ba5d63fd7dd3f52a38d0501evboxsync cbContent = sizeof(*pThis->u.pIndirectDataContent);
4ee2f4fc8e99dc69ba5d63fd7dd3f52a38d0501evboxsync }
4ee2f4fc8e99dc69ba5d63fd7dd3f52a38d0501evboxsync else if (RTAsn1ObjId_CompareWithString(&pThis->ContentType, RTCRTSPTSTINFO_OID) == 0)
4ee2f4fc8e99dc69ba5d63fd7dd3f52a38d0501evboxsync {
4ee2f4fc8e99dc69ba5d63fd7dd3f52a38d0501evboxsync enmChoice = RTCRPKCS7CONTENTINFOCHOICE_TSP_TST_INFO;
4ee2f4fc8e99dc69ba5d63fd7dd3f52a38d0501evboxsync cbContent = sizeof(*pThis->u.pTstInfo);
4ee2f4fc8e99dc69ba5d63fd7dd3f52a38d0501evboxsync }
4ee2f4fc8e99dc69ba5d63fd7dd3f52a38d0501evboxsync else
4ee2f4fc8e99dc69ba5d63fd7dd3f52a38d0501evboxsync {
4ee2f4fc8e99dc69ba5d63fd7dd3f52a38d0501evboxsync enmChoice = RTCRPKCS7CONTENTINFOCHOICE_UNKNOWN;
4ee2f4fc8e99dc69ba5d63fd7dd3f52a38d0501evboxsync cbContent = 0;
4ee2f4fc8e99dc69ba5d63fd7dd3f52a38d0501evboxsync }
4ee2f4fc8e99dc69ba5d63fd7dd3f52a38d0501evboxsync
4ee2f4fc8e99dc69ba5d63fd7dd3f52a38d0501evboxsync int rc = VINF_SUCCESS;
4ee2f4fc8e99dc69ba5d63fd7dd3f52a38d0501evboxsync if (enmChoice != RTCRPKCS7CONTENTINFOCHOICE_UNKNOWN)
4ee2f4fc8e99dc69ba5d63fd7dd3f52a38d0501evboxsync {
4ee2f4fc8e99dc69ba5d63fd7dd3f52a38d0501evboxsync /*
4ee2f4fc8e99dc69ba5d63fd7dd3f52a38d0501evboxsync * Detect CMS octet string and open the content cursor.
4ee2f4fc8e99dc69ba5d63fd7dd3f52a38d0501evboxsync * Current we don't have work with any contet which is octet string,
4ee2f4fc8e99dc69ba5d63fd7dd3f52a38d0501evboxsync * they're all sequences, which make detection so much simpler.
4ee2f4fc8e99dc69ba5d63fd7dd3f52a38d0501evboxsync */
4ee2f4fc8e99dc69ba5d63fd7dd3f52a38d0501evboxsync PRTASN1OCTETSTRING pOctetString = &pThis->Content;
4ee2f4fc8e99dc69ba5d63fd7dd3f52a38d0501evboxsync RTASN1CURSOR ContentCursor;
4ee2f4fc8e99dc69ba5d63fd7dd3f52a38d0501evboxsync rc = RTAsn1CursorInitSubFromCore(pCursor, &pThis->Content.Asn1Core, &ContentCursor, "Content");
4ee2f4fc8e99dc69ba5d63fd7dd3f52a38d0501evboxsync if ( RT_SUCCESS(rc)
4ee2f4fc8e99dc69ba5d63fd7dd3f52a38d0501evboxsync && RTAsn1CursorIsNextEx(&ContentCursor, ASN1_TAG_OCTET_STRING, ASN1_TAGFLAG_PRIMITIVE | ASN1_TAGCLASS_UNIVERSAL))
4ee2f4fc8e99dc69ba5d63fd7dd3f52a38d0501evboxsync {
4ee2f4fc8e99dc69ba5d63fd7dd3f52a38d0501evboxsync rc = RTAsn1MemAllocZ(&pThis->Content.EncapsulatedAllocation, (void **)&pThis->Content.pEncapsulated,
4ee2f4fc8e99dc69ba5d63fd7dd3f52a38d0501evboxsync sizeof(*pOctetString));
4ee2f4fc8e99dc69ba5d63fd7dd3f52a38d0501evboxsync if (RT_SUCCESS(rc))
4ee2f4fc8e99dc69ba5d63fd7dd3f52a38d0501evboxsync {
4ee2f4fc8e99dc69ba5d63fd7dd3f52a38d0501evboxsync pThis->pCmsContent = pOctetString = (PRTASN1OCTETSTRING)pThis->Content.pEncapsulated;
4ee2f4fc8e99dc69ba5d63fd7dd3f52a38d0501evboxsync rc = RTAsn1OctetString_DecodeAsn1(&ContentCursor, 0, pOctetString, "CmsContent");
4ee2f4fc8e99dc69ba5d63fd7dd3f52a38d0501evboxsync if (RT_SUCCESS(rc))
4ee2f4fc8e99dc69ba5d63fd7dd3f52a38d0501evboxsync rc = RTAsn1CursorCheckEnd(&ContentCursor);
4ee2f4fc8e99dc69ba5d63fd7dd3f52a38d0501evboxsync if (RT_SUCCESS(rc))
4ee2f4fc8e99dc69ba5d63fd7dd3f52a38d0501evboxsync rc = RTAsn1CursorInitSubFromCore(pCursor, &pOctetString->Asn1Core, &ContentCursor, "CmsContent");
4ee2f4fc8e99dc69ba5d63fd7dd3f52a38d0501evboxsync }
4ee2f4fc8e99dc69ba5d63fd7dd3f52a38d0501evboxsync }
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if (RT_SUCCESS(rc))
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync {
4ee2f4fc8e99dc69ba5d63fd7dd3f52a38d0501evboxsync /*
4ee2f4fc8e99dc69ba5d63fd7dd3f52a38d0501evboxsync * Allocate memory for the decoded content.
4ee2f4fc8e99dc69ba5d63fd7dd3f52a38d0501evboxsync */
4ee2f4fc8e99dc69ba5d63fd7dd3f52a38d0501evboxsync rc = RTAsn1MemAllocZ(&pOctetString->EncapsulatedAllocation, (void **)&pOctetString->pEncapsulated, cbContent);
b1f3a2dc94cfa582803b349a7ce9c7b2f94e58f1vboxsync if (RT_SUCCESS(rc))
4ee2f4fc8e99dc69ba5d63fd7dd3f52a38d0501evboxsync {
4ee2f4fc8e99dc69ba5d63fd7dd3f52a38d0501evboxsync pThis->u.pCore = pOctetString->pEncapsulated;
4ee2f4fc8e99dc69ba5d63fd7dd3f52a38d0501evboxsync
4ee2f4fc8e99dc69ba5d63fd7dd3f52a38d0501evboxsync /*
4ee2f4fc8e99dc69ba5d63fd7dd3f52a38d0501evboxsync * Decode it.
4ee2f4fc8e99dc69ba5d63fd7dd3f52a38d0501evboxsync */
4ee2f4fc8e99dc69ba5d63fd7dd3f52a38d0501evboxsync switch (enmChoice)
4ee2f4fc8e99dc69ba5d63fd7dd3f52a38d0501evboxsync {
4ee2f4fc8e99dc69ba5d63fd7dd3f52a38d0501evboxsync case RTCRPKCS7CONTENTINFOCHOICE_SIGNED_DATA:
4ee2f4fc8e99dc69ba5d63fd7dd3f52a38d0501evboxsync rc = RTCrPkcs7SignedData_DecodeAsn1(&ContentCursor, 0, pThis->u.pSignedData, "SignedData");
4ee2f4fc8e99dc69ba5d63fd7dd3f52a38d0501evboxsync break;
4ee2f4fc8e99dc69ba5d63fd7dd3f52a38d0501evboxsync case RTCRPKCS7CONTENTINFOCHOICE_SPC_INDIRECT_DATA_CONTENT:
4ee2f4fc8e99dc69ba5d63fd7dd3f52a38d0501evboxsync rc = RTCrSpcIndirectDataContent_DecodeAsn1(&ContentCursor, 0, pThis->u.pIndirectDataContent,
4ee2f4fc8e99dc69ba5d63fd7dd3f52a38d0501evboxsync "IndirectDataContent");
4ee2f4fc8e99dc69ba5d63fd7dd3f52a38d0501evboxsync break;
4ee2f4fc8e99dc69ba5d63fd7dd3f52a38d0501evboxsync case RTCRPKCS7CONTENTINFOCHOICE_TSP_TST_INFO:
4ee2f4fc8e99dc69ba5d63fd7dd3f52a38d0501evboxsync rc = RTCrTspTstInfo_DecodeAsn1(&ContentCursor, 0, pThis->u.pTstInfo, "TstInfo");
4ee2f4fc8e99dc69ba5d63fd7dd3f52a38d0501evboxsync break;
4ee2f4fc8e99dc69ba5d63fd7dd3f52a38d0501evboxsync default:
4ee2f4fc8e99dc69ba5d63fd7dd3f52a38d0501evboxsync AssertFailed();
4ee2f4fc8e99dc69ba5d63fd7dd3f52a38d0501evboxsync rc = VERR_IPE_NOT_REACHED_DEFAULT_CASE;
4ee2f4fc8e99dc69ba5d63fd7dd3f52a38d0501evboxsync break;
4ee2f4fc8e99dc69ba5d63fd7dd3f52a38d0501evboxsync }
4ee2f4fc8e99dc69ba5d63fd7dd3f52a38d0501evboxsync if (RT_SUCCESS(rc))
4ee2f4fc8e99dc69ba5d63fd7dd3f52a38d0501evboxsync rc = RTAsn1CursorCheckEnd(&ContentCursor);
4ee2f4fc8e99dc69ba5d63fd7dd3f52a38d0501evboxsync if (RT_SUCCESS(rc))
4ee2f4fc8e99dc69ba5d63fd7dd3f52a38d0501evboxsync return VINF_SUCCESS;
4ee2f4fc8e99dc69ba5d63fd7dd3f52a38d0501evboxsync
4ee2f4fc8e99dc69ba5d63fd7dd3f52a38d0501evboxsync RTAsn1MemFree(&pOctetString->EncapsulatedAllocation, pOctetString->pEncapsulated);
4ee2f4fc8e99dc69ba5d63fd7dd3f52a38d0501evboxsync pOctetString->pEncapsulated = NULL;
4ee2f4fc8e99dc69ba5d63fd7dd3f52a38d0501evboxsync pThis->u.pCore = NULL;
4ee2f4fc8e99dc69ba5d63fd7dd3f52a38d0501evboxsync }
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync }
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync }
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync return rc;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync}
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync/*
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * Generate the code.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync#include <iprt/asn1-generator-asn1-decoder.h>
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync