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