123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957 |
- /*
- ** This utility program reads the "manifest" and "manifest.uuid" files
- ** in a Fossil-generated source tree (where the repository has the
- ** "manifest" setting turned on - this is true for SQLite and Fossil itself)
- ** and verifies that the source code files are complete and unaltered by
- ** checking the SHA1 and SHA3 hashes of the source files contained in the
- ** "manifest" file.
- **
- ** On success it prints: "OK $HASH" where $HASH is the SHA3-256 hash of
- ** the check-in for the source tree. If it finds any discrepencies, it
- ** prints "Derived from $HASH with changes to:" followed by a list of files
- ** which have been altered.
- **
- ** USAGE:
- **
- ** src-verify [-x] [-v] $(ROOT)
- **
- ** Where ROOT is the root of the source tree - the directory that contains
- ** the "manifest" and "manifest.uuid" files. Add the "-v" option for
- ** some debugging output. With the -x option, the output is in a format
- ** that is intended to be read by a script rather by a human. The -x output
- ** format always has the SHA3 hash of the source check-in on the first line
- ** and lists files that have changed on subsequent lines.
- **
- ** Additional debugging options:
- **
- ** src-verify --sha1 FILE ...
- ** src-verify --sha3 FILE ...
- **
- ** Compute the SHA1 or SHA3-256 hashes for all of the FILEs named
- **
- ** COMPILING:
- **
- ** This utility is self-contained. It uses only the standard library.
- ** There are no other dependencies. Just compile it and run it.
- **
- ** LIMITATIONS:
- **
- ** * This utility assumes that the check-in hash uses SHA3-256.
- ** It is ok for individual file hashes to be SHA1, but the
- ** check-in itself must use a SHA3-256 hash.
- */
- #include <stdio.h>
- #include <string.h>
- #include <stdlib.h>
- #if !defined(_WIN32)
- # include <unistd.h>
- #else
- # include <io.h>
- # ifndef R_OK
- # define R_OK 04
- # endif
- # ifndef access
- # define access(f,m) _access((f),(m))
- # endif
- #endif
- typedef unsigned long long int u64;
- /*
- ** The SHA1 implementation below is adapted from:
- **
- ** $NetBSD: sha1.c,v 1.6 2009/11/06 20:31:18 joerg Exp $
- ** $OpenBSD: sha1.c,v 1.9 1997/07/23 21:12:32 kstailey Exp $
- **
- ** SHA-1 in C
- ** By Steve Reid <steve@edmweb.com>
- ** 100% Public Domain
- */
- typedef struct SHA1Context SHA1Context;
- struct SHA1Context {
- unsigned int state[5];
- unsigned int count[2];
- unsigned char buffer[64];
- };
- /*
- * blk0() and blk() perform the initial expand.
- * I got the idea of expanding during the round function from SSLeay
- *
- * blk0le() for little-endian and blk0be() for big-endian.
- */
- #define SHA_ROT(x,l,r) ((x) << (l) | (x) >> (r))
- #define rol(x,k) SHA_ROT(x,k,32-(k))
- #define ror(x,k) SHA_ROT(x,32-(k),k)
- #define blk0le(i) (block[i] = (ror(block[i],8)&0xFF00FF00) \
- |(rol(block[i],8)&0x00FF00FF))
- #define blk0be(i) block[i]
- #define blk(i) (block[i&15] = rol(block[(i+13)&15]^block[(i+8)&15] \
- ^block[(i+2)&15]^block[i&15],1))
- /*
- * (R0+R1), R2, R3, R4 are the different operations (rounds) used in SHA1
- *
- * Rl0() for little-endian and Rb0() for big-endian. Endianness is
- * determined at run-time.
- */
- #define Rl0(v,w,x,y,z,i) \
- z+=((w&(x^y))^y)+blk0le(i)+0x5A827999+rol(v,5);w=ror(w,2);
- #define Rb0(v,w,x,y,z,i) \
- z+=((w&(x^y))^y)+blk0be(i)+0x5A827999+rol(v,5);w=ror(w,2);
- #define R1(v,w,x,y,z,i) \
- z+=((w&(x^y))^y)+blk(i)+0x5A827999+rol(v,5);w=ror(w,2);
- #define R2(v,w,x,y,z,i) \
- z+=(w^x^y)+blk(i)+0x6ED9EBA1+rol(v,5);w=ror(w,2);
- #define R3(v,w,x,y,z,i) \
- z+=(((w|x)&y)|(w&x))+blk(i)+0x8F1BBCDC+rol(v,5);w=ror(w,2);
- #define R4(v,w,x,y,z,i) \
- z+=(w^x^y)+blk(i)+0xCA62C1D6+rol(v,5);w=ror(w,2);
- /*
- * Hash a single 512-bit block. This is the core of the algorithm.
- */
- #define a qq[0]
- #define b qq[1]
- #define c qq[2]
- #define d qq[3]
- #define e qq[4]
- void SHA1Transform(unsigned int state[5], const unsigned char buffer[64])
- {
- unsigned int qq[5]; /* a, b, c, d, e; */
- static int one = 1;
- unsigned int block[16];
- memcpy(block, buffer, 64);
- memcpy(qq,state,5*sizeof(unsigned int));
- /* Copy context->state[] to working vars */
- /*
- a = state[0];
- b = state[1];
- c = state[2];
- d = state[3];
- e = state[4];
- */
- /* 4 rounds of 20 operations each. Loop unrolled. */
- if( 1 == *(unsigned char*)&one ){
- Rl0(a,b,c,d,e, 0); Rl0(e,a,b,c,d, 1); Rl0(d,e,a,b,c, 2); Rl0(c,d,e,a,b, 3);
- Rl0(b,c,d,e,a, 4); Rl0(a,b,c,d,e, 5); Rl0(e,a,b,c,d, 6); Rl0(d,e,a,b,c, 7);
- Rl0(c,d,e,a,b, 8); Rl0(b,c,d,e,a, 9); Rl0(a,b,c,d,e,10); Rl0(e,a,b,c,d,11);
- Rl0(d,e,a,b,c,12); Rl0(c,d,e,a,b,13); Rl0(b,c,d,e,a,14); Rl0(a,b,c,d,e,15);
- }else{
- Rb0(a,b,c,d,e, 0); Rb0(e,a,b,c,d, 1); Rb0(d,e,a,b,c, 2); Rb0(c,d,e,a,b, 3);
- Rb0(b,c,d,e,a, 4); Rb0(a,b,c,d,e, 5); Rb0(e,a,b,c,d, 6); Rb0(d,e,a,b,c, 7);
- Rb0(c,d,e,a,b, 8); Rb0(b,c,d,e,a, 9); Rb0(a,b,c,d,e,10); Rb0(e,a,b,c,d,11);
- Rb0(d,e,a,b,c,12); Rb0(c,d,e,a,b,13); Rb0(b,c,d,e,a,14); Rb0(a,b,c,d,e,15);
- }
- R1(e,a,b,c,d,16); R1(d,e,a,b,c,17); R1(c,d,e,a,b,18); R1(b,c,d,e,a,19);
- R2(a,b,c,d,e,20); R2(e,a,b,c,d,21); R2(d,e,a,b,c,22); R2(c,d,e,a,b,23);
- R2(b,c,d,e,a,24); R2(a,b,c,d,e,25); R2(e,a,b,c,d,26); R2(d,e,a,b,c,27);
- R2(c,d,e,a,b,28); R2(b,c,d,e,a,29); R2(a,b,c,d,e,30); R2(e,a,b,c,d,31);
- R2(d,e,a,b,c,32); R2(c,d,e,a,b,33); R2(b,c,d,e,a,34); R2(a,b,c,d,e,35);
- R2(e,a,b,c,d,36); R2(d,e,a,b,c,37); R2(c,d,e,a,b,38); R2(b,c,d,e,a,39);
- R3(a,b,c,d,e,40); R3(e,a,b,c,d,41); R3(d,e,a,b,c,42); R3(c,d,e,a,b,43);
- R3(b,c,d,e,a,44); R3(a,b,c,d,e,45); R3(e,a,b,c,d,46); R3(d,e,a,b,c,47);
- R3(c,d,e,a,b,48); R3(b,c,d,e,a,49); R3(a,b,c,d,e,50); R3(e,a,b,c,d,51);
- R3(d,e,a,b,c,52); R3(c,d,e,a,b,53); R3(b,c,d,e,a,54); R3(a,b,c,d,e,55);
- R3(e,a,b,c,d,56); R3(d,e,a,b,c,57); R3(c,d,e,a,b,58); R3(b,c,d,e,a,59);
- R4(a,b,c,d,e,60); R4(e,a,b,c,d,61); R4(d,e,a,b,c,62); R4(c,d,e,a,b,63);
- R4(b,c,d,e,a,64); R4(a,b,c,d,e,65); R4(e,a,b,c,d,66); R4(d,e,a,b,c,67);
- R4(c,d,e,a,b,68); R4(b,c,d,e,a,69); R4(a,b,c,d,e,70); R4(e,a,b,c,d,71);
- R4(d,e,a,b,c,72); R4(c,d,e,a,b,73); R4(b,c,d,e,a,74); R4(a,b,c,d,e,75);
- R4(e,a,b,c,d,76); R4(d,e,a,b,c,77); R4(c,d,e,a,b,78); R4(b,c,d,e,a,79);
- /* Add the working vars back into context.state[] */
- state[0] += a;
- state[1] += b;
- state[2] += c;
- state[3] += d;
- state[4] += e;
- }
- /*
- * SHA1Init - Initialize new context
- */
- static void SHA1Init(SHA1Context *context){
- /* SHA1 initialization constants */
- context->state[0] = 0x67452301;
- context->state[1] = 0xEFCDAB89;
- context->state[2] = 0x98BADCFE;
- context->state[3] = 0x10325476;
- context->state[4] = 0xC3D2E1F0;
- context->count[0] = context->count[1] = 0;
- }
- /*
- * Run your data through this.
- */
- static void SHA1Update(
- SHA1Context *context,
- const unsigned char *data,
- unsigned int len
- ){
- unsigned int i, j;
- j = context->count[0];
- if ((context->count[0] += len << 3) < j)
- context->count[1] += (len>>29)+1;
- j = (j >> 3) & 63;
- if ((j + len) > 63) {
- (void)memcpy(&context->buffer[j], data, (i = 64-j));
- SHA1Transform(context->state, context->buffer);
- for ( ; i + 63 < len; i += 64)
- SHA1Transform(context->state, &data[i]);
- j = 0;
- } else {
- i = 0;
- }
- (void)memcpy(&context->buffer[j], &data[i], len - i);
- }
- /*
- * Add padding and return the message digest.
- */
- static void SHA1Final(unsigned char *digest, SHA1Context *context){
- unsigned int i;
- unsigned char finalcount[8];
- for (i = 0; i < 8; i++) {
- finalcount[i] = (unsigned char)((context->count[(i >= 4 ? 0 : 1)]
- >> ((3-(i & 3)) * 8) ) & 255); /* Endian independent */
- }
- SHA1Update(context, (const unsigned char *)"\200", 1);
- while ((context->count[0] & 504) != 448)
- SHA1Update(context, (const unsigned char *)"\0", 1);
- SHA1Update(context, finalcount, 8); /* Should cause a SHA1Transform() */
- if (digest) {
- for (i = 0; i < 20; i++)
- digest[i] = (unsigned char)
- ((context->state[i>>2] >> ((3-(i & 3)) * 8) ) & 255);
- }
- }
- /*
- ** Macros to determine whether the machine is big or little endian,
- ** and whether or not that determination is run-time or compile-time.
- **
- ** For best performance, an attempt is made to guess at the byte-order
- ** using C-preprocessor macros. If that is unsuccessful, or if
- ** -DSHA3_BYTEORDER=0 is set, then byte-order is determined
- ** at run-time.
- */
- #ifndef SHA3_BYTEORDER
- # if defined(i386) || defined(__i386__) || defined(_M_IX86) || \
- defined(__x86_64) || defined(__x86_64__) || defined(_M_X64) || \
- defined(_M_AMD64) || defined(_M_ARM) || defined(__x86) || \
- defined(__arm__)
- # define SHA3_BYTEORDER 1234
- # elif defined(sparc) || defined(__ppc__)
- # define SHA3_BYTEORDER 4321
- # else
- # define SHA3_BYTEORDER 0
- # endif
- #endif
- /*
- ** State structure for a SHA3 hash in progress
- */
- typedef struct SHA3Context SHA3Context;
- struct SHA3Context {
- union {
- u64 s[25]; /* Keccak state. 5x5 lines of 64 bits each */
- unsigned char x[1600]; /* ... or 1600 bytes */
- } u;
- unsigned nRate; /* Bytes of input accepted per Keccak iteration */
- unsigned nLoaded; /* Input bytes loaded into u.x[] so far this cycle */
- unsigned ixMask; /* Insert next input into u.x[nLoaded^ixMask]. */
- };
- /*
- ** A single step of the Keccak mixing function for a 1600-bit state
- */
- static void KeccakF1600Step(SHA3Context *p){
- int i;
- u64 B0, B1, B2, B3, B4;
- u64 C0, C1, C2, C3, C4;
- u64 D0, D1, D2, D3, D4;
- static const u64 RC[] = {
- 0x0000000000000001ULL, 0x0000000000008082ULL,
- 0x800000000000808aULL, 0x8000000080008000ULL,
- 0x000000000000808bULL, 0x0000000080000001ULL,
- 0x8000000080008081ULL, 0x8000000000008009ULL,
- 0x000000000000008aULL, 0x0000000000000088ULL,
- 0x0000000080008009ULL, 0x000000008000000aULL,
- 0x000000008000808bULL, 0x800000000000008bULL,
- 0x8000000000008089ULL, 0x8000000000008003ULL,
- 0x8000000000008002ULL, 0x8000000000000080ULL,
- 0x000000000000800aULL, 0x800000008000000aULL,
- 0x8000000080008081ULL, 0x8000000000008080ULL,
- 0x0000000080000001ULL, 0x8000000080008008ULL
- };
- # define A00 (p->u.s[0])
- # define A01 (p->u.s[1])
- # define A02 (p->u.s[2])
- # define A03 (p->u.s[3])
- # define A04 (p->u.s[4])
- # define A10 (p->u.s[5])
- # define A11 (p->u.s[6])
- # define A12 (p->u.s[7])
- # define A13 (p->u.s[8])
- # define A14 (p->u.s[9])
- # define A20 (p->u.s[10])
- # define A21 (p->u.s[11])
- # define A22 (p->u.s[12])
- # define A23 (p->u.s[13])
- # define A24 (p->u.s[14])
- # define A30 (p->u.s[15])
- # define A31 (p->u.s[16])
- # define A32 (p->u.s[17])
- # define A33 (p->u.s[18])
- # define A34 (p->u.s[19])
- # define A40 (p->u.s[20])
- # define A41 (p->u.s[21])
- # define A42 (p->u.s[22])
- # define A43 (p->u.s[23])
- # define A44 (p->u.s[24])
- # define ROL64(a,x) ((a<<x)|(a>>(64-x)))
- for(i=0; i<24; i+=4){
- C0 = A00^A10^A20^A30^A40;
- C1 = A01^A11^A21^A31^A41;
- C2 = A02^A12^A22^A32^A42;
- C3 = A03^A13^A23^A33^A43;
- C4 = A04^A14^A24^A34^A44;
- D0 = C4^ROL64(C1, 1);
- D1 = C0^ROL64(C2, 1);
- D2 = C1^ROL64(C3, 1);
- D3 = C2^ROL64(C4, 1);
- D4 = C3^ROL64(C0, 1);
- B0 = (A00^D0);
- B1 = ROL64((A11^D1), 44);
- B2 = ROL64((A22^D2), 43);
- B3 = ROL64((A33^D3), 21);
- B4 = ROL64((A44^D4), 14);
- A00 = B0 ^((~B1)& B2 );
- A00 ^= RC[i];
- A11 = B1 ^((~B2)& B3 );
- A22 = B2 ^((~B3)& B4 );
- A33 = B3 ^((~B4)& B0 );
- A44 = B4 ^((~B0)& B1 );
- B2 = ROL64((A20^D0), 3);
- B3 = ROL64((A31^D1), 45);
- B4 = ROL64((A42^D2), 61);
- B0 = ROL64((A03^D3), 28);
- B1 = ROL64((A14^D4), 20);
- A20 = B0 ^((~B1)& B2 );
- A31 = B1 ^((~B2)& B3 );
- A42 = B2 ^((~B3)& B4 );
- A03 = B3 ^((~B4)& B0 );
- A14 = B4 ^((~B0)& B1 );
- B4 = ROL64((A40^D0), 18);
- B0 = ROL64((A01^D1), 1);
- B1 = ROL64((A12^D2), 6);
- B2 = ROL64((A23^D3), 25);
- B3 = ROL64((A34^D4), 8);
- A40 = B0 ^((~B1)& B2 );
- A01 = B1 ^((~B2)& B3 );
- A12 = B2 ^((~B3)& B4 );
- A23 = B3 ^((~B4)& B0 );
- A34 = B4 ^((~B0)& B1 );
- B1 = ROL64((A10^D0), 36);
- B2 = ROL64((A21^D1), 10);
- B3 = ROL64((A32^D2), 15);
- B4 = ROL64((A43^D3), 56);
- B0 = ROL64((A04^D4), 27);
- A10 = B0 ^((~B1)& B2 );
- A21 = B1 ^((~B2)& B3 );
- A32 = B2 ^((~B3)& B4 );
- A43 = B3 ^((~B4)& B0 );
- A04 = B4 ^((~B0)& B1 );
- B3 = ROL64((A30^D0), 41);
- B4 = ROL64((A41^D1), 2);
- B0 = ROL64((A02^D2), 62);
- B1 = ROL64((A13^D3), 55);
- B2 = ROL64((A24^D4), 39);
- A30 = B0 ^((~B1)& B2 );
- A41 = B1 ^((~B2)& B3 );
- A02 = B2 ^((~B3)& B4 );
- A13 = B3 ^((~B4)& B0 );
- A24 = B4 ^((~B0)& B1 );
- C0 = A00^A20^A40^A10^A30;
- C1 = A11^A31^A01^A21^A41;
- C2 = A22^A42^A12^A32^A02;
- C3 = A33^A03^A23^A43^A13;
- C4 = A44^A14^A34^A04^A24;
- D0 = C4^ROL64(C1, 1);
- D1 = C0^ROL64(C2, 1);
- D2 = C1^ROL64(C3, 1);
- D3 = C2^ROL64(C4, 1);
- D4 = C3^ROL64(C0, 1);
- B0 = (A00^D0);
- B1 = ROL64((A31^D1), 44);
- B2 = ROL64((A12^D2), 43);
- B3 = ROL64((A43^D3), 21);
- B4 = ROL64((A24^D4), 14);
- A00 = B0 ^((~B1)& B2 );
- A00 ^= RC[i+1];
- A31 = B1 ^((~B2)& B3 );
- A12 = B2 ^((~B3)& B4 );
- A43 = B3 ^((~B4)& B0 );
- A24 = B4 ^((~B0)& B1 );
- B2 = ROL64((A40^D0), 3);
- B3 = ROL64((A21^D1), 45);
- B4 = ROL64((A02^D2), 61);
- B0 = ROL64((A33^D3), 28);
- B1 = ROL64((A14^D4), 20);
- A40 = B0 ^((~B1)& B2 );
- A21 = B1 ^((~B2)& B3 );
- A02 = B2 ^((~B3)& B4 );
- A33 = B3 ^((~B4)& B0 );
- A14 = B4 ^((~B0)& B1 );
- B4 = ROL64((A30^D0), 18);
- B0 = ROL64((A11^D1), 1);
- B1 = ROL64((A42^D2), 6);
- B2 = ROL64((A23^D3), 25);
- B3 = ROL64((A04^D4), 8);
- A30 = B0 ^((~B1)& B2 );
- A11 = B1 ^((~B2)& B3 );
- A42 = B2 ^((~B3)& B4 );
- A23 = B3 ^((~B4)& B0 );
- A04 = B4 ^((~B0)& B1 );
- B1 = ROL64((A20^D0), 36);
- B2 = ROL64((A01^D1), 10);
- B3 = ROL64((A32^D2), 15);
- B4 = ROL64((A13^D3), 56);
- B0 = ROL64((A44^D4), 27);
- A20 = B0 ^((~B1)& B2 );
- A01 = B1 ^((~B2)& B3 );
- A32 = B2 ^((~B3)& B4 );
- A13 = B3 ^((~B4)& B0 );
- A44 = B4 ^((~B0)& B1 );
- B3 = ROL64((A10^D0), 41);
- B4 = ROL64((A41^D1), 2);
- B0 = ROL64((A22^D2), 62);
- B1 = ROL64((A03^D3), 55);
- B2 = ROL64((A34^D4), 39);
- A10 = B0 ^((~B1)& B2 );
- A41 = B1 ^((~B2)& B3 );
- A22 = B2 ^((~B3)& B4 );
- A03 = B3 ^((~B4)& B0 );
- A34 = B4 ^((~B0)& B1 );
- C0 = A00^A40^A30^A20^A10;
- C1 = A31^A21^A11^A01^A41;
- C2 = A12^A02^A42^A32^A22;
- C3 = A43^A33^A23^A13^A03;
- C4 = A24^A14^A04^A44^A34;
- D0 = C4^ROL64(C1, 1);
- D1 = C0^ROL64(C2, 1);
- D2 = C1^ROL64(C3, 1);
- D3 = C2^ROL64(C4, 1);
- D4 = C3^ROL64(C0, 1);
- B0 = (A00^D0);
- B1 = ROL64((A21^D1), 44);
- B2 = ROL64((A42^D2), 43);
- B3 = ROL64((A13^D3), 21);
- B4 = ROL64((A34^D4), 14);
- A00 = B0 ^((~B1)& B2 );
- A00 ^= RC[i+2];
- A21 = B1 ^((~B2)& B3 );
- A42 = B2 ^((~B3)& B4 );
- A13 = B3 ^((~B4)& B0 );
- A34 = B4 ^((~B0)& B1 );
- B2 = ROL64((A30^D0), 3);
- B3 = ROL64((A01^D1), 45);
- B4 = ROL64((A22^D2), 61);
- B0 = ROL64((A43^D3), 28);
- B1 = ROL64((A14^D4), 20);
- A30 = B0 ^((~B1)& B2 );
- A01 = B1 ^((~B2)& B3 );
- A22 = B2 ^((~B3)& B4 );
- A43 = B3 ^((~B4)& B0 );
- A14 = B4 ^((~B0)& B1 );
- B4 = ROL64((A10^D0), 18);
- B0 = ROL64((A31^D1), 1);
- B1 = ROL64((A02^D2), 6);
- B2 = ROL64((A23^D3), 25);
- B3 = ROL64((A44^D4), 8);
- A10 = B0 ^((~B1)& B2 );
- A31 = B1 ^((~B2)& B3 );
- A02 = B2 ^((~B3)& B4 );
- A23 = B3 ^((~B4)& B0 );
- A44 = B4 ^((~B0)& B1 );
- B1 = ROL64((A40^D0), 36);
- B2 = ROL64((A11^D1), 10);
- B3 = ROL64((A32^D2), 15);
- B4 = ROL64((A03^D3), 56);
- B0 = ROL64((A24^D4), 27);
- A40 = B0 ^((~B1)& B2 );
- A11 = B1 ^((~B2)& B3 );
- A32 = B2 ^((~B3)& B4 );
- A03 = B3 ^((~B4)& B0 );
- A24 = B4 ^((~B0)& B1 );
- B3 = ROL64((A20^D0), 41);
- B4 = ROL64((A41^D1), 2);
- B0 = ROL64((A12^D2), 62);
- B1 = ROL64((A33^D3), 55);
- B2 = ROL64((A04^D4), 39);
- A20 = B0 ^((~B1)& B2 );
- A41 = B1 ^((~B2)& B3 );
- A12 = B2 ^((~B3)& B4 );
- A33 = B3 ^((~B4)& B0 );
- A04 = B4 ^((~B0)& B1 );
- C0 = A00^A30^A10^A40^A20;
- C1 = A21^A01^A31^A11^A41;
- C2 = A42^A22^A02^A32^A12;
- C3 = A13^A43^A23^A03^A33;
- C4 = A34^A14^A44^A24^A04;
- D0 = C4^ROL64(C1, 1);
- D1 = C0^ROL64(C2, 1);
- D2 = C1^ROL64(C3, 1);
- D3 = C2^ROL64(C4, 1);
- D4 = C3^ROL64(C0, 1);
- B0 = (A00^D0);
- B1 = ROL64((A01^D1), 44);
- B2 = ROL64((A02^D2), 43);
- B3 = ROL64((A03^D3), 21);
- B4 = ROL64((A04^D4), 14);
- A00 = B0 ^((~B1)& B2 );
- A00 ^= RC[i+3];
- A01 = B1 ^((~B2)& B3 );
- A02 = B2 ^((~B3)& B4 );
- A03 = B3 ^((~B4)& B0 );
- A04 = B4 ^((~B0)& B1 );
- B2 = ROL64((A10^D0), 3);
- B3 = ROL64((A11^D1), 45);
- B4 = ROL64((A12^D2), 61);
- B0 = ROL64((A13^D3), 28);
- B1 = ROL64((A14^D4), 20);
- A10 = B0 ^((~B1)& B2 );
- A11 = B1 ^((~B2)& B3 );
- A12 = B2 ^((~B3)& B4 );
- A13 = B3 ^((~B4)& B0 );
- A14 = B4 ^((~B0)& B1 );
- B4 = ROL64((A20^D0), 18);
- B0 = ROL64((A21^D1), 1);
- B1 = ROL64((A22^D2), 6);
- B2 = ROL64((A23^D3), 25);
- B3 = ROL64((A24^D4), 8);
- A20 = B0 ^((~B1)& B2 );
- A21 = B1 ^((~B2)& B3 );
- A22 = B2 ^((~B3)& B4 );
- A23 = B3 ^((~B4)& B0 );
- A24 = B4 ^((~B0)& B1 );
- B1 = ROL64((A30^D0), 36);
- B2 = ROL64((A31^D1), 10);
- B3 = ROL64((A32^D2), 15);
- B4 = ROL64((A33^D3), 56);
- B0 = ROL64((A34^D4), 27);
- A30 = B0 ^((~B1)& B2 );
- A31 = B1 ^((~B2)& B3 );
- A32 = B2 ^((~B3)& B4 );
- A33 = B3 ^((~B4)& B0 );
- A34 = B4 ^((~B0)& B1 );
- B3 = ROL64((A40^D0), 41);
- B4 = ROL64((A41^D1), 2);
- B0 = ROL64((A42^D2), 62);
- B1 = ROL64((A43^D3), 55);
- B2 = ROL64((A44^D4), 39);
- A40 = B0 ^((~B1)& B2 );
- A41 = B1 ^((~B2)& B3 );
- A42 = B2 ^((~B3)& B4 );
- A43 = B3 ^((~B4)& B0 );
- A44 = B4 ^((~B0)& B1 );
- }
- }
- /*
- ** Initialize a new hash. iSize determines the size of the hash
- ** in bits and should be one of 224, 256, 384, or 512. Or iSize
- ** can be zero to use the default hash size of 256 bits.
- */
- static void SHA3Init(SHA3Context *p, int iSize){
- memset(p, 0, sizeof(*p));
- if( iSize>=128 && iSize<=512 ){
- p->nRate = (1600 - ((iSize + 31)&~31)*2)/8;
- }else{
- p->nRate = (1600 - 2*256)/8;
- }
- #if SHA3_BYTEORDER==1234
- /* Known to be little-endian at compile-time. No-op */
- #elif SHA3_BYTEORDER==4321
- p->ixMask = 7; /* Big-endian */
- #else
- {
- static unsigned int one = 1;
- if( 1==*(unsigned char*)&one ){
- /* Little endian. No byte swapping. */
- p->ixMask = 0;
- }else{
- /* Big endian. Byte swap. */
- p->ixMask = 7;
- }
- }
- #endif
- }
- /*
- ** Make consecutive calls to the SHA3Update function to add new content
- ** to the hash
- */
- static void SHA3Update(
- SHA3Context *p,
- const unsigned char *aData,
- unsigned int nData
- ){
- unsigned int i = 0;
- #if SHA3_BYTEORDER==1234
- if( (p->nLoaded % 8)==0 && ((aData - (const unsigned char*)0)&7)==0 ){
- for(; i+7<nData; i+=8){
- p->u.s[p->nLoaded/8] ^= *(u64*)&aData[i];
- p->nLoaded += 8;
- if( p->nLoaded>=p->nRate ){
- KeccakF1600Step(p);
- p->nLoaded = 0;
- }
- }
- }
- #endif
- for(; i<nData; i++){
- #if SHA3_BYTEORDER==1234
- p->u.x[p->nLoaded] ^= aData[i];
- #elif SHA3_BYTEORDER==4321
- p->u.x[p->nLoaded^0x07] ^= aData[i];
- #else
- p->u.x[p->nLoaded^p->ixMask] ^= aData[i];
- #endif
- p->nLoaded++;
- if( p->nLoaded==p->nRate ){
- KeccakF1600Step(p);
- p->nLoaded = 0;
- }
- }
- }
- /*
- ** After all content has been added, invoke SHA3Final() to compute
- ** the final hash. The function returns a pointer to the binary
- ** hash value.
- */
- static unsigned char *SHA3Final(SHA3Context *p){
- unsigned int i;
- if( p->nLoaded==p->nRate-1 ){
- const unsigned char c1 = 0x86;
- SHA3Update(p, &c1, 1);
- }else{
- const unsigned char c2 = 0x06;
- const unsigned char c3 = 0x80;
- SHA3Update(p, &c2, 1);
- p->nLoaded = p->nRate - 1;
- SHA3Update(p, &c3, 1);
- }
- for(i=0; i<p->nRate; i++){
- p->u.x[i+p->nRate] = p->u.x[i^p->ixMask];
- }
- return &p->u.x[p->nRate];
- }
- /*
- ** Convert a digest into base-16.
- */
- static void DigestToBase16(unsigned char *digest, char *zBuf, int nByte){
- static const char zEncode[] = "0123456789abcdef";
- int ix;
- for(ix=0; ix<nByte; ix++){
- *zBuf++ = zEncode[(*digest>>4)&0xf];
- *zBuf++ = zEncode[*digest++ & 0xf];
- }
- *zBuf = '\0';
- }
- /*
- ** Compute the SHA3-256 checksum of a file on disk. Store the resulting
- ** checksum in the zCksum.
- **
- ** Return the number of errors.
- */
- void sha3sum_file(const char *zFilename, char *zCksum){
- FILE *in;
- SHA3Context ctx;
- char zBuf[10240];
- in = fopen(zFilename,"rb");
- if( in==0 ){
- zCksum[0] = 0;
- return;
- }
- SHA3Init(&ctx, 256);
- for(;;){
- size_t n;
- n = fread(zBuf, 1, sizeof(zBuf), in);
- if( n<=0 ) break;
- SHA3Update(&ctx, (unsigned char*)zBuf, (unsigned)n);
- }
- fclose(in);
- DigestToBase16(SHA3Final(&ctx), zCksum, 32);
- }
- /*
- ** Compute the SHA1 checksum of a file on disk. Store the resulting
- ** checksum in the zCksum.
- **
- ** Return the number of errors.
- */
- void sha1sum_file(const char *zFilename, char *zCksum){
- FILE *in;
- SHA1Context ctx;
- unsigned char zResult[20];
- char zBuf[10240];
- in = fopen(zFilename,"rb");
- if( in==0 ){
- zCksum[0] = 0;
- return;
- }
- SHA1Init(&ctx);
- for(;;){
- size_t n;
- n = fread(zBuf, 1, sizeof(zBuf), in);
- if( n<=0 ) break;
- SHA1Update(&ctx, (unsigned char*)zBuf, (unsigned)n);
- }
- fclose(in);
- SHA1Final(zResult, &ctx);
- DigestToBase16(zResult, zCksum, 20);
- }
-
- /*
- ** Decode a fossilized string in-place.
- */
- void defossilize(char *z){
- int i, j, cc;
- char *zSlash = strchr(z, '\\');
- if( zSlash==0 ) return;
- i = zSlash - z;
- for(j=i; (cc=z[i])!=0; i++){
- if( cc=='\\' && z[i+1] ){
- i++;
- switch( z[i] ){
- case 'n': cc = '\n'; break;
- case 's': cc = ' '; break;
- case 't': cc = '\t'; break;
- case 'r': cc = '\r'; break;
- case 'v': cc = '\v'; break;
- case 'f': cc = '\f'; break;
- case '0': cc = 0; break;
- case '\\': cc = '\\'; break;
- default: cc = z[i]; break;
- }
- }
- z[j++] = cc;
- }
- if( z[j] ) z[j] = 0;
- }
- /*
- ** Report that a single file is incorrect.
- */
- static void errorMsg(int *pnErr, const char *zVers, const char *zFile){
- if( *pnErr==0 ){
- printf("Derived from %.25s with changes to:\n", zVers);
- }
- printf(" %s\n", zFile);
- (*pnErr)++;
- }
- static void errorMsgNH(int *pnErr, const char *zVers, const char *zFile){
- if( *pnErr==0 ){
- printf("%s\n", zVers);
- }
- printf("%s\n", zFile);
- (*pnErr)++;
- }
- int main(int argc, char **argv){
- int i, j;
- int nDir;
- FILE *in;
- int bDebug = 0;
- int bNonHuman = 0;
- int bSeenManifestErr = 0;
- int nErr = 0;
- SHA3Context ctx3;
- const char *zDir = 0;
- void (*xErr)(int*,const char*,const char*);
- char zHash[100];
- char zCk[100];
- char zVers[100];
- char zLine[40000];
- char zFile[40000];
- xErr = errorMsg;
- for(i=1; i<argc; i++){
- const char *z = argv[i];
- if( z[0]!='-' ){
- if( zDir!=0 ){
- fprintf(stderr, "bad argument: %s\n", z);
- return 1;
- }
- zDir = z;
- continue;
- }
- if( z[1]=='-' && z[2]!=0 ) z++;
- if( strcmp(argv[1],"-sha1")==0 ){
- /* For testing purposes, if the first argument is --sha1, then simply
- ** compute and print the SHA1 checksum of all subsequent arguments. */
- for(i++; i<argc; i++){
- sha1sum_file(argv[i], zHash);
- printf("%s %s\n", zHash, argv[i]);
- }
- return 0;
- }
- if( strcmp(argv[1], "-sha3")==0 ){
- /* For testing purposes, if the first argument is --sha3, then simply
- ** compute and print the SHA3-256 checksum of all subsequent arguments. */
- for(i++; i<argc; i++){
- sha3sum_file(argv[i], zHash);
- printf("%s %s\n", zHash, argv[i]);
- }
- return 0;
- }
- if( strcmp(z,"-v")==0 ){
- bDebug = 1;
- continue;
- }
- if( strcmp(z,"-x")==0 ){
- bNonHuman = 1;
- xErr = errorMsgNH;
- continue;
- }
- fprintf(stderr, "Usage: %s DIRECTORY\n"
- " or: %s --sha1 FILE ...\n"
- " or: %s --sha3 FILE ...\n",
- argv[0], argv[0], argv[0]);
- return 1;
- }
- if( strlen(zDir)>1000 ){
- fprintf(stderr, "Directory argument too big: [%s]\n", zDir);
- return 1;
- }
- nDir = (int)strlen(zDir);
- if( nDir<0 ){
- fprintf(stderr, "Directory argument too short.\n");
- return 1;
- }
- memcpy(zFile, zDir, nDir);
- if( zFile[nDir-1]!='/' ){
- zFile[nDir++] = '/';
- }
- memcpy(&zFile[nDir], "manifest", 9);
- if( bDebug ){
- printf("manifest file: [%s]\n", zFile);
- }
- in = fopen(zFile, "rb");
- if( in==0 ){
- fprintf(stderr, "missing manifest: \"%s\"\n", zFile);
- return 1;
- }
- SHA3Init(&ctx3, 256);
- while( fgets(zLine, sizeof(zLine), in) ){
- if( zLine[0]=='#' ) break;
- SHA3Update(&ctx3, (unsigned char*)zLine, (int)strlen(zLine));
- }
- DigestToBase16(SHA3Final(&ctx3), zVers, 32);
-
- rewind(in);
- while( fgets(zLine, sizeof(zLine), in) ){
- if( zLine[0]!='F' ) continue;
- if( zLine[1]!=' ' ) continue;
- for(i=2, j=nDir; zLine[i]!=0 && zLine[i]!=' '; i++, j++){
- if( j<sizeof(zFile) ) zFile[j] = zLine[i];
- }
- if( j<sizeof(zFile) ) zFile[j] = 0;
- zFile[sizeof(zFile)-1] = 0;
- defossilize(&zFile[nDir]);
- if( zLine[i]!=' ' ){
- bSeenManifestErr = 1;
- continue;
- }
- for(i++, j=0; zLine[i]>='0' && zLine[i]<='f'; i++, j++){
- if( j<sizeof(zHash) ) zHash[j] = zLine[i];
- }
- if( j<sizeof(zHash) ) zHash[j] = 0;
- zHash[sizeof(zHash)-1] = 0;
- if( bDebug ){
- printf("%s %s\n", zFile, zHash);
- }
- if( access(zFile, R_OK)!=0 ){
- xErr(&nErr, zVers, &zFile[nDir]);
- continue;
- }
- if( strlen(zHash)==40 ){
- sha1sum_file(zFile, zCk);
- if( strcmp(zHash, zCk)!=0 ){
- xErr(&nErr, zVers, &zFile[nDir]);
- }
- }else if( strlen(zHash)==64 ){
- sha3sum_file(zFile, zCk);
- if( strcmp(zHash, zCk)!=0 ){
- xErr(&nErr, zVers, &zFile[nDir]);
- }
- }else{
- bSeenManifestErr = 1;
- xErr(&nErr, zVers, &zFile[nDir]);
- }
- }
- fclose(in);
- in = 0;
- if( bSeenManifestErr ) xErr(&nErr, zVers, "manifest");
- memcpy(&zFile[nDir], "manifest.uuid", 14);
- if( access(zFile, R_OK)!=0
- || (in = fopen(zFile,"rb"))==0
- || fgets(zLine, sizeof(zLine), in)==0
- || strlen(zLine)!=65
- || zLine[64]!='\n'
- || memcmp(zLine, zVers, 64)!=0
- ){
- xErr(&nErr, zVers, &zFile[nDir]);
- }
- if( in ) fclose(in);
-
- if( bNonHuman ){
- if( nErr ) return 0;
- printf("%s\n", zVers);
- }else{
- if( nErr ) return nErr;
- printf("OK %.25s\n", zVers);
- }
- return 0;
- }
|