1 //====- SHA256.cpp - SHA256 implementation ---*- C++ -* ======//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 /*
9  *  The SHA-256 Secure Hash Standard was published by NIST in 2002.
10  *
11  *  http://csrc.nist.gov/publications/fips/fips180-2/fips180-2.pdf
12  *
13  *   The implementation is based on nacl's sha256 implementation [0] and LLVM's
14  *  pre-exsiting SHA1 code [1].
15  *
16  *   [0] https://hyperelliptic.org/nacl/nacl-20110221.tar.bz2 (public domain
17  *       code)
18  *   [1] llvm/lib/Support/SHA1.{h,cpp}
19  */
20 //===----------------------------------------------------------------------===//
21 
22 #ifndef LLVM_SUPPORT_SHA256_H
23 #define LLVM_SUPPORT_SHA256_H
24 
25 #include <array>
26 #include <cstdint>
27 
28 namespace llvm {
29 
30 template <typename T> class ArrayRef;
31 class StringRef;
32 
33 class SHA256 {
34 public:
35   explicit SHA256() { init(); }
36 
37   /// Reinitialize the internal state
38   void init();
39 
40   /// Digest more data.
41   void update(ArrayRef<uint8_t> Data);
42 
43   /// Digest more data.
44   void update(StringRef Str);
45 
46   /// Return the current raw 256-bits SHA256 for the digested
47   /// data since the last call to init(). This call will add data to the
48   /// internal state and as such is not suited for getting an intermediate
49   /// result (see result()).
50   std::array<uint8_t, 32> final();
51 
52   /// Return the current raw 256-bits SHA256 for the digested
53   /// data since the last call to init(). This is suitable for getting the
54   /// SHA256 at any time without invalidating the internal state so that more
55   /// calls can be made into update.
56   std::array<uint8_t, 32> result();
57 
58   /// Returns a raw 256-bit SHA256 hash for the given data.
59   static std::array<uint8_t, 32> hash(ArrayRef<uint8_t> Data);
60 
61 private:
62   /// Define some constants.
63   /// "static constexpr" would be cleaner but MSVC does not support it yet.
64   enum { BLOCK_LENGTH = 64 };
65   enum { HASH_LENGTH = 32 };
66 
67   // Internal State
68   struct {
69     union {
70       uint8_t C[BLOCK_LENGTH];
71       uint32_t L[BLOCK_LENGTH / 4];
72     } Buffer;
73     uint32_t State[HASH_LENGTH / 4];
74     uint32_t ByteCount;
75     uint8_t BufferOffset;
76   } InternalState;
77 
78   // Helper
79   void writebyte(uint8_t data);
80   void hashBlock();
81   void addUncounted(uint8_t data);
82   void pad();
83 
84   void final(std::array<uint32_t, HASH_LENGTH / 4> &HashResult);
85 };
86 
87 } // namespace llvm
88 
89 #endif // LLVM_SUPPORT_SHA256_H
90