Coverage Report

Created: 2025-08-28 06:59

/src/boringssl/crypto/evp/evp.cc
Line
Count
Source (jump to first uncovered line)
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/evp.h>
16
17
#include <assert.h>
18
#include <string.h>
19
20
#include <openssl/err.h>
21
#include <openssl/mem.h>
22
#include <openssl/nid.h>
23
24
#include "../internal.h"
25
#include "internal.h"
26
27
28
// Node depends on |EVP_R_NOT_XOF_OR_INVALID_LENGTH|.
29
//
30
// TODO(davidben): Fix Node to not touch the error queue itself and remove this.
31
OPENSSL_DECLARE_ERROR_REASON(EVP, NOT_XOF_OR_INVALID_LENGTH)
32
33
// The HPKE module uses the EVP error namespace, but it lives in another
34
// directory.
35
OPENSSL_DECLARE_ERROR_REASON(EVP, EMPTY_PSK)
36
37
272k
EVP_PKEY *EVP_PKEY_new(void) {
38
272k
  EVP_PKEY *ret =
39
272k
      reinterpret_cast<EVP_PKEY *>(OPENSSL_zalloc(sizeof(EVP_PKEY)));
40
272k
  if (ret == NULL) {
41
0
    return NULL;
42
0
  }
43
44
272k
  ret->references = 1;
45
272k
  return ret;
46
272k
}
47
48
1.29M
void EVP_PKEY_free(EVP_PKEY *pkey) {
49
1.29M
  if (pkey == NULL) {
50
476k
    return;
51
476k
  }
52
53
819k
  if (!CRYPTO_refcount_dec_and_test_zero(&pkey->references)) {
54
547k
    return;
55
547k
  }
56
57
272k
  evp_pkey_set0(pkey, nullptr, nullptr);
58
272k
  OPENSSL_free(pkey);
59
272k
}
60
61
547k
int EVP_PKEY_up_ref(EVP_PKEY *pkey) {
62
547k
  CRYPTO_refcount_inc(&pkey->references);
63
547k
  return 1;
64
547k
}
65
66
11.0k
int EVP_PKEY_is_opaque(const EVP_PKEY *pkey) {
67
11.0k
  if (pkey->ameth && pkey->ameth->pkey_opaque) {
68
11.0k
    return pkey->ameth->pkey_opaque(pkey);
69
11.0k
  }
70
0
  return 0;
71
11.0k
}
72
73
11.0k
int EVP_PKEY_cmp(const EVP_PKEY *a, const EVP_PKEY *b) {
74
11.0k
  if (EVP_PKEY_id(a) != EVP_PKEY_id(b)) {
75
0
    return -1;
76
0
  }
77
78
11.0k
  if (a->ameth) {
79
11.0k
    int ret;
80
    // Compare parameters if the algorithm has them
81
11.0k
    if (a->ameth->param_cmp) {
82
0
      ret = a->ameth->param_cmp(a, b);
83
0
      if (ret <= 0) {
84
0
        return ret;
85
0
      }
86
0
    }
87
88
11.0k
    if (a->ameth->pub_cmp) {
89
11.0k
      return a->ameth->pub_cmp(a, b);
90
11.0k
    }
91
11.0k
  }
92
93
0
  return -2;
94
11.0k
}
95
96
0
int EVP_PKEY_copy_parameters(EVP_PKEY *to, const EVP_PKEY *from) {
97
0
  if (EVP_PKEY_id(to) == EVP_PKEY_NONE) {
98
    // TODO(crbug.com/42290409): This shouldn't leave |to| in a half-empty state
99
    // on error. The complexity here largely comes from parameterless DSA keys,
100
    // which we no longer support, so this function can probably be trimmed
101
    // down.
102
0
    evp_pkey_set0(to, from->ameth, nullptr);
103
0
  } else if (EVP_PKEY_id(to) != EVP_PKEY_id(from)) {
104
0
    OPENSSL_PUT_ERROR(EVP, EVP_R_DIFFERENT_KEY_TYPES);
105
0
    return 0;
106
0
  }
107
108
0
  if (EVP_PKEY_missing_parameters(from)) {
109
0
    OPENSSL_PUT_ERROR(EVP, EVP_R_MISSING_PARAMETERS);
110
0
    return 0;
111
0
  }
112
113
  // Once set, parameters may not change.
114
0
  if (!EVP_PKEY_missing_parameters(to)) {
115
0
    if (EVP_PKEY_cmp_parameters(to, from) == 1) {
116
0
      return 1;
117
0
    }
118
0
    OPENSSL_PUT_ERROR(EVP, EVP_R_DIFFERENT_PARAMETERS);
119
0
    return 0;
120
0
  }
121
122
0
  if (from->ameth && from->ameth->param_copy) {
123
0
    return from->ameth->param_copy(to, from);
124
0
  }
125
126
  // TODO(https://crbug.com/42290406): If the algorithm takes no parameters,
127
  // copying them should vacuously succeed. Better yet, simplify this whole
128
  // notion of parameter copying above.
129
0
  return 0;
130
0
}
131
132
0
int EVP_PKEY_missing_parameters(const EVP_PKEY *pkey) {
133
0
  if (pkey->ameth && pkey->ameth->param_missing) {
134
0
    return pkey->ameth->param_missing(pkey);
135
0
  }
136
0
  return 0;
137
0
}
138
139
217k
int EVP_PKEY_size(const EVP_PKEY *pkey) {
140
217k
  if (pkey && pkey->ameth && pkey->ameth->pkey_size) {
141
217k
    return pkey->ameth->pkey_size(pkey);
142
217k
  }
143
0
  return 0;
144
217k
}
145
146
0
int EVP_PKEY_bits(const EVP_PKEY *pkey) {
147
0
  if (pkey && pkey->ameth && pkey->ameth->pkey_bits) {
148
0
    return pkey->ameth->pkey_bits(pkey);
149
0
  }
150
0
  return 0;
151
0
}
152
153
705k
int EVP_PKEY_id(const EVP_PKEY *pkey) {
154
705k
  return pkey->ameth != nullptr ? pkey->ameth->pkey_id : EVP_PKEY_NONE;
155
705k
}
156
157
void evp_pkey_set0(EVP_PKEY *pkey, const EVP_PKEY_ASN1_METHOD *method,
158
452k
                   void *pkey_data) {
159
452k
  if (pkey->ameth && pkey->ameth->pkey_free) {
160
180k
    pkey->ameth->pkey_free(pkey);
161
180k
  }
162
452k
  pkey->ameth = method;
163
452k
  pkey->pkey = pkey_data;
164
452k
}
165
166
0
int EVP_PKEY_type(int nid) {
167
  // In OpenSSL, this was used to map between type aliases. BoringSSL supports
168
  // no type aliases, so this function is just the identity.
169
0
  return nid;
170
0
}
171
172
0
int EVP_PKEY_assign(EVP_PKEY *pkey, int type, void *key) {
173
  // This function can only be used to assign RSA, DSA, EC, and DH keys. Other
174
  // key types have internal representations which are not exposed through the
175
  // public API.
176
0
  switch (type) {
177
0
    case EVP_PKEY_RSA:
178
0
      return EVP_PKEY_assign_RSA(pkey, reinterpret_cast<RSA *>(key));
179
0
    case EVP_PKEY_DSA:
180
0
      return EVP_PKEY_assign_DSA(pkey, reinterpret_cast<DSA *>(key));
181
0
    case EVP_PKEY_EC:
182
0
      return EVP_PKEY_assign_EC_KEY(pkey, reinterpret_cast<EC_KEY *>(key));
183
0
    case EVP_PKEY_DH:
184
0
      return EVP_PKEY_assign_DH(pkey, reinterpret_cast<DH *>(key));
185
0
  }
186
187
0
  OPENSSL_PUT_ERROR(EVP, EVP_R_UNSUPPORTED_ALGORITHM);
188
0
  ERR_add_error_dataf("algorithm %d", type);
189
0
  return 0;
190
0
}
191
192
0
int EVP_PKEY_set_type(EVP_PKEY *pkey, int type) {
193
0
  if (pkey && pkey->pkey) {
194
    // Some callers rely on |pkey| getting cleared even if |type| is
195
    // unsupported, usually setting |type| to |EVP_PKEY_NONE|.
196
0
    evp_pkey_set0(pkey, nullptr, nullptr);
197
0
  }
198
199
  // This function broadly isn't useful. It initializes |EVP_PKEY| for a type,
200
  // but forgets to put anything in the |pkey|. The one pattern where it does
201
  // anything is |EVP_PKEY_X25519|, where it's needed to make
202
  // |EVP_PKEY_set1_tls_encodedpoint| work, so we support only that.
203
0
  const EVP_PKEY_ASN1_METHOD *ameth;
204
0
  if (type == EVP_PKEY_X25519) {
205
0
    ameth = &x25519_asn1_meth;
206
0
  } else {
207
0
    OPENSSL_PUT_ERROR(EVP, EVP_R_UNSUPPORTED_ALGORITHM);
208
0
    ERR_add_error_dataf("algorithm %d", type);
209
0
    return 0;
210
0
  }
211
212
0
  if (pkey) {
213
0
    evp_pkey_set0(pkey, ameth, nullptr);
214
0
  }
215
216
0
  return 1;
217
0
}
218
219
EVP_PKEY *EVP_PKEY_new_raw_private_key(int type, ENGINE *unused,
220
0
                                       const uint8_t *in, size_t len) {
221
  // To avoid pulling in all key types, look for specifically the key types that
222
  // support |set_priv_raw|.
223
0
  const EVP_PKEY_ASN1_METHOD *method;
224
0
  switch (type) {
225
0
    case EVP_PKEY_X25519:
226
0
      method = &x25519_asn1_meth;
227
0
      break;
228
0
    case EVP_PKEY_ED25519:
229
0
      method = &ed25519_asn1_meth;
230
0
      break;
231
0
    default:
232
0
      OPENSSL_PUT_ERROR(EVP, EVP_R_UNSUPPORTED_ALGORITHM);
233
0
      return nullptr;
234
0
  }
235
236
0
  bssl::UniquePtr<EVP_PKEY> ret(EVP_PKEY_new());
237
0
  if (ret == nullptr ||  //
238
0
      !method->set_priv_raw(ret.get(), in, len)) {
239
0
    return nullptr;
240
0
  }
241
242
0
  return ret.release();
243
0
}
244
245
EVP_PKEY *EVP_PKEY_new_raw_public_key(int type, ENGINE *unused,
246
0
                                      const uint8_t *in, size_t len) {
247
  // To avoid pulling in all key types, look for specifically the key types that
248
  // support |set_pub_raw|.
249
0
  const EVP_PKEY_ASN1_METHOD *method;
250
0
  switch (type) {
251
0
    case EVP_PKEY_X25519:
252
0
      method = &x25519_asn1_meth;
253
0
      break;
254
0
    case EVP_PKEY_ED25519:
255
0
      method = &ed25519_asn1_meth;
256
0
      break;
257
0
    default:
258
0
      OPENSSL_PUT_ERROR(EVP, EVP_R_UNSUPPORTED_ALGORITHM);
259
0
      return nullptr;
260
0
  }
261
262
0
  bssl::UniquePtr<EVP_PKEY> ret(EVP_PKEY_new());
263
0
  if (ret == nullptr ||  //
264
0
      !method->set_pub_raw(ret.get(), in, len)) {
265
0
    return nullptr;
266
0
  }
267
268
0
  return ret.release();
269
0
}
270
271
int EVP_PKEY_get_raw_private_key(const EVP_PKEY *pkey, uint8_t *out,
272
0
                                 size_t *out_len) {
273
0
  if (pkey->ameth->get_priv_raw == NULL) {
274
0
    OPENSSL_PUT_ERROR(EVP, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
275
0
    return 0;
276
0
  }
277
278
0
  return pkey->ameth->get_priv_raw(pkey, out, out_len);
279
0
}
280
281
int EVP_PKEY_get_raw_public_key(const EVP_PKEY *pkey, uint8_t *out,
282
0
                                size_t *out_len) {
283
0
  if (pkey->ameth->get_pub_raw == NULL) {
284
0
    OPENSSL_PUT_ERROR(EVP, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
285
0
    return 0;
286
0
  }
287
288
0
  return pkey->ameth->get_pub_raw(pkey, out, out_len);
289
0
}
290
291
0
int EVP_PKEY_cmp_parameters(const EVP_PKEY *a, const EVP_PKEY *b) {
292
0
  if (EVP_PKEY_id(a) != EVP_PKEY_id(b)) {
293
0
    return -1;
294
0
  }
295
0
  if (a->ameth && a->ameth->param_cmp) {
296
0
    return a->ameth->param_cmp(a, b);
297
0
  }
298
  // TODO(https://crbug.com/boringssl/536): If the algorithm doesn't use
299
  // parameters, they should compare as vacuously equal.
300
0
  return -2;
301
0
}
302
303
99.2k
int EVP_PKEY_CTX_set_signature_md(EVP_PKEY_CTX *ctx, const EVP_MD *md) {
304
99.2k
  return EVP_PKEY_CTX_ctrl(ctx, -1, EVP_PKEY_OP_TYPE_SIG, EVP_PKEY_CTRL_MD, 0,
305
99.2k
                           (void *)md);
306
99.2k
}
307
308
0
int EVP_PKEY_CTX_get_signature_md(EVP_PKEY_CTX *ctx, const EVP_MD **out_md) {
309
0
  return EVP_PKEY_CTX_ctrl(ctx, -1, EVP_PKEY_OP_TYPE_SIG, EVP_PKEY_CTRL_GET_MD,
310
0
                           0, (void *)out_md);
311
0
}
312
313
0
void *EVP_PKEY_get0(const EVP_PKEY *pkey) {
314
  // Node references, but never calls this function, so for now we return NULL.
315
  // If other projects require complete support, call |EVP_PKEY_get0_RSA|, etc.,
316
  // rather than reading |pkey->pkey| directly. This avoids problems if our
317
  // internal representation does not match the type the caller expects from
318
  // OpenSSL.
319
0
  return NULL;
320
0
}
321
322
0
void OpenSSL_add_all_algorithms(void) {}
323
324
0
void OPENSSL_add_all_algorithms_conf(void) {}
325
326
0
void OpenSSL_add_all_ciphers(void) {}
327
328
0
void OpenSSL_add_all_digests(void) {}
329
330
0
void EVP_cleanup(void) {}
331
332
int EVP_PKEY_set1_tls_encodedpoint(EVP_PKEY *pkey, const uint8_t *in,
333
0
                                   size_t len) {
334
0
  if (pkey->ameth->set1_tls_encodedpoint == NULL) {
335
0
    OPENSSL_PUT_ERROR(EVP, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
336
0
    return 0;
337
0
  }
338
339
0
  return pkey->ameth->set1_tls_encodedpoint(pkey, in, len);
340
0
}
341
342
0
size_t EVP_PKEY_get1_tls_encodedpoint(const EVP_PKEY *pkey, uint8_t **out_ptr) {
343
0
  if (pkey->ameth->get1_tls_encodedpoint == NULL) {
344
0
    OPENSSL_PUT_ERROR(EVP, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
345
0
    return 0;
346
0
  }
347
348
0
  return pkey->ameth->get1_tls_encodedpoint(pkey, out_ptr);
349
0
}
350
351
0
int EVP_PKEY_base_id(const EVP_PKEY *pkey) {
352
  // OpenSSL has two notions of key type because it supports multiple OIDs for
353
  // the same algorithm: NID_rsa vs NID_rsaEncryption and five distinct spelling
354
  // of DSA. We do not support these, so the base ID is simply the ID.
355
0
  return EVP_PKEY_id(pkey);
356
0
}