File: hmac.h

package info (click to toggle)
chromium 139.0.7258.127-1
  • links: PTS, VCS
  • area: main
  • in suites:
  • size: 6,122,068 kB
  • sloc: cpp: 35,100,771; ansic: 7,163,530; javascript: 4,103,002; python: 1,436,920; asm: 946,517; xml: 746,709; pascal: 187,653; perl: 88,691; sh: 88,436; objc: 79,953; sql: 51,488; cs: 44,583; fortran: 24,137; makefile: 22,147; tcl: 15,277; php: 13,980; yacc: 8,984; ruby: 7,485; awk: 3,720; lisp: 3,096; lex: 1,327; ada: 727; jsp: 228; sed: 36
file content (156 lines) | stat: -rw-r--r-- 6,164 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
// Copyright 2012 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

// Utility class for calculating the HMAC for a given message. We currently only
// support SHA-1 and SHA-256 for the hash algorithm, but this can be extended
// easily. Prefer the base::span and std::vector overloads over the
// std::string_view and std::string overloads.

#ifndef CRYPTO_HMAC_H_
#define CRYPTO_HMAC_H_

#include <stddef.h>

#include <array>
#include <memory>
#include <string_view>
#include <vector>

#include "base/containers/span.h"
#include "crypto/crypto_export.h"
#include "crypto/hash.h"

namespace crypto {

// TODO(https://issues.chromium.org/issues/374334448): Rework this interface and
// delete much of it.
class CRYPTO_EXPORT HMAC {
 public:
  // The set of supported hash functions. Extend as required.
  enum HashAlgorithm {
    SHA1,
    SHA256,
  };

  explicit HMAC(HashAlgorithm hash_alg);

  HMAC(const HMAC&) = delete;
  HMAC& operator=(const HMAC&) = delete;

  ~HMAC();

  // Returns the length of digest that this HMAC will create.
  size_t DigestLength() const;

  // TODO(abarth): Add a PreferredKeyLength() member function.

  // Initializes this instance using |key| of the length |key_length|. Call Init
  // only once. It returns false on the second or later calls.
  //
  // NOTE: the US Federal crypto standard FIPS 198, Section 3 says:
  //   The size of the key, K, shall be equal to or greater than L/2, where L
  //   is the size of the hash function output.
  // In FIPS 198-1 (and SP-800-107, which describes key size recommendations),
  // this requirement is gone.  But a system crypto library may still enforce
  // this old requirement.  If the key is shorter than this recommended value,
  // Init() may fail.
  [[nodiscard]] bool Init(const unsigned char* key, size_t key_length);

  // Initializes this instance using |key|. Call Init only once. It returns
  // false on the second or later calls.
  [[nodiscard]] bool Init(std::string_view key) {
    return Init(base::as_byte_span(key));
  }

  // Initializes this instance using |key|. Call Init only once. It returns
  // false on the second or later calls.
  [[nodiscard]] bool Init(base::span<const uint8_t> key) {
    return Init(key.data(), key.size());
  }

  // Calculates the HMAC for the message in |data| using the algorithm supplied
  // to the constructor and the key supplied to the Init method. The HMAC is
  // returned in |digest|, which has |digest_length| bytes of storage available.
  // If |digest_length| is smaller than DigestLength(), the output will be
  // truncated. If it is larger, this method will fail.
  [[nodiscard]] bool Sign(std::string_view data,
                          unsigned char* digest,
                          size_t digest_length) const;
  [[nodiscard]] bool Sign(base::span<const uint8_t> data,
                          base::span<uint8_t> digest) const;

  // Verifies that the HMAC for the message in |data| equals the HMAC provided
  // in |digest|, using the algorithm supplied to the constructor and the key
  // supplied to the Init method. Use of this method is strongly recommended
  // over using Sign() with a manual comparison (such as memcmp), as such
  // comparisons may result in side-channel disclosures, such as timing, that
  // undermine the cryptographic integrity. |digest| must be exactly
  // |DigestLength()| bytes long.
  [[nodiscard]] bool Verify(std::string_view data,
                            std::string_view digest) const;
  [[nodiscard]] bool Verify(base::span<const uint8_t> data,
                            base::span<const uint8_t> digest) const;

  // Verifies a truncated HMAC, behaving identical to Verify(), except
  // that |digest| is allowed to be smaller than |DigestLength()|.
  [[nodiscard]] bool VerifyTruncated(std::string_view data,
                                     std::string_view digest) const;
  [[nodiscard]] bool VerifyTruncated(base::span<const uint8_t> data,
                                     base::span<const uint8_t> digest) const;

 private:
  HashAlgorithm hash_alg_;
  bool initialized_;
  std::vector<unsigned char> key_;
};

namespace hmac {

// Single-shot interfaces for working with HMACs. Unless your code needs to be
// generic over hash kinds, you should use the convenience interfaces that are
// named after a specific kind, since they allow compile-time error checking of
// the hmac size.
CRYPTO_EXPORT std::array<uint8_t, crypto::hash::kSha1Size> SignSha1(
    base::span<const uint8_t> key,
    base::span<const uint8_t> data);

CRYPTO_EXPORT std::array<uint8_t, crypto::hash::kSha256Size> SignSha256(
    base::span<const uint8_t> key,
    base::span<const uint8_t> data);

CRYPTO_EXPORT std::array<uint8_t, crypto::hash::kSha512Size> SignSha512(
    base::span<const uint8_t> key,
    base::span<const uint8_t> data);

[[nodiscard]] CRYPTO_EXPORT bool VerifySha1(
    base::span<const uint8_t> key,
    base::span<const uint8_t> data,
    base::span<const uint8_t, crypto::hash::kSha1Size> hmac);

[[nodiscard]] CRYPTO_EXPORT bool VerifySha256(
    base::span<const uint8_t> key,
    base::span<const uint8_t> data,
    base::span<const uint8_t, crypto::hash::kSha256Size> hmac);

[[nodiscard]] CRYPTO_EXPORT bool VerifySha512(
    base::span<const uint8_t> key,
    base::span<const uint8_t> data,
    base::span<const uint8_t, crypto::hash::kSha512Size> hmac);

// If you need to be generic over hash types, you can instead use these, but you
// must pass the correct size buffer for |hmac|:
CRYPTO_EXPORT void Sign(crypto::hash::HashKind kind,
                        base::span<const uint8_t> key,
                        base::span<const uint8_t> data,
                        base::span<uint8_t> hmac);
[[nodiscard]] CRYPTO_EXPORT bool Verify(crypto::hash::HashKind kind,
                                        base::span<const uint8_t> key,
                                        base::span<const uint8_t> data,
                                        base::span<const uint8_t> hmac);

}  // namespace hmac

}  // namespace crypto

#endif  // CRYPTO_HMAC_H_