VirtualBox

source: vbox/trunk/src/VBox/Runtime/testcase/tstRTDigest.cpp@ 91472

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

IPRT: Adding SHA-3. bugref:9734

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 29.9 KB
Line 
1/* $Id: tstRTDigest.cpp 85614 2020-08-05 13:27:58Z vboxsync $ */
2/** @file
3 * IPRT Testcase - RTSha*, RTMd5, RTCrc*.
4 */
5
6/*
7 * Copyright (C) 2009-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
28/*********************************************************************************************************************************
29* Header Files *
30*********************************************************************************************************************************/
31#include <iprt/sha.h>
32#include <iprt/md2.h>
33#include <iprt/md5.h>
34#include <iprt/crc.h>
35
36#include <iprt/ctype.h>
37#include <iprt/err.h>
38#include <iprt/file.h>
39#include <iprt/getopt.h>
40#include <iprt/initterm.h>
41#include <iprt/param.h>
42#include <iprt/path.h>
43#include <iprt/process.h>
44#include <iprt/string.h>
45#include <iprt/stream.h>
46#include <iprt/crypto/digest.h>
47
48
49static int Error(const char *pszFormat, ...)
50{
51 char szName[RTPATH_MAX];
52 if (!RTProcGetExecutablePath(szName, sizeof(szName)))
53 strcpy(szName, "tstRTDigest");
54
55 RTStrmPrintf(g_pStdErr, "%s: error: ", RTPathFilename(szName));
56 va_list va;
57 va_start(va, pszFormat);
58 RTStrmPrintfV(g_pStdErr, pszFormat, va);
59 va_end(va);
60
61 return 1;
62}
63
64
65static int MyReadFile(RTFILE hFile, void *pvBuf, size_t cbToRead, size_t *pcbRead, uint64_t *pcbMaxLeft)
66{
67 int rc = VINF_SUCCESS;
68 if (*pcbMaxLeft > 0)
69 {
70 if (cbToRead > *pcbMaxLeft)
71 cbToRead = (size_t)*pcbMaxLeft;
72 rc = RTFileRead(hFile, pvBuf, cbToRead, pcbRead);
73 if (RT_SUCCESS(rc))
74 *pcbMaxLeft -= *pcbRead;
75 }
76 else
77 *pcbRead = 0;
78 return rc;
79}
80
81
82static char *MyGetNextSignificantLine(PRTSTREAM pFile, char *pszBuf, size_t cbBuf, uint32_t *piLine, int *prc)
83{
84 for (;;)
85 {
86 *pszBuf = '\0';
87 int rc = RTStrmGetLine(pFile, pszBuf, cbBuf);
88 if (RT_FAILURE(rc))
89 {
90 if (rc != VERR_EOF)
91 {
92 Error("Read error: %Rrc", rc);
93 *prc = rc;
94 return NULL;
95 }
96 if (!*pszBuf)
97 return NULL;
98 }
99 *piLine += 1;
100
101 /* Significant? */
102 char *pszStart = RTStrStrip(pszBuf);
103 if (*pszStart && *pszStart != '#')
104 return pszStart;
105 }
106}
107
108
109int main(int argc, char **argv)
110{
111 RTR3InitExe(argc, &argv, 0);
112
113 RTDIGESTTYPE enmDigestType = RTDIGESTTYPE_INVALID;
114 const char *pszDigestType = "NotSpecified";
115
116 enum
117 {
118 kMethod_Full,
119 kMethod_Block,
120 kMethod_File,
121 kMethod_CVAS
122 } enmMethod = kMethod_Block;
123
124 uint64_t offStart = 0;
125 uint64_t cbMax = UINT64_MAX;
126 bool fTestcase = false;
127
128 static const RTGETOPTDEF s_aOptions[] =
129 {
130 { "--type", 't', RTGETOPT_REQ_STRING },
131 { "--method", 'm', RTGETOPT_REQ_STRING },
132 { "--help", 'h', RTGETOPT_REQ_NOTHING },
133 { "--length", 'l', RTGETOPT_REQ_UINT64 },
134 { "--offset", 'o', RTGETOPT_REQ_UINT64 },
135 { "--testcase", 'x', RTGETOPT_REQ_NOTHING },
136 };
137
138 int ch;
139 RTGETOPTUNION ValueUnion;
140 RTGETOPTSTATE GetState;
141 RTGetOptInit(&GetState, argc, argv, s_aOptions, RT_ELEMENTS(s_aOptions), 1, RTGETOPTINIT_FLAGS_OPTS_FIRST);
142 while ((ch = RTGetOpt(&GetState, &ValueUnion)))
143 {
144 switch (ch)
145 {
146 case 't':
147 if (!RTStrICmp(ValueUnion.psz, "crc32"))
148 {
149 pszDigestType = "CRC32";
150 enmDigestType = RTDIGESTTYPE_CRC32;
151 }
152 else if (!RTStrICmp(ValueUnion.psz, "crc64"))
153 {
154 pszDigestType = "CRC64";
155 enmDigestType = RTDIGESTTYPE_CRC64;
156 }
157 else if (!RTStrICmp(ValueUnion.psz, "md2"))
158 {
159 pszDigestType = "MD2";
160 enmDigestType = RTDIGESTTYPE_MD2;
161 }
162 else if (!RTStrICmp(ValueUnion.psz, "md5"))
163 {
164 pszDigestType = "MD5";
165 enmDigestType = RTDIGESTTYPE_MD5;
166 }
167 else if (!RTStrICmp(ValueUnion.psz, "sha1"))
168 {
169 pszDigestType = "SHA-1";
170 enmDigestType = RTDIGESTTYPE_SHA1;
171 }
172 else if (!RTStrICmp(ValueUnion.psz, "sha224"))
173 {
174 pszDigestType = "SHA-224";
175 enmDigestType = RTDIGESTTYPE_SHA224;
176 }
177 else if (!RTStrICmp(ValueUnion.psz, "sha256"))
178 {
179 pszDigestType = "SHA-256";
180 enmDigestType = RTDIGESTTYPE_SHA256;
181 }
182 else if (!RTStrICmp(ValueUnion.psz, "sha384"))
183 {
184 pszDigestType = "SHA-384";
185 enmDigestType = RTDIGESTTYPE_SHA384;
186 }
187 else if (!RTStrICmp(ValueUnion.psz, "sha512"))
188 {
189 pszDigestType = "SHA-512";
190 enmDigestType = RTDIGESTTYPE_SHA512;
191 }
192 else if (!RTStrICmp(ValueUnion.psz, "sha512/224"))
193 {
194 pszDigestType = "SHA-512/224";
195 enmDigestType = RTDIGESTTYPE_SHA512T224;
196 }
197 else if (!RTStrICmp(ValueUnion.psz, "sha512/256"))
198 {
199 pszDigestType = "SHA-512/256";
200 enmDigestType = RTDIGESTTYPE_SHA3_256;
201 }
202 else if (!RTStrICmp(ValueUnion.psz, "sha3-224"))
203 {
204 pszDigestType = "SHA3-224";
205 enmDigestType = RTDIGESTTYPE_SHA3_224;
206 }
207 else if (!RTStrICmp(ValueUnion.psz, "sha3-256"))
208 {
209 pszDigestType = "SHA3-256";
210 enmDigestType = RTDIGESTTYPE_SHA3_256;
211 }
212 else if (!RTStrICmp(ValueUnion.psz, "sha3-384"))
213 {
214 pszDigestType = "SHA3-384";
215 enmDigestType = RTDIGESTTYPE_SHA3_384;
216 }
217 else if (!RTStrICmp(ValueUnion.psz, "sha3-512"))
218 {
219 pszDigestType = "SHA3-512";
220 enmDigestType = RTDIGESTTYPE_SHA3_512;
221 }
222#if 0
223 else if (!RTStrICmp(ValueUnion.psz, "shake128"))
224 {
225 pszDigestType = "SHAKE128";
226 enmDigestType = RTDIGESTTYPE_SHAKE128;
227 }
228 else if (!RTStrICmp(ValueUnion.psz, "shake256"))
229 {
230 pszDigestType = "SHAKE256";
231 enmDigestType = RTDIGESTTYPE_SHAKE256;
232 }
233#endif
234 else
235 {
236 Error("Invalid digest type: %s\n", ValueUnion.psz);
237 return 1;
238 }
239 break;
240
241 case 'm':
242 if (!RTStrICmp(ValueUnion.psz, "full"))
243 enmMethod = kMethod_Full;
244 else if (!RTStrICmp(ValueUnion.psz, "block"))
245 enmMethod = kMethod_Block;
246 else if (!RTStrICmp(ValueUnion.psz, "file"))
247 enmMethod = kMethod_File;
248 else if (!RTStrICmp(ValueUnion.psz, "cvas"))
249 enmMethod = kMethod_CVAS;
250 else
251 {
252 Error("Invalid digest method: %s\n", ValueUnion.psz);
253 return 1;
254 }
255 break;
256
257 case 'l':
258 cbMax = ValueUnion.u64;
259 break;
260
261 case 'o':
262 offStart = ValueUnion.u64;
263 break;
264
265 case 'x':
266 fTestcase = true;
267 break;
268
269 case 'h':
270 RTPrintf("usage: tstRTDigest -t <digest-type> [-o <offset>] [-l <length>] [-m method] [-x] file [file2 [..]]\n"
271 "\n"
272 "Options:\n"
273 " -t,--type <hash-algo>\n"
274 " -o,--offset <file-offset>\n"
275 " -l,--length <byte-count>\n"
276 " -m,--method <full|block|file|cvas>\n"
277 " block: Init+Update+Finalize, data from file(s). Default.\n"
278 " file: RTSha*DigestFromFile. Only SHA1 and SHA256.\n"
279 " cvas: NIST test vectors processed by RTCrDigest*.\n"
280 " full: Not implemented\n"
281 " -x,--testcase\n"
282 " For generating C code.\n"
283 );
284 return 1;
285
286 case VINF_GETOPT_NOT_OPTION:
287 {
288 if (enmDigestType == RTDIGESTTYPE_INVALID)
289 return Error("No digest type was specified\n");
290
291 switch (enmMethod)
292 {
293 case kMethod_Full:
294 return Error("Full file method is not implemented\n");
295
296 case kMethod_File:
297 if (offStart != 0 || cbMax != UINT64_MAX)
298 return Error("The -l and -o options do not work with the 'file' method.");
299 switch (enmDigestType)
300 {
301 case RTDIGESTTYPE_SHA1:
302 {
303 char *pszDigest;
304 int rc = RTSha1DigestFromFile(ValueUnion.psz, &pszDigest, NULL, NULL);
305 if (RT_FAILURE(rc))
306 return Error("RTSha1Digest(%s,) -> %Rrc\n", ValueUnion.psz, rc);
307 RTPrintf("%s %s\n", pszDigest, ValueUnion.psz);
308 RTStrFree(pszDigest);
309 break;
310 }
311
312 case RTDIGESTTYPE_SHA256:
313 {
314 char *pszDigest;
315 int rc = RTSha256DigestFromFile(ValueUnion.psz, &pszDigest, NULL, NULL);
316 if (RT_FAILURE(rc))
317 return Error("RTSha256Digest(%s,) -> %Rrc\n", ValueUnion.psz, rc);
318 RTPrintf("%s %s\n", pszDigest, ValueUnion.psz);
319 RTStrFree(pszDigest);
320 break;
321 }
322 default:
323 return Error("The file method isn't implemented for this digest\n");
324 }
325 break;
326
327 case kMethod_Block:
328 {
329 RTFILE hFile;
330 int rc = RTFileOpen(&hFile, ValueUnion.psz, RTFILE_O_READ | RTFILE_O_OPEN | RTFILE_O_DENY_WRITE);
331 if (RT_FAILURE(rc))
332 return Error("RTFileOpen(,%s,) -> %Rrc\n", ValueUnion.psz, rc);
333 if (offStart != 0)
334 {
335 rc = RTFileSeek(hFile, offStart, RTFILE_SEEK_BEGIN, NULL);
336 if (RT_FAILURE(rc))
337 return Error("RTFileSeek(%s,%ull) -> %Rrc\n", ValueUnion.psz, offStart, rc);
338 }
339
340 uint64_t cbMaxLeft = cbMax;
341 size_t cbRead;
342 uint8_t abBuf[_64K];
343 char *pszDigest = (char *)&abBuf[0];
344 switch (enmDigestType)
345 {
346 case RTDIGESTTYPE_CRC32:
347 {
348 uint32_t uCRC32 = RTCrc32Start();
349 for (;;)
350 {
351 rc = MyReadFile(hFile, abBuf, sizeof(abBuf), &cbRead, &cbMaxLeft);
352 if (RT_FAILURE(rc) || !cbRead)
353 break;
354 uCRC32 = RTCrc32Process(uCRC32, abBuf, cbRead);
355 }
356 uCRC32 = RTCrc32Finish(uCRC32);
357 RTStrPrintf(pszDigest, sizeof(abBuf), "%08RX32", uCRC32);
358 break;
359 }
360
361 case RTDIGESTTYPE_CRC64:
362 {
363 uint64_t uCRC64 = RTCrc64Start();
364 for (;;)
365 {
366 rc = MyReadFile(hFile, abBuf, sizeof(abBuf), &cbRead, &cbMaxLeft);
367 if (RT_FAILURE(rc) || !cbRead)
368 break;
369 uCRC64 = RTCrc64Process(uCRC64, abBuf, cbRead);
370 }
371 uCRC64 = RTCrc64Finish(uCRC64);
372 RTStrPrintf(pszDigest, sizeof(abBuf), "%016RX64", uCRC64);
373 break;
374 }
375
376 case RTDIGESTTYPE_MD2:
377 {
378 RTMD2CONTEXT Ctx;
379 RTMd2Init(&Ctx);
380 for (;;)
381 {
382 rc = MyReadFile(hFile, abBuf, sizeof(abBuf), &cbRead, &cbMaxLeft);
383 if (RT_FAILURE(rc) || !cbRead)
384 break;
385 RTMd2Update(&Ctx, abBuf, cbRead);
386 }
387 uint8_t abDigest[RTMD2_HASH_SIZE];
388 RTMd2Final(&Ctx, abDigest);
389 RTMd2ToString(abDigest, pszDigest, sizeof(abBuf));
390 break;
391 }
392
393 case RTDIGESTTYPE_MD5:
394 {
395 RTMD5CONTEXT Ctx;
396 RTMd5Init(&Ctx);
397 for (;;)
398 {
399 rc = MyReadFile(hFile, abBuf, sizeof(abBuf), &cbRead, &cbMaxLeft);
400 if (RT_FAILURE(rc) || !cbRead)
401 break;
402 RTMd5Update(&Ctx, abBuf, cbRead);
403 }
404 uint8_t abDigest[RTMD5HASHSIZE];
405 RTMd5Final(abDigest, &Ctx);
406 RTMd5ToString(abDigest, pszDigest, sizeof(abBuf));
407 break;
408 }
409
410 case RTDIGESTTYPE_SHA1:
411 {
412 RTSHA1CONTEXT Ctx;
413 RTSha1Init(&Ctx);
414 for (;;)
415 {
416 rc = MyReadFile(hFile, abBuf, sizeof(abBuf), &cbRead, &cbMaxLeft);
417 if (RT_FAILURE(rc) || !cbRead)
418 break;
419 RTSha1Update(&Ctx, abBuf, cbRead);
420 }
421 uint8_t abDigest[RTSHA1_HASH_SIZE];
422 RTSha1Final(&Ctx, abDigest);
423 RTSha1ToString(abDigest, pszDigest, sizeof(abBuf));
424 break;
425 }
426
427 case RTDIGESTTYPE_SHA256:
428 {
429 RTSHA256CONTEXT Ctx;
430 RTSha256Init(&Ctx);
431 for (;;)
432 {
433 rc = MyReadFile(hFile, abBuf, sizeof(abBuf), &cbRead, &cbMaxLeft);
434 if (RT_FAILURE(rc) || !cbRead)
435 break;
436 RTSha256Update(&Ctx, abBuf, cbRead);
437 }
438 uint8_t abDigest[RTSHA256_HASH_SIZE];
439 RTSha256Final(&Ctx, abDigest);
440 RTSha256ToString(abDigest, pszDigest, sizeof(abBuf));
441 break;
442 }
443
444 case RTDIGESTTYPE_SHA512:
445 {
446 RTSHA512CONTEXT Ctx;
447 RTSha512Init(&Ctx);
448 for (;;)
449 {
450 rc = MyReadFile(hFile, abBuf, sizeof(abBuf), &cbRead, &cbMaxLeft);
451 if (RT_FAILURE(rc) || !cbRead)
452 break;
453 RTSha512Update(&Ctx, abBuf, cbRead);
454 }
455 uint8_t abDigest[RTSHA512_HASH_SIZE];
456 RTSha512Final(&Ctx, abDigest);
457 RTSha512ToString(abDigest, pszDigest, sizeof(abBuf));
458 break;
459 }
460
461 case RTDIGESTTYPE_SHA3_224:
462 {
463 RTSHA3T224CONTEXT Ctx;
464 RTSha3t224Init(&Ctx);
465 for (;;)
466 {
467 rc = MyReadFile(hFile, abBuf, sizeof(abBuf), &cbRead, &cbMaxLeft);
468 if (RT_FAILURE(rc) || !cbRead)
469 break;
470 RTSha3t224Update(&Ctx, abBuf, cbRead);
471 }
472 uint8_t abDigest[RTSHA3_224_HASH_SIZE];
473 RTSha3t224Final(&Ctx, abDigest);
474 RTSha3t224ToString(abDigest, pszDigest, sizeof(abBuf));
475 break;
476 }
477
478 case RTDIGESTTYPE_SHA3_256:
479 {
480 RTSHA3T256CONTEXT Ctx;
481 RTSha3t256Init(&Ctx);
482 for (;;)
483 {
484 rc = MyReadFile(hFile, abBuf, sizeof(abBuf), &cbRead, &cbMaxLeft);
485 if (RT_FAILURE(rc) || !cbRead)
486 break;
487 RTSha3t256Update(&Ctx, abBuf, cbRead);
488 }
489 uint8_t abDigest[RTSHA3_256_HASH_SIZE];
490 RTSha3t256Final(&Ctx, abDigest);
491 RTSha3t256ToString(abDigest, pszDigest, sizeof(abBuf));
492 break;
493 }
494
495 case RTDIGESTTYPE_SHA3_384:
496 {
497 RTSHA3T384CONTEXT Ctx;
498 RTSha3t384Init(&Ctx);
499 for (;;)
500 {
501 rc = MyReadFile(hFile, abBuf, sizeof(abBuf), &cbRead, &cbMaxLeft);
502 if (RT_FAILURE(rc) || !cbRead)
503 break;
504 RTSha3t384Update(&Ctx, abBuf, cbRead);
505 }
506 uint8_t abDigest[RTSHA3_384_HASH_SIZE];
507 RTSha3t384Final(&Ctx, abDigest);
508 RTSha3t384ToString(abDigest, pszDigest, sizeof(abBuf));
509 break;
510 }
511
512 case RTDIGESTTYPE_SHA3_512:
513 {
514 RTSHA3T512CONTEXT Ctx;
515 RTSha3t512Init(&Ctx);
516 for (;;)
517 {
518 rc = MyReadFile(hFile, abBuf, sizeof(abBuf), &cbRead, &cbMaxLeft);
519 if (RT_FAILURE(rc) || !cbRead)
520 break;
521 RTSha3t512Update(&Ctx, abBuf, cbRead);
522 }
523 uint8_t abDigest[RTSHA3_512_HASH_SIZE];
524 RTSha3t512Final(&Ctx, abDigest);
525 RTSha3t512ToString(abDigest, pszDigest, sizeof(abBuf));
526 break;
527 }
528
529 /** @todo SHAKE128 and SHAKE256 */
530
531 default:
532 return Error("Internal error #1: %d %s\n", enmDigestType, pszDigest);
533 }
534 RTFileClose(hFile);
535 if (RT_FAILURE(rc) && rc != VERR_EOF)
536 {
537 RTPrintf("Partial: %s %s\n", pszDigest, ValueUnion.psz);
538 return Error("RTFileRead(%s) -> %Rrc\n", ValueUnion.psz, rc);
539 }
540
541 if (!fTestcase)
542 RTPrintf("%s %s\n", pszDigest, ValueUnion.psz);
543 else if (offStart)
544 RTPrintf(" { &g_abRandom72KB[%#4llx], %5llu, \"%s\", \"%s %llu bytes @%llu\" },\n",
545 offStart, cbMax - cbMaxLeft, pszDigest, pszDigestType, offStart, cbMax - cbMaxLeft);
546 else
547 RTPrintf(" { &g_abRandom72KB[0], %5llu, \"%s\", \"%s %llu bytes\" },\n",
548 cbMax - cbMaxLeft, pszDigest, pszDigestType, cbMax - cbMaxLeft);
549 break;
550 }
551
552
553 /*
554 * Process a SHS response file:
555 * http://csrc.nist.gov/groups/STM/cavp/index.html#03
556 */
557 case kMethod_CVAS:
558 {
559 RTCRDIGEST hDigest;
560 int rc = RTCrDigestCreateByType(&hDigest, enmDigestType);
561 if (RT_FAILURE(rc))
562 return Error("Failed to create digest calculator for %s: %Rrc", pszDigestType, rc);
563
564 uint32_t const cbDigest = RTCrDigestGetHashSize(hDigest);
565 if (!cbDigest || cbDigest >= _1K)
566 return Error("Unexpected hash size: %#x\n", cbDigest);
567
568 PRTSTREAM pFile;
569 rc = RTStrmOpen(ValueUnion.psz, "r", &pFile);
570 if (RT_FAILURE(rc))
571 return Error("Failed to open CVAS file '%s': %Rrc\n", ValueUnion.psz, rc);
572
573 /*
574 * Parse the input file.
575 * ASSUME order: Len, Msg, MD.
576 */
577 static char s_szLine[_256K];
578 char *psz;
579 uint32_t cPassed = 0;
580 uint32_t cErrors = 0;
581 uint32_t iLine = 1;
582 for (;;)
583 {
584 psz = MyGetNextSignificantLine(pFile, s_szLine, sizeof(s_szLine), &iLine, &rc);
585 if (!psz)
586 break;
587
588 /* Skip [L = 20] stuff. */
589 if (*psz == '[')
590 continue;
591
592 /* Message length. */
593 uint64_t cMessageBits;
594 if (RTStrNICmp(psz, RT_STR_TUPLE("Len =")))
595 return Error("%s(%d): Expected 'Len =' found '%.10s...'", ValueUnion.psz, iLine, psz);
596 psz = RTStrStripL(psz + 5);
597 rc = RTStrToUInt64Full(psz, 0, &cMessageBits);
598 if (rc != VINF_SUCCESS)
599 return Error("%s(%d): Error parsing length '%s': %Rrc\n", ValueUnion.psz, iLine, psz, rc);
600
601 /* The message text. */
602 psz = MyGetNextSignificantLine(pFile, s_szLine, sizeof(s_szLine), &iLine, &rc);
603 if (!psz)
604 return Error("%s(%d): Expected message text not EOF.", ValueUnion.psz, iLine);
605 if (RTStrNICmp(psz, RT_STR_TUPLE("Msg =")))
606 return Error("%s(%d): Expected 'Msg =' found '%.10s...'", ValueUnion.psz, iLine, psz);
607 psz = RTStrStripL(psz + 5);
608
609 size_t const cbMessage = (cMessageBits + 7) / 8;
610 static uint8_t s_abMessage[sizeof(s_szLine) / 2];
611 if (cbMessage > 0)
612 {
613 rc = RTStrConvertHexBytes(psz, s_abMessage, cbMessage, 0 /*fFlags*/);
614 if (rc != VINF_SUCCESS)
615 return Error("%s(%d): Error parsing message '%.10s...': %Rrc\n",
616 ValueUnion.psz, iLine, psz, rc);
617 }
618
619 /* The message digest. */
620 psz = MyGetNextSignificantLine(pFile, s_szLine, sizeof(s_szLine), &iLine, &rc);
621 if (!psz)
622 return Error("%s(%d): Expected message digest not EOF.", ValueUnion.psz, iLine);
623 if (RTStrNICmp(psz, RT_STR_TUPLE("MD =")))
624 return Error("%s(%d): Expected 'MD =' found '%.10s...'", ValueUnion.psz, iLine, psz);
625 psz = RTStrStripL(psz + 4);
626
627 static uint8_t s_abExpectedDigest[_1K];
628 rc = RTStrConvertHexBytes(psz, s_abExpectedDigest, cbDigest, 0 /*fFlags*/);
629 if (rc != VINF_SUCCESS)
630 return Error("%s(%d): Error parsing message digest '%.10s...': %Rrc\n",
631 ValueUnion.psz, iLine, psz, rc);
632
633 /*
634 * Do the testing.
635 */
636 rc = RTCrDigestReset(hDigest);
637 if (rc != VINF_SUCCESS)
638 return Error("RTCrDigestReset failed: %Rrc", rc);
639
640 rc = RTCrDigestUpdate(hDigest, s_abMessage, cbMessage);
641 if (rc != VINF_SUCCESS)
642 return Error("RTCrDigestUpdate failed: %Rrc", rc);
643
644 static uint8_t s_abActualDigest[_1K];
645 rc = RTCrDigestFinal(hDigest, s_abActualDigest, cbDigest);
646 if (rc != VINF_SUCCESS)
647 return Error("RTCrDigestFinal failed: %Rrc", rc);
648
649 if (memcmp(s_abActualDigest, s_abExpectedDigest, cbDigest) == 0)
650 cPassed++;
651 else
652 {
653 Error("%s(%d): Message digest mismatch. Expected %.*RThxs, got %.*RThxs.",
654 ValueUnion.psz, iLine, cbDigest, s_abExpectedDigest, cbDigest, s_abActualDigest);
655 cErrors++;
656 }
657 }
658
659 RTStrmClose(pFile);
660 if (cErrors > 0)
661 return Error("Failed: %u error%s (%u passed)", cErrors, cErrors == 1 ? "" : "s", cPassed);
662 RTPrintf("Passed %u test%s.\n", cPassed, cPassed == 1 ? "" : "s");
663 if (RT_FAILURE(rc))
664 return Error("Failed: %Rrc", rc);
665 break;
666 }
667
668 default:
669 return Error("Internal error #2\n");
670 }
671 break;
672 }
673
674 default:
675 return RTGetOptPrintError(ch, &ValueUnion);
676 }
677 }
678
679 return 0;
680}
681
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