VirtualBox

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

Last change on this file since 73097 was 73097, checked in by vboxsync, 7 years ago

*: Made RT_UOFFSETOF, RT_OFFSETOF, RT_UOFFSETOF_ADD and RT_OFFSETOF_ADD work like builtin_offsetof() and require compile time resolvable requests, adding RT_UOFFSETOF_DYN for the dynamic questions that can only be answered at runtime.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 9.8 KB
Line 
1/* $Id: pkix-signature-core.cpp 73097 2018-07-12 21:06:33Z vboxsync $ */
2/** @file
3 * IPRT - Crypto - Public Key Signature Schema Algorithm, Core API.
4 */
5
6/*
7 * Copyright (C) 2006-2017 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/err.h>
37#include <iprt/mem.h>
38#include <iprt/string.h>
39#include <iprt/crypto/digest.h>
40
41
42/*********************************************************************************************************************************
43* Structures and Typedefs *
44*********************************************************************************************************************************/
45/**
46 * Generic public key signature scheme instance.
47 */
48typedef struct RTCRPKIXSIGNATUREINT
49{
50 /** Magic value (RTCRPKIXSIGNATUREINT_MAGIC). */
51 uint32_t u32Magic;
52 /** Reference counter. */
53 uint32_t volatile cRefs;
54 /** Pointer to the message digest descriptor. */
55 PCRTCRPKIXSIGNATUREDESC pDesc;
56 /** The operation this instance is licensed for. */
57 bool fSigning;
58 /** State. */
59 uint32_t uState;
60#if ARCH_BITS == 32
61 uint32_t uPadding;
62#endif
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, PCRTASN1BITSTRING pKey, PCRTASN1DYNTYPE pParams)
89{
90 /*
91 * Validate input.
92 */
93 AssertPtrReturn(phSignature, VERR_INVALID_POINTER);
94 AssertPtrReturn(pDesc, VERR_INVALID_POINTER);
95 AssertPtrReturn(pKey, VERR_INVALID_POINTER);
96 AssertReturn(RTAsn1BitString_IsPresent(pKey), VERR_INVALID_PARAMETER);
97 if (pParams)
98 {
99 AssertPtrReturn(pParams, VERR_INVALID_POINTER);
100 if ( pParams->enmType == RTASN1TYPE_NULL
101 || !RTASN1CORE_IS_PRESENT(&pParams->u.Core))
102 pParams = NULL;
103 }
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 if (pDesc->pfnInit)
119 rc = pDesc->pfnInit(pDesc, pThis->abState, pvOpaque, fSigning, pKey, pParams);
120 if (RT_SUCCESS(rc))
121 {
122 *phSignature = pThis;
123 return VINF_SUCCESS;
124 }
125 pThis->u32Magic = 0;
126 RTMemFree(pThis);
127 }
128 else
129 rc = VERR_NO_MEMORY;
130 return rc;
131
132}
133
134
135RTDECL(uint32_t) RTCrPkixSignatureRetain(RTCRPKIXSIGNATURE hSignature)
136{
137 PRTCRPKIXSIGNATUREINT pThis = hSignature;
138 AssertPtrReturn(pThis, UINT32_MAX);
139 AssertReturn(pThis->u32Magic == RTCRPKIXSIGNATUREINT_MAGIC, UINT32_MAX);
140
141 uint32_t cRefs = ASMAtomicIncU32(&pThis->cRefs);
142 Assert(cRefs < 64);
143 return cRefs;
144}
145
146
147RTDECL(uint32_t) RTCrPkixSignatureRelease(RTCRPKIXSIGNATURE hSignature)
148{
149 PRTCRPKIXSIGNATUREINT pThis = hSignature;
150 if (pThis == NIL_RTCRPKIXSIGNATURE)
151 return 0;
152 AssertPtrReturn(pThis, UINT32_MAX);
153 AssertReturn(pThis->u32Magic == RTCRPKIXSIGNATUREINT_MAGIC, UINT32_MAX);
154
155 uint32_t cRefs = ASMAtomicDecU32(&pThis->cRefs);
156 Assert(cRefs < 64);
157 if (!cRefs)
158 {
159 pThis->u32Magic = ~RTCRPKIXSIGNATUREINT_MAGIC;
160 if (pThis->pDesc->pfnDelete)
161 pThis->pDesc->pfnDelete(pThis->pDesc, pThis->abState, pThis->fSigning);
162
163 size_t cbToWipe = RT_UOFFSETOF_DYN(RTCRPKIXSIGNATUREINT, abState[pThis->pDesc->cbState]);
164 RTMemWipeThoroughly(pThis, cbToWipe, 6);
165
166 RTMemFree(pThis);
167 }
168 return cRefs;
169}
170
171
172/**
173 * Resets the signature provider instance prior to a new signing or verification
174 * opartion.
175 *
176 * @returns IPRT status code.
177 * @param pThis The instance to reset.
178 */
179static int rtCrPkxiSignatureReset(PRTCRPKIXSIGNATUREINT pThis)
180{
181 if (pThis->uState == RTCRPKIXSIGNATURE_STATE_DONE)
182 {
183 if (pThis->pDesc->pfnReset)
184 {
185 int rc = pThis->pDesc->pfnReset(pThis->pDesc, pThis->abState, pThis->fSigning);
186 if (RT_FAILURE(rc))
187 {
188 pThis->uState = RTCRPKIXSIGNATURE_STATE_BUSTED;
189 return rc;
190 }
191 }
192 pThis->uState = RTCRPKIXSIGNATURE_STATE_READY;
193 }
194 return VINF_SUCCESS;
195}
196
197
198RTDECL(int) RTCrPkixSignatureVerify(RTCRPKIXSIGNATURE hSignature, RTCRDIGEST hDigest,
199 void const *pvSignature, size_t cbSignature)
200{
201 PRTCRPKIXSIGNATUREINT pThis = hSignature;
202 AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
203 AssertReturn(pThis->u32Magic == RTCRPKIXSIGNATUREINT_MAGIC, VERR_INVALID_HANDLE);
204 AssertReturn(!pThis->fSigning, VERR_INVALID_FUNCTION);
205 AssertReturn(pThis->uState == RTCRPKIXSIGNATURE_STATE_READY || pThis->uState == RTCRPKIXSIGNATURE_STATE_DONE, VERR_INVALID_STATE);
206
207 uint32_t cRefs = RTCrDigestRetain(hDigest);
208 AssertReturn(cRefs != UINT32_MAX, VERR_INVALID_HANDLE);
209
210 int rc = rtCrPkxiSignatureReset(pThis);
211 if (RT_SUCCESS(rc))
212 {
213 rc = pThis->pDesc->pfnVerify(pThis->pDesc, pThis->abState, hDigest, pvSignature, cbSignature);
214 pThis->uState = RTCRPKIXSIGNATURE_STATE_DONE;
215 }
216
217 RTCrDigestRelease(hDigest);
218 return rc;
219}
220
221
222RTDECL(int) RTCrPkixSignatureVerifyBitString(RTCRPKIXSIGNATURE hSignature, RTCRDIGEST hDigest, PCRTASN1BITSTRING pSignature)
223{
224 /*
225 * Just unpack it and pass it on to the lower level API.
226 */
227 AssertPtrReturn(pSignature, VERR_INVALID_POINTER);
228 AssertReturn(RTAsn1BitString_IsPresent(pSignature), VERR_INVALID_PARAMETER);
229 uint32_t cbData = RTASN1BITSTRING_GET_BYTE_SIZE(pSignature);
230 void const *pvData = RTASN1BITSTRING_GET_BIT0_PTR(pSignature);
231 AssertPtrReturn(pvData, VERR_INVALID_PARAMETER);
232
233 return RTCrPkixSignatureVerify(hSignature, hDigest, pvData, cbData);
234}
235
236
237RTDECL(int) RTCrPkixSignatureVerifyOctetString(RTCRPKIXSIGNATURE hSignature, RTCRDIGEST hDigest, PCRTASN1OCTETSTRING pSignature)
238{
239 /*
240 * Just unpack it and pass it on to the lower level API.
241 */
242 AssertPtrReturn(pSignature, VERR_INVALID_POINTER);
243 AssertReturn(RTAsn1OctetString_IsPresent(pSignature), VERR_INVALID_PARAMETER);
244 uint32_t cbData = pSignature->Asn1Core.cb;
245 void const *pvData = pSignature->Asn1Core.uData.pv;
246 AssertPtrReturn(pvData, VERR_INVALID_PARAMETER);
247
248 return RTCrPkixSignatureVerify(hSignature, hDigest, pvData, cbData);
249}
250
251
252RTDECL(int) RTCrPkixSignatureSign(RTCRPKIXSIGNATURE hSignature, RTCRDIGEST hDigest,
253 void *pvSignature, size_t *pcbSignature)
254{
255 PRTCRPKIXSIGNATUREINT pThis = hSignature;
256 AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
257 AssertReturn(pThis->u32Magic == RTCRPKIXSIGNATUREINT_MAGIC, VERR_INVALID_HANDLE);
258 AssertReturn(pThis->fSigning, VERR_INVALID_FUNCTION);
259 AssertReturn(pThis->uState == RTCRPKIXSIGNATURE_STATE_READY || pThis->uState == RTCRPKIXSIGNATURE_STATE_DONE, VERR_INVALID_STATE);
260
261 uint32_t cRefs = RTCrDigestRetain(hDigest);
262 AssertReturn(cRefs != UINT32_MAX, VERR_INVALID_HANDLE);
263
264 int rc = rtCrPkxiSignatureReset(pThis);
265 if (RT_SUCCESS(rc))
266 {
267 rc = pThis->pDesc->pfnSign(pThis->pDesc, pThis->abState, hDigest, pvSignature, pcbSignature);
268 if (rc != VERR_BUFFER_OVERFLOW)
269 pThis->uState = RTCRPKIXSIGNATURE_STATE_DONE;
270 }
271
272 RTCrDigestRelease(hDigest);
273 return rc;
274}
275
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