Coverage Report

Created: 2026-06-28 06:23

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/boringssl/crypto/bytestring/internal.h
Line
Count
Source
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
#include "../mem_internal.h"
25
26
27
BSSL_NAMESPACE_BEGIN
28
29
// CBS_asn1_ber_to_der reads a BER element from `in`. If it finds
30
// indefinite-length elements or constructed strings then it converts the BER
31
// data to DER, sets `out` to the converted contents and `*out_storage` to a
32
// buffer which the caller must release with `OPENSSL_free`. Otherwise, it sets
33
// `out` to the original BER element in `in` and `*out_storage` to NULL.
34
// Additionally, `*in` will be advanced over the BER element.
35
//
36
// This function should successfully process any valid BER input, however it
37
// will not convert all of BER's deviations from DER. BER is ambiguous between
38
// implicitly-tagged SEQUENCEs of strings and implicitly-tagged constructed
39
// strings. Implicitly-tagged strings must be parsed with
40
// `CBS_get_ber_implicitly_tagged_string` instead of `CBS_get_asn1`. The caller
41
// must also account for BER variations in the contents of a primitive.
42
//
43
// It returns one on success and zero otherwise.
44
OPENSSL_EXPORT int CBS_asn1_ber_to_der(CBS *in, CBS *out,
45
                                       uint8_t **out_storage);
46
47
// CBS_get_asn1_implicit_string parses a BER string of primitive type
48
// `inner_tag` implicitly-tagged with `outer_tag`. It sets `out` to the
49
// contents. If concatenation was needed, it sets `*out_storage` to a buffer
50
// which the caller must release with `OPENSSL_free`. Otherwise, it sets
51
// `*out_storage` to NULL.
52
//
53
// This function does not parse all of BER. It requires the string be
54
// definite-length. Constructed strings are allowed, but all children of the
55
// outermost element must be primitive. The caller should use
56
// `CBS_asn1_ber_to_der` before running this function.
57
//
58
// It returns one on success and zero otherwise.
59
OPENSSL_EXPORT int CBS_get_asn1_implicit_string(CBS *in, CBS *out,
60
                                                uint8_t **out_storage,
61
                                                CBS_ASN1_TAG outer_tag,
62
                                                CBS_ASN1_TAG inner_tag);
63
64
// CBB_finish_i2d calls `CBB_finish` on `cbb` which must have been initialized
65
// with `CBB_init`. If `outp` is not NULL then the result is written to `*outp`
66
// and `*outp` is advanced just past the output. It returns the number of bytes
67
// in the result, whether written or not, or a negative value on error.
68
//
69
// This function may be used to help implement legacy i2d ASN.1 functions.
70
OPENSSL_EXPORT int CBB_finish_i2d(CBB *cbb, uint8_t **outp);
71
72
// CBBAsSpan returns a span containing `cbb`'s contents. It does not flush
73
// `cbb`. The span is valid until the next operation to `cbb`.
74
//
75
// To avoid unfinalized length prefixes, it is a fatal error to call this on a
76
// CBB with any active children.
77
3.38k
inline Span<uint8_t> CBBAsSpan(const CBB *cbb) {
78
3.38k
  return Span(CBB_data(cbb), CBB_len(cbb));
79
3.38k
}
80
81
// CBBFinishArray behaves like `CBB_finish` but stores the result in an Array.
82
OPENSSL_EXPORT bool CBBFinishArray(CBB *cbb, Array<uint8_t> *out);
83
84
// D2IFromCBS takes a functor of type `Unique<T>(CBS*)` and implements the d2i
85
// calling convention. For compatibility with functions that don't tag their
86
// return value (e.g. public APIs), `T*(CBS)` is also accepted. The callback can
87
// assume that the `CBS`'s length fits in `long`. The callback should not access
88
// `out`, `inp`, or `len` directly.
89
template <typename T, typename CBSFunc>
90
17.9k
inline T *D2IFromCBS(T **out, const uint8_t **inp, long len, CBSFunc func) {
91
17.9k
  static_assert(std::is_invocable_v<CBSFunc, CBS *>);
92
17.9k
  static_assert(
93
17.9k
      std::is_same_v<std::invoke_result_t<CBSFunc, CBS *>, UniquePtr<T>> ||
94
17.9k
      std::is_same_v<std::invoke_result_t<CBSFunc, CBS *>, T *>);
95
17.9k
  if (len < 0) {
96
0
    OPENSSL_PUT_ERROR(ASN1, ASN1_R_BUFFER_TOO_SMALL);
97
0
    return nullptr;
98
0
  }
99
17.9k
  CBS cbs;
100
17.9k
  CBS_init(&cbs, *inp, len);
101
17.9k
  UniquePtr<T> ret(func(&cbs));
102
17.9k
  if (ret == nullptr) {
103
11.9k
    return nullptr;
104
11.9k
  }
105
6.04k
  if (out != nullptr) {
106
0
    UniquePtr<T> free_out(*out);
107
0
    *out = ret.get();
108
0
  }
109
6.04k
  *inp = CBS_data(&cbs);
110
6.04k
  return ret.release();
111
17.9k
}
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
90
4.48k
inline T *D2IFromCBS(T **out, const uint8_t **inp, long len, CBSFunc func) {
91
4.48k
  static_assert(std::is_invocable_v<CBSFunc, CBS *>);
92
4.48k
  static_assert(
93
4.48k
      std::is_same_v<std::invoke_result_t<CBSFunc, CBS *>, UniquePtr<T>> ||
94
4.48k
      std::is_same_v<std::invoke_result_t<CBSFunc, CBS *>, T *>);
95
4.48k
  if (len < 0) {
96
0
    OPENSSL_PUT_ERROR(ASN1, ASN1_R_BUFFER_TOO_SMALL);
97
0
    return nullptr;
98
0
  }
99
4.48k
  CBS cbs;
100
4.48k
  CBS_init(&cbs, *inp, len);
101
4.48k
  UniquePtr<T> ret(func(&cbs));
102
4.48k
  if (ret == nullptr) {
103
4.48k
    return nullptr;
104
4.48k
  }
105
8
  if (out != nullptr) {
106
0
    UniquePtr<T> free_out(*out);
107
0
    *out = ret.get();
108
0
  }
109
8
  *inp = CBS_data(&cbs);
110
8
  return ret.release();
111
4.48k
}
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
90
2
inline T *D2IFromCBS(T **out, const uint8_t **inp, long len, CBSFunc func) {
91
2
  static_assert(std::is_invocable_v<CBSFunc, CBS *>);
92
2
  static_assert(
93
2
      std::is_same_v<std::invoke_result_t<CBSFunc, CBS *>, UniquePtr<T>> ||
94
2
      std::is_same_v<std::invoke_result_t<CBSFunc, CBS *>, T *>);
95
2
  if (len < 0) {
96
0
    OPENSSL_PUT_ERROR(ASN1, ASN1_R_BUFFER_TOO_SMALL);
97
0
    return nullptr;
98
0
  }
99
2
  CBS cbs;
100
2
  CBS_init(&cbs, *inp, len);
101
2
  UniquePtr<T> ret(func(&cbs));
102
2
  if (ret == nullptr) {
103
0
    return nullptr;
104
0
  }
105
2
  if (out != nullptr) {
106
0
    UniquePtr<T> free_out(*out);
107
0
    *out = ret.get();
108
0
  }
109
2
  *inp = CBS_data(&cbs);
110
2
  return ret.release();
111
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)
x_name.cc:X509_name_st* bssl::D2IFromCBS<X509_name_st, d2i_X509_NAME::$_0>(X509_name_st**, unsigned char const**, long, d2i_X509_NAME::$_0)
Line
Count
Source
90
1.10k
inline T *D2IFromCBS(T **out, const uint8_t **inp, long len, CBSFunc func) {
91
1.10k
  static_assert(std::is_invocable_v<CBSFunc, CBS *>);
92
1.10k
  static_assert(
93
1.10k
      std::is_same_v<std::invoke_result_t<CBSFunc, CBS *>, UniquePtr<T>> ||
94
1.10k
      std::is_same_v<std::invoke_result_t<CBSFunc, CBS *>, T *>);
95
1.10k
  if (len < 0) {
96
0
    OPENSSL_PUT_ERROR(ASN1, ASN1_R_BUFFER_TOO_SMALL);
97
0
    return nullptr;
98
0
  }
99
1.10k
  CBS cbs;
100
1.10k
  CBS_init(&cbs, *inp, len);
101
1.10k
  UniquePtr<T> ret(func(&cbs));
102
1.10k
  if (ret == nullptr) {
103
437
    return nullptr;
104
437
  }
105
667
  if (out != nullptr) {
106
0
    UniquePtr<T> free_out(*out);
107
0
    *out = ret.get();
108
0
  }
109
667
  *inp = CBS_data(&cbs);
110
667
  return ret.release();
111
1.10k
}
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
90
12.3k
inline T *D2IFromCBS(T **out, const uint8_t **inp, long len, CBSFunc func) {
91
12.3k
  static_assert(std::is_invocable_v<CBSFunc, CBS *>);
92
12.3k
  static_assert(
93
12.3k
      std::is_same_v<std::invoke_result_t<CBSFunc, CBS *>, UniquePtr<T>> ||
94
12.3k
      std::is_same_v<std::invoke_result_t<CBSFunc, CBS *>, T *>);
95
12.3k
  if (len < 0) {
96
0
    OPENSSL_PUT_ERROR(ASN1, ASN1_R_BUFFER_TOO_SMALL);
97
0
    return nullptr;
98
0
  }
99
12.3k
  CBS cbs;
100
12.3k
  CBS_init(&cbs, *inp, len);
101
12.3k
  UniquePtr<T> ret(func(&cbs));
102
12.3k
  if (ret == nullptr) {
103
7.01k
    return nullptr;
104
7.01k
  }
105
5.37k
  if (out != nullptr) {
106
0
    UniquePtr<T> free_out(*out);
107
0
    *out = ret.get();
108
0
  }
109
5.37k
  *inp = CBS_data(&cbs);
110
5.37k
  return ret.release();
111
12.3k
}
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: a_type.cc:asn1_type_st* bssl::D2IFromCBS<asn1_type_st, d2i_ASN1_TYPE::$_0>(asn1_type_st**, unsigned char const**, long, d2i_ASN1_TYPE::$_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*))
112
113
// I2DFromCBB takes a functor of type `bool(CBB*)` and implements the i2d
114
// calling convention. It internally makes a `CBB` with the specified initial
115
// capacity. The callback should not access `outp` directly.
116
template <typename CBBFunc>
117
57.9k
inline int I2DFromCBB(size_t initial_capacity, uint8_t **outp, CBBFunc func) {
118
57.9k
  static_assert(std::is_invocable_v<CBBFunc, CBB *>);
119
57.9k
  static_assert(std::is_same_v<std::invoke_result_t<CBBFunc, CBB *>, bool>);
120
57.9k
  ScopedCBB cbb;
121
57.9k
  if (!CBB_init(cbb.get(), initial_capacity) || !func(cbb.get())) {
122
0
    return -1;
123
0
  }
124
57.9k
  return CBB_finish_i2d(cbb.get(), outp);
125
57.9k
}
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
117
44.6k
inline int I2DFromCBB(size_t initial_capacity, uint8_t **outp, CBBFunc func) {
118
44.6k
  static_assert(std::is_invocable_v<CBBFunc, CBB *>);
119
44.6k
  static_assert(std::is_same_v<std::invoke_result_t<CBBFunc, CBB *>, bool>);
120
44.6k
  ScopedCBB cbb;
121
44.6k
  if (!CBB_init(cbb.get(), initial_capacity) || !func(cbb.get())) {
122
0
    return -1;
123
0
  }
124
44.6k
  return CBB_finish_i2d(cbb.get(), outp);
125
44.6k
}
x_x509.cc:int bssl::I2DFromCBB<i2d_X509_tbs::$_0>(unsigned long, unsigned char**, i2d_X509_tbs::$_0)
Line
Count
Source
117
3.26k
inline int I2DFromCBB(size_t initial_capacity, uint8_t **outp, CBBFunc func) {
118
3.26k
  static_assert(std::is_invocable_v<CBBFunc, CBB *>);
119
3.26k
  static_assert(std::is_same_v<std::invoke_result_t<CBBFunc, CBB *>, bool>);
120
3.26k
  ScopedCBB cbb;
121
3.26k
  if (!CBB_init(cbb.get(), initial_capacity) || !func(cbb.get())) {
122
0
    return -1;
123
0
  }
124
3.26k
  return CBB_finish_i2d(cbb.get(), outp);
125
3.26k
}
Unexecuted instantiation: a_object.cc:int bssl::I2DFromCBB<i2d_ASN1_OBJECT::$_0>(unsigned long, unsigned char**, i2d_ASN1_OBJECT::$_0)
Unexecuted instantiation: a_type.cc:int bssl::I2DFromCBB<i2d_ASN1_TYPE::$_0>(unsigned long, unsigned char**, i2d_ASN1_TYPE::$_0)
tasn_enc.cc:int bssl::I2DFromCBB<ASN1_item_i2d::$_0>(unsigned long, unsigned char**, ASN1_item_i2d::$_0)
Line
Count
Source
117
9.99k
inline int I2DFromCBB(size_t initial_capacity, uint8_t **outp, CBBFunc func) {
118
9.99k
  static_assert(std::is_invocable_v<CBBFunc, CBB *>);
119
9.99k
  static_assert(std::is_same_v<std::invoke_result_t<CBBFunc, CBB *>, bool>);
120
9.99k
  ScopedCBB cbb;
121
9.99k
  if (!CBB_init(cbb.get(), initial_capacity) || !func(cbb.get())) {
122
0
    return -1;
123
0
  }
124
9.99k
  return CBB_finish_i2d(cbb.get(), outp);
125
9.99k
}
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)
126
127
BSSL_NAMESPACE_END
128
129
#endif  // OPENSSL_HEADER_CRYPTO_BYTESTRING_INTERNAL_H