VirtualBox

source: vbox/trunk/src/VBox/Runtime/common/checksum/openssl-sha3.cpp@ 85618

Last change on this file since 85618 was 85618, checked in by vboxsync, 4 years ago

IPRT: Adding SHA-3. [scm fix] bugref:9734

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 9.3 KB
Line 
1/* $Id: openssl-sha3.cpp 85618 2020-08-05 13:51:25Z vboxsync $ */
2/** @file
3 * IPRT - SHA-3 hash functions, OpenSSL based implementation.
4 */
5
6/*
7 * Copyright (C) 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#if 1 /* For now: */
28# include "alt-sha3.cpp"
29#else
30
31
32/*********************************************************************************************************************************
33* Header Files *
34*********************************************************************************************************************************/
35#include "internal/iprt.h"
36
37#include "internal/openssl-pre.h"
38#include <openssl/evp.h>
39#include "internal/openssl-post.h"
40
41
42/* Internal EVP structure that we fake here to avoid lots of casting. */
43struct evp_md_ctx_st
44{
45 void *apvWhatever[10];
46};
47
48/** The OpenSSL private context structure. */
49typedef struct RTSHA3PRIVATECTX
50{
51 /** RTSHA3PRIVATECTX_MAGIC / RTSHA3PRIVATECTX_MAGIC_FINAL / RTSHA3PRIVATECTX_MAGIC_DEAD */
52 uint64_t u64Magic;
53 /** The OpenSSL context. We cheat to avoid EVP_MD_CTX_new/free. */
54 struct evp_md_ctx_st MdCtx;
55} RTSHA3PRIVATECTX;
56
57#define RT_SHA3_PRIVATE_CONTEXT
58#include <iprt/sha.h>
59AssertCompile(RT_SIZEOFMEMB(RTSHA3CONTEXT, abPadding) >= RT_SIZEOFMEMB(RTSHA3CONTEXT, Private));
60
61#include <iprt/assert.h>
62#include <iprt/err.h>
63#include <iprt/string.h>
64
65
66/*********************************************************************************************************************************
67* Defined Constants And Macros *
68*********************************************************************************************************************************/
69#define RTSHA3PRIVATECTX_MAGIC UINT64_C(0xb6362d323c56b758)
70#define RTSHA3PRIVATECTX_MAGIC_FINAL UINT64_C(0x40890fe0e474215d)
71#define RTSHA3PRIVATECTX_MAGIC_DEAD UINT64_C(0xdead7a05081cbeef)
72
73
74static int rtSha3Init(PRTSHA3CONTEXT pCtx, const EVP_MD *pMdType)
75{
76 RT_ZERO(*pCtx); /* This is what EVP_MD_CTX_new does. */
77 pCtx->Private.u64Magic = RTSHA3PRIVATECTX_MAGIC;
78
79 AssertReturnStmt(EVP_DigestInit_ex(&pCtx->Private.MdCtx, pMdType, NULL /*engine*/),
80 pCtx->Private.u64Magic = RTSHA3PRIVATECTX_MAGIC_DEAD,
81 VERR_CR_DIGEST_OSSL_DIGEST_INIT_ERROR);
82 return VINF_SUCCESS;
83}
84
85
86static int rtSha3Update(PRTSHA3CONTEXT pCtx, uint8_t const *pbData, size_t cbData)
87{
88 AssertMsgReturn(pCtx->Private.u64Magic == RTSHA3PRIVATECTX_MAGIC, ("u64Magic=%RX64\n", pCtx->Private.u64Magic),
89 VERR_INVALID_CONTEXT);
90 AssertReturn(EVP_DigestUpdate(&pCtx->Private.MdCtx, pbData, cbData), VERR_GENERAL_FAILURE);
91 return VINF_SUCCESS;
92}
93
94
95static int rtSha3Final(PRTSHA3CONTEXT pCtx, uint8_t *pbDigest, size_t cbDigest)
96{
97 RT_BZERO(pbDigest, cbDigest);
98 AssertMsgReturn(pCtx->Private.u64Magic == RTSHA3PRIVATECTX_MAGIC, ("u64Magic=%RX64\n", pCtx->Private.u64Magic),
99 VERR_INVALID_CONTEXT);
100 AssertReturn(EVP_DigestFinal_ex(&pCtx->Private.MdCtx, pbDigest, NULL), VERR_GENERAL_FAILURE);
101
102 /* Implicit cleanup. */
103 EVP_MD_CTX_reset(&pCtx->Private.MdCtx);
104 pCtx->Private.u64Magic = RTSHA3PRIVATECTX_MAGIC_FINAL;
105 return VINF_SUCCESS;
106}
107
108
109static int rtSha3Cleanup(PRTSHA3CONTEXT pCtx)
110{
111 if (pCtx)
112 {
113 if (pCtx->Private.u64Magic == RTSHA3PRIVATECTX_MAGIC_FINAL)
114 { /* likely */ }
115 else if (pCtx->Private.u64Magic == RTSHA3PRIVATECTX_MAGIC)
116 EVP_MD_CTX_reset(&pCtx->Private.MdCtx);
117 else
118 AssertMsgFailedReturn(("u64Magic=%RX64\n", pCtx->Private.u64Magic), VERR_INVALID_CONTEXT);
119 pCtx->Private.u64Magic = RTSHA3PRIVATECTX_MAGIC_DEAD;
120 }
121 return VINF_SUCCESS;
122}
123
124
125static int rtSha3Clone(PRTSHA3CONTEXT pCtx, RTSHA3CONTEXT const *pCtxSrc)
126{
127 Assert(pCtx->Private.u64Magic != RTSHA3PRIVATECTX_MAGIC);
128 RT_ZERO(*pCtx); /* This is what EVP_MD_CTX_new does. */
129
130 AssertReturn(pCtxSrc->Private.u64Magic == RTSHA3PRIVATECTX_MAGIC, VERR_INVALID_CONTEXT);
131
132 pCtx->Private.u64Magic = RTSHA3PRIVATECTX_MAGIC;
133 AssertReturnStmt(EVP_MD_CTX_copy_ex(&pCtx->Private.MdCtx, &pCtxSrc->Private.MdCtx),
134 pCtx->Private.u64Magic = RTSHA3PRIVATECTX_MAGIC_DEAD,
135 VERR_CR_DIGEST_OSSL_DIGEST_CTX_COPY_ERROR);
136 return VINF_SUCCESS;
137}
138
139
140static int rtSha3(const void *pvData, size_t cbData, const EVP_MD *pMdType, uint8_t *pabHash, size_t cbHash)
141{
142 RT_BZERO(pabHash, cbHash);
143
144 int rc;
145 EVP_MD_CTX *pCtx = EVP_MD_CTX_new();
146 if (pCtx)
147 {
148 if (EVP_DigestInit_ex(pCtx, pMdType, NULL /*engine*/))
149 {
150 if (EVP_DigestUpdate(pCtx, pvData, cbData))
151 {
152 if (EVP_DigestFinal_ex(pCtx, pabHash, NULL))
153 rc = VINF_SUCCESS;
154 else
155 AssertFailedStmt(rc = VERR_GENERAL_FAILURE);
156 }
157 else
158 AssertFailedStmt(rc = VERR_GENERAL_FAILURE);
159 }
160 else
161 AssertFailedStmt(rc = VERR_CR_DIGEST_OSSL_DIGEST_INIT_ERROR);
162 EVP_MD_CTX_free(pCtx);
163 }
164 else
165 AssertFailedStmt(rc = VERR_NO_MEMORY);
166 return rc;
167}
168
169
170static bool rtSha3Check(const void *pvData, size_t cbData, const EVP_MD *pMdType,
171 const uint8_t *pabHash, uint8_t *pabHashTmp, size_t cbHash)
172{
173 int rc = rtSha3(pvData, cbData, pMdType, pabHashTmp, cbHash);
174 return RT_SUCCESS(rc) && memcmp(pabHash, pabHashTmp, cbHash) == 0;
175}
176
177
178/** Macro for declaring the interface for a SHA3 variation.
179 * @internal */
180#define RTSHA3_DEFINE_VARIANT(a_cBits, a_pMdType) \
181AssertCompile((a_cBits / 8) == RT_CONCAT3(RTSHA3_,a_cBits,_HASH_SIZE)); \
182\
183RTDECL(int) RT_CONCAT(RTSha3t,a_cBits)(const void *pvBuf, size_t cbBuf, uint8_t pabHash[RT_CONCAT3(RTSHA3_,a_cBits,_HASH_SIZE)]) \
184{ \
185 return rtSha3(pvBuf, cbBuf, a_pMdType, pabHash, (a_cBits) / 8); \
186} \
187RT_EXPORT_SYMBOL(RT_CONCAT(RTSha3t,a_cBits)); \
188\
189\
190RTDECL(bool) RT_CONCAT3(RTSha3t,a_cBits,Check)(const void *pvBuf, size_t cbBuf, \
191 uint8_t const pabHash[RT_CONCAT3(RTSHA3_,a_cBits,_HASH_SIZE)]) \
192{ \
193 uint8_t abHashTmp[(a_cBits) / 8]; \
194 return rtSha3Check(pvBuf, cbBuf, a_pMdType, pabHash, abHashTmp, (a_cBits) / 8); \
195} \
196RT_EXPORT_SYMBOL(RT_CONCAT3(RTSha3t,a_cBits,Check)); \
197\
198\
199RTDECL(int) RT_CONCAT3(RTSha3t,a_cBits,Init)(RT_CONCAT3(PRTSHA3T,a_cBits,CONTEXT) pCtx) \
200{ \
201 return rtSha3Init(&pCtx->Sha3, a_pMdType); \
202} \
203RT_EXPORT_SYMBOL(RT_CONCAT3(RTSha3t,a_cBits,Init)); \
204\
205\
206RTDECL(int) RT_CONCAT3(RTSha3t,a_cBits,Update)(RT_CONCAT3(PRTSHA3T,a_cBits,CONTEXT) pCtx, const void *pvBuf, size_t cbBuf) \
207{ \
208 return rtSha3Update(&pCtx->Sha3, (uint8_t const *)pvBuf, cbBuf); \
209} \
210RT_EXPORT_SYMBOL(RT_CONCAT3(RTSha3t,a_cBits,Update)); \
211\
212\
213RTDECL(int) RT_CONCAT3(RTSha3t,a_cBits,Final)(RT_CONCAT3(PRTSHA3T,a_cBits,CONTEXT) pCtx, \
214 uint8_t pabHash[RT_CONCAT3(RTSHA3_,a_cBits,_HASH_SIZE)]) \
215{ \
216 return rtSha3Final(&pCtx->Sha3, pabHash, (a_cBits) / 8); \
217} \
218RT_EXPORT_SYMBOL(RT_CONCAT3(RTSha3t,a_cBits,Final)); \
219\
220\
221RTDECL(int) RT_CONCAT3(RTSha3t,a_cBits,Cleanup)(RT_CONCAT3(PRTSHA3T,a_cBits,CONTEXT) pCtx) \
222{ \
223 return rtSha3Cleanup(&pCtx->Sha3); \
224} \
225RT_EXPORT_SYMBOL(RT_CONCAT3(RTSha3t,a_cBits,Cleanup)); \
226\
227\
228RTDECL(int) RT_CONCAT3(RTSha3t,a_cBits,Clone)(RT_CONCAT3(PRTSHA3T,a_cBits,CONTEXT) pCtx, \
229 RT_CONCAT3(RTSHA3T,a_cBits,CONTEXT) const *pCtxSrc) \
230{ \
231 return rtSha3Clone(&pCtx->Sha3, &pCtxSrc->Sha3); \
232} \
233RT_EXPORT_SYMBOL(RT_CONCAT3(RTSha3t,a_cBits,Clone)); \
234\
235\
236RTDECL(int) RT_CONCAT3(RTSha3t,a_cBits,ToString)(uint8_t const pabHash[RT_CONCAT3(RTSHA3_,a_cBits,_HASH_SIZE)], \
237 char *pszDigest, size_t cchDigest) \
238{ \
239 return RTStrPrintHexBytes(pszDigest, cchDigest, pabHash, (a_cBits) / 8, 0 /*fFlags*/); \
240} \
241RT_EXPORT_SYMBOL(RT_CONCAT3(RTSha3t,a_cBits,ToString)); \
242\
243\
244RTDECL(int) RT_CONCAT3(RTSha3t,a_cBits,FromString)(char const *pszDigest, uint8_t pabHash[RT_CONCAT3(RTSHA3_,a_cBits,_HASH_SIZE)]) \
245{ \
246 return RTStrConvertHexBytes(RTStrStripL(pszDigest), &pabHash[0], (a_cBits) / 8, 0 /*fFlags*/); \
247} \
248RT_EXPORT_SYMBOL(RT_CONCAT3(RTSha3t,a_cBits,FromString))
249
250
251RTSHA3_DEFINE_VARIANT(224, EVP_sha3_224());
252RTSHA3_DEFINE_VARIANT(256, EVP_sha3_256());
253RTSHA3_DEFINE_VARIANT(384, EVP_sha3_384());
254RTSHA3_DEFINE_VARIANT(512, EVP_sha3_512());
255
256#endif /* !alt-sha3.cpp */
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