tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

sha1.cc (4956B)


      1 // Copyright (c) 2011 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include "anglebase/sha1.h"
      6 
      7 #include <stddef.h>
      8 #include <stdint.h>
      9 #include <string.h>
     10 
     11 #include "anglebase/sys_byteorder.h"
     12 
     13 namespace angle
     14 {
     15 
     16 namespace base
     17 {
     18 
     19 // Implementation of SHA-1. Only handles data in byte-sized blocks,
     20 // which simplifies the code a fair bit.
     21 
     22 // Identifier names follow notation in FIPS PUB 180-3, where you'll
     23 // also find a description of the algorithm:
     24 // http://csrc.nist.gov/publications/fips/fips180-3/fips180-3_final.pdf
     25 
     26 // Usage example:
     27 //
     28 // SecureHashAlgorithm sha;
     29 // while(there is data to hash)
     30 //   sha.Update(moredata, size of data);
     31 // sha.Final();
     32 // memcpy(somewhere, sha.Digest(), 20);
     33 //
     34 // to reuse the instance of sha, call sha.Init();
     35 
     36 // TODO(jhawkins): Replace this implementation with a per-platform
     37 // implementation using each platform's crypto library.  See
     38 // http://crbug.com/47218
     39 
     40 class SecureHashAlgorithm
     41 {
     42  public:
     43    SecureHashAlgorithm() { Init(); }
     44 
     45    static const int kDigestSizeBytes;
     46 
     47    void Init();
     48    void Update(const void *data, size_t nbytes);
     49    void Final();
     50 
     51    // 20 bytes of message digest.
     52    const unsigned char *Digest() const { return reinterpret_cast<const unsigned char *>(H); }
     53 
     54  private:
     55    void Pad();
     56    void Process();
     57 
     58    uint32_t A, B, C, D, E;
     59 
     60    uint32_t H[5];
     61 
     62    union {
     63        uint32_t W[80];
     64        uint8_t M[64];
     65    };
     66 
     67    uint32_t cursor;
     68    uint64_t l;
     69 };
     70 
     71 static inline uint32_t f(uint32_t t, uint32_t B, uint32_t C, uint32_t D)
     72 {
     73    if (t < 20)
     74    {
     75        return (B & C) | ((~B) & D);
     76    }
     77    else if (t < 40)
     78    {
     79        return B ^ C ^ D;
     80    }
     81    else if (t < 60)
     82    {
     83        return (B & C) | (B & D) | (C & D);
     84    }
     85    else
     86    {
     87        return B ^ C ^ D;
     88    }
     89 }
     90 
     91 static inline uint32_t S(uint32_t n, uint32_t X)
     92 {
     93    return (X << n) | (X >> (32 - n));
     94 }
     95 
     96 static inline uint32_t K(uint32_t t)
     97 {
     98    if (t < 20)
     99    {
    100        return 0x5a827999;
    101    }
    102    else if (t < 40)
    103    {
    104        return 0x6ed9eba1;
    105    }
    106    else if (t < 60)
    107    {
    108        return 0x8f1bbcdc;
    109    }
    110    else
    111    {
    112        return 0xca62c1d6;
    113    }
    114 }
    115 
    116 const int SecureHashAlgorithm::kDigestSizeBytes = 20;
    117 
    118 void SecureHashAlgorithm::Init()
    119 {
    120    A      = 0;
    121    B      = 0;
    122    C      = 0;
    123    D      = 0;
    124    E      = 0;
    125    cursor = 0;
    126    l      = 0;
    127    H[0]   = 0x67452301;
    128    H[1]   = 0xefcdab89;
    129    H[2]   = 0x98badcfe;
    130    H[3]   = 0x10325476;
    131    H[4]   = 0xc3d2e1f0;
    132 }
    133 
    134 void SecureHashAlgorithm::Final()
    135 {
    136    Pad();
    137    Process();
    138 
    139    for (int t = 0; t < 5; ++t)
    140        H[t]   = ByteSwap(H[t]);
    141 }
    142 
    143 void SecureHashAlgorithm::Update(const void *data, size_t nbytes)
    144 {
    145    const uint8_t *d = reinterpret_cast<const uint8_t *>(data);
    146    while (nbytes--)
    147    {
    148        M[cursor++] = *d++;
    149        if (cursor >= 64)
    150            Process();
    151        l += 8;
    152    }
    153 }
    154 
    155 void SecureHashAlgorithm::Pad()
    156 {
    157    M[cursor++] = 0x80;
    158 
    159    if (cursor > 64 - 8)
    160    {
    161        // pad out to next block
    162        while (cursor < 64)
    163            M[cursor++] = 0;
    164 
    165        Process();
    166    }
    167 
    168    while (cursor < 64 - 8)
    169        M[cursor++] = 0;
    170 
    171    M[cursor++] = (l >> 56) & 0xff;
    172    M[cursor++] = (l >> 48) & 0xff;
    173    M[cursor++] = (l >> 40) & 0xff;
    174    M[cursor++] = (l >> 32) & 0xff;
    175    M[cursor++] = (l >> 24) & 0xff;
    176    M[cursor++] = (l >> 16) & 0xff;
    177    M[cursor++] = (l >> 8) & 0xff;
    178    M[cursor++] = l & 0xff;
    179 }
    180 
    181 void SecureHashAlgorithm::Process()
    182 {
    183    uint32_t t;
    184 
    185    // Each a...e corresponds to a section in the FIPS 180-3 algorithm.
    186 
    187    // a.
    188    //
    189    // W and M are in a union, so no need to memcpy.
    190    // memcpy(W, M, sizeof(M));
    191    for (t   = 0; t < 16; ++t)
    192        W[t] = ByteSwap(W[t]);
    193 
    194    // b.
    195    for (t   = 16; t < 80; ++t)
    196        W[t] = S(1, W[t - 3] ^ W[t - 8] ^ W[t - 14] ^ W[t - 16]);
    197 
    198    // c.
    199    A = H[0];
    200    B = H[1];
    201    C = H[2];
    202    D = H[3];
    203    E = H[4];
    204 
    205    // d.
    206    for (t = 0; t < 80; ++t)
    207    {
    208        uint32_t TEMP = S(5, A) + f(t, B, C, D) + E + W[t] + K(t);
    209        E             = D;
    210        D             = C;
    211        C             = S(30, B);
    212        B             = A;
    213        A             = TEMP;
    214    }
    215 
    216    // e.
    217    H[0] += A;
    218    H[1] += B;
    219    H[2] += C;
    220    H[3] += D;
    221    H[4] += E;
    222 
    223    cursor = 0;
    224 }
    225 
    226 std::string SHA1HashString(const std::string &str)
    227 {
    228    char hash[SecureHashAlgorithm::kDigestSizeBytes];
    229    SHA1HashBytes(reinterpret_cast<const unsigned char *>(str.c_str()), str.length(),
    230                  reinterpret_cast<unsigned char *>(hash));
    231    return std::string(hash, SecureHashAlgorithm::kDigestSizeBytes);
    232 }
    233 
    234 void SHA1HashBytes(const unsigned char *data, size_t len, unsigned char *hash)
    235 {
    236    SecureHashAlgorithm sha;
    237    sha.Update(data, len);
    238    sha.Final();
    239 
    240    memcpy(hash, sha.Digest(), SecureHashAlgorithm::kDigestSizeBytes);
    241 }
    242 
    243 }  // namespace base
    244 
    245 }  // namespace angle