VirtualBox

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

Last change on this file since 62477 was 62477, checked in by vboxsync, 8 years ago

(C) 2016

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 9.7 KB
Line 
1/* $Id: pkix-signature-core.cpp 62477 2016-07-22 18:27:37Z vboxsync $ */
2/** @file
3 * IPRT - Crypto - Public Key Signature Schema Algorithm, Core API.
4 */
5
6/*
7 * Copyright (C) 2006-2016 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_OFFSETOF(RTCRPKIXSIGNATUREINT, abState[pDesc->cbState]));
110 if (pThis)
111 {
112 pThis->u32Magic = RTCRPKIXSIGNATUREINT_MAGIC;
113 pThis->cRefs = 1;
114 pThis->pDesc = pDesc;
115 pThis->fSigning = fSigning;
116 pThis->uState = RTCRPKIXSIGNATURE_STATE_READY;
117 if (pDesc->pfnInit)
118 rc = pDesc->pfnInit(pDesc, pThis->abState, pvOpaque, fSigning, pKey, pParams);
119 if (RT_SUCCESS(rc))
120 {
121 *phSignature = pThis;
122 return VINF_SUCCESS;
123 }
124 pThis->u32Magic = 0;
125 RTMemFree(pThis);
126 }
127 else
128 rc = VERR_NO_MEMORY;
129 return rc;
130
131}
132
133
134RTDECL(uint32_t) RTCrPkixSignatureRetain(RTCRPKIXSIGNATURE hSignature)
135{
136 PRTCRPKIXSIGNATUREINT pThis = hSignature;
137 AssertPtrReturn(pThis, UINT32_MAX);
138 AssertReturn(pThis->u32Magic == RTCRPKIXSIGNATUREINT_MAGIC, UINT32_MAX);
139
140 uint32_t cRefs = ASMAtomicIncU32(&pThis->cRefs);
141 Assert(cRefs < 64);
142 return cRefs;
143}
144
145
146RTDECL(uint32_t) RTCrPkixSignatureRelease(RTCRPKIXSIGNATURE hSignature)
147{
148 PRTCRPKIXSIGNATUREINT pThis = hSignature;
149 if (pThis == NIL_RTCRPKIXSIGNATURE)
150 return 0;
151 AssertPtrReturn(pThis, UINT32_MAX);
152 AssertReturn(pThis->u32Magic == RTCRPKIXSIGNATUREINT_MAGIC, UINT32_MAX);
153
154 uint32_t cRefs = ASMAtomicDecU32(&pThis->cRefs);
155 Assert(cRefs < 64);
156 if (!cRefs)
157 {
158 pThis->u32Magic = ~RTCRPKIXSIGNATUREINT_MAGIC;
159 if (pThis->pDesc->pfnDelete)
160 pThis->pDesc->pfnDelete(pThis->pDesc, pThis->abState, pThis->fSigning);
161
162 size_t cbToWipe = RT_OFFSETOF(RTCRPKIXSIGNATUREINT, abState[pThis->pDesc->cbState]);
163 RTMemWipeThoroughly(pThis, cbToWipe, 6);
164
165 RTMemFree(pThis);
166 }
167 return cRefs;
168}
169
170
171/**
172 * Resets the signature provider instance prior to a new signing or verification
173 * opartion.
174 *
175 * @returns IPRT status code.
176 * @param pThis The instance to reset.
177 */
178static int rtCrPkxiSignatureReset(PRTCRPKIXSIGNATUREINT pThis)
179{
180 if (pThis->uState == RTCRPKIXSIGNATURE_STATE_DONE)
181 {
182 if (pThis->pDesc->pfnReset)
183 {
184 int rc = pThis->pDesc->pfnReset(pThis->pDesc, pThis->abState, pThis->fSigning);
185 if (RT_FAILURE(rc))
186 {
187 pThis->uState = RTCRPKIXSIGNATURE_STATE_BUSTED;
188 return rc;
189 }
190 }
191 pThis->uState = RTCRPKIXSIGNATURE_STATE_READY;
192 }
193 return VINF_SUCCESS;
194}
195
196
197RTDECL(int) RTCrPkixSignatureVerify(RTCRPKIXSIGNATURE hSignature, RTCRDIGEST hDigest,
198 void const *pvSignature, size_t cbSignature)
199{
200 PRTCRPKIXSIGNATUREINT pThis = hSignature;
201 AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
202 AssertReturn(pThis->u32Magic == RTCRPKIXSIGNATUREINT_MAGIC, VERR_INVALID_HANDLE);
203 AssertReturn(!pThis->fSigning, VERR_INVALID_FUNCTION);
204 AssertReturn(pThis->uState == RTCRPKIXSIGNATURE_STATE_READY || pThis->uState == RTCRPKIXSIGNATURE_STATE_DONE, VERR_INVALID_STATE);
205
206 uint32_t cRefs = RTCrDigestRetain(hDigest);
207 AssertReturn(cRefs != UINT32_MAX, VERR_INVALID_HANDLE);
208
209 int rc = rtCrPkxiSignatureReset(pThis);
210 if (RT_SUCCESS(rc))
211 {
212 rc = pThis->pDesc->pfnVerify(pThis->pDesc, pThis->abState, hDigest, pvSignature, cbSignature);
213 pThis->uState = RTCRPKIXSIGNATURE_STATE_DONE;
214 }
215
216 RTCrDigestRelease(hDigest);
217 return rc;
218}
219
220
221RTDECL(int) RTCrPkixSignatureVerifyBitString(RTCRPKIXSIGNATURE hSignature, RTCRDIGEST hDigest, PCRTASN1BITSTRING pSignature)
222{
223 /*
224 * Just unpack it and pass it on to the lower level API.
225 */
226 AssertPtrReturn(pSignature, VERR_INVALID_POINTER);
227 AssertReturn(RTAsn1BitString_IsPresent(pSignature), VERR_INVALID_PARAMETER);
228 uint32_t cbData = RTASN1BITSTRING_GET_BYTE_SIZE(pSignature);
229 void const *pvData = RTASN1BITSTRING_GET_BIT0_PTR(pSignature);
230 AssertPtrReturn(pvData, VERR_INVALID_PARAMETER);
231
232 return RTCrPkixSignatureVerify(hSignature, hDigest, pvData, cbData);
233}
234
235
236RTDECL(int) RTCrPkixSignatureVerifyOctetString(RTCRPKIXSIGNATURE hSignature, RTCRDIGEST hDigest, PCRTASN1OCTETSTRING pSignature)
237{
238 /*
239 * Just unpack it and pass it on to the lower level API.
240 */
241 AssertPtrReturn(pSignature, VERR_INVALID_POINTER);
242 AssertReturn(RTAsn1OctetString_IsPresent(pSignature), VERR_INVALID_PARAMETER);
243 uint32_t cbData = pSignature->Asn1Core.cb;
244 void const *pvData = pSignature->Asn1Core.uData.pv;
245 AssertPtrReturn(pvData, VERR_INVALID_PARAMETER);
246
247 return RTCrPkixSignatureVerify(hSignature, hDigest, pvData, cbData);
248}
249
250
251RTDECL(int) RTCrPkixSignatureSign(RTCRPKIXSIGNATURE hSignature, RTCRDIGEST hDigest,
252 void *pvSignature, size_t *pcbSignature)
253{
254 PRTCRPKIXSIGNATUREINT pThis = hSignature;
255 AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
256 AssertReturn(pThis->u32Magic == RTCRPKIXSIGNATUREINT_MAGIC, VERR_INVALID_HANDLE);
257 AssertReturn(pThis->fSigning, VERR_INVALID_FUNCTION);
258 AssertReturn(pThis->uState == RTCRPKIXSIGNATURE_STATE_READY || pThis->uState == RTCRPKIXSIGNATURE_STATE_DONE, VERR_INVALID_STATE);
259
260 uint32_t cRefs = RTCrDigestRetain(hDigest);
261 AssertReturn(cRefs != UINT32_MAX, VERR_INVALID_HANDLE);
262
263 int rc = rtCrPkxiSignatureReset(pThis);
264 if (RT_SUCCESS(rc))
265 {
266 rc = pThis->pDesc->pfnSign(pThis->pDesc, pThis->abState, hDigest, pvSignature, pcbSignature);
267 if (rc != VERR_BUFFER_OVERFLOW)
268 pThis->uState = RTCRPKIXSIGNATURE_STATE_DONE;
269 }
270
271 RTCrDigestRelease(hDigest);
272 return rc;
273}
274
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