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