1
/* $Id: RTSha1Digest.cpp $ */
3
* IPRT - SHA1 digest creation
5
* @todo Replace this with generic RTCrDigest based implementation. Too much
6
* stupid code duplication.
10
* Copyright (C) 2009-2010 Oracle Corporation
12
* This file is part of VirtualBox Open Source Edition (OSE), as
13
* available from http://www.virtualbox.org. This file is free software;
14
* you can redistribute it and/or modify it under the terms of the GNU
15
* General Public License (GPL) as published by the Free Software
16
* Foundation, in version 2 as it comes in the "COPYING" file of the
17
* VirtualBox OSE distribution. VirtualBox OSE is distributed in the
18
* hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
20
* The contents of this file may alternatively be used under the terms
21
* of the Common Development and Distribution License Version 1.0
22
* (CDDL) only, as it comes in the "COPYING.CDDL" file of the
23
* VirtualBox OSE distribution, in which case the provisions of the
24
* CDDL are applicable instead of those of the GPL.
26
* You may elect to license modified versions of this file under the
27
* terms and conditions of either the GPL or the CDDL or both.
31
/*******************************************************************************
33
*******************************************************************************/
34
#include "internal/iprt.h"
37
#include <iprt/alloca.h>
38
#include <iprt/assert.h>
40
#include <iprt/string.h>
41
#include <iprt/file.h>
44
RTR3DECL(int) RTSha1Digest(void* pvBuf, size_t cbBuf, char **ppszDigest, PFNRTPROGRESS pfnProgressCallback, void *pvUser)
47
AssertPtrReturn(pvBuf, VERR_INVALID_POINTER);
48
AssertPtrReturn(ppszDigest, VERR_INVALID_POINTER);
49
AssertPtrNullReturn(pfnProgressCallback, VERR_INVALID_PARAMETER);
51
int rc = VINF_SUCCESS;
54
/* Initialize the hash context. */
58
/* Buffer size for progress callback */
59
double rdMulti = 100.0 / (cbBuf ? cbBuf : 1);
62
char *pvTmp = (char*)pvBuf;
64
/* Process the memory in blocks */
65
size_t cbReadTotal = 0;
68
size_t cbRead = RT_MIN(cbBuf - cbReadTotal, _1M);
69
RTSha1Update(&Ctx, pvTmp, cbRead);
70
cbReadTotal += cbRead;
73
/* Call the progress callback if one is defined */
74
if (pfnProgressCallback)
76
rc = pfnProgressCallback((unsigned)(cbReadTotal * rdMulti), pvUser);
81
if (cbReadTotal == cbBuf)
86
/* Finally calculate & format the SHA1 sum */
87
uint8_t abHash[RTSHA1_HASH_SIZE];
88
RTSha1Final(&Ctx, abHash);
91
rc = RTStrAllocEx(&pszDigest, RTSHA1_DIGEST_LEN + 1);
94
rc = RTSha1ToString(abHash, pszDigest, RTSHA1_DIGEST_LEN + 1);
96
*ppszDigest = pszDigest;
105
RTR3DECL(int) RTSha1DigestFromFile(const char *pszFile, char **ppszDigest, PFNRTPROGRESS pfnProgressCallback, void *pvUser)
108
AssertPtrReturn(pszFile, VERR_INVALID_POINTER);
109
AssertPtrReturn(ppszDigest, VERR_INVALID_POINTER);
110
AssertPtrNullReturn(pfnProgressCallback, VERR_INVALID_PARAMETER);
114
/* Open the file to calculate a SHA1 sum of */
116
int rc = RTFileOpen(&hFile, pszFile, RTFILE_O_OPEN | RTFILE_O_READ | RTFILE_O_DENY_WRITE);
120
/* Fetch the file size. Only needed if there is a progress callback. */
122
if (pfnProgressCallback)
125
rc = RTFileGetSize(hFile, &cbFile);
131
rdMulti = 100.0 / (cbFile ? cbFile : 1);
134
/* Allocate a reasonably large buffer, fall back on a tiny one. */
137
void *pvBuf = pvBufFree = RTMemTmpAlloc(cbBuf);
141
pvBuf = alloca(cbBuf);
144
/* Initialize the hash context. */
148
/* Read that file in blocks */
149
size_t cbReadTotal = 0;
153
rc = RTFileRead(hFile, pvBuf, cbBuf, &cbRead);
154
if (RT_FAILURE(rc) || !cbRead)
156
RTSha1Update(&Ctx, pvBuf, cbRead);
157
cbReadTotal += cbRead;
159
/* Call the progress callback if one is defined */
160
if (pfnProgressCallback)
162
rc = pfnProgressCallback((unsigned)(cbReadTotal * rdMulti), pvUser);
164
break; /* canceled */
167
RTMemTmpFree(pvBufFree);
173
/* Finally calculate & format the SHA1 sum */
174
uint8_t abHash[RTSHA1_HASH_SIZE];
175
RTSha1Final(&Ctx, abHash);
178
rc = RTStrAllocEx(&pszDigest, RTSHA1_DIGEST_LEN + 1);
181
rc = RTSha1ToString(abHash, pszDigest, RTSHA1_DIGEST_LEN + 1);
183
*ppszDigest = pszDigest;
185
RTStrFree(pszDigest);