• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

randombit / botan / 5230455705

10 Jun 2023 02:30PM UTC coverage: 91.715% (-0.03%) from 91.746%
5230455705

push

github

randombit
Merge GH #3584 Change clang-format AllowShortFunctionsOnASingleLine config from All to Inline

77182 of 84154 relevant lines covered (91.72%)

11975295.43 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

88.89
/src/lib/x509/pkcs10.cpp
1
/*
2
* PKCS #10
3
* (C) 1999-2007,2017 Jack Lloyd
4
*
5
* Botan is released under the Simplified BSD License (see license.txt)
6
*/
7

8
#include <botan/pkcs10.h>
9

10
#include <botan/ber_dec.h>
11
#include <botan/der_enc.h>
12
#include <botan/pem.h>
13
#include <botan/pubkey.h>
14
#include <botan/x509_ext.h>
15
#include <botan/x509_key.h>
16
#include <botan/x509cert.h>
17

18
namespace Botan {
19

20
struct PKCS10_Data {
21
      X509_DN m_subject_dn;
22
      std::vector<uint8_t> m_public_key_bits;
23
      AlternativeName m_alt_name;
24
      std::string m_challenge;
25
      Extensions m_extensions;
26
};
27

28
std::string PKCS10_Request::PEM_label() const {
31✔
29
   return "CERTIFICATE REQUEST";
31✔
30
}
31

32
std::vector<std::string> PKCS10_Request::alternate_PEM_labels() const {
×
33
   return {"NEW CERTIFICATE REQUEST"};
×
34
}
35

36
PKCS10_Request::PKCS10_Request(DataSource& src) {
×
37
   load_data(src);
×
38
}
×
39

40
PKCS10_Request::PKCS10_Request(const std::vector<uint8_t>& vec) {
146✔
41
   DataSource_Memory src(vec.data(), vec.size());
146✔
42
   load_data(src);
146✔
43
}
146✔
44

45
#if defined(BOTAN_TARGET_OS_HAS_FILESYSTEM)
46
PKCS10_Request::PKCS10_Request(std::string_view fsname) {
18✔
47
   DataSource_Stream src(fsname, true);
18✔
48
   load_data(src);
18✔
49
}
18✔
50
#endif
51

52
//static
53
PKCS10_Request PKCS10_Request::create(const Private_Key& key,
146✔
54
                                      const X509_DN& subject_dn,
55
                                      const Extensions& extensions,
56
                                      std::string_view hash_fn,
57
                                      RandomNumberGenerator& rng,
58
                                      std::string_view padding_scheme,
59
                                      std::string_view challenge) {
60
   auto signer = choose_sig_format(key, rng, hash_fn, padding_scheme);
146✔
61
   const AlgorithmIdentifier sig_algo = signer->algorithm_identifier();
146✔
62

63
   const size_t PKCS10_VERSION = 0;
146✔
64

65
   DER_Encoder tbs_req;
146✔
66

67
   tbs_req.start_sequence()
146✔
68
      .encode(PKCS10_VERSION)
146✔
69
      .encode(subject_dn)
146✔
70
      .raw_bytes(key.subject_public_key())
146✔
71
      .start_explicit(0);
146✔
72

73
   if(challenge.empty() == false) {
146✔
74
      std::vector<uint8_t> value;
9✔
75
      DER_Encoder(value).encode(ASN1_String(challenge));
9✔
76
      tbs_req.encode(Attribute("PKCS9.ChallengePassword", value));
9✔
77
   }
9✔
78

79
   std::vector<uint8_t> extension_req;
146✔
80
   DER_Encoder(extension_req).start_sequence().encode(extensions).end_cons();
292✔
81
   tbs_req.encode(Attribute("PKCS9.ExtensionRequest", extension_req));
146✔
82

83
   // end the start_explicit above
84
   tbs_req.end_explicit().end_cons();
146✔
85

86
   const std::vector<uint8_t> req = X509_Object::make_signed(*signer, rng, sig_algo, tbs_req.get_contents());
146✔
87

88
   return PKCS10_Request(req);
292✔
89
}
292✔
90

91
/*
92
* Decode the CertificateRequestInfo
93
*/
94
namespace {
95

96
std::unique_ptr<PKCS10_Data> decode_pkcs10(const std::vector<uint8_t>& body) {
164✔
97
   auto data = std::make_unique<PKCS10_Data>();
164✔
98

99
   BER_Decoder cert_req_info(body);
164✔
100

101
   size_t version;
164✔
102
   cert_req_info.decode(version);
164✔
103
   if(version != 0) {
164✔
104
      throw Decoding_Error("Unknown version code in PKCS #10 request: " + std::to_string(version));
×
105
   }
106

107
   cert_req_info.decode(data->m_subject_dn);
164✔
108

109
   BER_Object public_key = cert_req_info.get_next_object();
164✔
110
   if(public_key.is_a(ASN1_Type::Sequence, ASN1_Class::Constructed) == false) {
164✔
111
      throw BER_Bad_Tag("PKCS10_Request: Unexpected tag for public key", public_key.tagging());
×
112
   }
113

114
   data->m_public_key_bits = ASN1::put_in_sequence(public_key.bits(), public_key.length());
164✔
115

116
   BER_Object attr_bits = cert_req_info.get_next_object();
164✔
117

118
   std::set<std::string> pkcs9_email;
164✔
119

120
   if(attr_bits.is_a(0, ASN1_Class::Constructed | ASN1_Class::ContextSpecific)) {
164✔
121
      BER_Decoder attributes(attr_bits);
164✔
122
      while(attributes.more_items()) {
337✔
123
         Attribute attr;
173✔
124
         attributes.decode(attr);
173✔
125

126
         const OID& oid = attr.object_identifier();
173✔
127
         BER_Decoder value(attr.get_parameters());
173✔
128

129
         if(oid == OID::from_string("PKCS9.EmailAddress")) {
173✔
130
            ASN1_String email;
×
131
            value.decode(email);
×
132
            pkcs9_email.insert(email.value());
×
133
         } else if(oid == OID::from_string("PKCS9.ChallengePassword")) {
173✔
134
            ASN1_String challenge_password;
9✔
135
            value.decode(challenge_password);
9✔
136
            data->m_challenge = challenge_password.value();
9✔
137
         } else if(oid == OID::from_string("PKCS9.ExtensionRequest")) {
173✔
138
            value.decode(data->m_extensions).verify_end();
164✔
139
         }
140
      }
173✔
141
      attributes.verify_end();
164✔
142
   } else if(attr_bits.is_set()) {
164✔
143
      throw BER_Bad_Tag("PKCS10_Request: Unexpected tag for attributes", attr_bits.tagging());
×
144
   }
145

146
   cert_req_info.verify_end();
164✔
147

148
   if(auto ext = data->m_extensions.get_extension_object_as<Cert_Extension::Subject_Alternative_Name>()) {
164✔
149
      data->m_alt_name = ext->get_alt_name();
45✔
150
   }
151

152
   for(const auto& email : pkcs9_email) {
164✔
153
      data->m_alt_name.add_attribute("RFC882", email);
×
154
   }
155

156
   return data;
328✔
157
}
492✔
158

159
}  // namespace
160

161
void PKCS10_Request::force_decode() {
164✔
162
   m_data.reset();
164✔
163

164
   m_data = decode_pkcs10(signed_body());
328✔
165

166
   auto key = this->subject_public_key();
164✔
167
   if(!this->check_signature(*key)) {
164✔
168
      throw Decoding_Error("PKCS #10 request: Bad signature detected");
×
169
   }
170
}
164✔
171

172
const PKCS10_Data& PKCS10_Request::data() const {
1,810✔
173
   if(m_data == nullptr) {
1,810✔
174
      throw Decoding_Error("PKCS10_Request decoding failed");
×
175
   }
176
   return *m_data;
1,810✔
177
}
178

179
/*
180
* Return the challenge password (if any)
181
*/
182
std::string PKCS10_Request::challenge_password() const {
9✔
183
   return data().m_challenge;
9✔
184
}
185

186
/*
187
* Return the name of the requestor
188
*/
189
const X509_DN& PKCS10_Request::subject_dn() const {
157✔
190
   return data().m_subject_dn;
157✔
191
}
192

193
/*
194
* Return the public key of the requestor
195
*/
196
const std::vector<uint8_t>& PKCS10_Request::raw_public_key() const {
613✔
197
   return data().m_public_key_bits;
613✔
198
}
199

200
/*
201
* Return the public key of the requestor
202
*/
203
std::unique_ptr<Public_Key> PKCS10_Request::subject_public_key() const {
317✔
204
   DataSource_Memory source(raw_public_key());
317✔
205
   return X509::load_key(source);
317✔
206
}
317✔
207

208
/*
209
* Return the alternative names of the requestor
210
*/
211
const AlternativeName& PKCS10_Request::subject_alt_name() const {
157✔
212
   return data().m_alt_name;
157✔
213
}
214

215
/*
216
* Return the X509v3 extensions
217
*/
218
const Extensions& PKCS10_Request::extensions() const {
874✔
219
   return data().m_extensions;
874✔
220
}
221

222
/*
223
* Return the key constraints (if any)
224
*/
225
Key_Constraints PKCS10_Request::constraints() const {
134✔
226
   if(auto ext = extensions().get(OID::from_string("X509v3.KeyUsage"))) {
268✔
227
      return dynamic_cast<Cert_Extension::Key_Usage&>(*ext).get_constraints();
38✔
228
   }
38✔
229

230
   return Key_Constraints::None;
96✔
231
}
232

233
/*
234
* Return the extendend key constraints (if any)
235
*/
236
std::vector<OID> PKCS10_Request::ex_constraints() const {
148✔
237
   if(auto ext = extensions().get(OID::from_string("X509v3.ExtendedKeyUsage"))) {
296✔
238
      return dynamic_cast<Cert_Extension::Extended_Key_Usage&>(*ext).object_identifiers();
9✔
239
   }
9✔
240

241
   return {};
148✔
242
}
243

244
/*
245
* Return is a CA certificate is requested
246
*/
247
bool PKCS10_Request::is_CA() const {
296✔
248
   if(auto ext = extensions().get(OID::from_string("X509v3.BasicConstraints"))) {
592✔
249
      return dynamic_cast<Cert_Extension::Basic_Constraints&>(*ext).get_is_ca();
278✔
250
   }
278✔
251

252
   return false;
18✔
253
}
254

255
/*
256
* Return the desired path limit (if any)
257
*/
258
size_t PKCS10_Request::path_limit() const {
148✔
259
   if(auto ext = extensions().get(OID::from_string("X509v3.BasicConstraints"))) {
296✔
260
      Cert_Extension::Basic_Constraints& basic_constraints = dynamic_cast<Cert_Extension::Basic_Constraints&>(*ext);
139✔
261
      if(basic_constraints.get_is_ca()) {
139✔
262
         return basic_constraints.get_path_limit();
14✔
263
      }
264
   }
14✔
265

266
   return 0;
134✔
267
}
268

269
}  // namespace Botan
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc