VirtualBox

source: vbox/trunk/src/VBox/Runtime/common/crypto/digest-core.cpp@ 59689

Last change on this file since 59689 was 59689, checked in by vboxsync, 9 years ago

IPRT: Added RTCrDigestGetAlgorithmOid, RTCrDigestTypeToAlgorithmOid, RTCrPkixPubKeyVerifySignedDigest, RTCrX509AlgorithmIdentifier_CombineEncryptionAndDigest, RTCrX509AlgorithmIdentifier_CombineEncryptionOidAndDigestOid, and RTCrX509AlgorithmIdentifier_CompareDigestOidAndEncryptedDigestOid.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 11.8 KB
Line 
1/* $Id: digest-core.cpp 59689 2016-02-15 21:25:36Z vboxsync $ */
2/** @file
3 * IPRT - Crypto - Cryptographic Hash / Message Digest API
4 */
5
6/*
7 * Copyright (C) 2006-2015 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/digest.h>
33
34#include <iprt/asm.h>
35#include <iprt/err.h>
36#include <iprt/mem.h>
37#include <iprt/string.h>
38#include <iprt/crypto/x509.h>
39
40
41/*********************************************************************************************************************************
42* Structures and Typedefs *
43*********************************************************************************************************************************/
44/**
45 * Generic message digest instance.
46 */
47typedef struct RTCRDIGESTINT
48{
49 /** Magic value (RTCRDIGESTINT_MAGIC). */
50 uint32_t u32Magic;
51 /** Reference counter. */
52 uint32_t volatile cRefs;
53 /** Pointer to the message digest descriptor. */
54 PCRTCRDIGESTDESC pDesc;
55 /** The offset into abState of the storage space . At
56 * least RTCRDIGESTDESC::cbHash bytes is available at that location. */
57 uint32_t offHash;
58 /** State. */
59 uint32_t uState;
60 /** The number of bytes consumed. */
61 uint64_t cbConsumed;
62 /** Opaque data specific to the message digest algorithm, size given by
63 * RTCRDIGESTDESC::cbState. This is followed by space for the final hash at
64 * offHash with size RTCRDIGESTDESC::cbHash. */
65 uint8_t abState[1];
66} RTCRDIGESTINT;
67/** Pointer to a message digest instance. */
68typedef RTCRDIGESTINT *PRTCRDIGESTINT;
69
70/** Magic value for RTCRDIGESTINT::u32Magic (Ralph C. Merkle). */
71#define RTCRDIGESTINT_MAGIC UINT32_C(0x19520202)
72
73/** @name RTCRDIGESTINT::uState values.
74 * @{ */
75/** Ready for more data. */
76#define RTCRDIGEST_STATE_READY UINT32_C(1)
77/** The hash has been finalized and can be found at offHash. */
78#define RTCRDIGEST_STATE_FINAL UINT32_C(2)
79/** Busted state, can happen after re-init. */
80#define RTCRDIGEST_STATE_BUSTED UINT32_C(3)
81/** @} */
82
83
84
85RTDECL(int) RTCrDigestCreate(PRTCRDIGEST phDigest, PCRTCRDIGESTDESC pDesc, void *pvOpaque)
86{
87 AssertPtrReturn(phDigest, VERR_INVALID_POINTER);
88 AssertPtrReturn(pDesc, VERR_INVALID_POINTER);
89
90 int rc = VINF_SUCCESS;
91 uint32_t offHash = RT_ALIGN_32(pDesc->cbState, 8);
92 PRTCRDIGESTINT pThis = (PRTCRDIGESTINT)RTMemAllocZ(RT_OFFSETOF(RTCRDIGESTINT, abState[offHash + pDesc->cbHash]));
93 if (pThis)
94 {
95 pThis->u32Magic = RTCRDIGESTINT_MAGIC;
96 pThis->cRefs = 1;
97 pThis->offHash = offHash;
98 pThis->pDesc = pDesc;
99 pThis->uState = RTCRDIGEST_STATE_READY;
100 if (pDesc->pfnInit)
101 rc = pDesc->pfnInit(pThis->abState, pvOpaque, false /*fReInit*/);
102 if (RT_SUCCESS(rc))
103 {
104 *phDigest = pThis;
105 return VINF_SUCCESS;
106 }
107 pThis->u32Magic = 0;
108 RTMemFree(pThis);
109 }
110 else
111 rc = VERR_NO_MEMORY;
112 return rc;
113}
114
115
116RTDECL(int) RTCrDigestClone(PRTCRDIGEST phDigest, RTCRDIGEST hSrc)
117{
118 AssertPtrReturn(phDigest, VERR_INVALID_POINTER);
119 AssertPtrReturn(hSrc, VERR_INVALID_HANDLE);
120 AssertReturn(hSrc->u32Magic == RTCRDIGESTINT_MAGIC, VERR_INVALID_HANDLE);
121
122 int rc = VINF_SUCCESS;
123 uint32_t const offHash = hSrc->offHash;
124 PRTCRDIGESTINT pThis = (PRTCRDIGESTINT)RTMemAllocZ(RT_OFFSETOF(RTCRDIGESTINT, abState[offHash + hSrc->pDesc->cbHash]));
125 if (pThis)
126 {
127 pThis->u32Magic = RTCRDIGESTINT_MAGIC;
128 pThis->cRefs = 1;
129 pThis->offHash = offHash;
130 pThis->pDesc = hSrc->pDesc;
131 if (hSrc->pDesc->pfnClone)
132 rc = hSrc->pDesc->pfnClone(pThis->abState, hSrc->abState);
133 else
134 memcpy(pThis->abState, hSrc->abState, offHash);
135 memcpy(&pThis->abState[offHash], &hSrc->abState[offHash], hSrc->pDesc->cbHash);
136 pThis->uState = hSrc->uState;
137
138 if (RT_SUCCESS(rc))
139 {
140 *phDigest = pThis;
141 return VINF_SUCCESS;
142 }
143 pThis->u32Magic = 0;
144 RTMemFree(pThis);
145 }
146 else
147 rc = VERR_NO_MEMORY;
148 return rc;
149}
150
151
152RTDECL(int) RTCrDigestReset(RTCRDIGEST hDigest)
153{
154 PRTCRDIGESTINT pThis = hDigest;
155 AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
156 AssertReturn(pThis->u32Magic == RTCRDIGESTINT_MAGIC, VERR_INVALID_HANDLE);
157
158 pThis->cbConsumed = 0;
159 pThis->uState = RTCRDIGEST_STATE_READY;
160
161 int rc = VINF_SUCCESS;
162 if (pThis->pDesc->pfnInit)
163 {
164 rc = pThis->pDesc->pfnInit(pThis->abState, NULL, true /*fReInit*/);
165 if (RT_FAILURE(rc))
166 pThis->uState = RTCRDIGEST_STATE_BUSTED;
167 RT_BZERO(&pThis->abState[pThis->offHash], pThis->pDesc->cbHash);
168 }
169 else
170 RT_BZERO(pThis->abState, pThis->offHash + pThis->pDesc->cbHash);
171 return rc;
172}
173
174
175RTDECL(uint32_t) RTCrDigestRetain(RTCRDIGEST hDigest)
176{
177 PRTCRDIGESTINT pThis = hDigest;
178 AssertPtrReturn(pThis, UINT32_MAX);
179 AssertReturn(pThis->u32Magic == RTCRDIGESTINT_MAGIC, UINT32_MAX);
180
181 uint32_t cRefs = ASMAtomicIncU32(&pThis->cRefs);
182 Assert(cRefs < 64);
183 return cRefs;
184}
185
186
187RTDECL(uint32_t) RTCrDigestRelease(RTCRDIGEST hDigest)
188{
189 PRTCRDIGESTINT pThis = hDigest;
190 if (pThis == NIL_RTCRDIGEST)
191 return 0;
192 AssertPtrReturn(pThis, UINT32_MAX);
193 AssertReturn(pThis->u32Magic == RTCRDIGESTINT_MAGIC, UINT32_MAX);
194
195 uint32_t cRefs = ASMAtomicDecU32(&pThis->cRefs);
196 if (!cRefs)
197 {
198 pThis->u32Magic = ~RTCRDIGESTINT_MAGIC;
199 if (pThis->pDesc->pfnDelete)
200 pThis->pDesc->pfnDelete(pThis->abState);
201 RTMemFree(pThis);
202 }
203 Assert(cRefs < 64);
204 return cRefs;
205}
206
207
208RTDECL(int) RTCrDigestUpdate(RTCRDIGEST hDigest, void const *pvData, size_t cbData)
209{
210 PRTCRDIGESTINT pThis = hDigest;
211 AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
212 AssertReturn(pThis->u32Magic == RTCRDIGESTINT_MAGIC, VERR_INVALID_HANDLE);
213 AssertReturn(pThis->uState == RTCRDIGEST_STATE_READY, VERR_INVALID_STATE);
214
215 pThis->pDesc->pfnUpdate(pThis->abState, pvData, cbData);
216 pThis->cbConsumed += cbData;
217 return VINF_SUCCESS;
218}
219
220
221RTDECL(int) RTCrDigestFinal(RTCRDIGEST hDigest, void *pvHash, size_t cbHash)
222{
223 PRTCRDIGESTINT pThis = hDigest;
224 AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
225 AssertReturn(pThis->u32Magic == RTCRDIGESTINT_MAGIC, VERR_INVALID_HANDLE);
226 AssertReturn(pThis->uState == RTCRDIGEST_STATE_READY || pThis->uState == RTCRDIGEST_STATE_FINAL, VERR_INVALID_STATE);
227 AssertPtrNullReturn(pvHash, VERR_INVALID_POINTER);
228
229 /*
230 * Make sure the hash calculation is final.
231 */
232 if (pThis->uState == RTCRDIGEST_STATE_READY)
233 {
234 pThis->pDesc->pfnFinal(pThis->abState, &pThis->abState[pThis->offHash]);
235 pThis->uState = RTCRDIGEST_STATE_FINAL;
236 }
237 else
238 AssertReturn(pThis->uState == RTCRDIGEST_STATE_FINAL, VERR_INVALID_STATE);
239
240 /*
241 * Copy out the hash if requested.
242 */
243 if (cbHash > 0)
244 {
245 uint32_t cbNeeded = pThis->pDesc->cbHash;
246 if (pThis->pDesc->pfnGetHashSize)
247 cbNeeded = pThis->pDesc->pfnGetHashSize(pThis->abState);
248 Assert(cbNeeded > 0);
249
250 if (cbNeeded == cbHash)
251 memcpy(pvHash, &pThis->abState[pThis->offHash], cbNeeded);
252 else if (cbNeeded > cbHash)
253 {
254 memcpy(pvHash, &pThis->abState[pThis->offHash], cbNeeded);
255 memset((uint8_t *)pvHash + cbNeeded, 0, cbHash - cbNeeded);
256 return VINF_BUFFER_UNDERFLOW;
257 }
258 else
259 {
260 memcpy(pvHash, &pThis->abState[pThis->offHash], cbHash);
261 return VERR_BUFFER_OVERFLOW;
262 }
263 }
264
265 return VINF_SUCCESS;
266}
267
268
269RTDECL(bool) RTCrDigestMatch(RTCRDIGEST hDigest, void const *pvHash, size_t cbHash)
270{
271 PRTCRDIGESTINT pThis = hDigest;
272
273 int rc = RTCrDigestFinal(pThis, NULL, 0);
274 AssertRCReturn(rc, false);
275
276 AssertPtrReturn(pvHash, false);
277 return pThis->pDesc->cbHash == cbHash
278 && !memcmp(&pThis->abState[pThis->offHash], pvHash, cbHash);
279}
280
281
282RTDECL(uint8_t const *) RTCrDigestGetHash(RTCRDIGEST hDigest)
283{
284 PRTCRDIGESTINT pThis = hDigest;
285 AssertPtrReturn(pThis, NULL);
286 AssertReturn(pThis->u32Magic == RTCRDIGESTINT_MAGIC, NULL);
287
288 int rc = RTCrDigestFinal(pThis, NULL, 0);
289 AssertRCReturn(rc, NULL);
290
291 return &pThis->abState[pThis->offHash];
292}
293
294
295RTDECL(uint32_t) RTCrDigestGetHashSize(RTCRDIGEST hDigest)
296{
297 PRTCRDIGESTINT pThis = hDigest;
298 AssertPtrReturn(pThis, 0);
299 AssertReturn(pThis->u32Magic == RTCRDIGESTINT_MAGIC, 0);
300 if (pThis->pDesc->pfnGetHashSize)
301 {
302 uint32_t cbHash = pThis->pDesc->pfnGetHashSize(pThis->abState);
303 Assert(cbHash <= pThis->pDesc->cbHash);
304 return cbHash;
305 }
306 return pThis->pDesc->cbHash;
307}
308
309
310RTDECL(uint64_t) RTCrDigestGetConsumedSize(RTCRDIGEST hDigest)
311{
312 PRTCRDIGESTINT pThis = hDigest;
313 AssertPtrReturn(pThis, 0);
314 AssertReturn(pThis->u32Magic == RTCRDIGESTINT_MAGIC, 0);
315 return pThis->cbConsumed;
316}
317
318
319RTDECL(bool) RTCrDigestIsFinalized(RTCRDIGEST hDigest)
320{
321 PRTCRDIGESTINT pThis = hDigest;
322 AssertPtrReturn(pThis, false);
323 AssertReturn(pThis->u32Magic == RTCRDIGESTINT_MAGIC, false);
324 return pThis->uState == RTCRDIGEST_STATE_FINAL;
325}
326
327
328RTDECL(RTDIGESTTYPE) RTCrDigestGetType(RTCRDIGEST hDigest)
329{
330 PRTCRDIGESTINT pThis = hDigest;
331 AssertPtrReturn(pThis, RTDIGESTTYPE_INVALID);
332 AssertReturn(pThis->u32Magic == RTCRDIGESTINT_MAGIC, RTDIGESTTYPE_INVALID);
333
334 RTDIGESTTYPE enmType = pThis->pDesc->enmType;
335 if (pThis->pDesc->pfnGetDigestType)
336 enmType = pThis->pDesc->pfnGetDigestType(pThis->abState);
337 return enmType;
338}
339
340
341RTDECL(const char *) RTCrDigestGetAlgorithmOid(RTCRDIGEST hDigest)
342{
343 return RTCrDigestTypeToAlgorithmOid(RTCrDigestGetType(hDigest));
344}
345
346
347RTDECL(const char *) RTCrDigestTypeToAlgorithmOid(RTDIGESTTYPE enmDigestType)
348{
349 switch (enmDigestType)
350 {
351 case RTDIGESTTYPE_MD2: return RTCRX509ALGORITHMIDENTIFIERID_MD2;
352 case RTDIGESTTYPE_MD4: return RTCRX509ALGORITHMIDENTIFIERID_MD4;
353 case RTDIGESTTYPE_MD5: return RTCRX509ALGORITHMIDENTIFIERID_MD5;
354 case RTDIGESTTYPE_SHA1: return RTCRX509ALGORITHMIDENTIFIERID_SHA1;
355 case RTDIGESTTYPE_SHA224: return RTCRX509ALGORITHMIDENTIFIERID_SHA224;
356 case RTDIGESTTYPE_SHA256: return RTCRX509ALGORITHMIDENTIFIERID_SHA256;
357 case RTDIGESTTYPE_SHA384: return RTCRX509ALGORITHMIDENTIFIERID_SHA384;
358 case RTDIGESTTYPE_SHA512: return RTCRX509ALGORITHMIDENTIFIERID_SHA512;
359 default: return NULL;
360 }
361}
362
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