]> git.ipfire.org Git - thirdparty/squid.git/blame - src/ssl/gadgets.cc
SourceFormat Enforcement (#68)
[thirdparty/squid.git] / src / ssl / gadgets.cc
CommitLineData
bbc27441 1/*
4ac4a490 2 * Copyright (C) 1996-2017 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"
95d2589c 10#include "ssl/gadgets.h"
cb4f4424 11
5107d2c4 12#include <openssl/asn1.h>
a594dbfa
CT
13#if HAVE_OPENSSL_X509V3_H
14#include <openssl/x509v3.h>
15#endif
95d2589c 16
95d2589c
CT
17EVP_PKEY * Ssl::createSslPrivateKey()
18{
19 Ssl::EVP_PKEY_Pointer pkey(EVP_PKEY_new());
20
21 if (!pkey)
22 return NULL;
23
2a268a06
CT
24 BIGNUM_Pointer bn(BN_new());
25 if (!bn)
26 return NULL;
27
28 if (!BN_set_word(bn.get(), RSA_F4))
29 return NULL;
30
31 Ssl::RSA_Pointer rsa(RSA_new());
32 if (!rsa)
33 return NULL;
ac756c8c 34
2a268a06
CT
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))
37 return NULL;
95d2589c
CT
38
39 if (!rsa)
40 return NULL;
41
42 if (!EVP_PKEY_assign_RSA(pkey.get(), (rsa.get())))
43 return NULL;
44
45 rsa.release();
46 return pkey.release();
47}
48
95d2589c
CT
49/**
50 \ingroup ServerProtocolSSLInternal
51 * Set serial random serial number or set random serial number.
52 */
53static bool setSerialNumber(ASN1_INTEGER *ai, BIGNUM const* serial)
54{
55 if (!ai)
56 return false;
57 Ssl::BIGNUM_Pointer bn(BN_new());
58 if (serial) {
59 bn.reset(BN_dup(serial));
60 } else {
61 if (!bn)
62 return false;
63
64 if (!BN_pseudo_rand(bn.get(), 64, 0, 0))
65 return false;
66 }
67
68 if (ai && !BN_to_ASN1_INTEGER(bn.get(), ai))
69 return false;
70 return true;
71}
72
f97700a0 73bool Ssl::writeCertAndPrivateKeyToMemory(Security::CertPointer const & cert, Ssl::EVP_PKEY_Pointer const & pkey, std::string & bufferToWrite)
95d2589c
CT
74{
75 bufferToWrite.clear();
76 if (!pkey || !cert)
77 return false;
78 BIO_Pointer bio(BIO_new(BIO_s_mem()));
79 if (!bio)
80 return false;
81
82 if (!PEM_write_bio_X509 (bio.get(), cert.get()))
83 return false;
84
85 if (!PEM_write_bio_PrivateKey(bio.get(), pkey.get(), NULL, NULL, 0, NULL, NULL))
86 return false;
87
88 char *ptr = NULL;
89 long len = BIO_get_mem_data(bio.get(), &ptr);
90 if (!ptr)
91 return false;
92
93 bufferToWrite = std::string(ptr, len);
94 return true;
95}
96
f97700a0 97bool Ssl::appendCertToMemory(Security::CertPointer const & cert, std::string & bufferToWrite)
9a90aace
CT
98{
99 if (!cert)
100 return false;
101
102 BIO_Pointer bio(BIO_new(BIO_s_mem()));
103 if (!bio)
104 return false;
105
106 if (!PEM_write_bio_X509 (bio.get(), cert.get()))
107 return false;
108
109 char *ptr = NULL;
110 long len = BIO_get_mem_data(bio.get(), &ptr);
111 if (!ptr)
112 return false;
113
87f237a9 114 if (!bufferToWrite.empty())
9a90aace
CT
115 bufferToWrite.append(" "); // add a space...
116
117 bufferToWrite.append(ptr, len);
118 return true;
119}
120
f97700a0 121bool Ssl::readCertAndPrivateKeyFromMemory(Security::CertPointer & cert, Ssl::EVP_PKEY_Pointer & pkey, char const * bufferToRead)
95d2589c
CT
122{
123 Ssl::BIO_Pointer bio(BIO_new(BIO_s_mem()));
124 BIO_puts(bio.get(), bufferToRead);
125
126 X509 * certPtr = NULL;
35b3559c 127 cert.resetWithoutLocking(PEM_read_bio_X509(bio.get(), &certPtr, 0, 0));
95d2589c
CT
128 if (!cert)
129 return false;
130
131 EVP_PKEY * pkeyPtr = NULL;
35b3559c 132 pkey.resetWithoutLocking(PEM_read_bio_PrivateKey(bio.get(), &pkeyPtr, 0, 0));
95d2589c
CT
133 if (!pkey)
134 return false;
135
136 return true;
137}
138
f97700a0 139bool Ssl::readCertFromMemory(Security::CertPointer & cert, char const * bufferToRead)
9a90aace
CT
140{
141 Ssl::BIO_Pointer bio(BIO_new(BIO_s_mem()));
142 BIO_puts(bio.get(), bufferToRead);
143
144 X509 * certPtr = NULL;
35b3559c 145 cert.resetWithoutLocking(PEM_read_bio_X509(bio.get(), &certPtr, 0, 0));
9a90aace
CT
146 if (!cert)
147 return false;
148
149 return true;
150}
151
bf94620c
CT
152// According to RFC 5280 (Section A.1), the common name length in a certificate
153// can be at most 64 characters
154static const size_t MaxCnLen = 64;
155
fb2178bb 156// Replace certs common name with the given
f97700a0 157static bool replaceCommonName(Security::CertPointer & cert, std::string const &rawCn)
fb2178bb 158{
4a962df3
AR
159 std::string cn = rawCn;
160
bf94620c
CT
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.
164 size_t pos = 0;
165 do {
166 pos = cn.find('.', pos + 1);
87f237a9 167 } while (pos != std::string::npos && (cn.length() - pos + 2) > MaxCnLen);
bf94620c
CT
168
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)
172 return false;
173
4a962df3 174 std::string fixedCn(1, '*');
bf94620c 175 fixedCn.append(cn.c_str() + pos);
4a962df3 176 cn = fixedCn;
bf94620c
CT
177 }
178
4a962df3
AR
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);
183
fb2178bb
CT
184 X509_NAME *name = X509_get_subject_name(cert.get());
185 if (!name)
186 return false;
187 // Remove the CN part:
188 int loc = X509_NAME_get_index_by_NID(name, NID_commonName, -1);
aebe6888
CT
189 if (loc >=0) {
190 X509_NAME_ENTRY *tmp = X509_NAME_get_entry(name, loc);
191 X509_NAME_delete_entry(name, loc);
192 X509_NAME_ENTRY_free(tmp);
193 }
fb2178bb
CT
194
195 // Add a new CN
196 return X509_NAME_add_entry_by_NID(name, NID_commonName, MBSTRING_ASC,
4a962df3 197 (unsigned char *)(cn.c_str()), -1, -1, 0);
fb2178bb
CT
198}
199
aebe6888
CT
200const char *Ssl::CertSignAlgorithmStr[] = {
201 "signTrusted",
87f237a9 202 "signUntrusted",
aebe6888
CT
203 "signSelf",
204 NULL
205};
206
fb2178bb
CT
207const char *Ssl::CertAdaptAlgorithmStr[] = {
208 "setValidAfter",
209 "setValidBefore",
210 "setCommonName",
211 NULL
212};
213
a0b971d5 214Ssl::CertificateProperties::CertificateProperties():
f53969cc
SM
215 setValidAfter(false),
216 setValidBefore(false),
217 setCommonName(false),
218 signAlgorithm(Ssl::algSignEnd),
219 signHash(NULL)
aebe6888
CT
220{}
221
5107d2c4
CT
222static void
223printX509Signature(const Security::CertPointer &cert, std::string &out)
224{
70cfe22f 225 const ASN1_BIT_STRING *sig = Ssl::X509_get_signature(cert);
5107d2c4
CT
226 if (sig && sig->data) {
227 const unsigned char *s = sig->data;
228 for (int i = 0; i < sig->length; ++i) {
229 char hex[3];
230 snprintf(hex, sizeof(hex), "%02x", s[i]);
231 out.append(hex);
232 }
233 }
234}
235
236std::string &
237Ssl::OnDiskCertificateDbKey(const Ssl::CertificateProperties &properties)
06997a38
CT
238{
239 static std::string certKey;
7fc31d31 240 certKey.clear();
06997a38 241 certKey.reserve(4096);
5107d2c4
CT
242 if (properties.mimicCert.get())
243 printX509Signature(properties.mimicCert, certKey);
06997a38 244
7fc31d31
AR
245 if (certKey.empty()) {
246 certKey.append("/CN=", 4);
5107d2c4 247 certKey.append(properties.commonName);
7fc31d31 248 }
06997a38 249
5107d2c4 250 if (properties.setValidAfter)
06997a38
CT
251 certKey.append("+SetValidAfter=on", 17);
252
5107d2c4 253 if (properties.setValidBefore)
06997a38
CT
254 certKey.append("+SetValidBefore=on", 18);
255
5107d2c4 256 if (properties.setCommonName) {
06997a38 257 certKey.append("+SetCommonName=", 15);
5107d2c4 258 certKey.append(properties.commonName);
06997a38
CT
259 }
260
5107d2c4 261 if (properties.signAlgorithm != Ssl::algSignEnd) {
06997a38 262 certKey.append("+Sign=", 6);
5107d2c4 263 certKey.append(certSignAlgorithm(properties.signAlgorithm));
06997a38
CT
264 }
265
5107d2c4 266 if (properties.signHash != NULL) {
3c26b00a 267 certKey.append("+SignHash=", 10);
5107d2c4 268 certKey.append(EVP_MD_name(properties.signHash));
3c26b00a
CT
269 }
270
06997a38
CT
271 return certKey;
272}
273
5f1318b1
CT
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
5ff0af8e 276/// possible. If the issuerCert certificate does not have the Subject Key
5f1318b1
CT
277/// Identifier extension (required to build the keyIdentifier field of
278/// AuthorityKeyIdentifier) then the authorityCertIssuer and
279/// authorityCertSerialNumber fields added.
280static bool
281mimicAuthorityKeyId(Security::CertPointer &cert, Security::CertPointer const &mimicCert, Security::CertPointer const &issuerCert)
282{
283 if (!mimicCert.get() || !issuerCert.get())
284 return false;
285
286 Ssl::AUTHORITY_KEYID_Pointer akid((AUTHORITY_KEYID *)X509_get_ext_d2i(mimicCert.get(), NID_authority_key_identifier, nullptr, nullptr));
287
288 bool addKeyId = false, addIssuer = false;
289 if (akid.get()) {
290 addKeyId = (akid.get()->keyid != nullptr);
291 addIssuer = (akid.get()->issuer && akid.get()->serial);
292 }
293
294 if (!addKeyId && !addIssuer)
295 return false; // No need to add AuthorityKeyIdentifier
296
297 Ssl::ASN1_OCTET_STRING_Pointer issuerKeyId;
298 if (addKeyId) {
299 X509_EXTENSION *ext;
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));
304 }
305 }
306
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())));
2a268a06 311 issuerSerial.reset(ASN1_INTEGER_dup(X509_get_serialNumber(issuerCert.get())));
5f1318b1
CT
312 }
313
314 Ssl::AUTHORITY_KEYID_Pointer theAuthKeyId(AUTHORITY_KEYID_new());
315 if (!theAuthKeyId.get())
316 return false;
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();
327 }
328 }
329 }
330
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))
334 return false;
335
336 const X509V3_EXT_METHOD *method = X509V3_EXT_get_nid(NID_authority_key_identifier);
337 if (!method)
338 return false;
339
340 unsigned char *ext_der = NULL;
341 int ext_len = ASN1_item_i2d((ASN1_VALUE *)theAuthKeyId.get(), &ext_der, ASN1_ITEM_ptr(method->it));
2a268a06 342 Ssl::ASN1_OCTET_STRING_Pointer extOct(ASN1_OCTET_STRING_new());
5f1318b1
CT
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())
347 return false;
348
349 extOct.release();
350 if (!X509_add_ext(cert.get(), extAuthKeyId.get(), -1))
351 return false;
352
353 return true;
354}
355
5c80eab2
CT
356/// Copy certificate extensions from cert to mimicCert.
357/// Returns the number of extensions copied.
bee6354e
CT
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
360// them.
5c80eab2 361static int
5f1318b1 362mimicExtensions(Security::CertPointer & cert, Security::CertPointer const &mimicCert, Security::CertPointer const &issuerCert)
bee6354e
CT
363{
364 static int extensions[]= {
365 NID_key_usage,
dcc9214e 366 NID_ext_key_usage,
bee6354e
CT
367 NID_basic_constraints,
368 0
369 };
370
789bf810
CT
371 // key usage bit names
372 enum {
373 DigitalSignature,
374 NonRepudiation,
375 KeyEncipherment, // NSS requires for RSA but not EC
376 DataEncipherment,
377 KeyAgreement,
378 KeyCertificateSign,
379 CRLSign,
380 EncipherOnly,
381 DecipherOnly
382 };
383
17e98f24
AJ
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);
387#else
2a268a06
CT
388 const int mimicAlgo = OBJ_obj2nid(mimicCert.get()->cert_info->key->algor->algorithm);
389 const bool rsaPkey = (mimicAlgo == NID_rsaEncryption);
2a268a06
CT
390#endif
391
5c80eab2 392 int added = 0;
bee6354e
CT
393 int nid;
394 for (int i = 0; (nid = extensions[i]) != 0; ++i) {
395 const int pos = X509_get_ext_by_NID(mimicCert.get(), nid, -1);
789bf810
CT
396 if (X509_EXTENSION *ext = X509_get_ext(mimicCert.get(), pos)) {
397 // Mimic extension exactly.
5c80eab2
CT
398 if (X509_add_ext(cert.get(), ext, -1))
399 ++added;
2a268a06 400 if (nid == NID_key_usage && !rsaPkey) {
789bf810
CT
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.
405
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);
e061c75e
CT
410
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,
f53969cc 416 &ext_der,
e061c75e
CT
417 (const ASN1_ITEM *)ASN1_ITEM_ptr(method->it));
418
2a268a06 419 ASN1_OCTET_STRING *ext_oct = ASN1_OCTET_STRING_new();
e061c75e
CT
420 ext_oct->data = ext_der;
421 ext_oct->length = ext_len;
422 X509_EXTENSION_set_data(ext, ext_oct);
423
2a268a06 424 ASN1_OCTET_STRING_free(ext_oct);
789bf810
CT
425 ASN1_BIT_STRING_free(keyusage);
426 }
427 }
428 }
bee6354e
CT
429 }
430
5f1318b1
CT
431 if (mimicAuthorityKeyId(cert, mimicCert, issuerCert))
432 ++added;
433
bee6354e
CT
434 // We could also restrict mimicking of the CA extension to CA:FALSE
435 // because Squid does not generate valid fake CA certificates.
5c80eab2
CT
436
437 return added;
bee6354e
CT
438}
439
add2db46
CT
440/// Adds a new subjectAltName extension contining Subject CN or returns false
441/// expects the caller to check for the existing subjectAltName extension
442static bool
443addAltNameWithSubjectCn(Security::CertPointer &cert)
444{
445 X509_NAME *name = X509_get_subject_name(cert.get());
446 if (!name)
447 return false;
448
449 const int loc = X509_NAME_get_index_by_NID(name, NID_commonName, -1);
450 if (loc < 0)
451 return false;
452
453 ASN1_STRING *cn_data = X509_NAME_ENTRY_get_data(X509_NAME_get_entry(name, loc));
454 if (!cn_data)
455 return false;
456
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)))
460 return false;
461
462 X509_EXTENSION *ext = X509V3_EXT_conf_nid(NULL, NULL, NID_subject_alt_name, dnsName);
463 if (!ext)
464 return false;
465
466 const bool result = X509_add_ext(cert.get(), ext, -1);
467
468 X509_EXTENSION_free(ext);
469 return result;
470}
471
f97700a0 472static bool buildCertificate(Security::CertPointer & cert, Ssl::CertificateProperties const &properties)
87f237a9 473{
9a90aace
CT
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.
aebe6888 476 if (properties.mimicCert.get()) {
0d57adf9
CT
477 // Leave subject empty if we cannot extract it from true cert.
478 if (X509_NAME *name = X509_get_subject_name(properties.mimicCert.get())) {
87f237a9 479 // X509_set_subject_name will call X509_dup for name
5367d845
CT
480 X509_set_subject_name(cert.get(), name);
481 }
aebe6888
CT
482 }
483
484 if (properties.setCommonName || !properties.mimicCert.get()) {
485 // In this case the CN of the certificate given by the user
bf94620c 486 // Ignore errors: it is better to make a certificate with no CN
051da40c 487 // than to quit ssl-crtd helper because we cannot make a certificate.
bf94620c
CT
488 // Most errors are caused by user input such as huge domain names.
489 (void)replaceCommonName(cert, properties.commonName);
fb2178bb 490 }
9a90aace 491
87f237a9 492 // We should get caCert notBefore and notAfter fields and do not allow
9a90aace
CT
493 // notBefore/notAfter values from certToMimic before/after notBefore/notAfter
494 // fields from caCert.
87f237a9 495 // Currently there is not any way in openssl tollkit to compare two ASN1_TIME
9a90aace 496 // objects.
fb2178bb 497 ASN1_TIME *aTime = NULL;
aebe6888
CT
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());
fb2178bb
CT
502
503 if (aTime) {
9a90aace
CT
504 if (!X509_set_notBefore(cert.get(), aTime))
505 return false;
87f237a9 506 } else if (!X509_gmtime_adj(X509_get_notBefore(cert.get()), (-2)*24*60*60))
9a90aace
CT
507 return false;
508
fb2178bb 509 aTime = NULL;
aebe6888
CT
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());
fb2178bb 514 if (aTime) {
9a90aace 515 if (!X509_set_notAfter(cert.get(), aTime))
b0137cd1 516 return false;
9a90aace 517 } else if (!X509_gmtime_adj(X509_get_notAfter(cert.get()), 60*60*24*356*3))
b0137cd1 518 return false;
9a90aace 519
add2db46
CT
520 int addedExtensions = 0;
521 bool useCommonNameAsAltName = true;
ad88633d 522 // mimic the alias and possibly subjectAltName
aebe6888
CT
523 if (properties.mimicCert.get()) {
524 unsigned char *alStr;
525 int alLen;
526 alStr = X509_alias_get0(properties.mimicCert.get(), &alLen);
527 if (alStr) {
528 X509_alias_set1(cert.get(), alStr, alLen);
529 }
530
ad88633d
AR
531 // Mimic subjectAltName unless we used a configured CN: browsers reject
532 // certificates with CN unrelated to subjectAltNames.
3b7ed55f 533 if (!properties.setCommonName) {
add2db46 534 int pos = X509_get_ext_by_NID(properties.mimicCert.get(), NID_subject_alt_name, -1);
87f237a9 535 X509_EXTENSION *ext=X509_get_ext(properties.mimicCert.get(), pos);
4a874fbd 536 if (ext) {
5c80eab2
CT
537 if (X509_add_ext(cert.get(), ext, -1))
538 ++addedExtensions;
4a874fbd 539 }
add2db46
CT
540 // We want to mimic the server-sent subjectAltName, not enhance it.
541 useCommonNameAsAltName = false;
3b7ed55f 542 }
bee6354e 543
5f1318b1 544 addedExtensions += mimicExtensions(cert, properties.mimicCert, properties.signWithX509);
aebe6888 545 }
9a90aace 546
add2db46
CT
547 if (useCommonNameAsAltName && addAltNameWithSubjectCn(cert))
548 ++addedExtensions;
549
550 // According to RFC 5280, using extensions requires v3 certificate.
551 if (addedExtensions)
552 X509_set_version(cert.get(), 2); // value 2 means v3
553
9a90aace
CT
554 return true;
555}
556
f97700a0 557static bool generateFakeSslCertificate(Security::CertPointer & certToStore, Ssl::EVP_PKEY_Pointer & pkeyToStore, Ssl::CertificateProperties const &properties, Ssl::BIGNUM_Pointer const &serial)
9a90aace 558{
aebe6888 559 Ssl::EVP_PKEY_Pointer pkey;
95588170
CT
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
35b3559c 564 pkey.resetWithoutLocking(Ssl::createSslPrivateKey());
95588170 565
9a90aace
CT
566 if (!pkey)
567 return false;
568
f97700a0 569 Security::CertPointer cert(X509_new());
9a90aace
CT
570 if (!cert)
571 return false;
572
573 // Set pub key and serial given by the caller
574 if (!X509_set_pubkey(cert.get(), pkey.get()))
575 return false;
a0b971d5 576 if (!setSerialNumber(X509_get_serialNumber(cert.get()), serial.get()))
9a90aace
CT
577 return false;
578
aebe6888
CT
579 // Fill the certificate with the required properties
580 if (!buildCertificate(cert, properties))
9a90aace
CT
581 return false;
582
aebe6888 583 int ret = 0;
9a90aace 584 // Set issuer name, from CA or our subject name for self signed cert
aebe6888
CT
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()));
589 if (!ret)
9a90aace
CT
590 return false;
591
3c26b00a
CT
592 const EVP_MD *hash = properties.signHash ? properties.signHash : EVP_get_digestbyname(SQUID_SSL_SIGN_HASH_IF_NONE);
593 assert(hash);
9a90aace 594 /*Now sign the request */
aebe6888 595 if (properties.signAlgorithm != Ssl::algSignSelf && properties.signWithPkey.get())
3c26b00a 596 ret = X509_sign(cert.get(), properties.signWithPkey.get(), hash);
9a90aace 597 else //else sign with self key (self signed request)
3c26b00a 598 ret = X509_sign(cert.get(), pkey.get(), hash);
9a90aace
CT
599
600 if (!ret)
601 return false;
602
35b3559c
AJ
603 certToStore = std::move(cert);
604 pkeyToStore = std::move(pkey);
9a90aace
CT
605 return true;
606}
607
4ece76b2
CT
608static BIGNUM *createCertSerial(unsigned char *md, unsigned int n)
609{
87f237a9 610
4ece76b2
CT
611 assert(n == 20); //for sha1 n is 20 (for md5 n is 16)
612
613 BIGNUM *serial = NULL;
614 serial = BN_bin2bn(md, n, NULL);
615
616 // if the serial is "0" set it to '1'
b9bb9562 617 if (BN_is_zero(serial) == true)
4ece76b2
CT
618 BN_one(serial);
619
c5bd24d6
CT
620 // serial size does not exceed 20 bytes
621 assert(BN_num_bits(serial) <= 160);
622
4ece76b2
CT
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);
631
632 return serial;
633}
634
a0b971d5
CT
635/// Return the SHA1 digest of the DER encoded version of the certificate
636/// stored in a BIGNUM
f97700a0 637static BIGNUM *x509Digest(Security::CertPointer const & cert)
a0b971d5
CT
638{
639 unsigned int n;
640 unsigned char md[EVP_MAX_MD_SIZE];
641
642 if (!X509_digest(cert.get(),EVP_sha1(),md,&n))
643 return NULL;
644
4ece76b2
CT
645 return createCertSerial(md, n);
646}
647
f97700a0 648static BIGNUM *x509Pubkeydigest(Security::CertPointer const & cert)
4ece76b2
CT
649{
650 unsigned int n;
651 unsigned char md[EVP_MAX_MD_SIZE];
652
653 if (!X509_pubkey_digest(cert.get(),EVP_sha1(),md,&n))
654 return NULL;
a0b971d5 655
4ece76b2 656 return createCertSerial(md, n);
a0b971d5
CT
657}
658
87f237a9
A
659/// Generate a unique serial number based on a Ssl::CertificateProperties object
660/// for a new generated certificate
a0b971d5
CT
661static bool createSerial(Ssl::BIGNUM_Pointer &serial, Ssl::CertificateProperties const &properties)
662{
663 Ssl::EVP_PKEY_Pointer fakePkey;
f97700a0 664 Security::CertPointer fakeCert;
a0b971d5 665
4ece76b2 666 serial.reset(x509Pubkeydigest(properties.signWithX509));
5cc307f3
CT
667 if (!serial.get()) {
668 serial.reset(BN_new());
0e62e0d6 669 BN_zero(serial.get());
5cc307f3 670 }
4ece76b2 671
a0b971d5
CT
672 if (!generateFakeSslCertificate(fakeCert, fakePkey, properties, serial))
673 return false;
674
675 // The x509Fingerprint return an SHA1 hash.
676 // both SHA1 hash and maximum serial number size are 20 bytes.
4ece76b2 677 BIGNUM *r = x509Digest(fakeCert);
a0b971d5
CT
678 if (!r)
679 return false;
680
a0b971d5
CT
681 serial.reset(r);
682 return true;
683}
684
f97700a0 685bool Ssl::generateSslCertificate(Security::CertPointer & certToStore, Ssl::EVP_PKEY_Pointer & pkeyToStore, Ssl::CertificateProperties const &properties)
a0b971d5
CT
686{
687 Ssl::BIGNUM_Pointer serial;
688
689 if (!createSerial(serial, properties))
690 return false;
691
692 return generateFakeSslCertificate(certToStore, pkeyToStore, properties, serial);
693}
694
5107d2c4
CT
695bool
696Ssl::OpenCertsFileForReading(Ssl::BIO_Pointer &bio, const char *filename)
95d2589c 697{
5107d2c4 698 bio.reset(BIO_new(BIO_s_file()));
95d2589c 699 if (!bio)
5107d2c4
CT
700 return false;
701 if (!BIO_read_filename(bio.get(), filename))
702 return false;
703 return true;
95d2589c
CT
704}
705
5107d2c4
CT
706bool
707Ssl::ReadX509Certificate(Ssl::BIO_Pointer &bio, Security::CertPointer & cert)
708{
709 assert(bio);
710 if (X509 *certificate = PEM_read_bio_X509(bio.get(), NULL, NULL, NULL)) {
711 cert.resetWithoutLocking(certificate);
712 return true;
713 }
714 return false;
715}
716
717bool
718Ssl::ReadPrivateKey(Ssl::BIO_Pointer &bio, Ssl::EVP_PKEY_Pointer &pkey, pem_password_cb *passwd_callback)
719{
720 assert(bio);
721 if (EVP_PKEY *akey = PEM_read_bio_PrivateKey(bio.get(), NULL, passwd_callback, NULL)) {
722 pkey.resetWithoutLocking(akey);
723 return true;
724 }
725 return false;
726}
727
728void
729Ssl::ReadPrivateKeyFromFile(char const * keyFilename, Ssl::EVP_PKEY_Pointer &pkey, pem_password_cb *passwd_callback)
95d2589c
CT
730{
731 if (!keyFilename)
5107d2c4
CT
732 return;
733 Ssl::BIO_Pointer bio;
734 if (!OpenCertsFileForReading(bio, keyFilename))
735 return;
736 ReadPrivateKey(bio, pkey, passwd_callback);
737}
738
739bool
740Ssl::OpenCertsFileForWriting(Ssl::BIO_Pointer &bio, const char *filename)
741{
742 bio.reset(BIO_new(BIO_s_file()));
95d2589c 743 if (!bio)
5107d2c4
CT
744 return false;
745 if (!BIO_write_filename(bio.get(), const_cast<char *>(filename)))
746 return false;
747 return true;
95d2589c
CT
748}
749
5107d2c4
CT
750bool
751Ssl::WriteX509Certificate(Ssl::BIO_Pointer &bio, const Security::CertPointer & cert)
95d2589c 752{
5107d2c4
CT
753 if (!cert || !bio)
754 return false;
755 if (!PEM_write_bio_X509(bio.get(), cert.get()))
756 return false;
757 return true;
758}
759
760bool
761Ssl::WritePrivateKey(Ssl::BIO_Pointer &bio, const Ssl::EVP_PKEY_Pointer &pkey)
762{
763 if (!pkey || !bio)
764 return false;
765 if (!PEM_write_bio_PrivateKey(bio.get(), pkey.get(), NULL, NULL, 0, NULL, NULL))
766 return false;
767 return true;
95d2589c
CT
768}
769
770bool Ssl::sslDateIsInTheFuture(char const * date)
771{
772 ASN1_UTCTIME tm;
773 tm.flags = 0;
774 tm.type = 23;
775 tm.data = (unsigned char *)date;
776 tm.length = strlen(date);
777
778 return (X509_cmp_current_time(&tm) > 0);
779}
e7bcc25f
CT
780
781/// Print the time represented by a ASN1_TIME struct to a string using GeneralizedTime format
782static bool asn1timeToGeneralizedTimeStr(ASN1_TIME *aTime, char *buf, int bufLen)
783{
87f237a9 784 // ASN1_Time holds time to UTCTime or GeneralizedTime form.
e7bcc25f
CT
785 // UTCTime has the form YYMMDDHHMMSS[Z | [+|-]offset]
786 // GeneralizedTime has the form YYYYMMDDHHMMSS[Z | [+|-] offset]
787
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)
791 return false;
792
793 char *str;
794 if (aTime->type == V_ASN1_UTCTIME) {
795 if (aTime->data[0] > '5') { // RFC 2459, section 4.1.2.5.1
796 buf[0] = '1';
797 buf[1] = '9';
798 } else {
799 buf[0] = '2';
800 buf[1] = '0';
801 }
802 str = buf +2;
87f237a9 803 } else // if (aTime->type == V_ASN1_GENERALIZEDTIME)
e7bcc25f
CT
804 str = buf;
805
806 memcpy(str, aTime->data, aTime->length);
807 str[aTime->length] = '\0';
808 return true;
809}
810
811static int asn1time_cmp(ASN1_TIME *asnTime1, ASN1_TIME *asnTime2)
812{
813 char strTime1[64], strTime2[64];
814 if (!asn1timeToGeneralizedTimeStr(asnTime1, strTime1, sizeof(strTime1)))
815 return -1;
816 if (!asn1timeToGeneralizedTimeStr(asnTime2, strTime2, sizeof(strTime2)))
817 return -1;
87f237a9 818
e7bcc25f
CT
819 return strcmp(strTime1, strTime2);
820}
821
4ece76b2 822bool Ssl::certificateMatchesProperties(X509 *cert, CertificateProperties const &properties)
e7bcc25f 823{
4ece76b2
CT
824 assert(cert);
825
826 // For non self-signed certificates we have to check if the signing certificate changed
827 if (properties.signAlgorithm != Ssl::algSignSelf) {
f4e4d4d6 828 assert(properties.signWithX509.get());
4ece76b2
CT
829 if (X509_check_issued(properties.signWithX509.get(), cert) != X509_V_OK)
830 return false;
831 }
87f237a9 832
4ece76b2
CT
833 X509 *cert2 = properties.mimicCert.get();
834 // If there is not certificate to mimic stop here
835 if (!cert2)
836 return true;
837
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)
842 return false;
87f237a9
A
843 } else if (properties.commonName != CommonHostName(cert))
844 return false;
845
4ece76b2
CT
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)
850 return false;
0efa4d01
CT
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)
853 return false;
4ece76b2 854 }
e7bcc25f 855
4ece76b2
CT
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)
860 return false;
0efa4d01
CT
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)
863 return false;
4ece76b2 864 }
0efa4d01 865
e7bcc25f
CT
866 char *alStr1;
867 int alLen;
4ece76b2 868 alStr1 = (char *)X509_alias_get0(cert, &alLen);
e7bcc25f
CT
869 char *alStr2 = (char *)X509_alias_get0(cert2, &alLen);
870 if ((!alStr1 && alStr2) || (alStr1 && !alStr2) ||
87f237a9 871 (alStr1 && alStr2 && strcmp(alStr1, alStr2)) != 0)
e7bcc25f 872 return false;
87f237a9 873
e7bcc25f
CT
874 // Compare subjectAltName extension
875 STACK_OF(GENERAL_NAME) * cert1_altnames;
4ece76b2 876 cert1_altnames = (STACK_OF(GENERAL_NAME)*)X509_get_ext_d2i(cert, NID_subject_alt_name, NULL, NULL);
e7bcc25f
CT
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);
879 bool match = true;
880 if (cert1_altnames) {
881 int numalts = sk_GENERAL_NAME_num(cert1_altnames);
a38ec4b1 882 for (int i = 0; match && i < numalts; ++i) {
2a268a06 883 GENERAL_NAME *aName = sk_GENERAL_NAME_value(cert1_altnames, i);
e7bcc25f
CT
884 match = sk_GENERAL_NAME_find(cert2_altnames, aName);
885 }
87f237a9 886 } else if (cert2_altnames)
e7bcc25f 887 match = false;
87f237a9 888
e7bcc25f
CT
889 sk_GENERAL_NAME_pop_free(cert1_altnames, GENERAL_NAME_free);
890 sk_GENERAL_NAME_pop_free(cert2_altnames, GENERAL_NAME_free);
891
892 return match;
893}
0efa4d01
CT
894
895static const char *getSubjectEntry(X509 *x509, int nid)
896{
897 static char name[1024] = ""; // stores common name (CN)
898
899 if (!x509)
900 return NULL;
901
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(
87f237a9
A
904 X509_get_subject_name(x509),
905 nid, name, sizeof(name));
0efa4d01
CT
906
907 if (nameLen > 0)
908 return name;
909
910 return NULL;
911}
912
913const char *Ssl::CommonHostName(X509 *x509)
914{
915 return getSubjectEntry(x509, NID_commonName);
916}
917
918const char *Ssl::getOrganization(X509 *x509)
919{
920 return getSubjectEntry(x509, NID_organizationName);
921}
922
5107d2c4
CT
923bool
924Ssl::CertificatesCmp(const Security::CertPointer &cert1, const Security::CertPointer &cert2)
925{
926 if (!cert1 || ! cert2)
927 return false;
928
929 int cert1Len;
930 unsigned char *cert1Asn = NULL;
931 cert1Len = ASN1_item_i2d((ASN1_VALUE *)cert1.get(), &cert1Asn, ASN1_ITEM_rptr(X509));
932
933 int cert2Len;
934 unsigned char *cert2Asn = NULL;
935 cert2Len = ASN1_item_i2d((ASN1_VALUE *)cert2.get(), &cert2Asn, ASN1_ITEM_rptr(X509));
936
937 if (cert1Len != cert2Len)
938 return false;
939
940 bool ret = (memcmp(cert1Asn, cert2Asn, cert1Len) == 0);
941
942 OPENSSL_free(cert1Asn);
943 OPENSSL_free(cert2Asn);
944
945 return ret;
946}
70cfe22f
AJ
947
948const ASN1_BIT_STRING *
949Ssl::X509_get_signature(const Security::CertPointer &cert)
950{
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;
955#else
956 ASN1_BIT_STRING *sig = nullptr;
957 X509_ALGOR *sig_alg = nullptr;
958#endif
959 X509_get0_signature(&sig, &sig_alg, cert.get());
960 return sig;
961#else
962 return cert->signature;
963#endif
964}
62b9cc19 965