duckstation

duckstation, but archived from the revision just before upstream changed it to a proprietary software project, this version is the libre one
git clone https://git.neptards.moe/u3shit/duckstation.git
Log | Files | Refs | README | LICENSE

sha1_digest.cpp (7512B)


      1 // SPDX-FileCopyrightText: 2019-2024 Connor McLaughlin <stenzek@gmail.com>
      2 // SPDX-License-Identifier: (GPL-3.0 OR PolyForm-Strict-1.0.0)
      3 
      4 #include "sha1_digest.h"
      5 #include "assert.h"
      6 
      7 #include <cstring>
      8 
      9 // mostly based on this implementation (public domain): https://gist.github.com/jrabbit/1042021
     10 #define rol(value, bits) (((value) << (bits)) | ((value) >> (32 - (bits))))
     11 
     12 /* blk0() and blk() perform the initial expand. */
     13 /* I got the idea of expanding during the round function from SSLeay */
     14 #define blk0(i) (block->l[i] = (rol(block->l[i], 24) & 0xFF00FF00) | (rol(block->l[i], 8) & 0x00FF00FF))
     15 #define blk(i)                                                                                                         \
     16   (block->l[i & 15] =                                                                                                  \
     17      rol(block->l[(i + 13) & 15] ^ block->l[(i + 8) & 15] ^ block->l[(i + 2) & 15] ^ block->l[i & 15], 1))
     18 
     19 /* (R0+R1), R2, R3, R4 are the different operations used in SHA1 */
     20 #define R0(v, w, x, y, z, i)                                                                                           \
     21   z += ((w & (x ^ y)) ^ y) + blk0(i) + 0x5A827999 + rol(v, 5);                                                         \
     22   w = rol(w, 30);
     23 #define R1(v, w, x, y, z, i)                                                                                           \
     24   z += ((w & (x ^ y)) ^ y) + blk(i) + 0x5A827999 + rol(v, 5);                                                          \
     25   w = rol(w, 30);
     26 #define R2(v, w, x, y, z, i)                                                                                           \
     27   z += (w ^ x ^ y) + blk(i) + 0x6ED9EBA1 + rol(v, 5);                                                                  \
     28   w = rol(w, 30);
     29 #define R3(v, w, x, y, z, i)                                                                                           \
     30   z += (((w | x) & y) | (w & x)) + blk(i) + 0x8F1BBCDC + rol(v, 5);                                                    \
     31   w = rol(w, 30);
     32 #define R4(v, w, x, y, z, i)                                                                                           \
     33   z += (w ^ x ^ y) + blk(i) + 0xCA62C1D6 + rol(v, 5);                                                                  \
     34   w = rol(w, 30);
     35 
     36 /* Hash a single 512-bit block. This is the core of the algorithm. */
     37 
     38 static void SHA1Transform(u32 state[5], const unsigned char buffer[64])
     39 {
     40   u32 a, b, c, d, e;
     41   typedef union
     42   {
     43     unsigned char c[64];
     44     u32 l[16];
     45   } CHAR64LONG16;
     46 
     47   CHAR64LONG16 block[1]; /* use array to appear as a pointer */
     48   std::memcpy(block, buffer, 64);
     49 
     50   /* Copy context->state[] to working vars */
     51   a = state[0];
     52   b = state[1];
     53   c = state[2];
     54   d = state[3];
     55   e = state[4];
     56   /* 4 rounds of 20 operations each. Loop unrolled. */
     57   R0(a, b, c, d, e, 0);
     58   R0(e, a, b, c, d, 1);
     59   R0(d, e, a, b, c, 2);
     60   R0(c, d, e, a, b, 3);
     61   R0(b, c, d, e, a, 4);
     62   R0(a, b, c, d, e, 5);
     63   R0(e, a, b, c, d, 6);
     64   R0(d, e, a, b, c, 7);
     65   R0(c, d, e, a, b, 8);
     66   R0(b, c, d, e, a, 9);
     67   R0(a, b, c, d, e, 10);
     68   R0(e, a, b, c, d, 11);
     69   R0(d, e, a, b, c, 12);
     70   R0(c, d, e, a, b, 13);
     71   R0(b, c, d, e, a, 14);
     72   R0(a, b, c, d, e, 15);
     73   R1(e, a, b, c, d, 16);
     74   R1(d, e, a, b, c, 17);
     75   R1(c, d, e, a, b, 18);
     76   R1(b, c, d, e, a, 19);
     77   R2(a, b, c, d, e, 20);
     78   R2(e, a, b, c, d, 21);
     79   R2(d, e, a, b, c, 22);
     80   R2(c, d, e, a, b, 23);
     81   R2(b, c, d, e, a, 24);
     82   R2(a, b, c, d, e, 25);
     83   R2(e, a, b, c, d, 26);
     84   R2(d, e, a, b, c, 27);
     85   R2(c, d, e, a, b, 28);
     86   R2(b, c, d, e, a, 29);
     87   R2(a, b, c, d, e, 30);
     88   R2(e, a, b, c, d, 31);
     89   R2(d, e, a, b, c, 32);
     90   R2(c, d, e, a, b, 33);
     91   R2(b, c, d, e, a, 34);
     92   R2(a, b, c, d, e, 35);
     93   R2(e, a, b, c, d, 36);
     94   R2(d, e, a, b, c, 37);
     95   R2(c, d, e, a, b, 38);
     96   R2(b, c, d, e, a, 39);
     97   R3(a, b, c, d, e, 40);
     98   R3(e, a, b, c, d, 41);
     99   R3(d, e, a, b, c, 42);
    100   R3(c, d, e, a, b, 43);
    101   R3(b, c, d, e, a, 44);
    102   R3(a, b, c, d, e, 45);
    103   R3(e, a, b, c, d, 46);
    104   R3(d, e, a, b, c, 47);
    105   R3(c, d, e, a, b, 48);
    106   R3(b, c, d, e, a, 49);
    107   R3(a, b, c, d, e, 50);
    108   R3(e, a, b, c, d, 51);
    109   R3(d, e, a, b, c, 52);
    110   R3(c, d, e, a, b, 53);
    111   R3(b, c, d, e, a, 54);
    112   R3(a, b, c, d, e, 55);
    113   R3(e, a, b, c, d, 56);
    114   R3(d, e, a, b, c, 57);
    115   R3(c, d, e, a, b, 58);
    116   R3(b, c, d, e, a, 59);
    117   R4(a, b, c, d, e, 60);
    118   R4(e, a, b, c, d, 61);
    119   R4(d, e, a, b, c, 62);
    120   R4(c, d, e, a, b, 63);
    121   R4(b, c, d, e, a, 64);
    122   R4(a, b, c, d, e, 65);
    123   R4(e, a, b, c, d, 66);
    124   R4(d, e, a, b, c, 67);
    125   R4(c, d, e, a, b, 68);
    126   R4(b, c, d, e, a, 69);
    127   R4(a, b, c, d, e, 70);
    128   R4(e, a, b, c, d, 71);
    129   R4(d, e, a, b, c, 72);
    130   R4(c, d, e, a, b, 73);
    131   R4(b, c, d, e, a, 74);
    132   R4(a, b, c, d, e, 75);
    133   R4(e, a, b, c, d, 76);
    134   R4(d, e, a, b, c, 77);
    135   R4(c, d, e, a, b, 78);
    136   R4(b, c, d, e, a, 79);
    137   /* Add the working vars back into context.state[] */
    138   state[0] += a;
    139   state[1] += b;
    140   state[2] += c;
    141   state[3] += d;
    142   state[4] += e;
    143 }
    144 
    145 SHA1Digest::SHA1Digest()
    146 {
    147   Reset();
    148 }
    149 
    150 /* SHA1Init - Initialize new context */
    151 
    152 void SHA1Digest::Reset()
    153 {
    154   /* SHA1 initialization constants */
    155   state[0] = 0x67452301;
    156   state[1] = 0xEFCDAB89;
    157   state[2] = 0x98BADCFE;
    158   state[3] = 0x10325476;
    159   state[4] = 0xC3D2E1F0;
    160   count[0] = count[1] = 0;
    161 }
    162 
    163 std::string SHA1Digest::DigestToString(const std::span<u8, DIGEST_SIZE> digest)
    164 {
    165   std::string ret;
    166   ret.reserve(DIGEST_SIZE * 2);
    167   for (u32 i = 0; i < DIGEST_SIZE; i++)
    168   {
    169     u8 nibble = digest[i] >> 4;
    170     if (nibble >= 0xA)
    171       ret.push_back('A' + (nibble - 0xA));
    172     else
    173       ret.push_back('0' + nibble);
    174     nibble = digest[i] & 0xF;
    175     if (nibble >= 0xA)
    176       ret.push_back('A' + (nibble - 0xA));
    177     else
    178       ret.push_back('0' + nibble);
    179   }
    180   return ret;
    181 }
    182 
    183 std::array<u8, SHA1Digest::DIGEST_SIZE> SHA1Digest::GetDigest(const void* data, size_t len)
    184 {
    185   std::array<u8, SHA1Digest::DIGEST_SIZE> ret;
    186   SHA1Digest digest;
    187   digest.Update(data, len);
    188   digest.Final(ret.data());
    189   return ret;
    190 }
    191 
    192 std::array<u8, SHA1Digest::DIGEST_SIZE> SHA1Digest::GetDigest(std::span<const u8> data)
    193 {
    194   std::array<u8, SHA1Digest::DIGEST_SIZE> ret;
    195   SHA1Digest digest;
    196   digest.Update(data);
    197   digest.Final(ret.data());
    198   return ret;
    199 }
    200 
    201 /* Run your data through this. */
    202 
    203 void SHA1Digest::Update(const void* data, size_t len)
    204 {
    205   const u8* bdata = static_cast<const u8*>(data);
    206   Assert(len <= std::numeric_limits<u32>::max());
    207   const u32 ulen = static_cast<u32>(len);
    208 
    209   u32 i;
    210   u32 j = count[0];
    211   if ((count[0] += ulen << 3) < j)
    212     count[1]++;
    213   count[1] += (ulen >> 29);
    214   j = (j >> 3) & 63;
    215   if ((j + ulen) > 63)
    216   {
    217     std::memcpy(&buffer[j], bdata, (i = 64 - j));
    218     SHA1Transform(state, buffer);
    219     for (; i + 63 < ulen; i += 64)
    220     {
    221       SHA1Transform(state, &bdata[i]);
    222     }
    223     j = 0;
    224   }
    225   else
    226   {
    227     i = 0;
    228   }
    229   memcpy(&buffer[j], &bdata[i], len - i);
    230 }
    231 
    232 void SHA1Digest::Update(std::span<const u8> data)
    233 {
    234   Update(data.data(), data.size());
    235 }
    236 
    237 /* Add padding and return the message digest. */
    238 
    239 void SHA1Digest::Final(u8 digest[DIGEST_SIZE])
    240 {
    241   u8 finalcount[8];
    242   u8 c;
    243 
    244   for (u32 i = 0; i < 8; i++)
    245   {
    246     finalcount[i] = (u8)((count[(i >= 4 ? 0 : 1)] >> ((3 - (i & 3)) * 8)) & 255); /* Endian independent */
    247   }
    248 
    249   c = 0200;
    250   Update(&c, 1);
    251   while ((count[0] & 504) != 448)
    252   {
    253     c = 0000;
    254     Update(&c, 1);
    255   }
    256   Update(finalcount, 8); /* Should cause a SHA1Transform() */
    257   for (u32 i = 0; i < 20; i++)
    258   {
    259     digest[i] = (u8)((state[i >> 2] >> ((3 - (i & 3)) * 8)) & 255);
    260   }
    261 }