| // Copyright 2017 The Fuchsia Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #ifndef SRC_LIB_DIGEST_DIGEST_H_ |
| #define SRC_LIB_DIGEST_DIGEST_H_ |
| |
| #include <stddef.h> |
| #include <stdint.h> |
| #include <zircon/compiler.h> |
| #include <zircon/types.h> |
| |
| #include <memory> |
| #include <ostream> |
| |
| #include <fbl/string.h> |
| |
| namespace digest { |
| |
| // The length (in bytes) of a SHA256 hash. |
| constexpr size_t kSha256Length = 32; |
| |
| // The length (in characters) of a stringified SHA256 hash. Does not include room for a |
| // null-terminator character. |
| constexpr size_t kSha256HexLength = (kSha256Length * 2); |
| |
| // This class represents a digest produced by a hash algorithm. |
| // This class is not thread safe. |
| class Digest final { |
| public: |
| Digest(); |
| explicit Digest(const uint8_t (&bytes)[kSha256Length]); |
| Digest(Digest&& other); |
| Digest& operator=(const uint8_t (&bytes)[kSha256Length]); |
| Digest& operator=(Digest&& other); |
| |
| // Copying a digest copies the digest bytes but can not be used for incrementally adding to |
| // the digest. The copy constructor/assignment code will assert if the source object is not |
| // finalized. |
| Digest(const Digest& other); |
| Digest& operator=(const Digest& other); |
| |
| ~Digest(); |
| |
| const uint8_t* get() const { return bytes_; } |
| constexpr size_t len() const { return sizeof(bytes_); } |
| |
| // Initializes the hash algorithm context. It must be called before Update, |
| // and after Final when reusing the Digest object. |
| void Init(); |
| |
| // Adds data to be hashed. This may be called multiple times between calls |
| // to |Init| and |Final|. If A and B are byte sequences of length A_len and |
| // B_len, respectively, and AB is the concatenation of A and B, then |
| // "Update(A, A_len); Update(B, B_len);" and "Update(AB, A_len + B_len)" |
| // yield the same internal state and will produce the same digest when |
| // |Final| is called. |
| void Update(const void* data, size_t len); |
| |
| // Completes the hash algorithm and returns the digest. This must only be |
| // called after a call to |Init|; intervening calls to |Update| are |
| // optional. |
| const uint8_t* Final(); |
| |
| // This convenience method performs the hash algorithm in "one shot": It |
| // calls |Init| and |Update(data, len)| before returning the result of |
| // calling |Final|. |
| const uint8_t* Hash(const void* data, size_t len); |
| |
| // Converts a null-terminated |hex| string to binary and stores it in this |
| // object. |hex| must represent |kLength| bytes, that is, it must have |
| // |kLength| * 2 characters. |
| zx_status_t Parse(const char* hex, size_t len); |
| zx_status_t Parse(const char* hex) { return Parse(hex, strlen(hex)); } |
| zx_status_t Parse(const fbl::String& hex) { return Parse(hex.c_str(), hex.length()); } |
| |
| // Returns the current digest as a hex string. |
| fbl::String ToString() const; |
| |
| // Writes digest to |out|. |
| void CopyTo(uint8_t (&out)[kSha256Length]) const { CopyTo(out, kSha256Length); } |
| |
| // Write digest to |out|. |len| must be at least |kSha256Length|; if it is |
| // greater, the remainder of |out| is filled with zeros. |
| void CopyTo(uint8_t* out, size_t len) const; |
| |
| // Like |CopyTo(out, len)|, but only writes the first |len| bytes of the digest to |out| if |len| |
| // is less than |kSha256Length|. |
| void CopyTruncatedTo(uint8_t* out, size_t len) const; |
| |
| // Equality operators. Those that take |const uint8_t *| arguments will |
| // read |kLength| bytes; callers MUST ensure there are sufficient bytes |
| // present. |
| bool Equals(const uint8_t* rhs, size_t rhs_len) const; |
| bool operator==(const Digest& rhs) const { return Equals(rhs.bytes_, kSha256Length); } |
| bool operator!=(const Digest& rhs) const { return !Equals(rhs.bytes_, kSha256Length); } |
| bool operator==(const uint8_t (&rhs)[kSha256Length]) const { return Equals(rhs, kSha256Length); } |
| bool operator!=(const uint8_t (&rhs)[kSha256Length]) const { return !Equals(rhs, kSha256Length); } |
| |
| // Allow a digest to be used in a map. |
| bool operator<(const Digest& rhs) const { return memcmp(bytes_, rhs.bytes_, kSha256Length) < 0; } |
| |
| private: |
| // Opaque crypto implementation context. |
| struct Context; |
| |
| friend std::ostream& operator<<(std::ostream&, const Digest&); |
| |
| // Opaque pointer to the crypto implementation context. |
| std::unique_ptr<Context> ctx_; |
| // The raw bytes of the current digest. This is filled in either by the |
| // assignment operators or the Parse and Final methods. |
| uint8_t bytes_[kSha256Length]; |
| }; |
| |
| std::ostream& operator<<(std::ostream&, const Digest&); |
| |
| } // namespace digest |
| |
| #endif // SRC_LIB_DIGEST_DIGEST_H_ |