VirtualBox

source: vbox/trunk/src/VBox/Runtime/common/crypto/pkcs7-sanity.cpp@ 64883

Last change on this file since 64883 was 64883, checked in by vboxsync, 8 years ago

IPRT/ASN.1: Refactored array handling (SET OF, SEQUENCE OF) to use a pointer array instead of an object instance array. The old approach would move objects around in memory after they'd be initialized/decoded, making certain core optimziations involving pointers to object members impossible, as well as causing potentially causing trouble when modifying structures that takes down pointers after decoding. Fixed validation bug in rtCrX509Name_CheckSanityExtra where it didn't check that the RDNs had subitems but instead checked the parent twice (slight risk).

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 11.4 KB
Line 
1/* $Id: pkcs7-sanity.cpp 64883 2016-12-15 15:26:20Z vboxsync $ */
2/** @file
3 * IPRT - Crypto - PKCS \#7, Sanity Checkers.
4 */
5
6/*
7 * Copyright (C) 2006-2016 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 *
17 * The contents of this file may alternatively be used under the terms
18 * of the Common Development and Distribution License Version 1.0
19 * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
20 * VirtualBox OSE distribution, in which case the provisions of the
21 * CDDL are applicable instead of those of the GPL.
22 *
23 * You may elect to license modified versions of this file under the
24 * terms and conditions of either the GPL or the CDDL or both.
25 */
26
27
28/*********************************************************************************************************************************
29* Header Files *
30*********************************************************************************************************************************/
31#include "internal/iprt.h"
32#include <iprt/crypto/pkcs7.h>
33
34#include <iprt/err.h>
35#include <iprt/string.h>
36
37//#include <iprt/stream.h>
38
39#include "pkcs7-internal.h"
40
41
42static int rtCrPkcs7SignedData_CheckSanityExtra(PCRTCRPKCS7SIGNEDDATA pSignedData, uint32_t fFlags,
43 PRTERRINFO pErrInfo, const char *pszErrorTag)
44{
45 bool const fAuthenticode = RT_BOOL(fFlags & RTCRPKCS7SIGNEDDATA_SANITY_F_AUTHENTICODE);
46 RT_NOREF_PV(fFlags);
47
48 //RTAsn1Dump(&pSignedData->SeqCore.Asn1Core, 0, 0, RTAsn1DumpStrmPrintfV, g_pStdOut);
49
50 if ( RTAsn1Integer_UnsignedCompareWithU32(&pSignedData->Version, RTCRPKCS7SIGNEDDATA_V1) != 0
51 && RTAsn1Integer_UnsignedCompareWithU32(&pSignedData->Version, RTCRPKCS7SIGNEDDATA_V3) != 0
52 && RTAsn1Integer_UnsignedCompareWithU32(&pSignedData->Version, RTCRPKCS7SIGNEDDATA_V4) != 0
53 && RTAsn1Integer_UnsignedCompareWithU32(&pSignedData->Version, RTCRPKCS7SIGNEDDATA_V5) != 0)
54 return RTErrInfoSetF(pErrInfo, VERR_CR_PKCS7_SIGNED_DATA_VERSION, "SignedData version is %llu, expected %u",
55 pSignedData->Version.uValue.u, RTCRPKCS7SIGNEDDATA_V1);
56
57 /*
58 * DigestAlgorithms.
59 */
60 if (pSignedData->DigestAlgorithms.cItems == 0) /** @todo this might be too strict */
61 return RTErrInfoSet(pErrInfo, VERR_CR_PKCS7_SIGNED_DATA_NO_DIGEST_ALGOS, "SignedData.DigestAlgorithms is empty");
62 if (pSignedData->DigestAlgorithms.cItems != 1 && fAuthenticode)
63 return RTErrInfoSetF(pErrInfo, VERR_CR_SPC_NOT_EXACTLY_ONE_DIGEST_ALGO,
64 "%s: SignedData.DigestAlgorithms has more than one algorithm (%u)",
65 pszErrorTag, pSignedData->DigestAlgorithms.cItems);
66
67 if (fFlags & RTCRPKCS7SIGNEDDATA_SANITY_F_ONLY_KNOWN_HASH)
68 for (uint32_t i = 0; i < pSignedData->DigestAlgorithms.cItems; i++)
69 {
70 if (RTCrX509AlgorithmIdentifier_QueryDigestType(pSignedData->DigestAlgorithms.papItems[i]) == RTDIGESTTYPE_INVALID)
71 return RTErrInfoSetF(pErrInfo, VERR_CR_PKCS7_UNKNOWN_DIGEST_ALGORITHM,
72 "%s: SignedData.DigestAlgorithms[%i] is not known: %s",
73 pszErrorTag, i, pSignedData->DigestAlgorithms.papItems[i]->Algorithm.szObjId);
74 if (pSignedData->DigestAlgorithms.papItems[i]->Parameters.enmType != RTASN1TYPE_NULL)
75 return RTErrInfoSetF(pErrInfo, VERR_CR_PKCS7_DIGEST_PARAMS_NOT_IMPL,
76 "%s: SignedData.DigestAlgorithms[%i] has parameters: tag=%u",
77 pszErrorTag, i, pSignedData->DigestAlgorithms.papItems[i]->Parameters.u.Core.uTag);
78 }
79
80 /*
81 * Certificates.
82 */
83 if ( (fFlags & RTCRPKCS7SIGNEDDATA_SANITY_F_SIGNING_CERT_PRESENT)
84 && pSignedData->Certificates.cItems == 0)
85 return RTErrInfoSetF(pErrInfo, VERR_CR_PKCS7_NO_CERTIFICATES,
86 "%s: SignedData.Certifcates is empty, expected at least one certificate", pszErrorTag);
87
88 /*
89 * Crls.
90 */
91 if (fAuthenticode && RTAsn1Core_IsPresent(&pSignedData->Crls))
92 return RTErrInfoSetF(pErrInfo, VERR_CR_PKCS7_EXPECTED_NO_CRLS,
93 "%s: SignedData.Crls is not empty as expected for authenticode.", pszErrorTag);
94 /** @todo check Crls when they become important. */
95
96 /*
97 * SignerInfos.
98 */
99 if (pSignedData->SignerInfos.cItems == 0)
100 return RTErrInfoSetF(pErrInfo, VERR_CR_PKCS7_NO_SIGNER_INFOS, "%s: SignedData.SignerInfos is empty?", pszErrorTag);
101 if (fAuthenticode && pSignedData->SignerInfos.cItems != 1)
102 return RTErrInfoSetF(pErrInfo, VERR_CR_PKCS7_EXPECTED_ONE_SIGNER_INFO,
103 "%s: SignedData.SignerInfos should have one entry for authenticode: %u",
104 pszErrorTag, pSignedData->SignerInfos.cItems);
105
106 for (uint32_t i = 0; i < pSignedData->SignerInfos.cItems; i++)
107 {
108 PCRTCRPKCS7SIGNERINFO pSignerInfo = pSignedData->SignerInfos.papItems[i];
109
110 if (RTAsn1Integer_UnsignedCompareWithU32(&pSignerInfo->Version, RTCRPKCS7SIGNERINFO_V1) != 0)
111 return RTErrInfoSetF(pErrInfo, VERR_CR_PKCS7_SIGNER_INFO_VERSION,
112 "%s: SignedData.SignerInfos[%u] version is %llu, expected %u",
113 pszErrorTag, i, pSignerInfo->Version.uValue.u, RTCRPKCS7SIGNERINFO_V1);
114
115 /* IssuerAndSerialNumber. */
116 int rc = RTCrX509Name_CheckSanity(&pSignerInfo->IssuerAndSerialNumber.Name, 0, pErrInfo,
117 "SignedData.SignerInfos[#].IssuerAndSerialNumber.Name");
118 if (RT_FAILURE(rc))
119 return rc;
120
121 if (pSignerInfo->IssuerAndSerialNumber.SerialNumber.Asn1Core.cb == 0)
122 return RTErrInfoSetF(pErrInfo, VERR_CR_PKCS7_SIGNER_INFO_NO_ISSUER_SERIAL_NO,
123 "%s: SignedData.SignerInfos[%u].IssuerAndSerialNumber.SerialNumber is missing (zero length)",
124 pszErrorTag, i);
125
126 PCRTCRX509CERTIFICATE pCert;
127 pCert = RTCrPkcs7SetOfCerts_FindX509ByIssuerAndSerialNumber(&pSignedData->Certificates,
128 &pSignerInfo->IssuerAndSerialNumber.Name,
129 &pSignerInfo->IssuerAndSerialNumber.SerialNumber);
130 if (!pCert && (fFlags & RTCRPKCS7SIGNEDDATA_SANITY_F_SIGNING_CERT_PRESENT))
131 return RTErrInfoSetF(pErrInfo, VERR_CR_PKCS7_SIGNER_CERT_NOT_SHIPPED,
132 "%s: SignedData.SignerInfos[%u].IssuerAndSerialNumber not found in T0.Certificates",
133 pszErrorTag, i);
134
135 /* DigestAlgorithm */
136 uint32_t j = 0;
137 while ( j < pSignedData->DigestAlgorithms.cItems
138 && RTCrX509AlgorithmIdentifier_Compare(pSignedData->DigestAlgorithms.papItems[j],
139 &pSignerInfo->DigestAlgorithm) != 0)
140 j++;
141 if (j >= pSignedData->DigestAlgorithms.cItems)
142 return RTErrInfoSetF(pErrInfo, VERR_CR_PKCS7_DIGEST_ALGO_NOT_FOUND_IN_LIST,
143 "%s: SignedData.SignerInfos[%u].DigestAlgorithm (%s) not found in SignedData.DigestAlgorithms",
144 pszErrorTag, i, pSignerInfo->DigestAlgorithm.Algorithm.szObjId);
145
146 /* Digest encryption algorithm. */
147#if 0 /** @todo Unimportant: Seen timestamp signatures specifying pkcs1-Sha256WithRsaEncryption in SignerInfo and just RSA in the certificate. Figure out how to compare the two. */
148 if ( pCert
149 && RTCrX509AlgorithmIdentifier_Compare(&pSignerInfo->DigestEncryptionAlgorithm,
150 &pCert->TbsCertificate.SubjectPublicKeyInfo.Algorithm) != 0)
151 return RTErrInfoSetF(pErrInfo, VERR_CR_PKCS7_SIGNER_INFO_DIGEST_ENCRYPT_MISMATCH,
152 "SignedData.SignerInfos[%u].DigestEncryptionAlgorithm (%s) mismatch with certificate (%s)",
153 i, pSignerInfo->DigestEncryptionAlgorithm.Algorithm.szObjId,
154 pCert->TbsCertificate.SubjectPublicKeyInfo.Algorithm.Algorithm.szObjId);
155#endif
156
157 /* Authenticated attributes we know. */
158 if (RTCrPkcs7Attributes_IsPresent(&pSignerInfo->AuthenticatedAttributes))
159 {
160 bool fFoundContentInfo = false;
161 bool fFoundMessageDigest = false;
162 for (j = 0; j < pSignerInfo->AuthenticatedAttributes.cItems; j++)
163 {
164 PCRTCRPKCS7ATTRIBUTE pAttrib = pSignerInfo->AuthenticatedAttributes.papItems[j];
165 if (RTAsn1ObjId_CompareWithString(&pAttrib->Type, RTCR_PKCS9_ID_CONTENT_TYPE_OID) == 0)
166 {
167 if (fFoundContentInfo)
168 return RTErrInfoSetF(pErrInfo, VERR_CR_PKCS7_MISSING_CONTENT_TYPE_ATTRIB,
169 "%s: Multiple authenticated content-type attributes.", pszErrorTag);
170 fFoundContentInfo = true;
171 AssertReturn(pAttrib->enmType == RTCRPKCS7ATTRIBUTETYPE_OBJ_IDS, VERR_INTERNAL_ERROR_3);
172 if (pAttrib->uValues.pObjIds->cItems != 1)
173 return RTErrInfoSetF(pErrInfo, VERR_CR_PKCS7_BAD_CONTENT_TYPE_ATTRIB,
174 "%s: Expected exactly one value for content-type attrib, found: %u",
175 pszErrorTag, pAttrib->uValues.pObjIds->cItems);
176 }
177 else if (RTAsn1ObjId_CompareWithString(&pAttrib->Type, RTCR_PKCS9_ID_MESSAGE_DIGEST_OID) == 0)
178 {
179 if (fFoundMessageDigest)
180 return RTErrInfoSetF(pErrInfo, VERR_CR_PKCS7_MISSING_MESSAGE_DIGEST_ATTRIB,
181 "%s: Multiple authenticated message-digest attributes.", pszErrorTag);
182 fFoundMessageDigest = true;
183 AssertReturn(pAttrib->enmType == RTCRPKCS7ATTRIBUTETYPE_OCTET_STRINGS, VERR_INTERNAL_ERROR_3);
184 if (pAttrib->uValues.pOctetStrings->cItems != 1)
185 return RTErrInfoSetF(pErrInfo, VERR_CR_PKCS7_BAD_CONTENT_TYPE_ATTRIB,
186 "%s: Expected exactly one value for message-digest attrib, found: %u",
187 pszErrorTag, pAttrib->uValues.pOctetStrings->cItems);
188 }
189 }
190
191 if (!fFoundContentInfo)
192 return RTErrInfoSetF(pErrInfo, VERR_CR_PKCS7_MISSING_CONTENT_TYPE_ATTRIB,
193 "%s: Missing authenticated content-type attribute.", pszErrorTag);
194 if (!fFoundMessageDigest)
195 return RTErrInfoSetF(pErrInfo, VERR_CR_PKCS7_MISSING_MESSAGE_DIGEST_ATTRIB,
196 "%s: Missing authenticated message-digest attribute.", pszErrorTag);
197 }
198 }
199
200 return VINF_SUCCESS;
201}
202
203
204/*
205 * Generate the code.
206 */
207#include <iprt/asn1-generator-sanity.h>
208
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette