Coverage Report

Created: 2025-09-05 06:13

/src/boringssl/crypto/bytestring/internal.h
Line
Count
Source (jump to first uncovered line)
1
// Copyright 2014 The BoringSSL Authors
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
#ifndef OPENSSL_HEADER_CRYPTO_BYTESTRING_INTERNAL_H
16
#define OPENSSL_HEADER_CRYPTO_BYTESTRING_INTERNAL_H
17
18
#include <openssl/asn1.h>
19
#include <openssl/bytestring.h>
20
#include <openssl/err.h>
21
22
#include <type_traits>
23
24
25
extern "C" {
26
27
// CBS_asn1_ber_to_der reads a BER element from |in|. If it finds
28
// indefinite-length elements or constructed strings then it converts the BER
29
// data to DER, sets |out| to the converted contents and |*out_storage| to a
30
// buffer which the caller must release with |OPENSSL_free|. Otherwise, it sets
31
// |out| to the original BER element in |in| and |*out_storage| to NULL.
32
// Additionally, |*in| will be advanced over the BER element.
33
//
34
// This function should successfully process any valid BER input, however it
35
// will not convert all of BER's deviations from DER. BER is ambiguous between
36
// implicitly-tagged SEQUENCEs of strings and implicitly-tagged constructed
37
// strings. Implicitly-tagged strings must be parsed with
38
// |CBS_get_ber_implicitly_tagged_string| instead of |CBS_get_asn1|. The caller
39
// must also account for BER variations in the contents of a primitive.
40
//
41
// It returns one on success and zero otherwise.
42
OPENSSL_EXPORT int CBS_asn1_ber_to_der(CBS *in, CBS *out,
43
                                       uint8_t **out_storage);
44
45
// CBS_get_asn1_implicit_string parses a BER string of primitive type
46
// |inner_tag| implicitly-tagged with |outer_tag|. It sets |out| to the
47
// contents. If concatenation was needed, it sets |*out_storage| to a buffer
48
// which the caller must release with |OPENSSL_free|. Otherwise, it sets
49
// |*out_storage| to NULL.
50
//
51
// This function does not parse all of BER. It requires the string be
52
// definite-length. Constructed strings are allowed, but all children of the
53
// outermost element must be primitive. The caller should use
54
// |CBS_asn1_ber_to_der| before running this function.
55
//
56
// It returns one on success and zero otherwise.
57
OPENSSL_EXPORT int CBS_get_asn1_implicit_string(CBS *in, CBS *out,
58
                                                uint8_t **out_storage,
59
                                                CBS_ASN1_TAG outer_tag,
60
                                                CBS_ASN1_TAG inner_tag);
61
62
// CBB_finish_i2d calls |CBB_finish| on |cbb| which must have been initialized
63
// with |CBB_init|. If |outp| is not NULL then the result is written to |*outp|
64
// and |*outp| is advanced just past the output. It returns the number of bytes
65
// in the result, whether written or not, or a negative value on error. On
66
// error, it calls |CBB_cleanup| on |cbb|.
67
//
68
// This function may be used to help implement legacy i2d ASN.1 functions.
69
int CBB_finish_i2d(CBB *cbb, uint8_t **outp);
70
71
}  // extern C
72
73
BSSL_NAMESPACE_BEGIN
74
75
// D2IFromCBS takes a functor of type |Unique<T>(CBS*)| and implements the d2i
76
// calling convention. For compatibility with functions that don't tag their
77
// return value (e.g. public APIs), |T*(CBS)| is also accepted. The callback can
78
// assume that the |CBS|'s length fits in |long|. The callback should not access
79
// |out|, |inp|, or |len| directly.
80
template <typename T, typename CBSFunc>
81
9.83k
inline T *D2IFromCBS(T **out, const uint8_t **inp, long len, CBSFunc func) {
82
9.83k
  static_assert(std::is_invocable_v<CBSFunc, CBS *>);
83
9.83k
  static_assert(
84
9.83k
      std::is_same_v<std::invoke_result_t<CBSFunc, CBS *>, UniquePtr<T>> ||
85
9.83k
      std::is_same_v<std::invoke_result_t<CBSFunc, CBS *>, T *>);
86
9.83k
  if (len < 0) {
87
0
    OPENSSL_PUT_ERROR(ASN1, ASN1_R_BUFFER_TOO_SMALL);
88
0
    return nullptr;
89
0
  }
90
9.83k
  CBS cbs;
91
9.83k
  CBS_init(&cbs, *inp, len);
92
9.83k
  UniquePtr<T> ret(func(&cbs));
93
9.83k
  if (ret == nullptr) {
94
7.00k
    return nullptr;
95
7.00k
  }
96
2.83k
  if (out != nullptr) {
97
0
    UniquePtr<T> free_out(*out);
98
0
    *out = ret.get();
99
0
  }
100
2.83k
  *inp = CBS_data(&cbs);
101
2.83k
  return ret.release();
102
9.83k
}
Unexecuted instantiation: ssl_x509.cc:ssl_session_st* bssl::D2IFromCBS<ssl_session_st, d2i_SSL_SESSION::$_0>(ssl_session_st**, unsigned char const**, long, d2i_SSL_SESSION::$_0)
Unexecuted instantiation: ec_asn1.cc:ec_key_st* bssl::D2IFromCBS<ec_key_st, d2i_ECPrivateKey::$_0>(ec_key_st**, unsigned char const**, long, d2i_ECPrivateKey::$_0)
Unexecuted instantiation: ec_group_st* bssl::D2IFromCBS<ec_group_st, ec_group_st* (*)(cbs_st*)>(ec_group_st**, unsigned char const**, long, ec_group_st* (*)(cbs_st*))
Unexecuted instantiation: ec_asn1.cc:ec_key_st* bssl::D2IFromCBS<ec_key_st, d2i_ECParameters::$_0>(ec_key_st**, unsigned char const**, long, d2i_ECParameters::$_0)
Unexecuted instantiation: ecdsa_sig_st* bssl::D2IFromCBS<ecdsa_sig_st, ecdsa_sig_st* (*)(cbs_st*)>(ecdsa_sig_st**, unsigned char const**, long, ecdsa_sig_st* (*)(cbs_st*))
evp_asn1.cc:evp_pkey_st* bssl::D2IFromCBS<evp_pkey_st, d2i_PrivateKey::$_0>(evp_pkey_st**, unsigned char const**, long, d2i_PrivateKey::$_0)
Line
Count
Source
81
4.06k
inline T *D2IFromCBS(T **out, const uint8_t **inp, long len, CBSFunc func) {
82
4.06k
  static_assert(std::is_invocable_v<CBSFunc, CBS *>);
83
4.06k
  static_assert(
84
4.06k
      std::is_same_v<std::invoke_result_t<CBSFunc, CBS *>, UniquePtr<T>> ||
85
4.06k
      std::is_same_v<std::invoke_result_t<CBSFunc, CBS *>, T *>);
86
4.06k
  if (len < 0) {
87
0
    OPENSSL_PUT_ERROR(ASN1, ASN1_R_BUFFER_TOO_SMALL);
88
0
    return nullptr;
89
0
  }
90
4.06k
  CBS cbs;
91
4.06k
  CBS_init(&cbs, *inp, len);
92
4.06k
  UniquePtr<T> ret(func(&cbs));
93
4.06k
  if (ret == nullptr) {
94
4.05k
    return nullptr;
95
4.05k
  }
96
6
  if (out != nullptr) {
97
0
    UniquePtr<T> free_out(*out);
98
0
    *out = ret.get();
99
0
  }
100
6
  *inp = CBS_data(&cbs);
101
6
  return ret.release();
102
4.06k
}
Unexecuted instantiation: evp_asn1.cc:evp_pkey_st* bssl::D2IFromCBS<evp_pkey_st, d2i_PublicKey::$_0>(evp_pkey_st**, unsigned char const**, long, d2i_PublicKey::$_0)
Unexecuted instantiation: evp_pkey_st* bssl::D2IFromCBS<evp_pkey_st, evp_pkey_st* (*)(cbs_st*)>(evp_pkey_st**, unsigned char const**, long, evp_pkey_st* (*)(cbs_st*))
Unexecuted instantiation: evp_asn1.cc:rsa_st* bssl::D2IFromCBS<rsa_st, d2i_RSA_PUBKEY::$_0>(rsa_st**, unsigned char const**, long, d2i_RSA_PUBKEY::$_0)
Unexecuted instantiation: evp_asn1.cc:dsa_st* bssl::D2IFromCBS<dsa_st, d2i_DSA_PUBKEY::$_0>(dsa_st**, unsigned char const**, long, d2i_DSA_PUBKEY::$_0)
Unexecuted instantiation: evp_asn1.cc:ec_key_st* bssl::D2IFromCBS<ec_key_st, d2i_EC_PUBKEY::$_0>(ec_key_st**, unsigned char const**, long, d2i_EC_PUBKEY::$_0)
rsa_st* bssl::D2IFromCBS<rsa_st, rsa_st* (*)(cbs_st*)>(rsa_st**, unsigned char const**, long, rsa_st* (*)(cbs_st*))
Line
Count
Source
81
2
inline T *D2IFromCBS(T **out, const uint8_t **inp, long len, CBSFunc func) {
82
2
  static_assert(std::is_invocable_v<CBSFunc, CBS *>);
83
2
  static_assert(
84
2
      std::is_same_v<std::invoke_result_t<CBSFunc, CBS *>, UniquePtr<T>> ||
85
2
      std::is_same_v<std::invoke_result_t<CBSFunc, CBS *>, T *>);
86
2
  if (len < 0) {
87
0
    OPENSSL_PUT_ERROR(ASN1, ASN1_R_BUFFER_TOO_SMALL);
88
0
    return nullptr;
89
0
  }
90
2
  CBS cbs;
91
2
  CBS_init(&cbs, *inp, len);
92
2
  UniquePtr<T> ret(func(&cbs));
93
2
  if (ret == nullptr) {
94
0
    return nullptr;
95
0
  }
96
2
  if (out != nullptr) {
97
0
    UniquePtr<T> free_out(*out);
98
0
    *out = ret.get();
99
0
  }
100
2
  *inp = CBS_data(&cbs);
101
2
  return ret.release();
102
2
}
Unexecuted instantiation: x_algor.cc:X509_algor_st* bssl::D2IFromCBS<X509_algor_st, d2i_X509_ALGOR::$_0>(X509_algor_st**, unsigned char const**, long, d2i_X509_ALGOR::$_0)
Unexecuted instantiation: x_pubkey.cc:X509_pubkey_st* bssl::D2IFromCBS<X509_pubkey_st, d2i_X509_PUBKEY::$_0>(X509_pubkey_st**, unsigned char const**, long, d2i_X509_PUBKEY::$_0)
x509_st* bssl::D2IFromCBS<x509_st, std::__1::unique_ptr<x509_st, bssl::internal::Deleter> (*)(cbs_st*)>(x509_st**, unsigned char const**, long, std::__1::unique_ptr<x509_st, bssl::internal::Deleter> (*)(cbs_st*))
Line
Count
Source
81
5.76k
inline T *D2IFromCBS(T **out, const uint8_t **inp, long len, CBSFunc func) {
82
5.76k
  static_assert(std::is_invocable_v<CBSFunc, CBS *>);
83
5.76k
  static_assert(
84
5.76k
      std::is_same_v<std::invoke_result_t<CBSFunc, CBS *>, UniquePtr<T>> ||
85
5.76k
      std::is_same_v<std::invoke_result_t<CBSFunc, CBS *>, T *>);
86
5.76k
  if (len < 0) {
87
0
    OPENSSL_PUT_ERROR(ASN1, ASN1_R_BUFFER_TOO_SMALL);
88
0
    return nullptr;
89
0
  }
90
5.76k
  CBS cbs;
91
5.76k
  CBS_init(&cbs, *inp, len);
92
5.76k
  UniquePtr<T> ret(func(&cbs));
93
5.76k
  if (ret == nullptr) {
94
2.94k
    return nullptr;
95
2.94k
  }
96
2.82k
  if (out != nullptr) {
97
0
    UniquePtr<T> free_out(*out);
98
0
    *out = ret.get();
99
0
  }
100
2.82k
  *inp = CBS_data(&cbs);
101
2.82k
  return ret.release();
102
5.76k
}
Unexecuted instantiation: a_object.cc:asn1_object_st* bssl::D2IFromCBS<asn1_object_st, d2i_ASN1_OBJECT::$_0>(asn1_object_st**, unsigned char const**, long, d2i_ASN1_OBJECT::$_0)
Unexecuted instantiation: a_object.cc:asn1_object_st* bssl::D2IFromCBS<asn1_object_st, c2i_ASN1_OBJECT::$_0>(asn1_object_st**, unsigned char const**, long, c2i_ASN1_OBJECT::$_0)
Unexecuted instantiation: dh_st* bssl::D2IFromCBS<dh_st, dh_st* (*)(cbs_st*)>(dh_st**, unsigned char const**, long, dh_st* (*)(cbs_st*))
Unexecuted instantiation: DSA_SIG_st* bssl::D2IFromCBS<DSA_SIG_st, DSA_SIG_st* (*)(cbs_st*)>(DSA_SIG_st**, unsigned char const**, long, DSA_SIG_st* (*)(cbs_st*))
Unexecuted instantiation: dsa_st* bssl::D2IFromCBS<dsa_st, dsa_st* (*)(cbs_st*)>(dsa_st**, unsigned char const**, long, dsa_st* (*)(cbs_st*))
103
104
// I2DFromCBB takes a functor of type |bool(CBB*)| and implements the i2d
105
// calling convention. It internally makes a |CBB| with the specified initial
106
// capacity. The callback should not access |outp| directly.
107
template <typename CBBFunc>
108
26.4k
inline int I2DFromCBB(size_t initial_capacity, uint8_t **outp, CBBFunc func) {
109
26.4k
  static_assert(std::is_invocable_v<CBBFunc, CBB *>);
110
26.4k
  static_assert(std::is_same_v<std::invoke_result_t<CBBFunc, CBB *>, bool>);
111
26.4k
  ScopedCBB cbb;
112
26.4k
  if (!CBB_init(cbb.get(), initial_capacity) || !func(cbb.get())) {
113
0
    return -1;
114
0
  }
115
26.4k
  return CBB_finish_i2d(cbb.get(), outp);
116
26.4k
}
Unexecuted instantiation: ec_asn1.cc:int bssl::I2DFromCBB<i2d_ECPrivateKey::$_0>(unsigned long, unsigned char**, i2d_ECPrivateKey::$_0)
Unexecuted instantiation: ec_asn1.cc:int bssl::I2DFromCBB<i2d_ECPKParameters::$_0>(unsigned long, unsigned char**, i2d_ECPKParameters::$_0)
Unexecuted instantiation: ec_asn1.cc:int bssl::I2DFromCBB<i2d_ECParameters::$_0>(unsigned long, unsigned char**, i2d_ECParameters::$_0)
Unexecuted instantiation: ec_asn1.cc:int bssl::I2DFromCBB<i2o_ECPublicKey::$_0>(unsigned long, unsigned char**, i2o_ECPublicKey::$_0)
Unexecuted instantiation: ecdsa_asn1.cc:int bssl::I2DFromCBB<i2d_ECDSA_SIG::$_0>(unsigned long, unsigned char**, i2d_ECDSA_SIG::$_0)
Unexecuted instantiation: evp_asn1.cc:int bssl::I2DFromCBB<i2d_PUBKEY::$_0>(unsigned long, unsigned char**, i2d_PUBKEY::$_0)
Unexecuted instantiation: rsa_asn1.cc:int bssl::I2DFromCBB<i2d_RSAPublicKey::$_0>(unsigned long, unsigned char**, i2d_RSAPublicKey::$_0)
Unexecuted instantiation: rsa_asn1.cc:int bssl::I2DFromCBB<i2d_RSAPrivateKey::$_0>(unsigned long, unsigned char**, i2d_RSAPrivateKey::$_0)
Unexecuted instantiation: x_algor.cc:int bssl::I2DFromCBB<i2d_X509_ALGOR::$_0>(unsigned long, unsigned char**, i2d_X509_ALGOR::$_0)
Unexecuted instantiation: x_pubkey.cc:int bssl::I2DFromCBB<i2d_X509_PUBKEY::$_0>(unsigned long, unsigned char**, i2d_X509_PUBKEY::$_0)
x_x509.cc:int bssl::I2DFromCBB<i2d_X509::$_0>(unsigned long, unsigned char**, i2d_X509::$_0)
Line
Count
Source
108
24.2k
inline int I2DFromCBB(size_t initial_capacity, uint8_t **outp, CBBFunc func) {
109
24.2k
  static_assert(std::is_invocable_v<CBBFunc, CBB *>);
110
24.2k
  static_assert(std::is_same_v<std::invoke_result_t<CBBFunc, CBB *>, bool>);
111
24.2k
  ScopedCBB cbb;
112
24.2k
  if (!CBB_init(cbb.get(), initial_capacity) || !func(cbb.get())) {
113
0
    return -1;
114
0
  }
115
24.2k
  return CBB_finish_i2d(cbb.get(), outp);
116
24.2k
}
x_x509.cc:int bssl::I2DFromCBB<i2d_X509_tbs::$_0>(unsigned long, unsigned char**, i2d_X509_tbs::$_0)
Line
Count
Source
108
2.20k
inline int I2DFromCBB(size_t initial_capacity, uint8_t **outp, CBBFunc func) {
109
2.20k
  static_assert(std::is_invocable_v<CBBFunc, CBB *>);
110
2.20k
  static_assert(std::is_same_v<std::invoke_result_t<CBBFunc, CBB *>, bool>);
111
2.20k
  ScopedCBB cbb;
112
2.20k
  if (!CBB_init(cbb.get(), initial_capacity) || !func(cbb.get())) {
113
0
    return -1;
114
0
  }
115
2.20k
  return CBB_finish_i2d(cbb.get(), outp);
116
2.20k
}
Unexecuted instantiation: a_object.cc:int bssl::I2DFromCBB<i2d_ASN1_OBJECT::$_0>(unsigned long, unsigned char**, i2d_ASN1_OBJECT::$_0)
Unexecuted instantiation: dh_asn1.cc:int bssl::I2DFromCBB<i2d_DHparams::$_0>(unsigned long, unsigned char**, i2d_DHparams::$_0)
Unexecuted instantiation: dsa_asn1.cc:int bssl::I2DFromCBB<i2d_DSA_SIG::$_0>(unsigned long, unsigned char**, i2d_DSA_SIG::$_0)
Unexecuted instantiation: dsa_asn1.cc:int bssl::I2DFromCBB<i2d_DSAPublicKey::$_0>(unsigned long, unsigned char**, i2d_DSAPublicKey::$_0)
Unexecuted instantiation: dsa_asn1.cc:int bssl::I2DFromCBB<i2d_DSAPrivateKey::$_0>(unsigned long, unsigned char**, i2d_DSAPrivateKey::$_0)
Unexecuted instantiation: dsa_asn1.cc:int bssl::I2DFromCBB<i2d_DSAparams::$_0>(unsigned long, unsigned char**, i2d_DSAparams::$_0)
117
118
BSSL_NAMESPACE_END
119
120
#endif  // OPENSSL_HEADER_CRYPTO_BYTESTRING_INTERNAL_H