VirtualBox

source: vbox/trunk/src/VBox/Runtime/testcase/tstRTCrX509-1.cpp@ 104626

Last change on this file since 104626 was 98103, checked in by vboxsync, 2 years ago

Copyright year updates by scm.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 10.3 KB
Line 
1/* $Id: tstRTCrX509-1.cpp 98103 2023-01-17 14:15:46Z vboxsync $ */
2/** @file
3 * IPRT testcase - Crypto - X.509 \#1.
4 */
5
6/*
7 * Copyright (C) 2016-2023 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 <iprt/crypto/x509.h>
42
43#include <iprt/err.h>
44#include <iprt/string.h>
45#include <iprt/test.h>
46
47#include "tstRTCrX509-1.h"
48
49
50/*********************************************************************************************************************************
51* Global Variables *
52*********************************************************************************************************************************/
53static RTTEST g_hTest;
54
55/** List of test certificates + keys, PEM encoding, and their corresponding
56 * .der certificate encodings. */
57static const struct
58{
59 const char *pszFile;
60 bool fMaybeNotInOpenSSL;
61 bool fSelfSigned;
62 int rcSuccessDigestQuality;
63
64 char const *pchPem;
65 size_t cbPem;
66
67 uint8_t const *pbDer;
68 size_t cbDer;
69} g_aFiles[] =
70{
71#define MY_CERT_ENTRY(a_fMaybeNotInOpenSSL, a_fSelfSigned, a_rcSuccessDigestQuality, a_Name) \
72 { #a_Name, a_fMaybeNotInOpenSSL, a_fSelfSigned, a_rcSuccessDigestQuality, \
73 (const char *)RT_CONCAT(g_abPem_, a_Name), RT_CONCAT(g_cbPem_, a_Name), \
74 RT_CONCAT(g_abDer_, a_Name), RT_CONCAT(g_cbDer_, a_Name) }
75 MY_CERT_ENTRY(true, true, VINF_CR_DIGEST_SEVERELY_COMPROMISED, md4),
76 MY_CERT_ENTRY(false, true, VINF_CR_DIGEST_COMPROMISED, md5),
77 MY_CERT_ENTRY(false, true, VINF_CR_DIGEST_DEPRECATED, sha1),
78 MY_CERT_ENTRY(false, true, VINF_SUCCESS, sha224),
79 MY_CERT_ENTRY(false, true, VINF_SUCCESS, sha256),
80 MY_CERT_ENTRY(false, true, VINF_SUCCESS, sha384),
81 MY_CERT_ENTRY(false, true, VINF_SUCCESS, sha512),
82 MY_CERT_ENTRY(false, false, -1, cert1),
83};
84
85
86static void test1()
87{
88 RTTestSub(g_hTest, "Basics");
89 int rc;
90 for (unsigned i = 0; i < RT_ELEMENTS(g_aFiles); i++)
91 {
92 /*
93 * Decode.
94 */
95 /* Raw decoding of DER bytes, structure will have pointers to the raw data. */
96 RTCRX509CERTIFICATE Cert0;
97 RTASN1CURSORPRIMARY PrimaryCursor;
98 RTAsn1CursorInitPrimary(&PrimaryCursor, g_aFiles[i].pbDer, (uint32_t)g_aFiles[i].cbDer,
99 NULL /*pErrInfo*/, &g_RTAsn1DefaultAllocator, RTASN1CURSOR_FLAGS_DER, NULL /*pszErrorTag*/);
100 rc = RTCrX509Certificate_DecodeAsn1(&PrimaryCursor.Cursor, 0, &Cert0, "Cert0");
101 if (RT_SUCCESS(rc))
102 {
103 rc = RTCrX509Certificate_CheckSanity(&Cert0, 0, NULL /*pErrInfo*/, "Cert0");
104 if (RT_SUCCESS(rc))
105 {
106 /* Check the API, this clones the certificate so no data pointers. */
107 RTCRX509CERTIFICATE Cert1;
108 memset(&Cert1, i, sizeof(Cert1));
109 rc = RTCrX509Certificate_ReadFromBuffer(&Cert1, g_aFiles[i].pbDer, g_aFiles[i].cbDer, 0 /*fFlags*/,
110 &g_RTAsn1EFenceAllocator, NULL /*pErrInfo*/, NULL /*pszErrorTag*/);
111 if (RT_SUCCESS(rc))
112 {
113 /* Read the PEM variant. */
114 RTCRX509CERTIFICATE Cert2;
115 memset(&Cert2, ~i, sizeof(Cert2));
116 rc = RTCrX509Certificate_ReadFromBuffer(&Cert2, g_aFiles[i].pchPem, g_aFiles[i].cbPem, 0 /*fFlags*/,
117 &g_RTAsn1DefaultAllocator, NULL /*pErrInfo*/, NULL /*pszErrorTag*/);
118 if (RT_SUCCESS(rc))
119 {
120 /*
121 * Compare them, they should be all the same.
122 */
123 if (RTCrX509Certificate_Compare(&Cert0, &Cert1) != 0)
124 RTTestIFailed("Cert0 and Cert1 (DER) decoding of file %s (#%u) differs", g_aFiles[i].pszFile, i);
125 else if (RTCrX509Certificate_Compare(&Cert0, &Cert2) != 0)
126 RTTestIFailed("Cert0 and Cert2 (PEM) decoding of file %s (#%u) differs", g_aFiles[i].pszFile, i);
127 else if (RTCrX509Certificate_Compare(&Cert1, &Cert2) != 0)
128 RTTestIFailed("Cert1 (DER) and Cert2 (PEM) decoding of file %s (#%u) differs", g_aFiles[i].pszFile, i);
129 else
130 {
131 /*
132 * Encode the certificates.
133 */
134 unsigned j;
135 PRTCRX509CERTIFICATE paCerts[] = { &Cert0, &Cert1, &Cert2 };
136 for (j = 0; j < RT_ELEMENTS(paCerts); j++)
137 {
138 uint32_t cbEncoded = ~(j ^ i);
139 RTTESTI_CHECK_RC(rc = RTAsn1EncodePrepare(&paCerts[j]->SeqCore.Asn1Core,
140 RTASN1ENCODE_F_DER, &cbEncoded, NULL), VINF_SUCCESS);
141 if (RT_SUCCESS(rc) && cbEncoded != g_aFiles[i].cbDer)
142 RTTestIFailed("RTAsn1EncodePrepare of file %s (#%u) returned %#x bytes instead of %#x",
143 g_aFiles[i].pszFile, i, cbEncoded, g_aFiles[i].cbDer);
144
145 cbEncoded = (uint32_t)g_aFiles[i].cbDer;
146 void *pvTmp = RTTestGuardedAllocTail(g_hTest, cbEncoded);
147 RTTESTI_CHECK_RC(rc = RTAsn1EncodeToBuffer(&paCerts[j]->SeqCore.Asn1Core, RTASN1ENCODE_F_DER,
148 pvTmp, cbEncoded, NULL /*pErrInfo*/), VINF_SUCCESS);
149 if (RT_SUCCESS(rc) && memcmp(pvTmp, g_aFiles[i].pbDer, cbEncoded) != 0)
150 RTTestIFailed("RTAsn1EncodeToBuffer produces the wrong output for file %s (#%u), variation %u",
151 g_aFiles[i].pszFile, i, j);
152 RTTestGuardedFree(g_hTest, pvTmp);
153 }
154
155 /*
156 * Check that our self signed check works.
157 */
158 RTTESTI_CHECK(RTCrX509Certificate_IsSelfSigned(&Cert0) == g_aFiles[i].fSelfSigned);
159 RTTESTI_CHECK(RTCrX509Certificate_IsSelfSigned(&Cert1) == g_aFiles[i].fSelfSigned);
160 RTTESTI_CHECK(RTCrX509Certificate_IsSelfSigned(&Cert2) == g_aFiles[i].fSelfSigned);
161
162 if (g_aFiles[i].fSelfSigned)
163 {
164 /*
165 * Verify the certificate signature (self signed).
166 */
167 for (j = 0; j < RT_ELEMENTS(paCerts); j++)
168 {
169 rc = RTCrX509Certificate_VerifySignatureSelfSigned(paCerts[j], NULL /*pErrInfo*/);
170 if (RT_FAILURE(rc))
171 RTTestIFailed("RTCrX509Certificate_VerifySignatureSelfSigned failed for %s (#%u), variation %u: %Rrc",
172 g_aFiles[i].pszFile, i, j, rc);
173 else if ( rc != g_aFiles[i].rcSuccessDigestQuality
174 && g_aFiles[i].rcSuccessDigestQuality != -1)
175 RTTestIFailed("RTCrX509Certificate_VerifySignatureSelfSigned returned %Rrc rather than %Rrc for %s (#%u), variation %u",
176 rc, g_aFiles[i].rcSuccessDigestQuality, g_aFiles[i].pszFile, i, j);
177 }
178 }
179 }
180
181 RTCrX509Certificate_Delete(&Cert2);
182 }
183 else
184 RTTestIFailed("Error %Rrc decoding PEM file %s (#%u)", rc, g_aFiles[i].pszFile, i);
185 RTCrX509Certificate_Delete(&Cert1);
186 }
187 else
188 RTTestIFailed("Error %Rrc decoding DER file %s (#%u)", rc, g_aFiles[i].pszFile, i);
189 }
190 RTCrX509Certificate_Delete(&Cert0);
191 }
192 }
193}
194
195
196
197
198int main()
199{
200 RTEXITCODE rcExit = RTTestInitAndCreate("tstRTCrX509-1", &g_hTest);
201 if (rcExit != RTEXITCODE_SUCCESS)
202 return rcExit;
203 RTTestBanner(g_hTest);
204
205 test1();
206
207
208 return RTTestSummaryAndDestroy(g_hTest);
209}
210
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