Coverage Report

Created: 2026-10-19 07:10

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/boringssl/crypto/fipsmodule/digestsign/digestsign.cc.inc
Line
Count
Source
1
// Copyright 2006-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 <assert.h>
16
17
#include <openssl/err.h>
18
#include <openssl/evp.h>
19
20
#include "../../evp/internal.h"
21
#include "../delocate.h"
22
#include "../digest/internal.h"
23
#include "../service_indicator/internal.h"
24
25
26
using namespace bssl;
27
28
enum evp_sign_verify_t {
29
  evp_sign,
30
  evp_verify,
31
};
32
33
6
DEFINE_LOCAL_DATA(struct evp_md_pctx_ops, md_pctx_ops) {
34
6
  out->free = EVP_PKEY_CTX_free;
35
6
  out->dup = EVP_PKEY_CTX_dup;
36
6
}
37
38
238k
static int uses_prehash(EVP_PKEY_CTX *pctx, enum evp_sign_verify_t op) {
39
238k
  return (op == evp_sign) ? (FromOpaque(pctx)->pmeth->sign != nullptr)
40
238k
                          : (FromOpaque(pctx)->pmeth->verify != nullptr);
41
238k
}
42
43
static int do_sigver_init(EVP_MD_CTX *ctx, EVP_PKEY_CTX **out_pctx,
44
                          const EVP_MD *type, ENGINE *e, const EVP_PKEY *pkey,
45
59.6k
                          enum evp_sign_verify_t op) {
46
59.6k
  UniquePtr<EVP_PKEY_CTX> pctx(EVP_PKEY_CTX_new(pkey, e));
47
59.6k
  if (pctx == nullptr) {
48
0
    return 0;
49
0
  }
50
51
59.6k
  if (op == evp_verify) {
52
42.0k
    if (!EVP_PKEY_verify_init(pctx.get())) {
53
0
      return 0;
54
0
    }
55
42.0k
  } else {
56
17.5k
    if (!EVP_PKEY_sign_init(pctx.get())) {
57
0
      return 0;
58
0
    }
59
17.5k
  }
60
61
59.6k
  if (type != nullptr && !EVP_PKEY_CTX_set_signature_md(pctx.get(), type)) {
62
0
    return 0;
63
0
  }
64
65
59.6k
  if (uses_prehash(pctx.get(), op)) {
66
59.6k
    if (type == nullptr) {
67
0
      OPENSSL_PUT_ERROR(EVP, EVP_R_NO_DEFAULT_DIGEST);
68
0
      return 0;
69
0
    }
70
59.6k
    if (!EVP_DigestInit_ex(ctx, type, e)) {
71
0
      return 0;
72
0
    }
73
59.6k
  } else {
74
0
    EVP_MD_CTX_reset(ctx);
75
0
  }
76
77
59.6k
  assert(ctx->pctx == nullptr);
78
59.6k
  ctx->pctx_ops = md_pctx_ops();
79
59.6k
  ctx->pctx = pctx.release();
80
59.6k
  if (out_pctx) {
81
59.6k
    *out_pctx = ctx->pctx;
82
59.6k
  }
83
59.6k
  return 1;
84
59.6k
}
85
86
int EVP_DigestSignInit(EVP_MD_CTX *ctx, EVP_PKEY_CTX **pctx, const EVP_MD *type,
87
17.5k
                       ENGINE *e, const EVP_PKEY *pkey) {
88
17.5k
  return do_sigver_init(ctx, pctx, type, e, pkey, evp_sign);
89
17.5k
}
90
91
int EVP_DigestVerifyInit(EVP_MD_CTX *ctx, EVP_PKEY_CTX **pctx,
92
42.0k
                         const EVP_MD *type, ENGINE *e, const EVP_PKEY *pkey) {
93
42.0k
  return do_sigver_init(ctx, pctx, type, e, pkey, evp_verify);
94
42.0k
}
95
96
17.5k
int EVP_DigestSignUpdate(EVP_MD_CTX *ctx, const void *data, size_t len) {
97
17.5k
  if (!uses_prehash(ctx->pctx, evp_sign)) {
98
0
    OPENSSL_PUT_ERROR(EVP, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
99
0
    return 0;
100
0
  }
101
102
17.5k
  return EVP_DigestUpdate(ctx, data, len);
103
17.5k
}
104
105
42.0k
int EVP_DigestVerifyUpdate(EVP_MD_CTX *ctx, const void *data, size_t len) {
106
42.0k
  if (!uses_prehash(ctx->pctx, evp_verify)) {
107
0
    OPENSSL_PUT_ERROR(EVP, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
108
0
    return 0;
109
0
  }
110
111
42.0k
  return EVP_DigestUpdate(ctx, data, len);
112
42.0k
}
113
114
int EVP_DigestSignFinal(EVP_MD_CTX *ctx, uint8_t *out_sig,
115
17.5k
                        size_t *out_sig_len) {
116
17.5k
  if (!uses_prehash(ctx->pctx, evp_sign)) {
117
0
    OPENSSL_PUT_ERROR(EVP, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
118
0
    return 0;
119
0
  }
120
121
17.5k
  if (out_sig) {
122
17.5k
    EVP_MD_CTX tmp_ctx;
123
17.5k
    int ret;
124
17.5k
    uint8_t md[EVP_MAX_MD_SIZE];
125
17.5k
    unsigned int mdlen;
126
127
17.5k
    FIPS_service_indicator_lock_state();
128
17.5k
    EVP_MD_CTX_init(&tmp_ctx);
129
17.5k
    ret = EVP_MD_CTX_copy_ex(&tmp_ctx, ctx) &&
130
17.5k
          EVP_DigestFinal_ex(&tmp_ctx, md, &mdlen) &&
131
17.5k
          EVP_PKEY_sign(ctx->pctx, out_sig, out_sig_len, md, mdlen);
132
17.5k
    EVP_MD_CTX_cleanup(&tmp_ctx);
133
17.5k
    FIPS_service_indicator_unlock_state();
134
135
17.5k
    if (ret) {
136
17.5k
      EVP_DigestSign_verify_service_indicator(ctx);
137
17.5k
    }
138
139
17.5k
    return ret;
140
17.5k
  } else {
141
0
    size_t s = EVP_MD_size(ctx->digest);
142
0
    return EVP_PKEY_sign(ctx->pctx, out_sig, out_sig_len, nullptr, s);
143
0
  }
144
17.5k
}
145
146
42.0k
int EVP_DigestVerifyFinal(EVP_MD_CTX *ctx, const uint8_t *sig, size_t sig_len) {
147
42.0k
  if (!uses_prehash(ctx->pctx, evp_verify)) {
148
0
    OPENSSL_PUT_ERROR(EVP, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
149
0
    return 0;
150
0
  }
151
152
42.0k
  EVP_MD_CTX tmp_ctx;
153
42.0k
  int ret;
154
42.0k
  uint8_t md[EVP_MAX_MD_SIZE];
155
42.0k
  unsigned int mdlen;
156
157
42.0k
  FIPS_service_indicator_lock_state();
158
42.0k
  EVP_MD_CTX_init(&tmp_ctx);
159
42.0k
  ret = EVP_MD_CTX_copy_ex(&tmp_ctx, ctx) &&
160
42.0k
        EVP_DigestFinal_ex(&tmp_ctx, md, &mdlen) &&
161
42.0k
        EVP_PKEY_verify(ctx->pctx, sig, sig_len, md, mdlen);
162
42.0k
  FIPS_service_indicator_unlock_state();
163
42.0k
  EVP_MD_CTX_cleanup(&tmp_ctx);
164
165
42.0k
  if (ret) {
166
0
    EVP_DigestVerify_verify_service_indicator(ctx);
167
0
  }
168
169
42.0k
  return ret;
170
42.0k
}
171
172
int EVP_DigestSign(EVP_MD_CTX *ctx, uint8_t *out_sig, size_t *out_sig_len,
173
17.5k
                   const uint8_t *data, size_t data_len) {
174
17.5k
  FIPS_service_indicator_lock_state();
175
17.5k
  int ret = 0;
176
177
17.5k
  if (uses_prehash(ctx->pctx, evp_sign)) {
178
    // If `out_sig` is NULL, the caller is only querying the maximum output
179
    // length. `data` should only be incorporated in the final call.
180
17.5k
    if (out_sig != nullptr && !EVP_DigestSignUpdate(ctx, data, data_len)) {
181
0
      goto end;
182
0
    }
183
184
17.5k
    ret = EVP_DigestSignFinal(ctx, out_sig, out_sig_len);
185
17.5k
    goto end;
186
17.5k
  }
187
188
0
  if (FromOpaque(ctx->pctx)->pmeth->sign_message == nullptr) {
189
0
    OPENSSL_PUT_ERROR(EVP, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
190
0
    goto end;
191
0
  }
192
193
0
  ret = FromOpaque(ctx->pctx)->pmeth->sign_message(
194
0
      FromOpaque(ctx->pctx), out_sig, out_sig_len, data, data_len);
195
196
17.5k
end:
197
17.5k
  FIPS_service_indicator_unlock_state();
198
17.5k
  if (ret) {
199
17.5k
    EVP_DigestSign_verify_service_indicator(ctx);
200
17.5k
  }
201
17.5k
  return ret;
202
0
}
203
204
int EVP_DigestVerify(EVP_MD_CTX *ctx, const uint8_t *sig, size_t sig_len,
205
42.0k
                     const uint8_t *data, size_t len) {
206
42.0k
  FIPS_service_indicator_lock_state();
207
42.0k
  int ret = 0;
208
209
42.0k
  if (uses_prehash(ctx->pctx, evp_verify)) {
210
42.0k
    ret = EVP_DigestVerifyUpdate(ctx, data, len) &&
211
42.0k
          EVP_DigestVerifyFinal(ctx, sig, sig_len);
212
42.0k
    goto end;
213
42.0k
  }
214
215
0
  if (FromOpaque(ctx->pctx)->pmeth->verify_message == nullptr) {
216
0
    OPENSSL_PUT_ERROR(EVP, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
217
0
    goto end;
218
0
  }
219
220
0
  ret = FromOpaque(ctx->pctx)->pmeth->verify_message(FromOpaque(ctx->pctx), sig,
221
0
                                                     sig_len, data, len);
222
223
42.0k
end:
224
42.0k
  FIPS_service_indicator_unlock_state();
225
42.0k
  if (ret) {
226
0
    EVP_DigestVerify_verify_service_indicator(ctx);
227
0
  }
228
42.0k
  return ret;
229
0
}