Coverage Report

Created: 2025-12-07 06:13

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/boringssl/crypto/fipsmodule/hmac/hmac.cc.inc
Line
Count
Source
1
// Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
2
//
3
// Licensed under the Apache License, Version 2.0 (the "License");
4
// you may not use this file except in compliance with the License.
5
// You may obtain a copy of the License at
6
//
7
//     https://www.apache.org/licenses/LICENSE-2.0
8
//
9
// Unless required by applicable law or agreed to in writing, software
10
// distributed under the License is distributed on an "AS IS" BASIS,
11
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
// See the License for the specific language governing permissions and
13
// limitations under the License.
14
15
#include <openssl/hmac.h>
16
17
#include <assert.h>
18
#include <string.h>
19
20
#include <openssl/digest.h>
21
#include <openssl/mem.h>
22
23
#include "../../internal.h"
24
#include "../service_indicator/internal.h"
25
26
27
uint8_t *HMAC(const EVP_MD *evp_md, const void *key, size_t key_len,
28
              const uint8_t *data, size_t data_len, uint8_t *out,
29
27.4k
              unsigned int *out_len) {
30
27.4k
  HMAC_CTX ctx;
31
27.4k
  HMAC_CTX_init(&ctx);
32
33
  // The underlying hash functions should not set the FIPS service indicator
34
  // until all operations have completed.
35
27.4k
  FIPS_service_indicator_lock_state();
36
27.4k
  const int ok = HMAC_Init_ex(&ctx, key, key_len, evp_md, nullptr) &&
37
27.4k
                 HMAC_Update(&ctx, data, data_len) &&
38
27.4k
                 HMAC_Final(&ctx, out, out_len);
39
27.4k
  FIPS_service_indicator_unlock_state();
40
41
27.4k
  HMAC_CTX_cleanup(&ctx);
42
43
27.4k
  if (!ok) {
44
0
    return nullptr;
45
0
  }
46
47
27.4k
  HMAC_verify_service_indicator(evp_md);
48
27.4k
  return out;
49
27.4k
}
50
51
981k
void HMAC_CTX_init(HMAC_CTX *ctx) {
52
981k
  ctx->md = nullptr;
53
981k
  EVP_MD_CTX_init(&ctx->i_ctx);
54
981k
  EVP_MD_CTX_init(&ctx->o_ctx);
55
981k
  EVP_MD_CTX_init(&ctx->md_ctx);
56
981k
}
57
58
60.6k
HMAC_CTX *HMAC_CTX_new(void) {
59
60.6k
  HMAC_CTX *ctx =
60
60.6k
      reinterpret_cast<HMAC_CTX *>(OPENSSL_malloc(sizeof(HMAC_CTX)));
61
60.6k
  if (ctx != nullptr) {
62
60.6k
    HMAC_CTX_init(ctx);
63
60.6k
  }
64
60.6k
  return ctx;
65
60.6k
}
66
67
981k
void HMAC_CTX_cleanup(HMAC_CTX *ctx) {
68
981k
  EVP_MD_CTX_cleanup(&ctx->i_ctx);
69
981k
  EVP_MD_CTX_cleanup(&ctx->o_ctx);
70
981k
  EVP_MD_CTX_cleanup(&ctx->md_ctx);
71
981k
  OPENSSL_cleanse(ctx, sizeof(HMAC_CTX));
72
981k
}
73
74
0
void HMAC_CTX_cleanse(HMAC_CTX *ctx) {
75
0
  EVP_MD_CTX_cleanse(&ctx->i_ctx);
76
0
  EVP_MD_CTX_cleanse(&ctx->o_ctx);
77
0
  EVP_MD_CTX_cleanse(&ctx->md_ctx);
78
0
  OPENSSL_cleanse(ctx, sizeof(HMAC_CTX));
79
0
}
80
81
60.6k
void HMAC_CTX_free(HMAC_CTX *ctx) {
82
60.6k
  if (ctx == nullptr) {
83
0
    return;
84
0
  }
85
86
60.6k
  HMAC_CTX_cleanup(ctx);
87
60.6k
  OPENSSL_free(ctx);
88
60.6k
}
89
90
int HMAC_Init_ex(HMAC_CTX *ctx, const void *key, size_t key_len,
91
560k
                 const EVP_MD *md, ENGINE *impl) {
92
560k
  int ret = 0;
93
560k
  FIPS_service_indicator_lock_state();
94
95
560k
  if (md == nullptr) {
96
5.14k
    md = ctx->md;
97
5.14k
  }
98
99
  // If either |key| is non-NULL or |md| has changed, initialize with a new key
100
  // rather than rewinding the previous one.
101
  //
102
  // TODO(davidben,eroman): Passing the previous |md| with a NULL |key| is
103
  // ambiguous between using the empty key and reusing the previous key. There
104
  // exist callers which intend the latter, but the former is an awkward edge
105
  // case. Fix to API to avoid this.
106
560k
  if (md != ctx->md || key != nullptr) {
107
555k
    uint8_t pad[EVP_MAX_MD_BLOCK_SIZE];
108
555k
    uint8_t key_block[EVP_MAX_MD_BLOCK_SIZE];
109
555k
    unsigned key_block_len;
110
111
555k
    size_t block_size = EVP_MD_block_size(md);
112
555k
    assert(block_size <= sizeof(key_block));
113
555k
    assert(EVP_MD_size(md) <= block_size);
114
555k
    if (block_size < key_len) {
115
      // Long keys are hashed.
116
7
      if (!EVP_DigestInit_ex(&ctx->md_ctx, md, impl) ||
117
7
          !EVP_DigestUpdate(&ctx->md_ctx, key, key_len) ||
118
7
          !EVP_DigestFinal_ex(&ctx->md_ctx, key_block, &key_block_len)) {
119
0
        goto out;
120
0
      }
121
555k
    } else {
122
555k
      assert(key_len <= sizeof(key_block));
123
555k
      OPENSSL_memcpy(key_block, key, key_len);
124
555k
      key_block_len = (unsigned)key_len;
125
555k
    }
126
    // Keys are then padded with zeros.
127
555k
    OPENSSL_memset(key_block + key_block_len, 0, block_size - key_block_len);
128
129
41.8M
    for (size_t i = 0; i < block_size; i++) {
130
41.2M
      pad[i] = 0x36 ^ key_block[i];
131
41.2M
    }
132
555k
    if (!EVP_DigestInit_ex(&ctx->i_ctx, md, impl) ||
133
555k
        !EVP_DigestUpdate(&ctx->i_ctx, pad, block_size)) {
134
0
      goto out;
135
0
    }
136
137
41.8M
    for (size_t i = 0; i < block_size; i++) {
138
41.2M
      pad[i] = 0x5c ^ key_block[i];
139
41.2M
    }
140
555k
    if (!EVP_DigestInit_ex(&ctx->o_ctx, md, impl) ||
141
555k
        !EVP_DigestUpdate(&ctx->o_ctx, pad, block_size)) {
142
0
      goto out;
143
0
    }
144
145
555k
    ctx->md = md;
146
555k
  }
147
148
560k
  ret = EVP_MD_CTX_copy_ex(&ctx->md_ctx, &ctx->i_ctx);
149
150
560k
out:
151
560k
  FIPS_service_indicator_unlock_state();
152
560k
  return ret;
153
560k
}
154
155
2.68M
int HMAC_Update(HMAC_CTX *ctx, const uint8_t *data, size_t data_len) {
156
2.68M
  return EVP_DigestUpdate(&ctx->md_ctx, data, data_len);
157
2.68M
}
158
159
1.04M
int HMAC_Final(HMAC_CTX *ctx, uint8_t *out, unsigned int *out_len) {
160
1.04M
  int ret = 0;
161
1.04M
  unsigned int i;
162
1.04M
  uint8_t buf[EVP_MAX_MD_SIZE];
163
164
1.04M
  FIPS_service_indicator_lock_state();
165
  // TODO(davidben): The only thing that can officially fail here is
166
  // |EVP_MD_CTX_copy_ex|, but even that should be impossible in this case.
167
1.04M
  if (!EVP_DigestFinal_ex(&ctx->md_ctx, buf, &i) ||
168
1.04M
      !EVP_MD_CTX_copy_ex(&ctx->md_ctx, &ctx->o_ctx) ||
169
1.04M
      !EVP_DigestUpdate(&ctx->md_ctx, buf, i) ||
170
1.04M
      !EVP_DigestFinal_ex(&ctx->md_ctx, out, out_len)) {
171
0
    goto out;
172
0
  }
173
174
1.04M
  ret = 1;
175
176
1.04M
out:
177
1.04M
  FIPS_service_indicator_unlock_state();
178
1.04M
  if (ret) {
179
1.04M
    HMAC_verify_service_indicator(ctx->md);
180
1.04M
  } else if (out_len) {
181
0
    *out_len = 0;
182
0
  }
183
1.04M
  return ret;
184
1.04M
}
185
186
23.5k
size_t HMAC_size(const HMAC_CTX *ctx) { return EVP_MD_size(ctx->md); }
187
188
0
const EVP_MD *HMAC_CTX_get_md(const HMAC_CTX *ctx) { return ctx->md; }
189
190
800k
int HMAC_CTX_copy_ex(HMAC_CTX *dest, const HMAC_CTX *src) {
191
800k
  if (!EVP_MD_CTX_copy_ex(&dest->i_ctx, &src->i_ctx) ||
192
800k
      !EVP_MD_CTX_copy_ex(&dest->o_ctx, &src->o_ctx) ||
193
800k
      !EVP_MD_CTX_copy_ex(&dest->md_ctx, &src->md_ctx)) {
194
0
    return 0;
195
0
  }
196
197
800k
  dest->md = src->md;
198
800k
  return 1;
199
800k
}
200
201
0
void HMAC_CTX_reset(HMAC_CTX *ctx) {
202
0
  HMAC_CTX_cleanup(ctx);
203
0
  HMAC_CTX_init(ctx);
204
0
}
205
206
0
int HMAC_Init(HMAC_CTX *ctx, const void *key, int key_len, const EVP_MD *md) {
207
0
  if (key && md) {
208
0
    HMAC_CTX_init(ctx);
209
0
  }
210
0
  return HMAC_Init_ex(ctx, key, key_len, md, nullptr);
211
0
}
212
213
0
int HMAC_CTX_copy(HMAC_CTX *dest, const HMAC_CTX *src) {
214
0
  HMAC_CTX_init(dest);
215
0
  return HMAC_CTX_copy_ex(dest, src);
216
0
}