VirtualBox

source: vbox/trunk/src/VBox/Runtime/common/checksum/alt-md2.cpp@ 81106

Last change on this file since 81106 was 76553, checked in by vboxsync, 6 years ago

scm --update-copyright-year

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 9.5 KB
Line 
1/* $Id: alt-md2.cpp 76553 2019-01-01 01:45:53Z vboxsync $ */
2/** @file
3 * IPRT - Message-Digest Algorithm 2, Alternative Implementation.
4 */
5
6/*
7 * Copyright (C) 2009-2019 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* Defined Constants And Macros *
30*********************************************************************************************************************************/
31/** The MD2 block size. */
32#define RTMD2_BLOCK_SIZE 16
33/** The offset of the buffer into RTMD2ALTPRIVATECTX::abStateX. */
34#define RTMD2_BUF_OFF RTMD2_BLOCK_SIZE
35
36
37/*********************************************************************************************************************************
38* Header Files *
39*********************************************************************************************************************************/
40#include "internal/iprt.h"
41#include <iprt/types.h>
42
43
44/** Our private context structure. */
45typedef struct RTMD2ALTPRIVATECTX
46{
47 /** The state (X).
48 * The staging buffer starts byte 16. */
49 uint8_t abStateX[RTMD2_BLOCK_SIZE * 3];
50 /** The checksum. */
51 uint8_t abChecksum[RTMD2_BLOCK_SIZE];
52 /** The number of buffered bytes. */
53 uint8_t cbBuffer;
54} RTMD2ALTPRIVATECTX;
55
56#define RT_MD2_PRIVATE_ALT_CONTEXT
57#include <iprt/md2.h>
58
59#include <iprt/assert.h>
60#include <iprt/string.h>
61
62AssertCompile(RT_SIZEOFMEMB(RTMD2CONTEXT, abPadding) >= RT_SIZEOFMEMB(RTMD2CONTEXT, AltPrivate));
63
64
65/*********************************************************************************************************************************
66* Global Variables *
67*********************************************************************************************************************************/
68/** PI substitation used by MD2. */
69static uint8_t const g_PiSubst[256] =
70{
71 41, 46, 67, 201, 162, 216, 124, 1, 61, 54, 84, 161, 236, 240, 6, 19,
72 98, 167, 5, 243, 192, 199, 115, 140, 152, 147, 43, 217, 188, 76, 130, 202,
73 30, 155, 87, 60, 253, 212, 224, 22, 103, 66, 111, 24, 138, 23, 229, 18,
74 190, 78, 196, 214, 218, 158, 222, 73, 160, 251, 245, 142, 187, 47, 238, 122,
75 169, 104, 121, 145, 21, 178, 7, 63, 148, 194, 16, 137, 11, 34, 95, 33,
76 128, 127, 93, 154, 90, 144, 50, 39, 53, 62, 204, 231, 191, 247, 151, 3,
77 255, 25, 48, 179, 72, 165, 181, 209, 215, 94, 146, 42, 172, 86, 170, 198,
78 79, 184, 56, 210, 150, 164, 125, 182, 118, 252, 107, 226, 156, 116, 4, 241,
79 69, 157, 112, 89, 100, 113, 135, 32, 134, 91, 207, 101, 230, 45, 168, 2,
80 27, 96, 37, 173, 174, 176, 185, 246, 28, 70, 97, 105, 52, 64, 126, 15,
81 85, 71, 163, 35, 221, 81, 175, 58, 195, 92, 249, 206, 186, 197, 234, 38,
82 44, 83, 13, 110, 133, 40, 132, 9, 211, 223, 205, 244, 65, 129, 77, 82,
83 106, 220, 55, 200, 108, 193, 171, 250, 36, 225, 123, 8, 12, 189, 177, 74,
84 120, 136, 149, 139, 227, 99, 232, 109, 233, 203, 213, 254, 59, 0, 29, 57,
85 242, 239, 183, 14, 102, 88, 208, 228, 166, 119, 114, 248, 235, 117, 75, 10,
86 49, 68, 80, 180, 143, 237, 31, 26, 219, 153, 141, 51, 159, 17, 131, 20,
87};
88
89
90RTDECL(void) RTMd2Init(PRTMD2CONTEXT pCtx)
91{
92 pCtx->AltPrivate.cbBuffer = 0;
93 RT_ZERO(pCtx->AltPrivate.abStateX);
94 RT_ZERO(pCtx->AltPrivate.abChecksum);
95}
96RT_EXPORT_SYMBOL(RTMd2Init);
97
98
99
100/**
101 * Initializes the processing of a whole block directly from the input buffer.
102 *
103 * This will update the checksum as well as initializing abStateX.
104 *
105 * @param pCtx The MD2 context.
106 * @param pbBlock The block.
107 */
108DECLINLINE(void) rtMd2BlockInit(PRTMD2CONTEXT pCtx, const uint8_t *pbBlock)
109{
110 uint8_t bL = pCtx->AltPrivate.abChecksum[15];
111 for (unsigned j = 0; j < RTMD2_BLOCK_SIZE; j++)
112 {
113 uint8_t bIn = pbBlock[j];
114 pCtx->AltPrivate.abStateX[j + RTMD2_BLOCK_SIZE] = bIn;
115 pCtx->AltPrivate.abStateX[j + RTMD2_BLOCK_SIZE * 2] = bIn ^ pCtx->AltPrivate.abStateX[j];
116 bL = pCtx->AltPrivate.abChecksum[j] ^= g_PiSubst[bIn ^ bL];
117 }
118}
119
120
121/**
122 * Special version of rtMd2BlockInit that does not update the checksum.
123 *
124 * This is used in the final round when adding the checksum to the calculation.
125 *
126 * @param pCtx The MD2 context.
127 * @param pbBlock The block (i.e. the checksum).
128 */
129DECLINLINE(void) rtMd2BlockInitNoChecksum(PRTMD2CONTEXT pCtx, const uint8_t *pbBlock)
130{
131 for (unsigned j = 0; j < RTMD2_BLOCK_SIZE; j++)
132 {
133 uint8_t bIn = pbBlock[j];
134 pCtx->AltPrivate.abStateX[j + RTMD2_BLOCK_SIZE] = bIn;
135 pCtx->AltPrivate.abStateX[j + RTMD2_BLOCK_SIZE * 2] = bIn ^ pCtx->AltPrivate.abStateX[j];
136 }
137}
138
139
140/**
141 * Initalizes the abStateX from a full buffer and update the checksum.
142 *
143 * The buffer is part of the abStateX structure (bytes 16 thru 31), so this
144 * is a somewhat reduced version of rtMd2BlockInit.
145 *
146 * @param pCtx The MD2 context.
147 */
148DECLINLINE(void) rtMd2BlockInitBuffered(PRTMD2CONTEXT pCtx)
149{
150 uint8_t bL = pCtx->AltPrivate.abChecksum[15];
151 for (unsigned j = 0; j < RTMD2_BLOCK_SIZE; j++)
152 {
153 uint8_t bIn = pCtx->AltPrivate.abStateX[j + RTMD2_BLOCK_SIZE];
154 pCtx->AltPrivate.abStateX[j + RTMD2_BLOCK_SIZE * 2] = bIn ^ pCtx->AltPrivate.abStateX[j];
155 bL = pCtx->AltPrivate.abChecksum[j] ^= g_PiSubst[bIn ^ bL];
156 }
157}
158
159
160/**
161 * Process the current block.
162 *
163 * Requires one of the rtMd2BlockInit functions to be called first.
164 *
165 * @param pCtx The MD2 context.
166 */
167DECLINLINE(void) rtMd2BlockProcess(PRTMD2CONTEXT pCtx)
168{
169 uint8_t bT = 0;
170 for (unsigned j = 0; j < 18; j++) /* 18 rounds */
171 {
172 for (unsigned k = 0; k < RTMD2_BLOCK_SIZE * 3; k++)
173 pCtx->AltPrivate.abStateX[k] = bT = pCtx->AltPrivate.abStateX[k] ^ g_PiSubst[bT];
174 bT += (uint8_t)j;
175 }
176}
177
178
179RTDECL(void) RTMd2Update(PRTMD2CONTEXT pCtx, const void *pvBuf, size_t cbBuf)
180{
181 Assert(pCtx->AltPrivate.cbBuffer < RTMD2_BLOCK_SIZE);
182 uint8_t const *pbBuf = (uint8_t const *)pvBuf;
183
184 /*
185 * Deal with buffered bytes first.
186 */
187 if (pCtx->AltPrivate.cbBuffer)
188 {
189 uint8_t cbMissing = RTMD2_BLOCK_SIZE - pCtx->AltPrivate.cbBuffer;
190 if (cbBuf >= cbMissing)
191 {
192 memcpy(&pCtx->AltPrivate.abStateX[RTMD2_BUF_OFF + pCtx->AltPrivate.cbBuffer], pbBuf, cbMissing);
193 pbBuf += cbMissing;
194 cbBuf -= cbMissing;
195
196 rtMd2BlockInitBuffered(pCtx);
197 rtMd2BlockProcess(pCtx);
198
199 pCtx->AltPrivate.cbBuffer = 0;
200 }
201 else
202 {
203 memcpy(&pCtx->AltPrivate.abStateX[RTMD2_BUF_OFF + pCtx->AltPrivate.cbBuffer], pbBuf, cbBuf);
204 pCtx->AltPrivate.cbBuffer += (uint8_t)cbBuf;
205 return;
206 }
207 }
208
209 /*
210 * Process full blocks directly from the input buffer.
211 */
212 while (cbBuf >= RTMD2_BLOCK_SIZE)
213 {
214 rtMd2BlockInit(pCtx, pbBuf);
215 rtMd2BlockProcess(pCtx);
216
217 pbBuf += RTMD2_BLOCK_SIZE;
218 cbBuf -= RTMD2_BLOCK_SIZE;
219 }
220
221 /*
222 * Stash any remaining bytes into the context buffer.
223 */
224 if (cbBuf > 0)
225 {
226 memcpy(&pCtx->AltPrivate.abStateX[RTMD2_BUF_OFF], pbBuf, cbBuf);
227 pCtx->AltPrivate.cbBuffer = (uint8_t)cbBuf;
228 }
229}
230RT_EXPORT_SYMBOL(RTMd2Update);
231
232
233RTDECL(void) RTMd2Final(PRTMD2CONTEXT pCtx, uint8_t pabDigest[RTMD2_HASH_SIZE])
234{
235 Assert(pCtx->AltPrivate.cbBuffer < RTMD2_BLOCK_SIZE);
236
237 /*
238 * Pad the message to a multiple of 16 bytes. This is done even if the
239 * message already is a multiple of 16.
240 */
241 unsigned cbPad = RTMD2_BLOCK_SIZE - pCtx->AltPrivate.cbBuffer;
242 memset(&pCtx->AltPrivate.abStateX[RTMD2_BUF_OFF + pCtx->AltPrivate.cbBuffer], cbPad, cbPad);
243 rtMd2BlockInitBuffered(pCtx);
244 rtMd2BlockProcess(pCtx);
245 pCtx->AltPrivate.cbBuffer = 0;
246
247 /*
248 * Add the checksum.
249 */
250 rtMd2BlockInitNoChecksum(pCtx, pCtx->AltPrivate.abChecksum);
251 rtMd2BlockProcess(pCtx);
252
253 /*
254 * Done. Just copy out the digest.
255 */
256 memcpy(pabDigest, pCtx->AltPrivate.abStateX, RTMD2_HASH_SIZE);
257
258 RT_ZERO(pCtx->AltPrivate);
259 pCtx->AltPrivate.cbBuffer = UINT8_MAX;
260}
261RT_EXPORT_SYMBOL(RTMd2Final);
262
263
264RTDECL(void) RTMd2(const void *pvBuf, size_t cbBuf, uint8_t pabDigest[RTMD2_HASH_SIZE])
265{
266 RTMD2CONTEXT Ctx;
267 RTMd2Init(&Ctx);
268 RTMd2Update(&Ctx, pvBuf, cbBuf);
269 RTMd2Final(&Ctx, pabDigest);
270}
271RT_EXPORT_SYMBOL(RTMd2);
272
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