VirtualBox

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

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