2 * Copyright (C) 1996-2022 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.
9 #ifndef SQUID_SSL_GADGETS_H
10 #define SQUID_SSL_GADGETS_H
14 #include "base/HardFun.h"
15 #include "compat/openssl.h"
16 #include "security/forward.h"
17 #include "ssl/crtd_message.h"
21 #if HAVE_OPENSSL_ASN1_H
22 #include <openssl/asn1.h>
24 #if HAVE_OPENSSL_TXT_DB_H
25 #include <openssl/txt_db.h>
27 #if HAVE_OPENSSL_X509V3_H
28 #include <openssl/x509v3.h>
34 \defgroup SslCrtdSslAPI SSL certificate generator API
35 These functions must not depend on Squid runtime code such as debug()
36 because they are used by security_file_certgen helper.
39 #if !defined(SQUID_SSL_SIGN_HASH_IF_NONE)
40 #define SQUID_SSL_SIGN_HASH_IF_NONE "sha256"
44 * std::unique_ptr typedefs for common SSL objects
46 sk_dtor_wrapper(sk_X509
, STACK_OF(X509
) *, X509_free
);
47 typedef std::unique_ptr
<STACK_OF(X509
), sk_X509_free_wrapper
> X509_STACK_Pointer
;
49 typedef std::unique_ptr
<BIGNUM
, HardFun
<void, BIGNUM
*, &BN_free
>> BIGNUM_Pointer
;
51 typedef std::unique_ptr
<BIO
, HardFun
<void, BIO
*, &BIO_vfree
>> BIO_Pointer
;
53 typedef std::unique_ptr
<ASN1_INTEGER
, HardFun
<void, ASN1_INTEGER
*, &ASN1_INTEGER_free
>> ASN1_INT_Pointer
;
55 typedef std::unique_ptr
<ASN1_OCTET_STRING
, HardFun
<void, ASN1_OCTET_STRING
*, &ASN1_OCTET_STRING_free
>> ASN1_OCTET_STRING_Pointer
;
57 typedef std::unique_ptr
<TXT_DB
, HardFun
<void, TXT_DB
*, &TXT_DB_free
>> TXT_DB_Pointer
;
59 typedef std::unique_ptr
<X509_NAME
, HardFun
<void, X509_NAME
*, &X509_NAME_free
>> X509_NAME_Pointer
;
61 typedef std::unique_ptr
<RSA
, HardFun
<void, RSA
*, &RSA_free
>> RSA_Pointer
;
63 typedef std::unique_ptr
<X509_REQ
, HardFun
<void, X509_REQ
*, &X509_REQ_free
>> X509_REQ_Pointer
;
65 typedef std::unique_ptr
<AUTHORITY_KEYID
, HardFun
<void, AUTHORITY_KEYID
*, &AUTHORITY_KEYID_free
>> AUTHORITY_KEYID_Pointer
;
67 sk_dtor_wrapper(sk_GENERAL_NAME
, STACK_OF(GENERAL_NAME
) *, GENERAL_NAME_free
);
68 typedef std::unique_ptr
<STACK_OF(GENERAL_NAME
), sk_GENERAL_NAME_free_wrapper
> GENERAL_NAME_STACK_Pointer
;
70 typedef std::unique_ptr
<GENERAL_NAME
, HardFun
<void, GENERAL_NAME
*, &GENERAL_NAME_free
>> GENERAL_NAME_Pointer
;
72 typedef std::unique_ptr
<X509_EXTENSION
, HardFun
<void, X509_EXTENSION
*, &X509_EXTENSION_free
>> X509_EXTENSION_Pointer
;
74 typedef std::unique_ptr
<X509_STORE_CTX
, HardFun
<void, X509_STORE_CTX
*, &X509_STORE_CTX_free
>> X509_STORE_CTX_Pointer
;
76 // not using CtoCpp1() here because OpenSSL_free() takes void* rather than char*
77 inline void OPENSSL_free_for_c_strings(char * const string
) { OPENSSL_free(string
); }
78 using UniqueCString
= std::unique_ptr
<char, HardFun
<void, char *, &OPENSSL_free_for_c_strings
> >;
80 /// Clear any errors accumulated by OpenSSL in its global storage.
83 /// Manipulator to report errors accumulated by OpenSSL in its global storage.
84 /// Each error is reported on a dedicated Debug::Extra line.
85 /// Nothing is reported if there are no errors.
86 /// Also clears all reported errors.
87 std::ostream
&ReportAndForgetErrors(std::ostream
&);
90 \ingroup SslCrtdSslAPI
91 * Create 1024 bits rsa key.
93 EVP_PKEY
* createSslPrivateKey();
96 \ingroup SslCrtdSslAPI
97 * Write private key and SSL certificate to memory.
99 bool writeCertAndPrivateKeyToMemory(Security::CertPointer
const & cert
, Security::PrivateKeyPointer
const & pkey
, std::string
& bufferToWrite
);
102 \ingroup SslCrtdSslAPI
103 * Append SSL certificate to bufferToWrite.
105 bool appendCertToMemory(Security::CertPointer
const & cert
, std::string
& bufferToWrite
);
108 \ingroup SslCrtdSslAPI
109 * Write private key and SSL certificate to memory.
111 bool readCertAndPrivateKeyFromMemory(Security::CertPointer
& cert
, Security::PrivateKeyPointer
& pkey
, char const * bufferToRead
);
113 /// Creates and returns a BIO for reading from the given c-string.
114 /// The returned BIO lifetime must not exceed that of the given c-string!
115 BIO_Pointer
ReadOnlyBioTiedTo(const char *);
118 \ingroup SslCrtdSslAPI
119 * Read private key from file.
121 void ReadPrivateKeyFromFile(char const * keyFilename
, Security::PrivateKeyPointer
&pkey
, pem_password_cb
*passwd_callback
);
124 \ingroup SslCrtdSslAPI
125 * Initialize the bio with the file 'filename' opened for reading
127 bool OpenCertsFileForReading(BIO_Pointer
&bio
, const char *filename
);
129 /// Reads and returns a certificate using the given OpenSSL BIO.
130 /// Never returns a nil pointer.
131 Security::CertPointer
ReadCertificate(const BIO_Pointer
&);
133 /// Reads and returns a certificate using the given OpenSSL BIO.
134 /// \returns a nil pointer if the given BIO is empty or exhausted
135 Security::CertPointer
ReadOptionalCertificate(const BIO_Pointer
&);
138 \ingroup SslCrtdSslAPI
139 * Read a private key from bio
141 bool ReadPrivateKey(BIO_Pointer
&bio
, Security::PrivateKeyPointer
&pkey
, pem_password_cb
*passwd_callback
);
144 \ingroup SslCrtdSslAPI
145 * Initialize the bio with the file 'filename' opened for writing
148 bool OpenCertsFileForWriting(BIO_Pointer
&bio
, const char *filename
);
151 \ingroup SslCrtdSslAPI
152 * Write certificate to BIO.
154 bool WriteX509Certificate(BIO_Pointer
&bio
, const Security::CertPointer
& cert
);
157 \ingroup SslCrtdSslAPI
158 * Write private key to BIO.
160 bool WritePrivateKey(BIO_Pointer
&bio
, const Security::PrivateKeyPointer
&pkey
);
162 /// a RAII wrapper for the memory-allocating flavor of X509_NAME_oneline()
163 UniqueCString
OneLineSummary(X509_NAME
&);
166 \ingroup SslCrtdSslAPI
167 * Supported certificate signing algorithms
169 enum CertSignAlgorithm
{algSignTrusted
= 0, algSignUntrusted
, algSignSelf
, algSignEnd
};
172 \ingroup SslCrtdSslAPI
173 * Short names for certificate signing algorithms
176 extern const char *CertSignAlgorithmStr
[];
179 \ingroup SslCrtdSslAPI
180 * Return the short name of the signing algorithm "sg"
182 inline const char *certSignAlgorithm(int sg
)
184 if (sg
>=0 && sg
< Ssl::algSignEnd
)
185 return Ssl::CertSignAlgorithmStr
[sg
];
191 \ingroup SslCrtdSslAPI
192 * Return the id of the signing algorithm "sg"
194 inline CertSignAlgorithm
certSignAlgorithmId(const char *sg
)
196 for (int i
= 0; i
< algSignEnd
&& Ssl::CertSignAlgorithmStr
[i
] != nullptr; i
++)
197 if (strcmp(Ssl::CertSignAlgorithmStr
[i
], sg
) == 0)
198 return (CertSignAlgorithm
)i
;
204 \ingroup SslCrtdSslAPI
205 * Supported certificate adaptation algorithms
207 enum CertAdaptAlgorithm
{algSetValidAfter
= 0, algSetValidBefore
, algSetCommonName
, algSetEnd
};
210 \ingroup SslCrtdSslAPI
211 * Short names for certificate adaptation algorithms
213 extern const char *CertAdaptAlgorithmStr
[];
216 \ingroup SslCrtdSslAPI
217 * Return the short name of the adaptation algorithm "alg"
219 inline const char *sslCertAdaptAlgoritm(int alg
)
221 if (alg
>=0 && alg
< Ssl::algSetEnd
)
222 return Ssl::CertAdaptAlgorithmStr
[alg
];
228 \ingroup SslCrtdSslAPI
229 * Simple struct to pass certificate generation parameters to generateSslCertificate function.
231 class CertificateProperties
234 CertificateProperties();
235 Security::CertPointer mimicCert
; ///< Certificate to mimic
236 Security::CertPointer signWithX509
; ///< Certificate to sign the generated request
237 Security::PrivateKeyPointer signWithPkey
; ///< The key of the signing certificate
238 bool setValidAfter
; ///< Do not mimic "Not Valid After" field
239 bool setValidBefore
; ///< Do not mimic "Not Valid Before" field
240 bool setCommonName
; ///< Replace the CN field of the mimicking subject with the given
241 std::string commonName
; ///< A CN to use for the generated certificate
242 CertSignAlgorithm signAlgorithm
; ///< The signing algorithm to use
243 const EVP_MD
*signHash
; ///< The signing hash to use
245 CertificateProperties(CertificateProperties
&);
246 CertificateProperties
&operator =(CertificateProperties
const &);
249 /// \ingroup SslCrtdSslAPI
250 /// \returns certificate database key
251 std::string
& OnDiskCertificateDbKey(const CertificateProperties
&);
254 \ingroup SslCrtdSslAPI
255 * Decide on the kind of certificate and generate a CA- or self-signed one.
256 * The generated certificate will inherite properties from certToMimic
257 * Return generated certificate and private key in resultX509 and resultPkey
260 bool generateSslCertificate(Security::CertPointer
& cert
, Security::PrivateKeyPointer
& pkey
, CertificateProperties
const &properties
);
263 \ingroup SslCrtdSslAPI
264 * Verify date. Date format it ASN1_UTCTIME. if there is out of date error,
267 bool sslDateIsInTheFuture(char const * date
);
270 \ingroup SslCrtdSslAPI
271 * Check if the major fields of a certificates matches the properties given by
272 * a CertficateProperties object
273 \return true if the certificates matches false otherwise.
275 bool certificateMatchesProperties(X509
*peer_cert
, CertificateProperties
const &properties
);
278 \ingroup ServerProtocolSSLAPI
279 * Returns CN from the certificate, suitable for use as a host name.
280 * Uses static memory to temporary store the extracted name.
282 const char *CommonHostName(X509
*x509
);
285 \ingroup ServerProtocolSSLAPI
286 * Returns Organization from the certificate.
287 * Uses static memory to temporary store the extracted name.
289 const char *getOrganization(X509
*x509
);
291 /// \ingroup ServerProtocolSSLAPI
292 /// \return whether both certificates exist and are the same (e.g., have identical ASN.1 images)
293 bool CertificatesCmp(const Security::CertPointer
&cert1
, const Security::CertPointer
&cert2
);
295 /// wrapper for OpenSSL X509_get0_signature() which takes care of
296 /// portability issues with older OpenSSL versions
297 const ASN1_BIT_STRING
*X509_get_signature(const Security::CertPointer
&);
301 #endif // USE_OPENSSL
302 #endif // SQUID_SSL_GADGETS_H