]> git.ipfire.org Git - thirdparty/squid.git/blame - src/ssl/gadgets.cc
Maintenance: Removed most NULLs using modernize-use-nullptr (#1075)
[thirdparty/squid.git] / src / ssl / gadgets.cc
CommitLineData
bbc27441 1/*
bf95c10a 2 * Copyright (C) 1996-2022 The Squid Software Foundation and contributors
bbc27441
AJ
3 *
4 * Squid software is distributed under GPLv2+ license and includes
5 * contributions from numerous individuals and organizations.
6 * Please see the COPYING and CONTRIBUTORS files for details.
7 */
8
f7f3304a 9#include "squid.h"
ac1b16b5
AR
10#include "base/IoManip.h"
11#include "error/SysErrorDetail.h"
12#include "security/Io.h"
13#include "sbuf/Stream.h"
95d2589c 14#include "ssl/gadgets.h"
cb4f4424 15
ac1b16b5
AR
16void
17Ssl::ForgetErrors()
18{
19 if (ERR_peek_last_error()) {
20 debugs(83, 5, "forgetting stale OpenSSL errors:" << ReportAndForgetErrors);
21 // forget errors if section/level-specific debugging above was disabled
22 while (ERR_get_error()) {}
23 }
24
25 // Technically, the caller should just ignore (potentially stale) errno when
26 // no system calls have failed. However, due to OpenSSL error-reporting API
27 // deficiencies, many callers cannot detect when a TLS error was caused by a
28 // system call failure. We forget the stale errno (just like we forget stale
29 // OpenSSL errors above) so that the caller only uses fresh errno values.
30 errno = 0;
31}
32
33std::ostream &
34Ssl::ReportAndForgetErrors(std::ostream &os)
35{
36 unsigned int reported = 0; // efficiently marks ForgetErrors() call boundary
37 while (const auto errorToForget = ERR_get_error())
38 os << Debug::Extra << "OpenSSL-saved error #" << (++reported) << ": " << asHex(errorToForget);
39 return os;
40}
41
42[[ noreturn ]] static void
43ThrowErrors(const char * const problem, const int savedErrno, const SourceLocation &where)
44{
45 throw TextException(ToSBuf(problem, ": ",
46 Ssl::ReportAndForgetErrors,
47 ReportSysError(savedErrno)),
48 where);
49}
50
95d2589c
CT
51EVP_PKEY * Ssl::createSslPrivateKey()
52{
cf487124 53 Security::PrivateKeyPointer pkey(EVP_PKEY_new());
95d2589c
CT
54
55 if (!pkey)
aee3523a 56 return nullptr;
95d2589c 57
2a268a06
CT
58 BIGNUM_Pointer bn(BN_new());
59 if (!bn)
aee3523a 60 return nullptr;
2a268a06
CT
61
62 if (!BN_set_word(bn.get(), RSA_F4))
aee3523a 63 return nullptr;
2a268a06
CT
64
65 Ssl::RSA_Pointer rsa(RSA_new());
66 if (!rsa)
aee3523a 67 return nullptr;
ac756c8c 68
2a268a06 69 int num = 2048; // Maybe use 4096 RSA keys, or better make it configurable?
aee3523a
AR
70 if (!RSA_generate_key_ex(rsa.get(), num, bn.get(), nullptr))
71 return nullptr;
95d2589c 72
95d2589c 73 if (!EVP_PKEY_assign_RSA(pkey.get(), (rsa.get())))
aee3523a 74 return nullptr;
95d2589c
CT
75
76 rsa.release();
77 return pkey.release();
78}
79
95d2589c
CT
80/**
81 \ingroup ServerProtocolSSLInternal
82 * Set serial random serial number or set random serial number.
83 */
84static bool setSerialNumber(ASN1_INTEGER *ai, BIGNUM const* serial)
85{
86 if (!ai)
87 return false;
88 Ssl::BIGNUM_Pointer bn(BN_new());
89 if (serial) {
90 bn.reset(BN_dup(serial));
91 } else {
92 if (!bn)
93 return false;
94
95 if (!BN_pseudo_rand(bn.get(), 64, 0, 0))
96 return false;
97 }
98
99 if (ai && !BN_to_ASN1_INTEGER(bn.get(), ai))
100 return false;
101 return true;
102}
103
cf487124 104bool Ssl::writeCertAndPrivateKeyToMemory(Security::CertPointer const & cert, Security::PrivateKeyPointer const & pkey, std::string & bufferToWrite)
95d2589c
CT
105{
106 bufferToWrite.clear();
107 if (!pkey || !cert)
108 return false;
109 BIO_Pointer bio(BIO_new(BIO_s_mem()));
110 if (!bio)
111 return false;
112
113 if (!PEM_write_bio_X509 (bio.get(), cert.get()))
114 return false;
115
aee3523a 116 if (!PEM_write_bio_PrivateKey(bio.get(), pkey.get(), nullptr, nullptr, 0, nullptr, nullptr))
95d2589c
CT
117 return false;
118
aee3523a 119 char *ptr = nullptr;
95d2589c
CT
120 long len = BIO_get_mem_data(bio.get(), &ptr);
121 if (!ptr)
122 return false;
123
124 bufferToWrite = std::string(ptr, len);
125 return true;
126}
127
f97700a0 128bool Ssl::appendCertToMemory(Security::CertPointer const & cert, std::string & bufferToWrite)
9a90aace
CT
129{
130 if (!cert)
131 return false;
132
133 BIO_Pointer bio(BIO_new(BIO_s_mem()));
134 if (!bio)
135 return false;
136
137 if (!PEM_write_bio_X509 (bio.get(), cert.get()))
138 return false;
139
aee3523a 140 char *ptr = nullptr;
9a90aace
CT
141 long len = BIO_get_mem_data(bio.get(), &ptr);
142 if (!ptr)
143 return false;
144
87f237a9 145 if (!bufferToWrite.empty())
9a90aace
CT
146 bufferToWrite.append(" "); // add a space...
147
148 bufferToWrite.append(ptr, len);
149 return true;
150}
151
cf487124 152bool Ssl::readCertAndPrivateKeyFromMemory(Security::CertPointer & cert, Security::PrivateKeyPointer & pkey, char const * bufferToRead)
95d2589c
CT
153{
154 Ssl::BIO_Pointer bio(BIO_new(BIO_s_mem()));
155 BIO_puts(bio.get(), bufferToRead);
156
ac1b16b5
AR
157 try {
158 cert = ReadCertificate(bio);
159 } catch (...) {
160 debugs(83, DBG_IMPORTANT, "ERROR: Cannot deserialize a signing certificate:" <<
161 Debug::Extra << "problem: " << CurrentException);
162 cert.reset();
163 pkey.reset();
95d2589c 164 return false;
ac1b16b5 165 }
95d2589c 166
aee3523a
AR
167 EVP_PKEY * pkeyPtr = nullptr;
168 pkey.resetWithoutLocking(PEM_read_bio_PrivateKey(bio.get(), &pkeyPtr, nullptr, nullptr));
95d2589c
CT
169 if (!pkey)
170 return false;
171
172 return true;
173}
174
ac1b16b5
AR
175// TODO: Convert matching BIO_s_mem() callers.
176Ssl::BIO_Pointer
177Ssl::ReadOnlyBioTiedTo(const char * const bufferToRead)
9a90aace 178{
ac1b16b5
AR
179 ForgetErrors();
180 // OpenSSL BIO API is not const-correct, but OpenSSL does not free or modify
181 // BIO_new_mem_buf() data because it is marked with BIO_FLAGS_MEM_RDONLY.
182 const auto castedBuffer = const_cast<char*>(bufferToRead);
183 if (const auto bio = BIO_new_mem_buf(castedBuffer, -1)) // no memcpy()
184 return BIO_Pointer(bio);
185 const auto savedErrno = errno;
186 ThrowErrors("cannot allocate OpenSSL BIO structure", savedErrno, Here());
9a90aace
CT
187}
188
bf94620c
CT
189// According to RFC 5280 (Section A.1), the common name length in a certificate
190// can be at most 64 characters
191static const size_t MaxCnLen = 64;
192
fb2178bb 193// Replace certs common name with the given
f97700a0 194static bool replaceCommonName(Security::CertPointer & cert, std::string const &rawCn)
fb2178bb 195{
4a962df3
AR
196 std::string cn = rawCn;
197
bf94620c 198 if (cn.length() > MaxCnLen) {
2f8abb64 199 // In the case the length of CN is more than the maximum supported size
bf94620c
CT
200 // try to use the first upper level domain.
201 size_t pos = 0;
202 do {
203 pos = cn.find('.', pos + 1);
87f237a9 204 } while (pos != std::string::npos && (cn.length() - pos + 2) > MaxCnLen);
bf94620c
CT
205
206 // If no short domain found or this domain is a toplevel domain
207 // we failed to find a good cn name.
208 if (pos == std::string::npos || cn.find('.', pos + 1) == std::string::npos)
209 return false;
210
4a962df3 211 std::string fixedCn(1, '*');
bf94620c 212 fixedCn.append(cn.c_str() + pos);
4a962df3 213 cn = fixedCn;
bf94620c
CT
214 }
215
4a962df3
AR
216 // Assume [] surround an IPv6 address and strip them because browsers such
217 // as Firefox, Chromium, and Safari prefer bare IPv6 addresses in CNs.
218 if (cn.length() > 2 && *cn.begin() == '[' && *cn.rbegin() == ']')
219 cn = cn.substr(1, cn.size()-2);
220
fb2178bb
CT
221 X509_NAME *name = X509_get_subject_name(cert.get());
222 if (!name)
223 return false;
224 // Remove the CN part:
225 int loc = X509_NAME_get_index_by_NID(name, NID_commonName, -1);
aebe6888
CT
226 if (loc >=0) {
227 X509_NAME_ENTRY *tmp = X509_NAME_get_entry(name, loc);
228 X509_NAME_delete_entry(name, loc);
229 X509_NAME_ENTRY_free(tmp);
230 }
fb2178bb
CT
231
232 // Add a new CN
233 return X509_NAME_add_entry_by_NID(name, NID_commonName, MBSTRING_ASC,
4a962df3 234 (unsigned char *)(cn.c_str()), -1, -1, 0);
fb2178bb
CT
235}
236
aebe6888
CT
237const char *Ssl::CertSignAlgorithmStr[] = {
238 "signTrusted",
87f237a9 239 "signUntrusted",
aebe6888 240 "signSelf",
aee3523a 241 nullptr
aebe6888
CT
242};
243
fb2178bb
CT
244const char *Ssl::CertAdaptAlgorithmStr[] = {
245 "setValidAfter",
246 "setValidBefore",
247 "setCommonName",
aee3523a 248 nullptr
fb2178bb
CT
249};
250
a0b971d5 251Ssl::CertificateProperties::CertificateProperties():
f53969cc
SM
252 setValidAfter(false),
253 setValidBefore(false),
254 setCommonName(false),
255 signAlgorithm(Ssl::algSignEnd),
aee3523a 256 signHash(nullptr)
aebe6888
CT
257{}
258
5107d2c4
CT
259static void
260printX509Signature(const Security::CertPointer &cert, std::string &out)
261{
70cfe22f 262 const ASN1_BIT_STRING *sig = Ssl::X509_get_signature(cert);
5107d2c4
CT
263 if (sig && sig->data) {
264 const unsigned char *s = sig->data;
265 for (int i = 0; i < sig->length; ++i) {
266 char hex[3];
267 snprintf(hex, sizeof(hex), "%02x", s[i]);
268 out.append(hex);
269 }
270 }
271}
272
273std::string &
274Ssl::OnDiskCertificateDbKey(const Ssl::CertificateProperties &properties)
06997a38
CT
275{
276 static std::string certKey;
7fc31d31 277 certKey.clear();
06997a38 278 certKey.reserve(4096);
5107d2c4
CT
279 if (properties.mimicCert.get())
280 printX509Signature(properties.mimicCert, certKey);
06997a38 281
7fc31d31
AR
282 if (certKey.empty()) {
283 certKey.append("/CN=", 4);
5107d2c4 284 certKey.append(properties.commonName);
7fc31d31 285 }
06997a38 286
5107d2c4 287 if (properties.setValidAfter)
06997a38
CT
288 certKey.append("+SetValidAfter=on", 17);
289
5107d2c4 290 if (properties.setValidBefore)
06997a38
CT
291 certKey.append("+SetValidBefore=on", 18);
292
5107d2c4 293 if (properties.setCommonName) {
06997a38 294 certKey.append("+SetCommonName=", 15);
5107d2c4 295 certKey.append(properties.commonName);
06997a38
CT
296 }
297
5107d2c4 298 if (properties.signAlgorithm != Ssl::algSignEnd) {
06997a38 299 certKey.append("+Sign=", 6);
5107d2c4 300 certKey.append(certSignAlgorithm(properties.signAlgorithm));
06997a38
CT
301 }
302
aee3523a 303 if (properties.signHash != nullptr) {
3c26b00a 304 certKey.append("+SignHash=", 10);
5107d2c4 305 certKey.append(EVP_MD_name(properties.signHash));
3c26b00a
CT
306 }
307
06997a38
CT
308 return certKey;
309}
310
5f1318b1
CT
311/// Check if mimicCert certificate has the Authority Key Identifier extension
312/// and if yes add the extension to cert certificate with the same fields if
5ff0af8e 313/// possible. If the issuerCert certificate does not have the Subject Key
5f1318b1
CT
314/// Identifier extension (required to build the keyIdentifier field of
315/// AuthorityKeyIdentifier) then the authorityCertIssuer and
316/// authorityCertSerialNumber fields added.
317static bool
318mimicAuthorityKeyId(Security::CertPointer &cert, Security::CertPointer const &mimicCert, Security::CertPointer const &issuerCert)
319{
320 if (!mimicCert.get() || !issuerCert.get())
321 return false;
322
323 Ssl::AUTHORITY_KEYID_Pointer akid((AUTHORITY_KEYID *)X509_get_ext_d2i(mimicCert.get(), NID_authority_key_identifier, nullptr, nullptr));
324
325 bool addKeyId = false, addIssuer = false;
326 if (akid.get()) {
327 addKeyId = (akid.get()->keyid != nullptr);
328 addIssuer = (akid.get()->issuer && akid.get()->serial);
329 }
330
331 if (!addKeyId && !addIssuer)
332 return false; // No need to add AuthorityKeyIdentifier
333
334 Ssl::ASN1_OCTET_STRING_Pointer issuerKeyId;
335 if (addKeyId) {
336 X509_EXTENSION *ext;
337 // Check if the issuer has the Subject Key Identifier extension
338 const int indx = X509_get_ext_by_NID(issuerCert.get(), NID_subject_key_identifier, -1);
339 if (indx >= 0 && (ext = X509_get_ext(issuerCert.get(), indx))) {
340 issuerKeyId.reset((ASN1_OCTET_STRING *)X509V3_EXT_d2i(ext));
341 }
342 }
343
344 Ssl::X509_NAME_Pointer issuerName;
345 Ssl::ASN1_INT_Pointer issuerSerial;
346 if (issuerKeyId.get() == nullptr || addIssuer) {
347 issuerName.reset(X509_NAME_dup(X509_get_issuer_name(issuerCert.get())));
2a268a06 348 issuerSerial.reset(ASN1_INTEGER_dup(X509_get_serialNumber(issuerCert.get())));
5f1318b1
CT
349 }
350
351 Ssl::AUTHORITY_KEYID_Pointer theAuthKeyId(AUTHORITY_KEYID_new());
352 if (!theAuthKeyId.get())
353 return false;
354 theAuthKeyId.get()->keyid = issuerKeyId.release();
355 if (issuerName && issuerSerial) {
356 Ssl::GENERAL_NAME_STACK_Pointer genNames(sk_GENERAL_NAME_new_null());
357 if (genNames.get()) {
358 if (GENERAL_NAME *aname = GENERAL_NAME_new()) {
359 sk_GENERAL_NAME_push(genNames.get(), aname);
360 aname->type = GEN_DIRNAME;
361 aname->d.dirn = issuerName.release();
362 theAuthKeyId.get()->issuer = genNames.release();
363 theAuthKeyId.get()->serial = issuerSerial.release();
364 }
365 }
366 }
367
368 // The Authority Key Identifier extension should include KeyId or/and both
369 /// issuer name and issuer serial
370 if (!theAuthKeyId.get()->keyid && (!theAuthKeyId.get()->issuer || !theAuthKeyId.get()->serial))
371 return false;
372
373 const X509V3_EXT_METHOD *method = X509V3_EXT_get_nid(NID_authority_key_identifier);
374 if (!method)
375 return false;
376
aee3523a 377 unsigned char *ext_der = nullptr;
5f1318b1 378 int ext_len = ASN1_item_i2d((ASN1_VALUE *)theAuthKeyId.get(), &ext_der, ASN1_ITEM_ptr(method->it));
2a268a06 379 Ssl::ASN1_OCTET_STRING_Pointer extOct(ASN1_OCTET_STRING_new());
5f1318b1
CT
380 extOct.get()->data = ext_der;
381 extOct.get()->length = ext_len;
aee3523a 382 Ssl::X509_EXTENSION_Pointer extAuthKeyId(X509_EXTENSION_create_by_NID(nullptr, NID_authority_key_identifier, 0, extOct.get()));
5f1318b1
CT
383 if (!extAuthKeyId.get())
384 return false;
385
386 extOct.release();
387 if (!X509_add_ext(cert.get(), extAuthKeyId.get(), -1))
388 return false;
389
390 return true;
391}
392
5c80eab2
CT
393/// Copy certificate extensions from cert to mimicCert.
394/// Returns the number of extensions copied.
bee6354e
CT
395// Currently only extensions which are reported by the users that required are
396// mimicked. More safe to mimic extensions would be added here if users request
397// them.
5c80eab2 398static int
5f1318b1 399mimicExtensions(Security::CertPointer & cert, Security::CertPointer const &mimicCert, Security::CertPointer const &issuerCert)
bee6354e
CT
400{
401 static int extensions[]= {
402 NID_key_usage,
dcc9214e 403 NID_ext_key_usage,
bee6354e
CT
404 NID_basic_constraints,
405 0
406 };
407
789bf810
CT
408 // key usage bit names
409 enum {
410 DigitalSignature,
411 NonRepudiation,
412 KeyEncipherment, // NSS requires for RSA but not EC
413 DataEncipherment,
414 KeyAgreement,
415 KeyCertificateSign,
416 CRLSign,
417 EncipherOnly,
418 DecipherOnly
419 };
420
6e70401d
AR
421 // XXX: Add PublicKeyPointer. In OpenSSL, public and private keys are
422 // internally represented by EVP_PKEY pair, but GnuTLS uses distinct types.
423 const Security::PrivateKeyPointer certKey(X509_get_pubkey(mimicCert.get()));
424 const auto rsaPkey = EVP_PKEY_get0_RSA(certKey.get()) != nullptr;
2a268a06 425
5c80eab2 426 int added = 0;
bee6354e
CT
427 int nid;
428 for (int i = 0; (nid = extensions[i]) != 0; ++i) {
429 const int pos = X509_get_ext_by_NID(mimicCert.get(), nid, -1);
789bf810
CT
430 if (X509_EXTENSION *ext = X509_get_ext(mimicCert.get(), pos)) {
431 // Mimic extension exactly.
5c80eab2
CT
432 if (X509_add_ext(cert.get(), ext, -1))
433 ++added;
2a268a06 434 if (nid == NID_key_usage && !rsaPkey) {
2f8abb64 435 // NSS does not require the KeyEncipherment flag on EC keys
789bf810
CT
436 // but it does require it for RSA keys. Since ssl-bump
437 // substitutes RSA keys for EC ones, we need to ensure that
438 // that the more stringent requirements are met.
439
440 const int p = X509_get_ext_by_NID(cert.get(), NID_key_usage, -1);
aee3523a 441 if ((ext = X509_get_ext(cert.get(), p)) != nullptr) {
789bf810
CT
442 ASN1_BIT_STRING *keyusage = (ASN1_BIT_STRING *)X509V3_EXT_d2i(ext);
443 ASN1_BIT_STRING_set_bit(keyusage, KeyEncipherment, 1);
e061c75e
CT
444
445 //Build the ASN1_OCTET_STRING
446 const X509V3_EXT_METHOD *method = X509V3_EXT_get(ext);
447 assert(method && method->it);
aee3523a 448 unsigned char *ext_der = nullptr;
e061c75e 449 int ext_len = ASN1_item_i2d((ASN1_VALUE *)keyusage,
f53969cc 450 &ext_der,
e061c75e
CT
451 (const ASN1_ITEM *)ASN1_ITEM_ptr(method->it));
452
2a268a06 453 ASN1_OCTET_STRING *ext_oct = ASN1_OCTET_STRING_new();
e061c75e
CT
454 ext_oct->data = ext_der;
455 ext_oct->length = ext_len;
456 X509_EXTENSION_set_data(ext, ext_oct);
457
2a268a06 458 ASN1_OCTET_STRING_free(ext_oct);
789bf810
CT
459 ASN1_BIT_STRING_free(keyusage);
460 }
461 }
462 }
bee6354e
CT
463 }
464
5f1318b1
CT
465 if (mimicAuthorityKeyId(cert, mimicCert, issuerCert))
466 ++added;
467
bee6354e
CT
468 // We could also restrict mimicking of the CA extension to CA:FALSE
469 // because Squid does not generate valid fake CA certificates.
5c80eab2
CT
470
471 return added;
bee6354e
CT
472}
473
add2db46
CT
474/// Adds a new subjectAltName extension contining Subject CN or returns false
475/// expects the caller to check for the existing subjectAltName extension
476static bool
477addAltNameWithSubjectCn(Security::CertPointer &cert)
478{
479 X509_NAME *name = X509_get_subject_name(cert.get());
480 if (!name)
481 return false;
482
483 const int loc = X509_NAME_get_index_by_NID(name, NID_commonName, -1);
484 if (loc < 0)
485 return false;
486
487 ASN1_STRING *cn_data = X509_NAME_ENTRY_get_data(X509_NAME_get_entry(name, loc));
488 if (!cn_data)
489 return false;
490
491 char dnsName[1024]; // DNS names are limited to 256 characters
492 const int res = snprintf(dnsName, sizeof(dnsName), "DNS:%*s", cn_data->length, cn_data->data);
493 if (res <= 0 || res >= static_cast<int>(sizeof(dnsName)))
494 return false;
495
aee3523a 496 X509_EXTENSION *ext = X509V3_EXT_conf_nid(nullptr, nullptr, NID_subject_alt_name, dnsName);
add2db46
CT
497 if (!ext)
498 return false;
499
500 const bool result = X509_add_ext(cert.get(), ext, -1);
501
502 X509_EXTENSION_free(ext);
503 return result;
504}
505
f97700a0 506static bool buildCertificate(Security::CertPointer & cert, Ssl::CertificateProperties const &properties)
87f237a9 507{
9a90aace
CT
508 // not an Ssl::X509_NAME_Pointer because X509_REQ_get_subject_name()
509 // returns a pointer to the existing subject name. Nothing to clean here.
aebe6888 510 if (properties.mimicCert.get()) {
0d57adf9
CT
511 // Leave subject empty if we cannot extract it from true cert.
512 if (X509_NAME *name = X509_get_subject_name(properties.mimicCert.get())) {
87f237a9 513 // X509_set_subject_name will call X509_dup for name
5367d845
CT
514 X509_set_subject_name(cert.get(), name);
515 }
aebe6888
CT
516 }
517
518 if (properties.setCommonName || !properties.mimicCert.get()) {
519 // In this case the CN of the certificate given by the user
bf94620c 520 // Ignore errors: it is better to make a certificate with no CN
051da40c 521 // than to quit ssl-crtd helper because we cannot make a certificate.
bf94620c
CT
522 // Most errors are caused by user input such as huge domain names.
523 (void)replaceCommonName(cert, properties.commonName);
fb2178bb 524 }
9a90aace 525
87f237a9 526 // We should get caCert notBefore and notAfter fields and do not allow
9a90aace
CT
527 // notBefore/notAfter values from certToMimic before/after notBefore/notAfter
528 // fields from caCert.
87f237a9 529 // Currently there is not any way in openssl tollkit to compare two ASN1_TIME
9a90aace 530 // objects.
aee3523a 531 ASN1_TIME *aTime = nullptr;
aebe6888 532 if (!properties.setValidBefore && properties.mimicCert.get())
24b30fdc 533 aTime = X509_getm_notBefore(properties.mimicCert.get());
aebe6888 534 if (!aTime && properties.signWithX509.get())
24b30fdc 535 aTime = X509_getm_notBefore(properties.signWithX509.get());
fb2178bb
CT
536
537 if (aTime) {
24b30fdc 538 if (!X509_set1_notBefore(cert.get(), aTime))
9a90aace 539 return false;
24b30fdc 540 } else if (!X509_gmtime_adj(X509_getm_notBefore(cert.get()), (-2)*24*60*60))
9a90aace
CT
541 return false;
542
aee3523a 543 aTime = nullptr;
aebe6888 544 if (!properties.setValidAfter && properties.mimicCert.get())
24b30fdc 545 aTime = X509_getm_notAfter(properties.mimicCert.get());
aebe6888 546 if (!aTime && properties.signWithX509.get())
24b30fdc 547 aTime = X509_getm_notAfter(properties.signWithX509.get());
fb2178bb 548 if (aTime) {
24b30fdc 549 if (!X509_set1_notAfter(cert.get(), aTime))
b0137cd1 550 return false;
95bbbcc6 551 } else if (!X509_gmtime_adj(X509_getm_notAfter(cert.get()), 60*60*24*365*3))
b0137cd1 552 return false;
9a90aace 553
add2db46
CT
554 int addedExtensions = 0;
555 bool useCommonNameAsAltName = true;
ad88633d 556 // mimic the alias and possibly subjectAltName
aebe6888
CT
557 if (properties.mimicCert.get()) {
558 unsigned char *alStr;
559 int alLen;
560 alStr = X509_alias_get0(properties.mimicCert.get(), &alLen);
561 if (alStr) {
562 X509_alias_set1(cert.get(), alStr, alLen);
563 }
564
ad88633d
AR
565 // Mimic subjectAltName unless we used a configured CN: browsers reject
566 // certificates with CN unrelated to subjectAltNames.
3b7ed55f 567 if (!properties.setCommonName) {
add2db46 568 int pos = X509_get_ext_by_NID(properties.mimicCert.get(), NID_subject_alt_name, -1);
87f237a9 569 X509_EXTENSION *ext=X509_get_ext(properties.mimicCert.get(), pos);
4a874fbd 570 if (ext) {
5c80eab2
CT
571 if (X509_add_ext(cert.get(), ext, -1))
572 ++addedExtensions;
4a874fbd 573 }
add2db46
CT
574 // We want to mimic the server-sent subjectAltName, not enhance it.
575 useCommonNameAsAltName = false;
3b7ed55f 576 }
bee6354e 577
5f1318b1 578 addedExtensions += mimicExtensions(cert, properties.mimicCert, properties.signWithX509);
aebe6888 579 }
9a90aace 580
add2db46
CT
581 if (useCommonNameAsAltName && addAltNameWithSubjectCn(cert))
582 ++addedExtensions;
583
584 // According to RFC 5280, using extensions requires v3 certificate.
585 if (addedExtensions)
586 X509_set_version(cert.get(), 2); // value 2 means v3
587
9a90aace
CT
588 return true;
589}
590
cf487124 591static bool generateFakeSslCertificate(Security::CertPointer & certToStore, Security::PrivateKeyPointer & pkeyToStore, Ssl::CertificateProperties const &properties, Ssl::BIGNUM_Pointer const &serial)
9a90aace 592{
cf487124 593 Security::PrivateKeyPointer pkey;
95588170
CT
594 // Use signing certificates private key as generated certificate private key
595 if (properties.signWithPkey.get())
596 pkey.resetAndLock(properties.signWithPkey.get());
597 else // if not exist generate one
35b3559c 598 pkey.resetWithoutLocking(Ssl::createSslPrivateKey());
95588170 599
9a90aace
CT
600 if (!pkey)
601 return false;
602
f97700a0 603 Security::CertPointer cert(X509_new());
9a90aace
CT
604 if (!cert)
605 return false;
606
607 // Set pub key and serial given by the caller
608 if (!X509_set_pubkey(cert.get(), pkey.get()))
609 return false;
a0b971d5 610 if (!setSerialNumber(X509_get_serialNumber(cert.get()), serial.get()))
9a90aace
CT
611 return false;
612
aebe6888
CT
613 // Fill the certificate with the required properties
614 if (!buildCertificate(cert, properties))
9a90aace
CT
615 return false;
616
aebe6888 617 int ret = 0;
9a90aace 618 // Set issuer name, from CA or our subject name for self signed cert
aebe6888
CT
619 if (properties.signAlgorithm != Ssl::algSignSelf && properties.signWithX509.get())
620 ret = X509_set_issuer_name(cert.get(), X509_get_subject_name(properties.signWithX509.get()));
621 else // Self signed certificate, set issuer to self
622 ret = X509_set_issuer_name(cert.get(), X509_get_subject_name(cert.get()));
623 if (!ret)
9a90aace
CT
624 return false;
625
3c26b00a
CT
626 const EVP_MD *hash = properties.signHash ? properties.signHash : EVP_get_digestbyname(SQUID_SSL_SIGN_HASH_IF_NONE);
627 assert(hash);
9a90aace 628 /*Now sign the request */
aebe6888 629 if (properties.signAlgorithm != Ssl::algSignSelf && properties.signWithPkey.get())
3c26b00a 630 ret = X509_sign(cert.get(), properties.signWithPkey.get(), hash);
9a90aace 631 else //else sign with self key (self signed request)
3c26b00a 632 ret = X509_sign(cert.get(), pkey.get(), hash);
9a90aace
CT
633
634 if (!ret)
635 return false;
636
35b3559c
AJ
637 certToStore = std::move(cert);
638 pkeyToStore = std::move(pkey);
9a90aace
CT
639 return true;
640}
641
4ece76b2
CT
642static BIGNUM *createCertSerial(unsigned char *md, unsigned int n)
643{
87f237a9 644
4ece76b2
CT
645 assert(n == 20); //for sha1 n is 20 (for md5 n is 16)
646
aee3523a
AR
647 BIGNUM *serial = nullptr;
648 serial = BN_bin2bn(md, n, nullptr);
4ece76b2
CT
649
650 // if the serial is "0" set it to '1'
b9bb9562 651 if (BN_is_zero(serial) == true)
4ece76b2
CT
652 BN_one(serial);
653
c5bd24d6
CT
654 // serial size does not exceed 20 bytes
655 assert(BN_num_bits(serial) <= 160);
656
4ece76b2
CT
657 // According the RFC 5280, serial is an 20 bytes ASN.1 INTEGER (a signed big integer)
658 // and the maximum value for X.509 certificate serial number is 2^159-1 and
659 // the minimum 0. If the first bit of the serial is '1' ( eg 2^160-1),
660 // will result to a negative integer.
661 // To handle this, if the produced serial is greater than 2^159-1
662 // truncate the last bit
663 if (BN_is_bit_set(serial, 159))
664 BN_clear_bit(serial, 159);
665
666 return serial;
667}
668
a0b971d5
CT
669/// Return the SHA1 digest of the DER encoded version of the certificate
670/// stored in a BIGNUM
f97700a0 671static BIGNUM *x509Digest(Security::CertPointer const & cert)
a0b971d5
CT
672{
673 unsigned int n;
674 unsigned char md[EVP_MAX_MD_SIZE];
675
676 if (!X509_digest(cert.get(),EVP_sha1(),md,&n))
aee3523a 677 return nullptr;
a0b971d5 678
4ece76b2
CT
679 return createCertSerial(md, n);
680}
681
f97700a0 682static BIGNUM *x509Pubkeydigest(Security::CertPointer const & cert)
4ece76b2
CT
683{
684 unsigned int n;
685 unsigned char md[EVP_MAX_MD_SIZE];
686
687 if (!X509_pubkey_digest(cert.get(),EVP_sha1(),md,&n))
aee3523a 688 return nullptr;
a0b971d5 689
4ece76b2 690 return createCertSerial(md, n);
a0b971d5
CT
691}
692
87f237a9
A
693/// Generate a unique serial number based on a Ssl::CertificateProperties object
694/// for a new generated certificate
a0b971d5
CT
695static bool createSerial(Ssl::BIGNUM_Pointer &serial, Ssl::CertificateProperties const &properties)
696{
cf487124 697 Security::PrivateKeyPointer fakePkey;
f97700a0 698 Security::CertPointer fakeCert;
a0b971d5 699
4ece76b2 700 serial.reset(x509Pubkeydigest(properties.signWithX509));
5cc307f3
CT
701 if (!serial.get()) {
702 serial.reset(BN_new());
0e62e0d6 703 BN_zero(serial.get());
5cc307f3 704 }
4ece76b2 705
a0b971d5
CT
706 if (!generateFakeSslCertificate(fakeCert, fakePkey, properties, serial))
707 return false;
708
709 // The x509Fingerprint return an SHA1 hash.
710 // both SHA1 hash and maximum serial number size are 20 bytes.
4ece76b2 711 BIGNUM *r = x509Digest(fakeCert);
a0b971d5
CT
712 if (!r)
713 return false;
714
a0b971d5
CT
715 serial.reset(r);
716 return true;
717}
718
cf487124 719bool Ssl::generateSslCertificate(Security::CertPointer & certToStore, Security::PrivateKeyPointer & pkeyToStore, Ssl::CertificateProperties const &properties)
a0b971d5
CT
720{
721 Ssl::BIGNUM_Pointer serial;
722
723 if (!createSerial(serial, properties))
724 return false;
725
726 return generateFakeSslCertificate(certToStore, pkeyToStore, properties, serial);
727}
728
5107d2c4
CT
729bool
730Ssl::OpenCertsFileForReading(Ssl::BIO_Pointer &bio, const char *filename)
95d2589c 731{
5107d2c4 732 bio.reset(BIO_new(BIO_s_file()));
95d2589c 733 if (!bio)
5107d2c4
CT
734 return false;
735 if (!BIO_read_filename(bio.get(), filename))
736 return false;
737 return true;
95d2589c
CT
738}
739
b05c1954 740Security::CertPointer
ac1b16b5 741Ssl::ReadOptionalCertificate(const BIO_Pointer &bio)
5107d2c4 742{
ac1b16b5
AR
743 Assure(bio);
744 ForgetErrors();
745 if (const auto cert = PEM_read_bio_X509(bio.get(), nullptr, nullptr, nullptr))
746 return Security::CertPointer(cert);
747 const auto savedErrno = errno;
748
749 // PEM_R_NO_START_LINE means OpenSSL could not find a BEGIN CERTIFICATE
750 // marker after successfully reading input. That includes such use cases as
751 // empty input, valid input exhausted by previous extractions, malformed
752 // input, and valid key-only input without the certificate. We cannot
753 // distinguish all these outcomes and treat this error as an EOF condition.
754 if (ERR_GET_REASON(ERR_peek_last_error()) == PEM_R_NO_START_LINE) {
755 // consume PEM_R_NO_START_LINE to clean global error queue (if that was
756 // the only error) and/or to let us check for other errors (otherwise)
757 (void)ERR_get_error();
758 if (!ERR_peek_last_error())
759 return nullptr; // EOF without any other errors
760 }
761
762 ThrowErrors("cannot read a PEM-encoded certificate", savedErrno, Here());
763}
764
765Security::CertPointer
766Ssl::ReadCertificate(const BIO_Pointer &bio)
767{
768 if (const auto cert = ReadOptionalCertificate(bio))
769 return cert;
770
771 // PEM_R_NO_START_LINE
772 throw TextException("missing a required PEM-encoded certificate", Here());
5107d2c4
CT
773}
774
775bool
cf487124 776Ssl::ReadPrivateKey(Ssl::BIO_Pointer &bio, Security::PrivateKeyPointer &pkey, pem_password_cb *passwd_callback)
5107d2c4
CT
777{
778 assert(bio);
aee3523a 779 if (EVP_PKEY *akey = PEM_read_bio_PrivateKey(bio.get(), nullptr, passwd_callback, nullptr)) {
5107d2c4
CT
780 pkey.resetWithoutLocking(akey);
781 return true;
782 }
783 return false;
784}
785
786void
cf487124 787Ssl::ReadPrivateKeyFromFile(char const * keyFilename, Security::PrivateKeyPointer &pkey, pem_password_cb *passwd_callback)
95d2589c
CT
788{
789 if (!keyFilename)
5107d2c4
CT
790 return;
791 Ssl::BIO_Pointer bio;
792 if (!OpenCertsFileForReading(bio, keyFilename))
793 return;
794 ReadPrivateKey(bio, pkey, passwd_callback);
795}
796
797bool
798Ssl::OpenCertsFileForWriting(Ssl::BIO_Pointer &bio, const char *filename)
799{
800 bio.reset(BIO_new(BIO_s_file()));
95d2589c 801 if (!bio)
5107d2c4
CT
802 return false;
803 if (!BIO_write_filename(bio.get(), const_cast<char *>(filename)))
804 return false;
805 return true;
95d2589c
CT
806}
807
5107d2c4
CT
808bool
809Ssl::WriteX509Certificate(Ssl::BIO_Pointer &bio, const Security::CertPointer & cert)
95d2589c 810{
5107d2c4
CT
811 if (!cert || !bio)
812 return false;
813 if (!PEM_write_bio_X509(bio.get(), cert.get()))
814 return false;
815 return true;
816}
817
818bool
cf487124 819Ssl::WritePrivateKey(Ssl::BIO_Pointer &bio, const Security::PrivateKeyPointer &pkey)
5107d2c4
CT
820{
821 if (!pkey || !bio)
822 return false;
aee3523a 823 if (!PEM_write_bio_PrivateKey(bio.get(), pkey.get(), nullptr, nullptr, 0, nullptr, nullptr))
5107d2c4
CT
824 return false;
825 return true;
95d2589c
CT
826}
827
907831e6
AR
828Ssl::UniqueCString
829Ssl::OneLineSummary(X509_NAME &name)
830{
831 return Ssl::UniqueCString(X509_NAME_oneline(&name, nullptr, 0));
832}
833
95d2589c
CT
834bool Ssl::sslDateIsInTheFuture(char const * date)
835{
836 ASN1_UTCTIME tm;
837 tm.flags = 0;
838 tm.type = 23;
839 tm.data = (unsigned char *)date;
840 tm.length = strlen(date);
841
842 return (X509_cmp_current_time(&tm) > 0);
843}
e7bcc25f
CT
844
845/// Print the time represented by a ASN1_TIME struct to a string using GeneralizedTime format
846static bool asn1timeToGeneralizedTimeStr(ASN1_TIME *aTime, char *buf, int bufLen)
847{
87f237a9 848 // ASN1_Time holds time to UTCTime or GeneralizedTime form.
e7bcc25f
CT
849 // UTCTime has the form YYMMDDHHMMSS[Z | [+|-]offset]
850 // GeneralizedTime has the form YYYYMMDDHHMMSS[Z | [+|-] offset]
851
852 // length should have space for data plus 2 extra bytes for the two extra year fields
853 // plus the '\0' char.
854 if ((aTime->length + 3) > bufLen)
855 return false;
856
857 char *str;
858 if (aTime->type == V_ASN1_UTCTIME) {
859 if (aTime->data[0] > '5') { // RFC 2459, section 4.1.2.5.1
860 buf[0] = '1';
861 buf[1] = '9';
862 } else {
863 buf[0] = '2';
864 buf[1] = '0';
865 }
866 str = buf +2;
87f237a9 867 } else // if (aTime->type == V_ASN1_GENERALIZEDTIME)
e7bcc25f
CT
868 str = buf;
869
870 memcpy(str, aTime->data, aTime->length);
871 str[aTime->length] = '\0';
872 return true;
873}
874
875static int asn1time_cmp(ASN1_TIME *asnTime1, ASN1_TIME *asnTime2)
876{
877 char strTime1[64], strTime2[64];
878 if (!asn1timeToGeneralizedTimeStr(asnTime1, strTime1, sizeof(strTime1)))
879 return -1;
880 if (!asn1timeToGeneralizedTimeStr(asnTime2, strTime2, sizeof(strTime2)))
881 return -1;
87f237a9 882
e7bcc25f
CT
883 return strcmp(strTime1, strTime2);
884}
885
4ece76b2 886bool Ssl::certificateMatchesProperties(X509 *cert, CertificateProperties const &properties)
e7bcc25f 887{
4ece76b2
CT
888 assert(cert);
889
890 // For non self-signed certificates we have to check if the signing certificate changed
891 if (properties.signAlgorithm != Ssl::algSignSelf) {
f4e4d4d6 892 assert(properties.signWithX509.get());
4ece76b2
CT
893 if (X509_check_issued(properties.signWithX509.get(), cert) != X509_V_OK)
894 return false;
895 }
87f237a9 896
4ece76b2
CT
897 X509 *cert2 = properties.mimicCert.get();
898 // If there is not certificate to mimic stop here
899 if (!cert2)
900 return true;
901
902 if (!properties.setCommonName) {
903 X509_NAME *cert1_name = X509_get_subject_name(cert);
904 X509_NAME *cert2_name = X509_get_subject_name(cert2);
905 if (X509_NAME_cmp(cert1_name, cert2_name) != 0)
906 return false;
87f237a9
A
907 } else if (properties.commonName != CommonHostName(cert))
908 return false;
909
4ece76b2 910 if (!properties.setValidBefore) {
24b30fdc
EQ
911 const auto aTime = X509_getm_notBefore(cert);
912 const auto bTime = X509_getm_notBefore(cert2);
4ece76b2
CT
913 if (asn1time_cmp(aTime, bTime) != 0)
914 return false;
24b30fdc 915 } else if (X509_cmp_current_time(X509_getm_notBefore(cert)) >= 0) {
0efa4d01
CT
916 // notBefore does not exist (=0) or it is in the future (>0)
917 return false;
4ece76b2 918 }
e7bcc25f 919
4ece76b2 920 if (!properties.setValidAfter) {
24b30fdc
EQ
921 const auto aTime = X509_getm_notAfter(cert);
922 const auto bTime = X509_getm_notAfter(cert2);
4ece76b2
CT
923 if (asn1time_cmp(aTime, bTime) != 0)
924 return false;
24b30fdc 925 } else if (X509_cmp_current_time(X509_getm_notAfter(cert)) <= 0) {
0efa4d01
CT
926 // notAfter does not exist (0) or it is in the past (<0)
927 return false;
4ece76b2 928 }
0efa4d01 929
e7bcc25f
CT
930 char *alStr1;
931 int alLen;
4ece76b2 932 alStr1 = (char *)X509_alias_get0(cert, &alLen);
e7bcc25f
CT
933 char *alStr2 = (char *)X509_alias_get0(cert2, &alLen);
934 if ((!alStr1 && alStr2) || (alStr1 && !alStr2) ||
87f237a9 935 (alStr1 && alStr2 && strcmp(alStr1, alStr2)) != 0)
e7bcc25f 936 return false;
87f237a9 937
e7bcc25f
CT
938 // Compare subjectAltName extension
939 STACK_OF(GENERAL_NAME) * cert1_altnames;
aee3523a 940 cert1_altnames = (STACK_OF(GENERAL_NAME)*)X509_get_ext_d2i(cert, NID_subject_alt_name, nullptr, nullptr);
e7bcc25f 941 STACK_OF(GENERAL_NAME) * cert2_altnames;
aee3523a 942 cert2_altnames = (STACK_OF(GENERAL_NAME)*)X509_get_ext_d2i(cert2, NID_subject_alt_name, nullptr, nullptr);
e7bcc25f
CT
943 bool match = true;
944 if (cert1_altnames) {
945 int numalts = sk_GENERAL_NAME_num(cert1_altnames);
a38ec4b1 946 for (int i = 0; match && i < numalts; ++i) {
2a268a06 947 GENERAL_NAME *aName = sk_GENERAL_NAME_value(cert1_altnames, i);
e7bcc25f
CT
948 match = sk_GENERAL_NAME_find(cert2_altnames, aName);
949 }
87f237a9 950 } else if (cert2_altnames)
e7bcc25f 951 match = false;
87f237a9 952
e7bcc25f
CT
953 sk_GENERAL_NAME_pop_free(cert1_altnames, GENERAL_NAME_free);
954 sk_GENERAL_NAME_pop_free(cert2_altnames, GENERAL_NAME_free);
955
956 return match;
957}
0efa4d01
CT
958
959static const char *getSubjectEntry(X509 *x509, int nid)
960{
961 static char name[1024] = ""; // stores common name (CN)
962
963 if (!x509)
aee3523a 964 return nullptr;
0efa4d01
CT
965
966 // TODO: What if the entry is a UTF8String? See X509_NAME_get_index_by_NID(3ssl).
967 const int nameLen = X509_NAME_get_text_by_NID(
87f237a9
A
968 X509_get_subject_name(x509),
969 nid, name, sizeof(name));
0efa4d01
CT
970
971 if (nameLen > 0)
972 return name;
973
aee3523a 974 return nullptr;
0efa4d01
CT
975}
976
977const char *Ssl::CommonHostName(X509 *x509)
978{
979 return getSubjectEntry(x509, NID_commonName);
980}
981
982const char *Ssl::getOrganization(X509 *x509)
983{
984 return getSubjectEntry(x509, NID_organizationName);
985}
986
5107d2c4
CT
987bool
988Ssl::CertificatesCmp(const Security::CertPointer &cert1, const Security::CertPointer &cert2)
989{
990 if (!cert1 || ! cert2)
991 return false;
992
993 int cert1Len;
aee3523a 994 unsigned char *cert1Asn = nullptr;
5107d2c4
CT
995 cert1Len = ASN1_item_i2d((ASN1_VALUE *)cert1.get(), &cert1Asn, ASN1_ITEM_rptr(X509));
996
997 int cert2Len;
aee3523a 998 unsigned char *cert2Asn = nullptr;
5107d2c4
CT
999 cert2Len = ASN1_item_i2d((ASN1_VALUE *)cert2.get(), &cert2Asn, ASN1_ITEM_rptr(X509));
1000
1001 if (cert1Len != cert2Len)
1002 return false;
1003
1004 bool ret = (memcmp(cert1Asn, cert2Asn, cert1Len) == 0);
1005
1006 OPENSSL_free(cert1Asn);
1007 OPENSSL_free(cert2Asn);
1008
1009 return ret;
1010}
70cfe22f
AJ
1011
1012const ASN1_BIT_STRING *
1013Ssl::X509_get_signature(const Security::CertPointer &cert)
1014{
24b30fdc
EQ
1015 SQUID_CONST_X509_GET0_SIGNATURE_ARGS ASN1_BIT_STRING *sig = nullptr;
1016 SQUID_CONST_X509_GET0_SIGNATURE_ARGS X509_ALGOR *sig_alg = nullptr;
1017
70cfe22f
AJ
1018 X509_get0_signature(&sig, &sig_alg, cert.get());
1019 return sig;
70cfe22f 1020}
62b9cc19 1021