VirtualBox

source: vbox/trunk/src/VBox/Runtime/common/crypto/pkix-signature-core.cpp@ 98103

Last change on this file since 98103 was 98103, checked in by vboxsync, 23 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: 10.4 KB
Line 
1/* $Id: pkix-signature-core.cpp 98103 2023-01-17 14:15:46Z vboxsync $ */
2/** @file
3 * IPRT - Crypto - Public Key Signature Schema Algorithm, Core API.
4 */
5
6/*
7 * Copyright (C) 2006-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 "internal/iprt.h"
42#include <iprt/crypto/pkix.h>
43
44#include <iprt/assert.h>
45#include <iprt/asm.h>
46#include <iprt/errcore.h>
47#include <iprt/mem.h>
48#include <iprt/string.h>
49#include <iprt/crypto/digest.h>
50#include <iprt/crypto/key.h>
51
52
53/*********************************************************************************************************************************
54* Structures and Typedefs *
55*********************************************************************************************************************************/
56/**
57 * Generic public key signature scheme instance.
58 */
59typedef struct RTCRPKIXSIGNATUREINT
60{
61 /** Magic value (RTCRPKIXSIGNATUREINT_MAGIC). */
62 uint32_t u32Magic;
63 /** Reference counter. */
64 uint32_t volatile cRefs;
65 /** Pointer to the message digest descriptor. */
66 PCRTCRPKIXSIGNATUREDESC pDesc;
67 /** Key being used (referrenced of course). */
68 RTCRKEY hKey;
69 /** The operation this instance is licensed for. */
70 bool fSigning;
71 /** State. */
72 uint32_t uState;
73
74 /** Opaque data specific to the message digest algorithm, size given by
75 * RTCRPKIXSIGNATUREDESC::cbState. */
76 uint8_t abState[1];
77} RTCRPKIXSIGNATUREINT;
78AssertCompileMemberAlignment(RTCRPKIXSIGNATUREINT, abState, 8);
79/** Pointer to a public key algorithm instance. */
80typedef RTCRPKIXSIGNATUREINT *PRTCRPKIXSIGNATUREINT;
81
82/** Magic value for RTCRPKIXSIGNATUREINT::u32Magic (Baley Withfield Diffie). */
83#define RTCRPKIXSIGNATUREINT_MAGIC UINT32_C(0x19440605)
84
85/** @name RTCRPKIXSIGNATUREINT::uState values.
86 * @{ */
87/** Ready to go. */
88#define RTCRPKIXSIGNATURE_STATE_READY UINT32_C(1)
89/** Need reset. */
90#define RTCRPKIXSIGNATURE_STATE_DONE UINT32_C(2)
91/** Busted state, can happen after re-init. */
92#define RTCRPKIXSIGNATURE_STATE_BUSTED UINT32_C(3)
93/** @} */
94
95
96
97RTDECL(int) RTCrPkixSignatureCreate(PRTCRPKIXSIGNATURE phSignature, PCRTCRPKIXSIGNATUREDESC pDesc, void *pvOpaque,
98 bool fSigning, RTCRKEY hKey, PCRTASN1DYNTYPE pParams)
99{
100 /*
101 * Validate input.
102 */
103 AssertPtrReturn(phSignature, VERR_INVALID_POINTER);
104 AssertPtrReturn(pDesc, VERR_INVALID_POINTER);
105 if (pParams)
106 {
107 AssertPtrReturn(pParams, VERR_INVALID_POINTER);
108 if ( pParams->enmType == RTASN1TYPE_NULL
109 || !RTASN1CORE_IS_PRESENT(&pParams->u.Core))
110 pParams = NULL;
111 }
112 uint32_t cKeyRefs = RTCrKeyRetain(hKey);
113 AssertReturn(cKeyRefs != UINT32_MAX, VERR_INVALID_HANDLE);
114
115 /*
116 * Instantiate the algorithm for the given operation.
117 */
118 int rc = VINF_SUCCESS;
119 PRTCRPKIXSIGNATUREINT pThis = (PRTCRPKIXSIGNATUREINT)RTMemAllocZ(RT_UOFFSETOF_DYN(RTCRPKIXSIGNATUREINT,
120 abState[pDesc->cbState]));
121 if (pThis)
122 {
123 pThis->u32Magic = RTCRPKIXSIGNATUREINT_MAGIC;
124 pThis->cRefs = 1;
125 pThis->pDesc = pDesc;
126 pThis->fSigning = fSigning;
127 pThis->uState = RTCRPKIXSIGNATURE_STATE_READY;
128 pThis->hKey = hKey;
129 if (pDesc->pfnInit)
130 rc = pDesc->pfnInit(pDesc, pThis->abState, pvOpaque, fSigning, hKey, pParams);
131 if (RT_SUCCESS(rc))
132 {
133 *phSignature = pThis;
134 return VINF_SUCCESS;
135 }
136 pThis->u32Magic = 0;
137 RTMemFree(pThis);
138 }
139 else
140 rc = VERR_NO_MEMORY;
141 RTCrKeyRelease(hKey);
142 return rc;
143
144}
145
146
147RTDECL(uint32_t) RTCrPkixSignatureRetain(RTCRPKIXSIGNATURE hSignature)
148{
149 PRTCRPKIXSIGNATUREINT pThis = hSignature;
150 AssertPtrReturn(pThis, UINT32_MAX);
151 AssertReturn(pThis->u32Magic == RTCRPKIXSIGNATUREINT_MAGIC, UINT32_MAX);
152
153 uint32_t cRefs = ASMAtomicIncU32(&pThis->cRefs);
154 Assert(cRefs < 64);
155 return cRefs;
156}
157
158
159/**
160 * Destructor worker.
161 */
162static uint32_t rtCrPkixSignatureDestructor(PRTCRPKIXSIGNATUREINT pThis)
163{
164 pThis->u32Magic = ~RTCRPKIXSIGNATUREINT_MAGIC;
165 if (pThis->pDesc->pfnDelete)
166 pThis->pDesc->pfnDelete(pThis->pDesc, pThis->abState, pThis->fSigning);
167
168 RTCrKeyRelease(pThis->hKey);
169 pThis->hKey = NIL_RTCRKEY;
170
171 size_t cbToWipe = RT_UOFFSETOF_DYN(RTCRPKIXSIGNATUREINT, abState[pThis->pDesc->cbState]);
172 RTMemWipeThoroughly(pThis, cbToWipe, 6);
173
174 RTMemFree(pThis);
175 return 0;
176}
177
178
179RTDECL(uint32_t) RTCrPkixSignatureRelease(RTCRPKIXSIGNATURE hSignature)
180{
181 PRTCRPKIXSIGNATUREINT pThis = hSignature;
182 if (pThis == NIL_RTCRPKIXSIGNATURE)
183 return 0;
184 AssertPtrReturn(pThis, UINT32_MAX);
185 AssertReturn(pThis->u32Magic == RTCRPKIXSIGNATUREINT_MAGIC, UINT32_MAX);
186
187 uint32_t cRefs = ASMAtomicDecU32(&pThis->cRefs);
188 Assert(cRefs < 64);
189 if (!cRefs)
190 return rtCrPkixSignatureDestructor(pThis);
191 return cRefs;
192}
193
194
195/**
196 * Resets the signature provider instance prior to a new signing or verification
197 * opartion.
198 *
199 * @returns IPRT status code.
200 * @param pThis The instance to reset.
201 */
202static int rtCrPkxiSignatureReset(PRTCRPKIXSIGNATUREINT pThis)
203{
204 if (pThis->uState == RTCRPKIXSIGNATURE_STATE_DONE)
205 {
206 if (pThis->pDesc->pfnReset)
207 {
208 int rc = pThis->pDesc->pfnReset(pThis->pDesc, pThis->abState, pThis->fSigning);
209 if (RT_FAILURE(rc))
210 {
211 pThis->uState = RTCRPKIXSIGNATURE_STATE_BUSTED;
212 return rc;
213 }
214 }
215 pThis->uState = RTCRPKIXSIGNATURE_STATE_READY;
216 }
217 return VINF_SUCCESS;
218}
219
220
221RTDECL(int) RTCrPkixSignatureVerify(RTCRPKIXSIGNATURE hSignature, RTCRDIGEST hDigest,
222 void const *pvSignature, size_t cbSignature)
223{
224 PRTCRPKIXSIGNATUREINT pThis = hSignature;
225 AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
226 AssertReturn(pThis->u32Magic == RTCRPKIXSIGNATUREINT_MAGIC, VERR_INVALID_HANDLE);
227 AssertReturn(!pThis->fSigning, VERR_INVALID_FUNCTION);
228 AssertReturn(pThis->uState == RTCRPKIXSIGNATURE_STATE_READY || pThis->uState == RTCRPKIXSIGNATURE_STATE_DONE, VERR_INVALID_STATE);
229
230 uint32_t cRefs = RTCrDigestRetain(hDigest);
231 AssertReturn(cRefs != UINT32_MAX, VERR_INVALID_HANDLE);
232
233 int rc = rtCrPkxiSignatureReset(pThis);
234 if (RT_SUCCESS(rc))
235 {
236 rc = pThis->pDesc->pfnVerify(pThis->pDesc, pThis->abState, pThis->hKey, hDigest, pvSignature, cbSignature);
237 pThis->uState = RTCRPKIXSIGNATURE_STATE_DONE;
238 }
239
240 RTCrDigestRelease(hDigest);
241 return rc;
242}
243
244
245RTDECL(int) RTCrPkixSignatureVerifyBitString(RTCRPKIXSIGNATURE hSignature, RTCRDIGEST hDigest, PCRTASN1BITSTRING pSignature)
246{
247 /*
248 * Just unpack it and pass it on to the lower level API.
249 */
250 AssertPtrReturn(pSignature, VERR_INVALID_POINTER);
251 AssertReturn(RTAsn1BitString_IsPresent(pSignature), VERR_INVALID_PARAMETER);
252 uint32_t cbData = RTASN1BITSTRING_GET_BYTE_SIZE(pSignature);
253 void const *pvData = RTASN1BITSTRING_GET_BIT0_PTR(pSignature);
254 AssertPtrReturn(pvData, VERR_INVALID_PARAMETER);
255
256 return RTCrPkixSignatureVerify(hSignature, hDigest, pvData, cbData);
257}
258
259
260RTDECL(int) RTCrPkixSignatureVerifyOctetString(RTCRPKIXSIGNATURE hSignature, RTCRDIGEST hDigest, PCRTASN1OCTETSTRING pSignature)
261{
262 /*
263 * Just unpack it and pass it on to the lower level API.
264 */
265 AssertPtrReturn(pSignature, VERR_INVALID_POINTER);
266 AssertReturn(RTAsn1OctetString_IsPresent(pSignature), VERR_INVALID_PARAMETER);
267 uint32_t cbData = pSignature->Asn1Core.cb;
268 void const *pvData = pSignature->Asn1Core.uData.pv;
269 AssertPtrReturn(pvData, VERR_INVALID_PARAMETER);
270
271 return RTCrPkixSignatureVerify(hSignature, hDigest, pvData, cbData);
272}
273
274
275RTDECL(int) RTCrPkixSignatureSign(RTCRPKIXSIGNATURE hSignature, RTCRDIGEST hDigest,
276 void *pvSignature, size_t *pcbSignature)
277{
278 PRTCRPKIXSIGNATUREINT pThis = hSignature;
279 AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
280 AssertReturn(pThis->u32Magic == RTCRPKIXSIGNATUREINT_MAGIC, VERR_INVALID_HANDLE);
281 AssertReturn(pThis->fSigning, VERR_INVALID_FUNCTION);
282 AssertReturn(pThis->uState == RTCRPKIXSIGNATURE_STATE_READY || pThis->uState == RTCRPKIXSIGNATURE_STATE_DONE, VERR_INVALID_STATE);
283
284 uint32_t cRefs = RTCrDigestRetain(hDigest);
285 AssertReturn(cRefs != UINT32_MAX, VERR_INVALID_HANDLE);
286
287 int rc = rtCrPkxiSignatureReset(pThis);
288 if (RT_SUCCESS(rc))
289 {
290 rc = pThis->pDesc->pfnSign(pThis->pDesc, pThis->abState, pThis->hKey, hDigest, pvSignature, pcbSignature);
291 if (rc != VERR_BUFFER_OVERFLOW)
292 pThis->uState = RTCRPKIXSIGNATURE_STATE_DONE;
293 }
294
295 RTCrDigestRelease(hDigest);
296 return rc;
297}
298
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