VirtualBox

source: vbox/trunk/src/VBox/Runtime/common/crypto/pkcs7-core.cpp

Last change on this file was 106061, checked in by vboxsync, 3 months ago

Copyright year updates by scm.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 8.8 KB
Line 
1/* $Id: pkcs7-core.cpp 106061 2024-09-16 14:03:52Z vboxsync $ */
2/** @file
3 * IPRT - Crypto - PKCS \#7, Core APIs.
4 */
5
6/*
7 * Copyright (C) 2006-2024 Oracle and/or its affiliates.
8 *
9 * This file is part of VirtualBox base platform packages, as
10 * available from https://www.virtualbox.org.
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation, in version 3 of the
15 * License.
16 *
17 * This program is distributed in the hope that it will be useful, but
18 * WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 * General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, see <https://www.gnu.org/licenses>.
24 *
25 * The contents of this file may alternatively be used under the terms
26 * of the Common Development and Distribution License Version 1.0
27 * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
28 * in the VirtualBox distribution, in which case the provisions of the
29 * CDDL are applicable instead of those of the GPL.
30 *
31 * You may elect to license modified versions of this file under the
32 * terms and conditions of either the GPL or the CDDL or both.
33 *
34 * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
35 */
36
37
38/*********************************************************************************************************************************
39* Header Files *
40*********************************************************************************************************************************/
41#include "internal/iprt.h"
42#include <iprt/crypto/pkcs7.h>
43
44#include <iprt/errcore.h>
45#include <iprt/mem.h>
46#include <iprt/string.h>
47#include <iprt/crypto/digest.h>
48#include <iprt/crypto/tsp.h>
49
50#include "pkcs7-internal.h"
51
52/*
53 * PKCS #7 Attributes
54 */
55
56RTDECL(int) RTCrPkcs7Attributes_HashAttributes(PRTCRPKCS7ATTRIBUTES pAttributes, RTCRDIGEST hDigest, PRTERRINFO pErrInfo)
57{
58 /* ASSUMES that the attributes are encoded according to DER. */
59 uint8_t const *pbData;
60 uint32_t cbData;
61 void *pvFree = NULL;
62 int rc = RTAsn1EncodeQueryRawBits(RTCrPkcs7Attributes_GetAsn1Core(pAttributes),
63 &pbData, &cbData, &pvFree, pErrInfo);
64 if (RT_SUCCESS(rc))
65 {
66 uint8_t bSetOfTag = ASN1_TAG_SET | ASN1_TAGCLASS_UNIVERSAL | ASN1_TAGFLAG_CONSTRUCTED;
67 rc = RTCrDigestUpdate(hDigest, &bSetOfTag, sizeof(bSetOfTag)); /* Replace the implict tag with a SET-OF tag. */
68 if (RT_SUCCESS(rc))
69 rc = RTCrDigestUpdate(hDigest, pbData + sizeof(bSetOfTag), cbData - sizeof(bSetOfTag)); /* Skip the implicit tag. */
70 if (RT_SUCCESS(rc))
71 rc = RTCrDigestFinal(hDigest, NULL, 0);
72 else
73 RTErrInfoSet(pErrInfo, rc, "RTCrDigestUpdate failed");
74 RTMemTmpFree(pvFree);
75 }
76 return rc;
77}
78
79
80/*
81 * PKCS #7 SignerInfo
82 */
83
84RTDECL(PCRTASN1TIME) RTCrPkcs7SignerInfo_GetSigningTime(PCRTCRPKCS7SIGNERINFO pThis, PCRTCRPKCS7SIGNERINFO *ppSignerInfo)
85{
86 /*
87 * Check the immediate level, unless we're continuing a previous search.
88 * Note! We ASSUME a single signing time attribute, which simplifies the interface.
89 */
90 uint32_t cAttrsLeft;
91 PRTCRPKCS7ATTRIBUTE const *ppAttr;
92 if (!ppSignerInfo || *ppSignerInfo == NULL)
93 {
94 cAttrsLeft = pThis->AuthenticatedAttributes.cItems;
95 ppAttr = pThis->AuthenticatedAttributes.papItems;
96 while (cAttrsLeft-- > 0)
97 {
98 PCRTCRPKCS7ATTRIBUTE pAttr = *ppAttr;
99 if ( pAttr->enmType == RTCRPKCS7ATTRIBUTETYPE_SIGNING_TIME
100 && pAttr->uValues.pSigningTime->cItems > 0)
101 {
102 if (ppSignerInfo)
103 *ppSignerInfo = pThis;
104 return pAttr->uValues.pSigningTime->papItems[0];
105 }
106 ppAttr++;
107 }
108 }
109 else if (*ppSignerInfo == pThis)
110 *ppSignerInfo = NULL;
111
112 /*
113 * Check counter signatures.
114 */
115 cAttrsLeft = pThis->UnauthenticatedAttributes.cItems;
116 ppAttr = pThis->UnauthenticatedAttributes.papItems;
117 while (cAttrsLeft-- > 0)
118 {
119 PCRTCRPKCS7ATTRIBUTE pAttr = *ppAttr;
120 if (pAttr->enmType == RTCRPKCS7ATTRIBUTETYPE_COUNTER_SIGNATURES)
121 {
122 uint32_t cSignatures = pAttr->uValues.pCounterSignatures->cItems;
123 PRTCRPKCS7SIGNERINFO *ppSignature = pAttr->uValues.pCounterSignatures->papItems;
124
125 /* Skip past the previous counter signature. */
126 if (ppSignerInfo && *ppSignerInfo != NULL)
127 while (cSignatures > 0)
128 {
129 cSignatures--;
130 if (*ppSignature == *ppSignerInfo)
131 {
132 *ppSignerInfo = NULL;
133 ppSignature++;
134 break;
135 }
136 ppSignature++;
137 }
138
139 /* Search the counter signatures (if any remaining). */
140 while (cSignatures-- > 0)
141 {
142 PCRTCRPKCS7SIGNERINFO pSignature = *ppSignature;
143 uint32_t cCounterAttrsLeft = pSignature->AuthenticatedAttributes.cItems;
144 PRTCRPKCS7ATTRIBUTE const *ppCounterAttr = pSignature->AuthenticatedAttributes.papItems;
145 while (cCounterAttrsLeft-- > 0)
146 {
147 PCRTCRPKCS7ATTRIBUTE pCounterAttr = *ppCounterAttr;
148 if ( pCounterAttr->enmType == RTCRPKCS7ATTRIBUTETYPE_SIGNING_TIME
149 && pCounterAttr->uValues.pSigningTime->cItems > 0)
150 {
151 if (ppSignerInfo)
152 *ppSignerInfo = pSignature;
153 return pCounterAttr->uValues.pSigningTime->papItems[0];
154 }
155 ppCounterAttr++;
156 }
157 ppSignature++;
158 }
159 }
160 ppAttr++;
161 }
162
163 /*
164 * No signing timestamp found.
165 */
166 if (ppSignerInfo)
167 *ppSignerInfo = NULL;
168
169 return NULL;
170}
171
172
173RTDECL(PCRTASN1TIME) RTCrPkcs7SignerInfo_GetMsTimestamp(PCRTCRPKCS7SIGNERINFO pThis, PCRTCRPKCS7CONTENTINFO *ppContentInfoRet)
174{
175 /*
176 * Assume there is only one, so no need to enumerate anything here.
177 */
178 uint32_t cAttrsLeft = pThis->UnauthenticatedAttributes.cItems;
179 PRTCRPKCS7ATTRIBUTE const *ppAttr = pThis->UnauthenticatedAttributes.papItems;
180 while (cAttrsLeft-- > 0)
181 {
182 PCRTCRPKCS7ATTRIBUTE pAttr = *ppAttr;
183 if (pAttr->enmType == RTCRPKCS7ATTRIBUTETYPE_MS_TIMESTAMP)
184 {
185 uint32_t cLeft = pAttr->uValues.pContentInfos->cItems;
186 PRTCRPKCS7CONTENTINFO const *ppContentInfo = pAttr->uValues.pContentInfos->papItems;
187 while (cLeft-- > 0)
188 {
189 PCRTCRPKCS7CONTENTINFO pContentInfo = *ppContentInfo;
190 if (RTAsn1ObjId_CompareWithString(&pContentInfo->ContentType, RTCRPKCS7SIGNEDDATA_OID) == 0)
191 {
192 if (RTAsn1ObjId_CompareWithString(&pContentInfo->u.pSignedData->ContentInfo.ContentType,
193 RTCRTSPTSTINFO_OID) == 0)
194 {
195 if (ppContentInfoRet)
196 *ppContentInfoRet = pContentInfo;
197 return &pContentInfo->u.pSignedData->ContentInfo.u.pTstInfo->GenTime;
198 }
199 }
200
201 pContentInfo++;
202 }
203 }
204 ppAttr++;
205 }
206
207 /*
208 * No signature was found.
209 */
210 if (ppContentInfoRet)
211 *ppContentInfoRet = NULL;
212
213 return NULL;
214}
215
216
217/*
218 * PKCS #7 ContentInfo.
219 */
220
221RTDECL(bool) RTCrPkcs7ContentInfo_IsSignedData(PCRTCRPKCS7CONTENTINFO pThis)
222{
223 return RTAsn1ObjId_CompareWithString(&pThis->ContentType, RTCRPKCS7SIGNEDDATA_OID) == 0;
224}
225
226
227/*
228 * Set of some kind of certificate supported by PKCS #7 or CMS.
229 */
230
231RTDECL(PCRTCRX509CERTIFICATE)
232RTCrPkcs7SetOfCerts_FindX509ByIssuerAndSerialNumber(PCRTCRPKCS7SETOFCERTS pCertificates,
233 PCRTCRX509NAME pIssuer, PCRTASN1INTEGER pSerialNumber)
234{
235 for (uint32_t i = 0; i < pCertificates->cItems; i++)
236 {
237 PCRTCRPKCS7CERT pCert = pCertificates->papItems[i];
238 if ( pCert->enmChoice == RTCRPKCS7CERTCHOICE_X509
239 && RTCrX509Certificate_MatchIssuerAndSerialNumber(pCert->u.pX509Cert, pIssuer, pSerialNumber))
240 return pCert->u.pX509Cert;
241 }
242 return NULL;
243}
244
245
246/*
247 * Generate the standard core code.
248 */
249#include <iprt/asn1-generator-core.h>
250
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