2 * Copyright (C) 1996-2017 The Squid Software Foundation and contributors
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.
10 #include "ssl/gadgets.h"
12 #include <openssl/asn1.h>
13 #if HAVE_OPENSSL_X509V3_H
14 #include <openssl/x509v3.h>
17 EVP_PKEY
* Ssl::createSslPrivateKey()
19 Ssl::EVP_PKEY_Pointer
pkey(EVP_PKEY_new());
24 BIGNUM_Pointer
bn(BN_new());
28 if (!BN_set_word(bn
.get(), RSA_F4
))
31 Ssl::RSA_Pointer
rsa(RSA_new());
35 int num
= 2048; // Maybe use 4096 RSA keys, or better make it configurable?
36 if (!RSA_generate_key_ex(rsa
.get(), num
, bn
.get(), NULL
))
42 if (!EVP_PKEY_assign_RSA(pkey
.get(), (rsa
.get())))
46 return pkey
.release();
50 \ingroup ServerProtocolSSLInternal
51 * Set serial random serial number or set random serial number.
53 static bool setSerialNumber(ASN1_INTEGER
*ai
, BIGNUM
const* serial
)
57 Ssl::BIGNUM_Pointer
bn(BN_new());
59 bn
.reset(BN_dup(serial
));
64 if (!BN_pseudo_rand(bn
.get(), 64, 0, 0))
68 if (ai
&& !BN_to_ASN1_INTEGER(bn
.get(), ai
))
73 bool Ssl::writeCertAndPrivateKeyToMemory(Security::CertPointer
const & cert
, Ssl::EVP_PKEY_Pointer
const & pkey
, std::string
& bufferToWrite
)
75 bufferToWrite
.clear();
78 BIO_Pointer
bio(BIO_new(BIO_s_mem()));
82 if (!PEM_write_bio_X509 (bio
.get(), cert
.get()))
85 if (!PEM_write_bio_PrivateKey(bio
.get(), pkey
.get(), NULL
, NULL
, 0, NULL
, NULL
))
89 long len
= BIO_get_mem_data(bio
.get(), &ptr
);
93 bufferToWrite
= std::string(ptr
, len
);
97 bool Ssl::appendCertToMemory(Security::CertPointer
const & cert
, std::string
& bufferToWrite
)
102 BIO_Pointer
bio(BIO_new(BIO_s_mem()));
106 if (!PEM_write_bio_X509 (bio
.get(), cert
.get()))
110 long len
= BIO_get_mem_data(bio
.get(), &ptr
);
114 if (!bufferToWrite
.empty())
115 bufferToWrite
.append(" "); // add a space...
117 bufferToWrite
.append(ptr
, len
);
121 bool Ssl::readCertAndPrivateKeyFromMemory(Security::CertPointer
& cert
, Ssl::EVP_PKEY_Pointer
& pkey
, char const * bufferToRead
)
123 Ssl::BIO_Pointer
bio(BIO_new(BIO_s_mem()));
124 BIO_puts(bio
.get(), bufferToRead
);
126 X509
* certPtr
= NULL
;
127 cert
.resetWithoutLocking(PEM_read_bio_X509(bio
.get(), &certPtr
, 0, 0));
131 EVP_PKEY
* pkeyPtr
= NULL
;
132 pkey
.resetWithoutLocking(PEM_read_bio_PrivateKey(bio
.get(), &pkeyPtr
, 0, 0));
139 bool Ssl::readCertFromMemory(Security::CertPointer
& cert
, char const * bufferToRead
)
141 Ssl::BIO_Pointer
bio(BIO_new(BIO_s_mem()));
142 BIO_puts(bio
.get(), bufferToRead
);
144 X509
* certPtr
= NULL
;
145 cert
.resetWithoutLocking(PEM_read_bio_X509(bio
.get(), &certPtr
, 0, 0));
152 // According to RFC 5280 (Section A.1), the common name length in a certificate
153 // can be at most 64 characters
154 static const size_t MaxCnLen
= 64;
156 // Replace certs common name with the given
157 static bool replaceCommonName(Security::CertPointer
& cert
, std::string
const &rawCn
)
159 std::string cn
= rawCn
;
161 if (cn
.length() > MaxCnLen
) {
162 // In the case the length od CN is more than the maximum supported size
163 // try to use the first upper level domain.
166 pos
= cn
.find('.', pos
+ 1);
167 } while (pos
!= std::string::npos
&& (cn
.length() - pos
+ 2) > MaxCnLen
);
169 // If no short domain found or this domain is a toplevel domain
170 // we failed to find a good cn name.
171 if (pos
== std::string::npos
|| cn
.find('.', pos
+ 1) == std::string::npos
)
174 std::string
fixedCn(1, '*');
175 fixedCn
.append(cn
.c_str() + pos
);
179 // Assume [] surround an IPv6 address and strip them because browsers such
180 // as Firefox, Chromium, and Safari prefer bare IPv6 addresses in CNs.
181 if (cn
.length() > 2 && *cn
.begin() == '[' && *cn
.rbegin() == ']')
182 cn
= cn
.substr(1, cn
.size()-2);
184 X509_NAME
*name
= X509_get_subject_name(cert
.get());
187 // Remove the CN part:
188 int loc
= X509_NAME_get_index_by_NID(name
, NID_commonName
, -1);
190 X509_NAME_ENTRY
*tmp
= X509_NAME_get_entry(name
, loc
);
191 X509_NAME_delete_entry(name
, loc
);
192 X509_NAME_ENTRY_free(tmp
);
196 return X509_NAME_add_entry_by_NID(name
, NID_commonName
, MBSTRING_ASC
,
197 (unsigned char *)(cn
.c_str()), -1, -1, 0);
200 const char *Ssl::CertSignAlgorithmStr
[] = {
207 const char *Ssl::CertAdaptAlgorithmStr
[] = {
214 Ssl::CertificateProperties::CertificateProperties():
215 setValidAfter(false),
216 setValidBefore(false),
217 setCommonName(false),
218 signAlgorithm(Ssl::algSignEnd
),
223 printX509Signature(const Security::CertPointer
&cert
, std::string
&out
)
225 const ASN1_BIT_STRING
*sig
= Ssl::X509_get_signature(cert
);
226 if (sig
&& sig
->data
) {
227 const unsigned char *s
= sig
->data
;
228 for (int i
= 0; i
< sig
->length
; ++i
) {
230 snprintf(hex
, sizeof(hex
), "%02x", s
[i
]);
237 Ssl::OnDiskCertificateDbKey(const Ssl::CertificateProperties
&properties
)
239 static std::string certKey
;
241 certKey
.reserve(4096);
242 if (properties
.mimicCert
.get())
243 printX509Signature(properties
.mimicCert
, certKey
);
245 if (certKey
.empty()) {
246 certKey
.append("/CN=", 4);
247 certKey
.append(properties
.commonName
);
250 if (properties
.setValidAfter
)
251 certKey
.append("+SetValidAfter=on", 17);
253 if (properties
.setValidBefore
)
254 certKey
.append("+SetValidBefore=on", 18);
256 if (properties
.setCommonName
) {
257 certKey
.append("+SetCommonName=", 15);
258 certKey
.append(properties
.commonName
);
261 if (properties
.signAlgorithm
!= Ssl::algSignEnd
) {
262 certKey
.append("+Sign=", 6);
263 certKey
.append(certSignAlgorithm(properties
.signAlgorithm
));
266 if (properties
.signHash
!= NULL
) {
267 certKey
.append("+SignHash=", 10);
268 certKey
.append(EVP_MD_name(properties
.signHash
));
274 /// Check if mimicCert certificate has the Authority Key Identifier extension
275 /// and if yes add the extension to cert certificate with the same fields if
276 /// possible. If the issuerCert certificate does not have the Subject Key
277 /// Identifier extension (required to build the keyIdentifier field of
278 /// AuthorityKeyIdentifier) then the authorityCertIssuer and
279 /// authorityCertSerialNumber fields added.
281 mimicAuthorityKeyId(Security::CertPointer
&cert
, Security::CertPointer
const &mimicCert
, Security::CertPointer
const &issuerCert
)
283 if (!mimicCert
.get() || !issuerCert
.get())
286 Ssl::AUTHORITY_KEYID_Pointer
akid((AUTHORITY_KEYID
*)X509_get_ext_d2i(mimicCert
.get(), NID_authority_key_identifier
, nullptr, nullptr));
288 bool addKeyId
= false, addIssuer
= false;
290 addKeyId
= (akid
.get()->keyid
!= nullptr);
291 addIssuer
= (akid
.get()->issuer
&& akid
.get()->serial
);
294 if (!addKeyId
&& !addIssuer
)
295 return false; // No need to add AuthorityKeyIdentifier
297 Ssl::ASN1_OCTET_STRING_Pointer issuerKeyId
;
300 // Check if the issuer has the Subject Key Identifier extension
301 const int indx
= X509_get_ext_by_NID(issuerCert
.get(), NID_subject_key_identifier
, -1);
302 if (indx
>= 0 && (ext
= X509_get_ext(issuerCert
.get(), indx
))) {
303 issuerKeyId
.reset((ASN1_OCTET_STRING
*)X509V3_EXT_d2i(ext
));
307 Ssl::X509_NAME_Pointer issuerName
;
308 Ssl::ASN1_INT_Pointer issuerSerial
;
309 if (issuerKeyId
.get() == nullptr || addIssuer
) {
310 issuerName
.reset(X509_NAME_dup(X509_get_issuer_name(issuerCert
.get())));
311 issuerSerial
.reset(ASN1_INTEGER_dup(X509_get_serialNumber(issuerCert
.get())));
314 Ssl::AUTHORITY_KEYID_Pointer
theAuthKeyId(AUTHORITY_KEYID_new());
315 if (!theAuthKeyId
.get())
317 theAuthKeyId
.get()->keyid
= issuerKeyId
.release();
318 if (issuerName
&& issuerSerial
) {
319 Ssl::GENERAL_NAME_STACK_Pointer
genNames(sk_GENERAL_NAME_new_null());
320 if (genNames
.get()) {
321 if (GENERAL_NAME
*aname
= GENERAL_NAME_new()) {
322 sk_GENERAL_NAME_push(genNames
.get(), aname
);
323 aname
->type
= GEN_DIRNAME
;
324 aname
->d
.dirn
= issuerName
.release();
325 theAuthKeyId
.get()->issuer
= genNames
.release();
326 theAuthKeyId
.get()->serial
= issuerSerial
.release();
331 // The Authority Key Identifier extension should include KeyId or/and both
332 /// issuer name and issuer serial
333 if (!theAuthKeyId
.get()->keyid
&& (!theAuthKeyId
.get()->issuer
|| !theAuthKeyId
.get()->serial
))
336 const X509V3_EXT_METHOD
*method
= X509V3_EXT_get_nid(NID_authority_key_identifier
);
340 unsigned char *ext_der
= NULL
;
341 int ext_len
= ASN1_item_i2d((ASN1_VALUE
*)theAuthKeyId
.get(), &ext_der
, ASN1_ITEM_ptr(method
->it
));
342 Ssl::ASN1_OCTET_STRING_Pointer
extOct(ASN1_OCTET_STRING_new());
343 extOct
.get()->data
= ext_der
;
344 extOct
.get()->length
= ext_len
;
345 Ssl::X509_EXTENSION_Pointer
extAuthKeyId(X509_EXTENSION_create_by_NID(NULL
, NID_authority_key_identifier
, 0, extOct
.get()));
346 if (!extAuthKeyId
.get())
350 if (!X509_add_ext(cert
.get(), extAuthKeyId
.get(), -1))
356 /// Copy certificate extensions from cert to mimicCert.
357 /// Returns the number of extensions copied.
358 // Currently only extensions which are reported by the users that required are
359 // mimicked. More safe to mimic extensions would be added here if users request
362 mimicExtensions(Security::CertPointer
& cert
, Security::CertPointer
const &mimicCert
, Security::CertPointer
const &issuerCert
)
364 static int extensions
[]= {
367 NID_basic_constraints
,
371 // key usage bit names
375 KeyEncipherment
, // NSS requires for RSA but not EC
384 #if HAVE_LIBCRYPTO_EVP_PKEY_GET0_RSA
385 EVP_PKEY
*certKey
= X509_get_pubkey(mimicCert
.get());
386 const bool rsaPkey
= (EVP_PKEY_get0_RSA(certKey
) != nullptr);
388 const int mimicAlgo
= OBJ_obj2nid(mimicCert
.get()->cert_info
->key
->algor
->algorithm
);
389 const bool rsaPkey
= (mimicAlgo
== NID_rsaEncryption
);
394 for (int i
= 0; (nid
= extensions
[i
]) != 0; ++i
) {
395 const int pos
= X509_get_ext_by_NID(mimicCert
.get(), nid
, -1);
396 if (X509_EXTENSION
*ext
= X509_get_ext(mimicCert
.get(), pos
)) {
397 // Mimic extension exactly.
398 if (X509_add_ext(cert
.get(), ext
, -1))
400 if (nid
== NID_key_usage
&& !rsaPkey
) {
401 // NSS does not requre the KeyEncipherment flag on EC keys
402 // but it does require it for RSA keys. Since ssl-bump
403 // substitutes RSA keys for EC ones, we need to ensure that
404 // that the more stringent requirements are met.
406 const int p
= X509_get_ext_by_NID(cert
.get(), NID_key_usage
, -1);
407 if ((ext
= X509_get_ext(cert
.get(), p
)) != NULL
) {
408 ASN1_BIT_STRING
*keyusage
= (ASN1_BIT_STRING
*)X509V3_EXT_d2i(ext
);
409 ASN1_BIT_STRING_set_bit(keyusage
, KeyEncipherment
, 1);
411 //Build the ASN1_OCTET_STRING
412 const X509V3_EXT_METHOD
*method
= X509V3_EXT_get(ext
);
413 assert(method
&& method
->it
);
414 unsigned char *ext_der
= NULL
;
415 int ext_len
= ASN1_item_i2d((ASN1_VALUE
*)keyusage
,
417 (const ASN1_ITEM
*)ASN1_ITEM_ptr(method
->it
));
419 ASN1_OCTET_STRING
*ext_oct
= ASN1_OCTET_STRING_new();
420 ext_oct
->data
= ext_der
;
421 ext_oct
->length
= ext_len
;
422 X509_EXTENSION_set_data(ext
, ext_oct
);
424 ASN1_OCTET_STRING_free(ext_oct
);
425 ASN1_BIT_STRING_free(keyusage
);
431 if (mimicAuthorityKeyId(cert
, mimicCert
, issuerCert
))
434 // We could also restrict mimicking of the CA extension to CA:FALSE
435 // because Squid does not generate valid fake CA certificates.
440 /// Adds a new subjectAltName extension contining Subject CN or returns false
441 /// expects the caller to check for the existing subjectAltName extension
443 addAltNameWithSubjectCn(Security::CertPointer
&cert
)
445 X509_NAME
*name
= X509_get_subject_name(cert
.get());
449 const int loc
= X509_NAME_get_index_by_NID(name
, NID_commonName
, -1);
453 ASN1_STRING
*cn_data
= X509_NAME_ENTRY_get_data(X509_NAME_get_entry(name
, loc
));
457 char dnsName
[1024]; // DNS names are limited to 256 characters
458 const int res
= snprintf(dnsName
, sizeof(dnsName
), "DNS:%*s", cn_data
->length
, cn_data
->data
);
459 if (res
<= 0 || res
>= static_cast<int>(sizeof(dnsName
)))
462 X509_EXTENSION
*ext
= X509V3_EXT_conf_nid(NULL
, NULL
, NID_subject_alt_name
, dnsName
);
466 const bool result
= X509_add_ext(cert
.get(), ext
, -1);
468 X509_EXTENSION_free(ext
);
472 static bool buildCertificate(Security::CertPointer
& cert
, Ssl::CertificateProperties
const &properties
)
474 // not an Ssl::X509_NAME_Pointer because X509_REQ_get_subject_name()
475 // returns a pointer to the existing subject name. Nothing to clean here.
476 if (properties
.mimicCert
.get()) {
477 // Leave subject empty if we cannot extract it from true cert.
478 if (X509_NAME
*name
= X509_get_subject_name(properties
.mimicCert
.get())) {
479 // X509_set_subject_name will call X509_dup for name
480 X509_set_subject_name(cert
.get(), name
);
484 if (properties
.setCommonName
|| !properties
.mimicCert
.get()) {
485 // In this case the CN of the certificate given by the user
486 // Ignore errors: it is better to make a certificate with no CN
487 // than to quit ssl-crtd helper because we cannot make a certificate.
488 // Most errors are caused by user input such as huge domain names.
489 (void)replaceCommonName(cert
, properties
.commonName
);
492 // We should get caCert notBefore and notAfter fields and do not allow
493 // notBefore/notAfter values from certToMimic before/after notBefore/notAfter
494 // fields from caCert.
495 // Currently there is not any way in openssl tollkit to compare two ASN1_TIME
497 ASN1_TIME
*aTime
= NULL
;
498 if (!properties
.setValidBefore
&& properties
.mimicCert
.get())
499 aTime
= X509_get_notBefore(properties
.mimicCert
.get());
500 if (!aTime
&& properties
.signWithX509
.get())
501 aTime
= X509_get_notBefore(properties
.signWithX509
.get());
504 if (!X509_set_notBefore(cert
.get(), aTime
))
506 } else if (!X509_gmtime_adj(X509_get_notBefore(cert
.get()), (-2)*24*60*60))
510 if (!properties
.setValidAfter
&& properties
.mimicCert
.get())
511 aTime
= X509_get_notAfter(properties
.mimicCert
.get());
512 if (!aTime
&& properties
.signWithX509
.get())
513 aTime
= X509_get_notAfter(properties
.signWithX509
.get());
515 if (!X509_set_notAfter(cert
.get(), aTime
))
517 } else if (!X509_gmtime_adj(X509_get_notAfter(cert
.get()), 60*60*24*356*3))
520 int addedExtensions
= 0;
521 bool useCommonNameAsAltName
= true;
522 // mimic the alias and possibly subjectAltName
523 if (properties
.mimicCert
.get()) {
524 unsigned char *alStr
;
526 alStr
= X509_alias_get0(properties
.mimicCert
.get(), &alLen
);
528 X509_alias_set1(cert
.get(), alStr
, alLen
);
531 // Mimic subjectAltName unless we used a configured CN: browsers reject
532 // certificates with CN unrelated to subjectAltNames.
533 if (!properties
.setCommonName
) {
534 int pos
= X509_get_ext_by_NID(properties
.mimicCert
.get(), NID_subject_alt_name
, -1);
535 X509_EXTENSION
*ext
=X509_get_ext(properties
.mimicCert
.get(), pos
);
537 if (X509_add_ext(cert
.get(), ext
, -1))
540 // We want to mimic the server-sent subjectAltName, not enhance it.
541 useCommonNameAsAltName
= false;
544 addedExtensions
+= mimicExtensions(cert
, properties
.mimicCert
, properties
.signWithX509
);
547 if (useCommonNameAsAltName
&& addAltNameWithSubjectCn(cert
))
550 // According to RFC 5280, using extensions requires v3 certificate.
552 X509_set_version(cert
.get(), 2); // value 2 means v3
557 static bool generateFakeSslCertificate(Security::CertPointer
& certToStore
, Ssl::EVP_PKEY_Pointer
& pkeyToStore
, Ssl::CertificateProperties
const &properties
, Ssl::BIGNUM_Pointer
const &serial
)
559 Ssl::EVP_PKEY_Pointer pkey
;
560 // Use signing certificates private key as generated certificate private key
561 if (properties
.signWithPkey
.get())
562 pkey
.resetAndLock(properties
.signWithPkey
.get());
563 else // if not exist generate one
564 pkey
.resetWithoutLocking(Ssl::createSslPrivateKey());
569 Security::CertPointer
cert(X509_new());
573 // Set pub key and serial given by the caller
574 if (!X509_set_pubkey(cert
.get(), pkey
.get()))
576 if (!setSerialNumber(X509_get_serialNumber(cert
.get()), serial
.get()))
579 // Fill the certificate with the required properties
580 if (!buildCertificate(cert
, properties
))
584 // Set issuer name, from CA or our subject name for self signed cert
585 if (properties
.signAlgorithm
!= Ssl::algSignSelf
&& properties
.signWithX509
.get())
586 ret
= X509_set_issuer_name(cert
.get(), X509_get_subject_name(properties
.signWithX509
.get()));
587 else // Self signed certificate, set issuer to self
588 ret
= X509_set_issuer_name(cert
.get(), X509_get_subject_name(cert
.get()));
592 const EVP_MD
*hash
= properties
.signHash
? properties
.signHash
: EVP_get_digestbyname(SQUID_SSL_SIGN_HASH_IF_NONE
);
594 /*Now sign the request */
595 if (properties
.signAlgorithm
!= Ssl::algSignSelf
&& properties
.signWithPkey
.get())
596 ret
= X509_sign(cert
.get(), properties
.signWithPkey
.get(), hash
);
597 else //else sign with self key (self signed request)
598 ret
= X509_sign(cert
.get(), pkey
.get(), hash
);
603 certToStore
= std::move(cert
);
604 pkeyToStore
= std::move(pkey
);
608 static BIGNUM
*createCertSerial(unsigned char *md
, unsigned int n
)
611 assert(n
== 20); //for sha1 n is 20 (for md5 n is 16)
613 BIGNUM
*serial
= NULL
;
614 serial
= BN_bin2bn(md
, n
, NULL
);
616 // if the serial is "0" set it to '1'
617 if (BN_is_zero(serial
) == true)
620 // serial size does not exceed 20 bytes
621 assert(BN_num_bits(serial
) <= 160);
623 // According the RFC 5280, serial is an 20 bytes ASN.1 INTEGER (a signed big integer)
624 // and the maximum value for X.509 certificate serial number is 2^159-1 and
625 // the minimum 0. If the first bit of the serial is '1' ( eg 2^160-1),
626 // will result to a negative integer.
627 // To handle this, if the produced serial is greater than 2^159-1
628 // truncate the last bit
629 if (BN_is_bit_set(serial
, 159))
630 BN_clear_bit(serial
, 159);
635 /// Return the SHA1 digest of the DER encoded version of the certificate
636 /// stored in a BIGNUM
637 static BIGNUM
*x509Digest(Security::CertPointer
const & cert
)
640 unsigned char md
[EVP_MAX_MD_SIZE
];
642 if (!X509_digest(cert
.get(),EVP_sha1(),md
,&n
))
645 return createCertSerial(md
, n
);
648 static BIGNUM
*x509Pubkeydigest(Security::CertPointer
const & cert
)
651 unsigned char md
[EVP_MAX_MD_SIZE
];
653 if (!X509_pubkey_digest(cert
.get(),EVP_sha1(),md
,&n
))
656 return createCertSerial(md
, n
);
659 /// Generate a unique serial number based on a Ssl::CertificateProperties object
660 /// for a new generated certificate
661 static bool createSerial(Ssl::BIGNUM_Pointer
&serial
, Ssl::CertificateProperties
const &properties
)
663 Ssl::EVP_PKEY_Pointer fakePkey
;
664 Security::CertPointer fakeCert
;
666 serial
.reset(x509Pubkeydigest(properties
.signWithX509
));
668 serial
.reset(BN_new());
669 BN_zero(serial
.get());
672 if (!generateFakeSslCertificate(fakeCert
, fakePkey
, properties
, serial
))
675 // The x509Fingerprint return an SHA1 hash.
676 // both SHA1 hash and maximum serial number size are 20 bytes.
677 BIGNUM
*r
= x509Digest(fakeCert
);
685 bool Ssl::generateSslCertificate(Security::CertPointer
& certToStore
, Ssl::EVP_PKEY_Pointer
& pkeyToStore
, Ssl::CertificateProperties
const &properties
)
687 Ssl::BIGNUM_Pointer serial
;
689 if (!createSerial(serial
, properties
))
692 return generateFakeSslCertificate(certToStore
, pkeyToStore
, properties
, serial
);
696 Ssl::OpenCertsFileForReading(Ssl::BIO_Pointer
&bio
, const char *filename
)
698 bio
.reset(BIO_new(BIO_s_file()));
701 if (!BIO_read_filename(bio
.get(), filename
))
707 Ssl::ReadX509Certificate(Ssl::BIO_Pointer
&bio
, Security::CertPointer
& cert
)
710 if (X509
*certificate
= PEM_read_bio_X509(bio
.get(), NULL
, NULL
, NULL
)) {
711 cert
.resetWithoutLocking(certificate
);
718 Ssl::ReadPrivateKey(Ssl::BIO_Pointer
&bio
, Ssl::EVP_PKEY_Pointer
&pkey
, pem_password_cb
*passwd_callback
)
721 if (EVP_PKEY
*akey
= PEM_read_bio_PrivateKey(bio
.get(), NULL
, passwd_callback
, NULL
)) {
722 pkey
.resetWithoutLocking(akey
);
729 Ssl::ReadPrivateKeyFromFile(char const * keyFilename
, Ssl::EVP_PKEY_Pointer
&pkey
, pem_password_cb
*passwd_callback
)
733 Ssl::BIO_Pointer bio
;
734 if (!OpenCertsFileForReading(bio
, keyFilename
))
736 ReadPrivateKey(bio
, pkey
, passwd_callback
);
740 Ssl::OpenCertsFileForWriting(Ssl::BIO_Pointer
&bio
, const char *filename
)
742 bio
.reset(BIO_new(BIO_s_file()));
745 if (!BIO_write_filename(bio
.get(), const_cast<char *>(filename
)))
751 Ssl::WriteX509Certificate(Ssl::BIO_Pointer
&bio
, const Security::CertPointer
& cert
)
755 if (!PEM_write_bio_X509(bio
.get(), cert
.get()))
761 Ssl::WritePrivateKey(Ssl::BIO_Pointer
&bio
, const Ssl::EVP_PKEY_Pointer
&pkey
)
765 if (!PEM_write_bio_PrivateKey(bio
.get(), pkey
.get(), NULL
, NULL
, 0, NULL
, NULL
))
770 bool Ssl::sslDateIsInTheFuture(char const * date
)
775 tm
.data
= (unsigned char *)date
;
776 tm
.length
= strlen(date
);
778 return (X509_cmp_current_time(&tm
) > 0);
781 /// Print the time represented by a ASN1_TIME struct to a string using GeneralizedTime format
782 static bool asn1timeToGeneralizedTimeStr(ASN1_TIME
*aTime
, char *buf
, int bufLen
)
784 // ASN1_Time holds time to UTCTime or GeneralizedTime form.
785 // UTCTime has the form YYMMDDHHMMSS[Z | [+|-]offset]
786 // GeneralizedTime has the form YYYYMMDDHHMMSS[Z | [+|-] offset]
788 // length should have space for data plus 2 extra bytes for the two extra year fields
789 // plus the '\0' char.
790 if ((aTime
->length
+ 3) > bufLen
)
794 if (aTime
->type
== V_ASN1_UTCTIME
) {
795 if (aTime
->data
[0] > '5') { // RFC 2459, section 4.1.2.5.1
803 } else // if (aTime->type == V_ASN1_GENERALIZEDTIME)
806 memcpy(str
, aTime
->data
, aTime
->length
);
807 str
[aTime
->length
] = '\0';
811 static int asn1time_cmp(ASN1_TIME
*asnTime1
, ASN1_TIME
*asnTime2
)
813 char strTime1
[64], strTime2
[64];
814 if (!asn1timeToGeneralizedTimeStr(asnTime1
, strTime1
, sizeof(strTime1
)))
816 if (!asn1timeToGeneralizedTimeStr(asnTime2
, strTime2
, sizeof(strTime2
)))
819 return strcmp(strTime1
, strTime2
);
822 bool Ssl::certificateMatchesProperties(X509
*cert
, CertificateProperties
const &properties
)
826 // For non self-signed certificates we have to check if the signing certificate changed
827 if (properties
.signAlgorithm
!= Ssl::algSignSelf
) {
828 assert(properties
.signWithX509
.get());
829 if (X509_check_issued(properties
.signWithX509
.get(), cert
) != X509_V_OK
)
833 X509
*cert2
= properties
.mimicCert
.get();
834 // If there is not certificate to mimic stop here
838 if (!properties
.setCommonName
) {
839 X509_NAME
*cert1_name
= X509_get_subject_name(cert
);
840 X509_NAME
*cert2_name
= X509_get_subject_name(cert2
);
841 if (X509_NAME_cmp(cert1_name
, cert2_name
) != 0)
843 } else if (properties
.commonName
!= CommonHostName(cert
))
846 if (!properties
.setValidBefore
) {
847 ASN1_TIME
*aTime
= X509_get_notBefore(cert
);
848 ASN1_TIME
*bTime
= X509_get_notBefore(cert2
);
849 if (asn1time_cmp(aTime
, bTime
) != 0)
851 } else if (X509_cmp_current_time(X509_get_notBefore(cert
)) >= 0) {
852 // notBefore does not exist (=0) or it is in the future (>0)
856 if (!properties
.setValidAfter
) {
857 ASN1_TIME
*aTime
= X509_get_notAfter(cert
);
858 ASN1_TIME
*bTime
= X509_get_notAfter(cert2
);
859 if (asn1time_cmp(aTime
, bTime
) != 0)
861 } else if (X509_cmp_current_time(X509_get_notAfter(cert
)) <= 0) {
862 // notAfter does not exist (0) or it is in the past (<0)
868 alStr1
= (char *)X509_alias_get0(cert
, &alLen
);
869 char *alStr2
= (char *)X509_alias_get0(cert2
, &alLen
);
870 if ((!alStr1
&& alStr2
) || (alStr1
&& !alStr2
) ||
871 (alStr1
&& alStr2
&& strcmp(alStr1
, alStr2
)) != 0)
874 // Compare subjectAltName extension
875 STACK_OF(GENERAL_NAME
) * cert1_altnames
;
876 cert1_altnames
= (STACK_OF(GENERAL_NAME
)*)X509_get_ext_d2i(cert
, NID_subject_alt_name
, NULL
, NULL
);
877 STACK_OF(GENERAL_NAME
) * cert2_altnames
;
878 cert2_altnames
= (STACK_OF(GENERAL_NAME
)*)X509_get_ext_d2i(cert2
, NID_subject_alt_name
, NULL
, NULL
);
880 if (cert1_altnames
) {
881 int numalts
= sk_GENERAL_NAME_num(cert1_altnames
);
882 for (int i
= 0; match
&& i
< numalts
; ++i
) {
883 GENERAL_NAME
*aName
= sk_GENERAL_NAME_value(cert1_altnames
, i
);
884 match
= sk_GENERAL_NAME_find(cert2_altnames
, aName
);
886 } else if (cert2_altnames
)
889 sk_GENERAL_NAME_pop_free(cert1_altnames
, GENERAL_NAME_free
);
890 sk_GENERAL_NAME_pop_free(cert2_altnames
, GENERAL_NAME_free
);
895 static const char *getSubjectEntry(X509
*x509
, int nid
)
897 static char name
[1024] = ""; // stores common name (CN)
902 // TODO: What if the entry is a UTF8String? See X509_NAME_get_index_by_NID(3ssl).
903 const int nameLen
= X509_NAME_get_text_by_NID(
904 X509_get_subject_name(x509
),
905 nid
, name
, sizeof(name
));
913 const char *Ssl::CommonHostName(X509
*x509
)
915 return getSubjectEntry(x509
, NID_commonName
);
918 const char *Ssl::getOrganization(X509
*x509
)
920 return getSubjectEntry(x509
, NID_organizationName
);
924 Ssl::CertificatesCmp(const Security::CertPointer
&cert1
, const Security::CertPointer
&cert2
)
926 if (!cert1
|| ! cert2
)
930 unsigned char *cert1Asn
= NULL
;
931 cert1Len
= ASN1_item_i2d((ASN1_VALUE
*)cert1
.get(), &cert1Asn
, ASN1_ITEM_rptr(X509
));
934 unsigned char *cert2Asn
= NULL
;
935 cert2Len
= ASN1_item_i2d((ASN1_VALUE
*)cert2
.get(), &cert2Asn
, ASN1_ITEM_rptr(X509
));
937 if (cert1Len
!= cert2Len
)
940 bool ret
= (memcmp(cert1Asn
, cert2Asn
, cert1Len
) == 0);
942 OPENSSL_free(cert1Asn
);
943 OPENSSL_free(cert2Asn
);
948 const ASN1_BIT_STRING
*
949 Ssl::X509_get_signature(const Security::CertPointer
&cert
)
951 #if HAVE_LIBCRYPTO_X509_GET0_SIGNATURE
952 #if SQUID_USE_CONST_X509_GET0_SIGNATURE_ARGS
953 const ASN1_BIT_STRING
*sig
= nullptr;
954 const X509_ALGOR
*sig_alg
= nullptr;
956 ASN1_BIT_STRING
*sig
= nullptr;
957 X509_ALGOR
*sig_alg
= nullptr;
959 X509_get0_signature(&sig
, &sig_alg
, cert
.get());
962 return cert
->signature
;