VirtualBox

source: vbox/trunk/src/VBox/Runtime/common/checksum/RTSha1Digest.cpp

Last change on this file was 98103, checked in by vboxsync, 16 months ago

Copyright year updates by scm.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 6.1 KB
Line 
1/* $Id: RTSha1Digest.cpp 98103 2023-01-17 14:15:46Z vboxsync $ */
2/** @file
3 * IPRT - SHA1 digest creation
4 *
5 * @todo Replace this with generic RTCrDigest based implementation. Too much
6 * stupid code duplication.
7 */
8
9/*
10 * Copyright (C) 2009-2023 Oracle and/or its affiliates.
11 *
12 * This file is part of VirtualBox base platform packages, as
13 * available from https://www.virtualbox.org.
14 *
15 * This program is free software; you can redistribute it and/or
16 * modify it under the terms of the GNU General Public License
17 * as published by the Free Software Foundation, in version 3 of the
18 * License.
19 *
20 * This program is distributed in the hope that it will be useful, but
21 * WITHOUT ANY WARRANTY; without even the implied warranty of
22 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
23 * General Public License for more details.
24 *
25 * You should have received a copy of the GNU General Public License
26 * along with this program; if not, see <https://www.gnu.org/licenses>.
27 *
28 * The contents of this file may alternatively be used under the terms
29 * of the Common Development and Distribution License Version 1.0
30 * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
31 * in the VirtualBox distribution, in which case the provisions of the
32 * CDDL are applicable instead of those of the GPL.
33 *
34 * You may elect to license modified versions of this file under the
35 * terms and conditions of either the GPL or the CDDL or both.
36 *
37 * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
38 */
39
40
41/*********************************************************************************************************************************
42* Header Files *
43*********************************************************************************************************************************/
44#include "internal/iprt.h"
45#include <iprt/sha.h>
46
47#include <iprt/alloca.h>
48#include <iprt/assert.h>
49#include <iprt/errcore.h>
50#include <iprt/mem.h>
51#include <iprt/string.h>
52#include <iprt/file.h>
53
54
55RTR3DECL(int) RTSha1Digest(void* pvBuf, size_t cbBuf, char **ppszDigest, PFNRTPROGRESS pfnProgressCallback, void *pvUser)
56{
57 /* Validate input */
58 AssertPtrReturn(pvBuf, VERR_INVALID_POINTER);
59 AssertPtrReturn(ppszDigest, VERR_INVALID_POINTER);
60 AssertPtrNullReturn(pfnProgressCallback, VERR_INVALID_PARAMETER);
61
62 int rc = VINF_SUCCESS;
63 *ppszDigest = NULL;
64
65 /* Initialize the hash context. */
66 RTSHA1CONTEXT Ctx;
67 RTSha1Init(&Ctx);
68
69 /* Buffer size for progress callback */
70 double rdMulti = 100.0 / (cbBuf ? (double)cbBuf : 1.0);
71
72 /* Working buffer */
73 char *pvTmp = (char*)pvBuf;
74
75 /* Process the memory in blocks */
76 size_t cbReadTotal = 0;
77 for (;;)
78 {
79 size_t cbRead = RT_MIN(cbBuf - cbReadTotal, _1M);
80 RTSha1Update(&Ctx, pvTmp, cbRead);
81 cbReadTotal += cbRead;
82 pvTmp += cbRead;
83
84 /* Call the progress callback if one is defined */
85 if (pfnProgressCallback)
86 {
87 rc = pfnProgressCallback((unsigned)((double)cbReadTotal * rdMulti), pvUser);
88 if (RT_FAILURE(rc))
89 break; /* canceled */
90 }
91 /* Finished? */
92 if (cbReadTotal == cbBuf)
93 break;
94 }
95 if (RT_SUCCESS(rc))
96 {
97 /* Finally calculate & format the SHA1 sum */
98 uint8_t abHash[RTSHA1_HASH_SIZE];
99 RTSha1Final(&Ctx, abHash);
100
101 char *pszDigest;
102 rc = RTStrAllocEx(&pszDigest, RTSHA1_DIGEST_LEN + 1);
103 if (RT_SUCCESS(rc))
104 {
105 rc = RTSha1ToString(abHash, pszDigest, RTSHA1_DIGEST_LEN + 1);
106 if (RT_SUCCESS(rc))
107 *ppszDigest = pszDigest;
108 else
109 RTStrFree(pszDigest);
110 }
111 }
112
113 return rc;
114}
115
116RTR3DECL(int) RTSha1DigestFromFile(const char *pszFile, char **ppszDigest, PFNRTPROGRESS pfnProgressCallback, void *pvUser)
117{
118 /* Validate input */
119 AssertPtrReturn(pszFile, VERR_INVALID_POINTER);
120 AssertPtrReturn(ppszDigest, VERR_INVALID_POINTER);
121 AssertPtrNullReturn(pfnProgressCallback, VERR_INVALID_PARAMETER);
122
123 *ppszDigest = NULL;
124
125 /* Open the file to calculate a SHA1 sum of */
126 RTFILE hFile;
127 int rc = RTFileOpen(&hFile, pszFile, RTFILE_O_OPEN | RTFILE_O_READ | RTFILE_O_DENY_WRITE);
128 if (RT_FAILURE(rc))
129 return rc;
130
131 /* Fetch the file size. Only needed if there is a progress callback. */
132 double rdMulti = 0.0;
133 if (pfnProgressCallback)
134 {
135 uint64_t cbFile;
136 rc = RTFileQuerySize(hFile, &cbFile);
137 if (RT_FAILURE(rc))
138 {
139 RTFileClose(hFile);
140 return rc;
141 }
142 rdMulti = 100.0 / (cbFile ? (double)cbFile : 1.0);
143 }
144
145 /* Allocate a reasonably large buffer, fall back on a tiny one. */
146 void *pvBufFree;
147 size_t cbBuf = _1M;
148 void *pvBuf = pvBufFree = RTMemTmpAlloc(cbBuf);
149 if (!pvBuf)
150 {
151 cbBuf = 0x1000;
152 pvBuf = alloca(cbBuf);
153 }
154
155 /* Initialize the hash context. */
156 RTSHA1CONTEXT Ctx;
157 RTSha1Init(&Ctx);
158
159 /* Read that file in blocks */
160 size_t cbReadTotal = 0;
161 for (;;)
162 {
163 size_t cbRead;
164 rc = RTFileRead(hFile, pvBuf, cbBuf, &cbRead);
165 if (RT_FAILURE(rc) || !cbRead)
166 break;
167 RTSha1Update(&Ctx, pvBuf, cbRead);
168 cbReadTotal += cbRead;
169
170 /* Call the progress callback if one is defined */
171 if (pfnProgressCallback)
172 {
173 rc = pfnProgressCallback((unsigned)((double)cbReadTotal * rdMulti), pvUser);
174 if (RT_FAILURE(rc))
175 break; /* canceled */
176 }
177 }
178 RTMemTmpFree(pvBufFree);
179 RTFileClose(hFile);
180
181 if (RT_FAILURE(rc))
182 return rc;
183
184 /* Finally calculate & format the SHA1 sum */
185 uint8_t abHash[RTSHA1_HASH_SIZE];
186 RTSha1Final(&Ctx, abHash);
187
188 char *pszDigest;
189 rc = RTStrAllocEx(&pszDigest, RTSHA1_DIGEST_LEN + 1);
190 if (RT_SUCCESS(rc))
191 {
192 rc = RTSha1ToString(abHash, pszDigest, RTSHA1_DIGEST_LEN + 1);
193 if (RT_SUCCESS(rc))
194 *ppszDigest = pszDigest;
195 else
196 RTStrFree(pszDigest);
197 }
198
199 return rc;
200}
201
Note: See TracBrowser for help on using the repository browser.

© 2023 Oracle
ContactPrivacy policyTerms of Use