1 /*
2 *
3 * Copyright (C) 1998-2019, OFFIS e.V.
4 * All rights reserved. See COPYRIGHT file for details.
5 *
6 * This software and supporting documentation were developed by
7 *
8 * OFFIS e.V.
9 * R&D Division Health
10 * Escherweg 2
11 * D-26121 Oldenburg, Germany
12 *
13 *
14 * Module: dcmtls
15 *
16 * Author: Marco Eichelberg
17 *
18 * Purpose:
19 * classes: DcmTLSTransportLayer
20 *
21 */
22
23 #include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */
24 #include "dcmtk/dcmtls/tlslayer.h"
25 #include "dcmtk/dcmtls/tlsdefin.h"
26
27 #ifdef WITH_OPENSSL
28
29 #define INCLUDE_CSTDLIB
30 #include "dcmtk/ofstd/ofstdinc.h"
31
32 BEGIN_EXTERN_C
33 #ifdef HAVE_WINDOWS_H
34 #define WIN32_LEAN_AND_MEAN
35 #include <windows.h>
36 #include <winbase.h>
37 #endif
38 #include <openssl/ssl.h>
39 #include <openssl/rand.h>
40 #include <openssl/err.h>
41 #include <openssl/dh.h>
42 END_EXTERN_C
43
44 #include "dcmtk/dcmtls/tlslayer.h"
45 #include "dcmtk/dcmtls/tlstrans.h"
46 #include "dcmtk/dcmnet/dicom.h"
47
48 #ifdef HAVE_SSL_CTX_GET0_PARAM
49 #define DCMTK_SSL_CTX_get0_param SSL_CTX_get0_param
50 #else
51 #define DCMTK_SSL_CTX_get0_param(A) A->param;
52 #endif
53
54 #if OPENSSL_VERSION_NUMBER < 0x10002000L || defined(LIBRESSL_VERSION_NUMBER)
55 #define X509_get_signature_nid(x509) OBJ_obj2nid((x509)->sig_alg->algorithm)
56 #endif
57
58 #if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
59 #define SSL_CTX_get_cert_store(ctx) (ctx)->cert_store
60 #define EVP_PKEY_base_id(key) EVP_PKEY_type((key)->type)
61 #define DH_bits(dh) BN_num_bits((dh)->p)
62 #define SSL_CTX_get_ciphers(ctx) (ctx)->cipher_list
63 #endif
64
65 extern "C" int DcmTLSTransportLayer_certificateValidationCallback(int ok, X509_STORE_CTX *storeContext);
66
67 OFLogger DCM_dcmtlsLogger = OFLog::getLogger("dcmtk.dcmtls");
68
69
70 /* This static function creates a hard-coded set of Diffie-Hellman parameters
71 * with 2048 bits key size that is used for ephemeral Diffie-Hellmane
72 * (DHE_) ciphersuites unless the user replaces the parameter set
73 * by calling DcmTLSTransportLayer::setTempDHParameters().
74 * Using a hard-coded DH parameter set is safe because the DH key exchange
75 * does not require these parameters to be secret. It is, however, still
76 * preferable to use a user-generated set of parameters.
77 *
78 * Generated by calling "openssl dhparam -C -noout 2048".
79 */
get_dh2048()80 static DH *get_dh2048()
81 {
82 static unsigned char dh2048_p[] = {
83 0xC8, 0x04, 0xF6, 0xBF, 0x4B, 0xA6, 0xBA, 0x24, 0xD8, 0x79,
84 0xA9, 0x70, 0xFF, 0xA0, 0x6B, 0x9F, 0x9D, 0x56, 0x0F, 0x41,
85 0x75, 0x70, 0x69, 0x17, 0xBC, 0x89, 0xB5, 0x38, 0xEE, 0x8A,
86 0xA9, 0x2E, 0xFD, 0xC8, 0xD3, 0xBA, 0x43, 0x77, 0x51, 0x46,
87 0xBF, 0x59, 0xE0, 0x57, 0xFA, 0x55, 0x6A, 0xC2, 0x4B, 0x63,
88 0x24, 0xEE, 0x9E, 0x64, 0x96, 0xBE, 0x13, 0xF7, 0x0B, 0xEC,
89 0x0E, 0xEA, 0xC8, 0x8B, 0x3A, 0x59, 0xB5, 0x28, 0xF6, 0x49,
90 0x40, 0xC7, 0x89, 0x80, 0x39, 0x97, 0x66, 0x7A, 0xC5, 0x90,
91 0xB7, 0x98, 0x3F, 0x11, 0x45, 0xEA, 0xA2, 0xF1, 0x77, 0x7B,
92 0xBE, 0x3F, 0x5A, 0x5C, 0xD5, 0xA4, 0x5F, 0xBA, 0x96, 0x87,
93 0x77, 0x2D, 0x23, 0xA0, 0x56, 0x5B, 0x14, 0x2D, 0xD6, 0x6C,
94 0xF1, 0xCC, 0x0F, 0xD9, 0x7D, 0x42, 0x72, 0x9A, 0x8B, 0xBE,
95 0x3E, 0xCB, 0xB4, 0xE3, 0xB9, 0xA8, 0xC2, 0x8F, 0xBA, 0xEB,
96 0x12, 0xFE, 0x3E, 0x90, 0x4B, 0xDC, 0x8C, 0xA0, 0xD2, 0x26,
97 0x1F, 0x26, 0x78, 0x6E, 0x89, 0x15, 0x59, 0xED, 0x8B, 0x7E,
98 0x00, 0x5E, 0xFF, 0xDB, 0x55, 0x60, 0xE3, 0x52, 0x8A, 0x03,
99 0x9C, 0xE1, 0x33, 0xE6, 0x9F, 0x17, 0x39, 0x42, 0xE7, 0x26,
100 0xAE, 0x3D, 0xC0, 0x66, 0x9F, 0x3C, 0x97, 0xC6, 0x75, 0xAC,
101 0x5B, 0xD1, 0xB2, 0x51, 0xCA, 0xB6, 0x4F, 0xFD, 0xAF, 0x41,
102 0xF8, 0x8B, 0x5A, 0x8D, 0xC7, 0xCA, 0x3A, 0xB7, 0xE3, 0x00,
103 0x7D, 0x20, 0xFA, 0xF1, 0xDE, 0xDA, 0x10, 0xBD, 0x85, 0x09,
104 0xA0, 0xE1, 0x24, 0x18, 0x64, 0x38, 0xBA, 0x1C, 0x16, 0x15,
105 0x71, 0xA6, 0xC2, 0x02, 0xBA, 0x27, 0xF4, 0xE3, 0x3F, 0xA2,
106 0x2E, 0x89, 0xBA, 0xC9, 0xCD, 0x0B, 0x5A, 0x95, 0x26, 0x7D,
107 0x10, 0xBE, 0xE3, 0x96, 0x99, 0x4A, 0x2F, 0xAB, 0x9B, 0xBD,
108 0xD0, 0xB9, 0xDC, 0x43, 0xF9, 0xCB
109 };
110 static unsigned char dh2048_g[] = { 0x02 };
111
112 DH *dh;
113 if ((dh=DH_new()) == NULL) return(NULL);
114
115 #if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
116 dh->p=BN_bin2bn(dh2048_p,sizeof(dh2048_p),NULL);
117 dh->g=BN_bin2bn(dh2048_g,sizeof(dh2048_g),NULL);
118 if ((dh->p == NULL) || (dh->g == NULL))
119 {
120 DH_free(dh);
121 return(NULL);
122 }
123 #else
124 // API change in OpenSSL 1.1.0: DH is now an opaque type
125 BIGNUM *dhp_bn = BN_bin2bn(dh2048_p, sizeof (dh2048_p), NULL);
126 BIGNUM *dhg_bn = BN_bin2bn(dh2048_g, sizeof (dh2048_g), NULL);
127 if (dhp_bn == NULL || dhg_bn == NULL || !DH_set0_pqg(dh, dhp_bn, NULL, dhg_bn))
128 {
129 DH_free(dh);
130 BN_free(dhp_bn);
131 BN_free(dhg_bn);
132 return NULL;
133 }
134 #endif
135
136 return dh;
137 }
138
DcmTLSTransportLayer_certificateValidationCallback(int ok,X509_STORE_CTX *)139 int DcmTLSTransportLayer_certificateValidationCallback(int ok, X509_STORE_CTX * /* storeContext */)
140 {
141 // this callback is called whenever OpenSSL has validated a X.509 certificate.
142 // we could for example print it:
143 // DcmTLSTransportLayer::printX509Certificate(cout, storeContext->cert);
144 return ok;
145 }
146
147 /* buf : buffer to write password into
148 * size : length of buffer in bytes
149 * rwflag : nonzero if the password will be used as a new password, i.e. user should be asked to repeat the password
150 * userdata: arbitrary pointer that can be set with SSL_CTX_set_default_passwd_cb_userdata()
151 * returns : number of bytes written to password buffer, -1 upon error
152 */
153 extern "C" int DcmTLSTransportLayer_passwordCallback(char *buf, int size, int rwflag, void *userdata);
154
DcmTLSTransportLayer_passwordCallback(char * buf,int size,int,void * userdata)155 int DcmTLSTransportLayer_passwordCallback(char *buf, int size, int /* rwflag */, void *userdata)
156 {
157 if (userdata == NULL) return -1;
158 OFString *password = OFreinterpret_cast(OFString *, userdata);
159 int passwordSize = OFstatic_cast(int, password->length());
160 if (passwordSize > size) passwordSize = size;
161 strncpy(buf, password->c_str(), passwordSize);
162 return passwordSize;
163 }
164
165
166 // The TLS Supported Elliptic Curves extension (RFC 4492) is only supported in OpenSSL 1.0.2 and newer.
167 // When compiling with OpenSSL 1.0.1, we are not using computeEllipticCurveList().
168 #if OPENSSL_VERSION_NUMBER >= 0x10002000L && !defined(LIBRESSL_VERSION_NUMBER)
169
170 /** determine the list of elliptic curves supported by the OpenSSL library
171 * for use with the TLS elliptic curve extension.
172 * @param ecvector a list of supported elliptic curves that have 256 or
173 * more bits is added to this vector upon return.
174 */
computeEllipticCurveList(OFVector<int> & ecvector)175 static void computeEllipticCurveList(OFVector<int>& ecvector)
176 {
177 // BCP 195: Curves of less than 192 bits SHOULD NOT be used.
178 // Actually we only enable curves with at least 256 bits in DCMTK, following NIST and BSI recommendations.
179 const int eclist[] = {
180 // The list of elliptic curves actually supported by OpenSSL 1.0.2
181 // seems to be undocumented. See implementation of tls1_ec_nid2curve_id()
182 // for a list of supported NIDs. Here are all elliptic curves
183 // supported by OpenSSL 1.0.2 that have 256 or more bits.
184 //
185 // Compiled versions of OpenSSL may further reduce this list.
186 // For example, OpenSSL on RHEL 7.6 only supports four of these curves.
187 // We therefore simply test each curve and only retain those that are
188 // accepted by SSL_CTX_set1_curves().
189
190 NID_X9_62_prime256v1, NID_secp256k1, NID_secp384r1,
191 NID_secp521r1, NID_sect283k1, NID_sect283r1,
192 NID_sect409k1, NID_sect409r1, NID_sect571k1,
193 NID_sect571r1, NID_brainpoolP256r1, NID_brainpoolP384r1,
194 NID_brainpoolP512r1
195 };
196
197 // create a SSL context object
198 #if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
199 SSL_CTX *ctx = SSL_CTX_new(SSLv23_method());
200 if (ctx) SSL_CTX_set_options(ctx, SSL_OP_NO_SSLv2|SSL_OP_NO_SSLv3);
201 #else
202 SSL_CTX *ctx = SSL_CTX_new(TLS_method());
203 if (ctx) SSL_CTX_set_security_level(ctx, 0);
204 #endif
205 if (ctx)
206 {
207 size_t numentries = sizeof(eclist) / sizeof(int);
208 ecvector.reserve(numentries);
209 for (size_t i = 0; i < numentries; ++i)
210 {
211 // try to set the given elliptic curve
212 if (SSL_CTX_set1_curves(ctx, &eclist[i], 1))
213 {
214 // if successful, add to the list of supported elliptic curves
215 ecvector.push_back(eclist[i]);
216 }
217 }
218 // delete the SSL context object
219 SSL_CTX_free(ctx);
220 }
221 }
222
223 #endif
224
225
DcmTLSTransportLayer()226 DcmTLSTransportLayer::DcmTLSTransportLayer()
227 : DcmTransportLayer()
228 , transportLayerContext(NULL)
229 , canWriteRandseed(OFFalse)
230 , privateKeyPasswd()
231 , role(NET_ACCEPTORREQUESTOR)
232 {
233 }
234
DcmTLSTransportLayer(T_ASC_NetworkRole networkRole,const char * randFile,OFBool initOpenSSL)235 DcmTLSTransportLayer::DcmTLSTransportLayer(T_ASC_NetworkRole networkRole, const char *randFile, OFBool initOpenSSL)
236 : DcmTransportLayer()
237 , transportLayerContext(NULL)
238 , canWriteRandseed(OFFalse)
239 , privateKeyPasswd()
240 , role(networkRole)
241 {
242 if (initOpenSSL) initializeOpenSSL();
243 if (randFile) seedPRNG(randFile);
244
245 #if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
246 // on versions of OpenSSL older than 1.1.0, we use the
247 // SSLv23 methods and not the TLSv1 methods because the latter
248 // only accept TLS 1.0 and prevent the negotiation of newer
249 // versions of TLS.
250 // We use SSL_CTX_set_options() to disable SSLv2 and SSLv3.
251 switch (networkRole)
252 {
253 case NET_ACCEPTOR:
254 transportLayerContext = SSL_CTX_new(SSLv23_server_method());
255 break;
256 case NET_REQUESTOR:
257 transportLayerContext = SSL_CTX_new(SSLv23_client_method());
258 break;
259 case NET_ACCEPTORREQUESTOR:
260 transportLayerContext = SSL_CTX_new(SSLv23_method());
261 break;
262 }
263 if (transportLayerContext) SSL_CTX_set_options(transportLayerContext, SSL_OP_NO_SSLv2|SSL_OP_NO_SSLv3);
264 #else
265 // starting with OpenSSL 1.1.0, a new TLS_method() is offered
266 // that automatically selects the highest version of the TLS
267 // protocol supported by client and server.
268 // The previous TLSv1_methods are now deprecated and generate
269 // a warning.
270 switch (networkRole)
271 {
272 case NET_ACCEPTOR:
273 transportLayerContext = SSL_CTX_new(TLS_server_method());
274 break;
275 case NET_REQUESTOR:
276 transportLayerContext = SSL_CTX_new(TLS_client_method());
277 break;
278 case NET_ACCEPTORREQUESTOR:
279 transportLayerContext = SSL_CTX_new(TLS_method());
280 break;
281 }
282
283 // starting with OpenSSL 1.1.0, we explicitly need to set the security level to 0
284 // if we want to support any of the NULL ciphersuites. Since we manage the list
285 // of supported ciphersuites ourselves and prevent a mix of NULL and non-NULL
286 // ciphersuites, this is safe.
287 if (transportLayerContext) SSL_CTX_set_security_level(transportLayerContext, 0);
288 #endif
289
290 if (transportLayerContext == NULL)
291 {
292 const char *result = ERR_reason_error_string(ERR_peek_error());
293 if (result == NULL) result = "unknown error in SSL_CTX_new()";
294 DCMTLS_ERROR("unable to create TLS transport layer: " << result);
295 }
296 else
297 {
298 // create default set of DH parameters
299 DH *dhparams = get_dh2048();
300 if (dhparams)
301 {
302 SSL_CTX_set_tmp_dh(transportLayerContext,dhparams);
303 DH_free(dhparams); // safe because of reference counting
304 }
305 else DCMTLS_ERROR("unable to create Diffie-Hellman parameters.");
306
307 // create Elliptic Curve DH parameters
308 #ifndef OPENSSL_NO_ECDH
309 #if OPENSSL_VERSION_NUMBER < 0x10002000L || defined(LIBRESSL_VERSION_NUMBER)
310 // we create ECDH parameters for the NIST P-256 (secp256r1) curve
311 // as recommended by BCP 195.
312 EC_KEY *ecdh = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1);
313 if (ecdh)
314 {
315 SSL_CTX_set_tmp_ecdh(transportLayerContext, ecdh);
316 EC_KEY_free(ecdh); /* Safe because of reference counts */
317 }
318 else DCMTLS_ERROR("unable to create Elliptic-Curve Diffie-Hellman parameters.");
319 #else
320 // OpenSSL 1.0.2 and newer have this function, which causes
321 // the server to automatically select the most appropriate shared curve for each client.
322 if (0 == SSL_CTX_set_ecdh_auto(transportLayerContext, 1))
323 {
324 DCMTLS_ERROR("unable to create Elliptic-Curve Diffie-Hellman parameters.");
325 }
326 #endif /* OPENSSL_VERSION_NUMBER < 0x10002000L */
327 #endif /* OPENSSL_NO_ECDH */
328
329 // set default certificate verification strategy
330 setCertificateVerification(DCV_requireCertificate);
331
332 #if OPENSSL_VERSION_NUMBER >= 0x10002000L && !defined(LIBRESSL_VERSION_NUMBER)
333 // The TLS 1.2 Signature Algorithms extension is only supported in OpenSSL 1.0.2 and newer.
334
335 if (networkRole != NET_ACCEPTOR)
336 {
337 // BCP 195: Clients SHOULD indicate to servers that they request SHA-256,
338 // by using the "Signature Algorithms" extension defined in TLS 1.2.
339 // We implement this by requesting SHA-256 OR BETTER, i.e. we also indicate
340 // support for SHA-384 and SHA-512.
341
342 const int slist[] = {NID_sha256, EVP_PKEY_RSA, NID_sha384, EVP_PKEY_RSA, NID_sha512, EVP_PKEY_RSA,
343 #if OPENSSL_VERSION_NUMBER >= 0x10101000L
344 // Connections between a client and a server that both use OpenSSL 1.1.1
345 // will fail unless RSA-PSS is also offered as a signature algorithm.
346 NID_sha256, EVP_PKEY_RSA_PSS, NID_sha384, EVP_PKEY_RSA_PSS, NID_sha512, EVP_PKEY_RSA_PSS,
347 #endif
348 NID_sha256, EVP_PKEY_DSA, NID_sha384, EVP_PKEY_DSA, NID_sha512, EVP_PKEY_DSA,
349 NID_sha256, EVP_PKEY_EC, NID_sha384, EVP_PKEY_EC, NID_sha512, EVP_PKEY_EC};
350
351 if (0 == SSL_CTX_set1_sigalgs(transportLayerContext, slist, sizeof(slist)/sizeof(int)))
352 {
353 DCMTLS_ERROR("unable to configure the TLS 1.2 Signature Algorithms extension.");
354 }
355 }
356
357 // The TLS Supported Elliptic Curves extension (RFC 4492) is only supported in OpenSSL 1.0.2 and newer.
358
359 // BCP 195: Both clients and servers SHOULD include the "Supported Elliptic Curves" extension.
360 // For interoperability, clients and servers SHOULD support the NIST P-256 (secp256r1) curve
361 // (in OpenSSL this curve is called "prime256v1").
362
363 OFVector<int> ecvector;
364 computeEllipticCurveList(ecvector);
365 if (ecvector.size() > 0) // only try to add the EC extension if we actually do support at least one curve
366 {
367 if (0 == SSL_CTX_set1_curves(transportLayerContext, &ecvector[0], OFstatic_cast(int, ecvector.size())))
368 {
369 DCMTLS_ERROR("unable to configure the TLS Supported Elliptic Curves extension.");
370 }
371 }
372 #endif /* OPENSSL_VERSION_NUMBER >= 0x10002000L */
373
374 if (NET_REQUESTOR != networkRole)
375 {
376 // BCP 195: Servers MUST prefer TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 over weaker cipher suites whenever it is proposed, even if it is not the first proposal.
377 // BCP 195: Servers SHOULD prefer stronger cipher suites unless there are compelling reasons to choose otherwise
378 // BCP 195: Implementations MUST support and prefer to negotiate cipher suites offering forward secrecy
379 // This all requires that when acting as a server we select the ciphersuites by our order of preference,
380 // which implements all three recommendations by sorting the list of supported ciphersuites appropriately.
381 if (0 == SSL_CTX_set_options(transportLayerContext, SSL_OP_CIPHER_SERVER_PREFERENCE))
382 {
383 DCMTLS_ERROR("unable to configure the TLS layer to select ciphersuites by server preference.");
384 }
385 }
386
387 } /* transportLayerContext != NULL */
388 }
389
DcmTLSTransportLayer(OFrvalue_ref (DcmTLSTransportLayer)rhs)390 DcmTLSTransportLayer::DcmTLSTransportLayer(OFrvalue_ref(DcmTLSTransportLayer) rhs)
391 : DcmTransportLayer(OFrvalue_ref_upcast(DcmTransportLayer, rhs))
392 , transportLayerContext(rhs.transportLayerContext)
393 , canWriteRandseed(OFmove(OFrvalue_access(rhs).canWriteRandseed))
394 , privateKeyPasswd(OFmove(OFrvalue_access(rhs).privateKeyPasswd))
395 {
396 OFrvalue_access(rhs).transportLayerContext = NULL;
397 }
398
operator =(OFrvalue_ref (DcmTLSTransportLayer)rhs)399 DcmTLSTransportLayer& DcmTLSTransportLayer::operator=(OFrvalue_ref(DcmTLSTransportLayer) rhs)
400 {
401 if (this != &rhs)
402 {
403 clear();
404 DcmTransportLayer::operator=(OFrvalue_ref_upcast(DcmTransportLayer, rhs));
405 transportLayerContext = rhs.transportLayerContext;
406 canWriteRandseed = OFmove(OFrvalue_access(rhs).canWriteRandseed);
407 privateKeyPasswd = OFmove(OFrvalue_access(rhs).privateKeyPasswd);
408 OFrvalue_access(rhs).transportLayerContext = NULL;
409 }
410 return *this;
411 }
412
clear()413 void DcmTLSTransportLayer::clear()
414 {
415 if (transportLayerContext)
416 {
417 SSL_CTX_free(transportLayerContext);
418 transportLayerContext = NULL;
419 canWriteRandseed = OFFalse;
420 privateKeyPasswd.clear();
421 }
422 }
423
operator OFBool() const424 DcmTLSTransportLayer::operator OFBool() const
425 {
426 return !!transportLayerContext;
427 }
428
operator !() const429 OFBool DcmTLSTransportLayer::operator!() const
430 {
431 return !transportLayerContext;
432 }
433
setTempDHParameters(const char * filename)434 OFBool DcmTLSTransportLayer::setTempDHParameters(const char *filename)
435 {
436 if ((filename==NULL)||(transportLayerContext==NULL)) return OFFalse;
437 DH *dh = NULL;
438 BIO *bio = BIO_new_file(filename,"r");
439 if (bio)
440 {
441 dh = PEM_read_bio_DHparams(bio,NULL,NULL,NULL);
442 BIO_free(bio);
443 if (dh)
444 {
445 // check BCP 195 recommendation: With a key exchange based on modular
446 // exponential (MODP) Diffie-Hellman groups ("DHE" cipher suites),
447 // DH key lengths of at least 2048 bits are RECOMMENDED.
448 if (DH_bits(dh) < 2048)
449 {
450 DCMTLS_WARN("Key length of Diffie-Hellman parameter file too short: RFC 7525 recommends at least 2048 bits, but the key in file '"
451 << filename << "' is only " << DH_bits(dh) << " bits.");
452 if (ciphersuites.getTLSProfile() == TSP_Profile_BCP195_Extended)
453 {
454 // Extended BCP 195 profile: Reject DH parameter set, because it has less than 2048 bits
455 // This will cause the default DH parameter set (which is large enough) to be used
456 DH_free(dh);
457 return OFFalse;
458 }
459 }
460 SSL_CTX_set_tmp_dh(transportLayerContext,dh);
461 DH_free(dh); /* Safe because of reference counts in OpenSSL */
462 return OFTrue;
463 }
464 }
465 return OFFalse;
466 }
467
setPrivateKeyPasswd(const char * thePasswd)468 void DcmTLSTransportLayer::setPrivateKeyPasswd(const char *thePasswd)
469 {
470 if (thePasswd) privateKeyPasswd = thePasswd;
471 else privateKeyPasswd.clear();
472 if (transportLayerContext)
473 {
474 /* register callback that replaces console input */
475 SSL_CTX_set_default_passwd_cb(transportLayerContext, DcmTLSTransportLayer_passwordCallback);
476 SSL_CTX_set_default_passwd_cb_userdata(transportLayerContext, &privateKeyPasswd);
477 }
478 return;
479 }
480
setPrivateKeyPasswdFromConsole()481 void DcmTLSTransportLayer::setPrivateKeyPasswdFromConsole()
482 {
483 privateKeyPasswd.clear();
484 if (transportLayerContext)
485 {
486 /* deregister callback that replaces console input */
487 SSL_CTX_set_default_passwd_cb(transportLayerContext, NULL);
488 SSL_CTX_set_default_passwd_cb_userdata(transportLayerContext, NULL);
489 }
490 return;
491 }
492
setCertificateVerification(DcmCertificateVerification verificationType)493 void DcmTLSTransportLayer::setCertificateVerification(DcmCertificateVerification verificationType)
494 {
495 if (transportLayerContext)
496 {
497 int vmode = 0;
498 switch (verificationType)
499 {
500 case DCV_requireCertificate:
501 vmode = SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT;
502 break;
503 case DCV_checkCertificate:
504 vmode = SSL_VERIFY_PEER;
505 break;
506 case DCV_ignoreCertificate:
507 break;
508 }
509 SSL_CTX_set_verify(transportLayerContext, vmode, DcmTLSTransportLayer_certificateValidationCallback);
510 }
511 return;
512 }
513
activateCipherSuites()514 DcmTransportLayerStatus DcmTLSTransportLayer::activateCipherSuites()
515 {
516 OFString cslist;
517 ciphersuites.getListOfCipherSuitesForOpenSSL(cslist, (role != NET_REQUESTOR));
518 if (transportLayerContext)
519 {
520 if (!SSL_CTX_set_cipher_list(transportLayerContext, cslist.c_str()))
521 {
522 const char *err = ERR_reason_error_string(ERR_peek_error());
523 if (err) DCMTLS_ERROR("OpenSSL error: " << err);
524 return TCS_tlsError;
525 }
526
527 SSL_CTX_set_options(transportLayerContext, ciphersuites.getTLSOptions());
528
529 #if OPENSSL_VERSION_NUMBER >= 0x10101000L && !defined(LIBRESSL_VERSION_NUMBER)
530 // when compiling with OpenSSL 1.1.1 or newer, set the maximum supported
531 // TLS protocol version to TLS 1.2 if required (i.e. for the historic
532 // security profiles, which would otherwise show unexpected behaviour).
533 if (! ciphersuites.isTLS13Enabled())
534 {
535 SSL_CTX_set_max_proto_version(transportLayerContext, TLS1_2_VERSION);
536 }
537 #endif
538 } else return TCS_illegalCall;
539
540 return TCS_ok;
541 }
542
setCipherSuites(const char * suites)543 DcmTransportLayerStatus DcmTLSTransportLayer::setCipherSuites(const char *suites)
544 {
545 if (transportLayerContext && suites)
546 {
547 if (!SSL_CTX_set_cipher_list(transportLayerContext, suites))
548 {
549 const char *err = ERR_reason_error_string(ERR_peek_error());
550 if (err) DCMTLS_ERROR("OpenSSL error: " << err);
551 return TCS_tlsError;
552 }
553 } else return TCS_illegalCall;
554 return TCS_ok;
555 }
556
~DcmTLSTransportLayer()557 DcmTLSTransportLayer::~DcmTLSTransportLayer()
558 {
559 clear();
560 }
561
setPrivateKeyFile(const char * fileName,DcmKeyFileFormat fileType)562 DcmTransportLayerStatus DcmTLSTransportLayer::setPrivateKeyFile(const char *fileName, DcmKeyFileFormat fileType)
563 {
564 if (transportLayerContext)
565 {
566 if (0 >= SSL_CTX_use_PrivateKey_file(transportLayerContext, fileName, lookupOpenSSLCertificateFormat(fileType)))
567 {
568 const char *err = ERR_reason_error_string(ERR_peek_error());
569 if (err) DCMTLS_ERROR("OpenSSL error: " << err);
570 return TCS_tlsError;
571 }
572 } else return TCS_illegalCall;
573 return TCS_ok;
574 }
575
setCertificateFile(const char * fileName,DcmKeyFileFormat fileType)576 DcmTransportLayerStatus DcmTLSTransportLayer::setCertificateFile(const char *fileName, DcmKeyFileFormat fileType)
577 {
578 if (transportLayerContext)
579 {
580 int result = 0;
581 X509 *certificate = loadCertificateFile(fileName, fileType);
582 if (certificate)
583 {
584 // TODO: Check if the certificate is RSA, and if so, if the public key is >= 2048 bits
585 int bits = getRSAKeySize(certificate);
586 if ((bits > 0) && (bits < 2048))
587 {
588 DCMTLS_WARN("Key length of RSA public key too short: RFC 7525 recommends at least 2048 bits for RSA keys, but the key in certificate file '"
589 << fileName << "' is only " << bits << " bits.");
590 }
591 const char *hash = checkRSAHashKeyIsSHA2(certificate);
592 if (hash)
593 {
594 DCMTLS_WARN("Certificate hash key not SHA-256: RFC 7525 recommends the use of SHA-256 for RSA certificates, but certificate file '"
595 << fileName << "' uses '" << hash << "'.");
596 }
597 result = SSL_CTX_use_certificate(transportLayerContext, certificate); // copies certificate into context
598 X509_free(certificate);
599 } else result = -1;
600
601 if (result <= 0)
602 {
603 const char *err = ERR_reason_error_string(ERR_peek_error());
604 if (err) DCMTLS_ERROR("OpenSSL error: " << err);
605 return TCS_tlsError;
606 }
607 } else return TCS_illegalCall;
608 return TCS_ok;
609 }
610
checkPrivateKeyMatchesCertificate()611 OFBool DcmTLSTransportLayer::checkPrivateKeyMatchesCertificate()
612 {
613 if (transportLayerContext)
614 {
615 if (SSL_CTX_check_private_key(transportLayerContext)) return OFTrue;
616 }
617 return OFFalse;
618 }
619
addVerificationFlags(unsigned long flags)620 DcmTransportLayerStatus DcmTLSTransportLayer::addVerificationFlags(unsigned long flags)
621 {
622 X509_VERIFY_PARAM* const parameter = DCMTK_SSL_CTX_get0_param(transportLayerContext);
623 return parameter && X509_VERIFY_PARAM_set_flags(parameter,flags) ? TCS_ok : TCS_unspecifiedError;
624 }
625
addTrustedCertificateFile(const char * fileName,DcmKeyFileFormat fileType)626 DcmTransportLayerStatus DcmTLSTransportLayer::addTrustedCertificateFile(const char *fileName, DcmKeyFileFormat fileType)
627 {
628 if (transportLayerContext)
629 {
630 X509_LOOKUP *x509_lookup = X509_STORE_add_lookup(SSL_CTX_get_cert_store(transportLayerContext), X509_LOOKUP_file());
631 if (x509_lookup == NULL)
632 {
633 const char *err = ERR_reason_error_string(ERR_peek_error());
634 if (err) DCMTLS_ERROR("OpenSSL error: " << err);
635 return TCS_tlsError;
636 }
637 if (! X509_LOOKUP_load_file(x509_lookup, fileName, lookupOpenSSLCertificateFormat(fileType)))
638 {
639 const char *err = ERR_reason_error_string(ERR_peek_error());
640 if (err) DCMTLS_ERROR("OpenSSL error: " << err);
641 return TCS_tlsError;
642 }
643 } else return TCS_illegalCall;
644 return TCS_ok;
645 }
646
addTrustedCertificateDir(const char * pathName,DcmKeyFileFormat fileType)647 DcmTransportLayerStatus DcmTLSTransportLayer::addTrustedCertificateDir(const char *pathName, DcmKeyFileFormat fileType)
648 {
649 if (transportLayerContext)
650 {
651 X509_LOOKUP *x509_lookup = X509_STORE_add_lookup(SSL_CTX_get_cert_store(transportLayerContext), X509_LOOKUP_hash_dir());
652 if (x509_lookup == NULL)
653 {
654 const char *err = ERR_reason_error_string(ERR_peek_error());
655 if (err) DCMTLS_ERROR("OpenSSL error: " << err);
656 return TCS_tlsError;
657 }
658 if (! X509_LOOKUP_add_dir(x509_lookup, pathName, lookupOpenSSLCertificateFormat(fileType)))
659 {
660 const char *err = ERR_reason_error_string(ERR_peek_error());
661 if (err) DCMTLS_ERROR("OpenSSL error: " << err);
662 return TCS_tlsError;
663 }
664 } else return TCS_illegalCall;
665 return TCS_ok;
666 }
667
addTrustedClientCertificateFile(const char * fileName)668 DcmTransportLayerStatus DcmTLSTransportLayer::addTrustedClientCertificateFile(const char *fileName)
669 {
670 if (transportLayerContext)
671 {
672 STACK_OF(X509_NAME) *caNames = sk_X509_NAME_dup(SSL_CTX_get_client_CA_list(transportLayerContext));
673 if (caNames == NULL) caNames = sk_X509_NAME_new_null();
674 STACK_OF(X509_NAME) *newCaNames = SSL_load_client_CA_file(fileName);
675 for (int i = 0; i < sk_X509_NAME_num(newCaNames); ++i)
676 {
677 X509_NAME *newCaName = sk_X509_NAME_value(newCaNames,i);
678 if (sk_X509_NAME_find(caNames,newCaName) == -1)
679 {
680 sk_X509_NAME_push(caNames,X509_NAME_dup(newCaName));
681 }
682 }
683 sk_X509_NAME_pop_free(newCaNames,X509_NAME_free);
684 SSL_CTX_set_client_CA_list(transportLayerContext,caNames);
685 } else return TCS_illegalCall;
686 return TCS_ok;
687 }
688
createConnection(DcmNativeSocketType openSocket,OFBool useSecureLayer)689 DcmTransportConnection *DcmTLSTransportLayer::createConnection(DcmNativeSocketType openSocket, OFBool useSecureLayer)
690 {
691 if (useSecureLayer)
692 {
693 if (transportLayerContext)
694 {
695 SSL *newConnection = SSL_new(transportLayerContext);
696 if (newConnection)
697 {
698 int s = OFstatic_cast(int, openSocket);
699 if (openSocket != OFstatic_cast(DcmNativeSocketType, s))
700 {
701 // On Win64, the native type for sockets there is an unsigned 64-bit integer,
702 // and OpenSSL uses a signed 32-bit int file descriptor.
703 // This should be fixed in OpenSSL, there is nothing we can do here
704 // except to check whether the type conversion truncates the value and,
705 // in this case, issue an error message.
706 DCMTLS_ERROR("Conversion of 64-bit socket type to int in OpenSSL API causes loss of information.");
707 }
708 SSL_set_fd(newConnection, s);
709 return new DcmTLSConnection(openSocket, newConnection);
710 }
711 }
712 return NULL;
713 }
714 else return DcmTransportLayer::createConnection(openSocket, useSecureLayer);
715 }
716
seedPRNG(const char * randFile)717 void DcmTLSTransportLayer::seedPRNG(const char *randFile)
718 {
719 #ifdef _WIN32
720 RAND_screen();
721 #endif
722 if (randFile)
723 {
724 #ifdef HAVE_RAND_EGD
725 if (RAND_egd(randFile) <= 0)
726 #endif
727 {
728 RAND_load_file(randFile ,-1);
729 }
730 }
731 if (RAND_status()) canWriteRandseed = OFTrue;
732 else
733 {
734 /* warn user */
735 DCMTLS_WARN("PRNG for TLS not seeded with sufficient random data.");
736 }
737 }
738
addPRNGseed(void * buf,size_t bufSize)739 void DcmTLSTransportLayer::addPRNGseed(void *buf, size_t bufSize)
740 {
741 RAND_seed(buf,OFstatic_cast(int, bufSize));
742 }
743
writeRandomSeed(const char * randFile)744 OFBool DcmTLSTransportLayer::writeRandomSeed(const char *randFile)
745 {
746 if (canWriteRandseed && randFile)
747 {
748 if (RAND_write_file(randFile)) return OFTrue;
749 }
750 return OFFalse;
751 }
752
dumpX509Certificate(X509 * peerCertificate)753 OFString DcmTLSTransportLayer::dumpX509Certificate(X509 *peerCertificate)
754 {
755 if (peerCertificate)
756 {
757 long certVersion = 0; /* certificate type */
758 long certSerialNumber = -1; /* certificate serial number */
759 OFString certValidNotBefore; /* certificate validity - not before */
760 OFString certValidNotAfter; /* certificate validity - not after */
761 char certSubjectName[1024]; /* certificate subject name (DN) */
762 char certIssuerName[1024]; /* certificate issuer name (DN) */
763 const char *certPubKeyType = "unknown"; /* certificate public key type */
764 int certPubKeyBits = 0; /* certificate number of bits in public key */
765 certSubjectName[0]= '\0';
766 certIssuerName[0]= '\0';
767 certVersion = X509_get_version(peerCertificate) +1;
768 certSerialNumber = ASN1_INTEGER_get(X509_get_serialNumber(peerCertificate));
769 BIO *certValidNotBeforeBIO = BIO_new(BIO_s_mem());
770 char *bufptr = NULL;
771 if (certValidNotBeforeBIO)
772 {
773 ASN1_UTCTIME_print(certValidNotBeforeBIO, X509_get_notBefore(peerCertificate));
774 BIO_write(certValidNotBeforeBIO,"\0",1);
775 BIO_get_mem_data(certValidNotBeforeBIO, OFreinterpret_cast(char *, &bufptr));
776 if (bufptr) certValidNotBefore = bufptr;
777 BIO_free(certValidNotBeforeBIO);
778 }
779 bufptr = NULL;
780 BIO *certValidNotAfterBIO = BIO_new(BIO_s_mem());
781 if (certValidNotAfterBIO)
782 {
783 ASN1_UTCTIME_print(certValidNotAfterBIO, X509_get_notAfter(peerCertificate));
784 BIO_write(certValidNotAfterBIO,"\0",1);
785 BIO_get_mem_data(certValidNotAfterBIO, OFreinterpret_cast(char *, &bufptr));
786 if (bufptr) certValidNotAfter = bufptr;
787 BIO_free(certValidNotAfterBIO);
788 }
789 X509_NAME_oneline(X509_get_subject_name(peerCertificate), certSubjectName, 1024);
790 X509_NAME_oneline(X509_get_issuer_name(peerCertificate), certIssuerName, 1024);
791 EVP_PKEY *pubkey = X509_get_pubkey(peerCertificate); // creates copy of public key
792 if (pubkey)
793 {
794 switch (EVP_PKEY_base_id(pubkey))
795 {
796 case EVP_PKEY_RSA:
797 certPubKeyType = "RSA";
798 break;
799 case EVP_PKEY_DSA:
800 certPubKeyType = "DSA";
801 break;
802 case EVP_PKEY_DH:
803 certPubKeyType = "DH";
804 break;
805 default:
806 /* nothing */
807 break;
808 }
809 certPubKeyBits = EVP_PKEY_bits(pubkey);
810 EVP_PKEY_free(pubkey);
811 }
812 OFOStringStream out;
813 out << "Peer X.509v" << certVersion << " Certificate" << OFendl
814 << " Subject : " << certSubjectName << OFendl
815 << " Issued by : " << certIssuerName << OFendl
816 << " Serial no. : " << certSerialNumber << OFendl
817 << " Validity : not before " << certValidNotBefore << ", not after " << certValidNotAfter << OFendl
818 << " Public key : " << certPubKeyType << ", " << certPubKeyBits << " bits" << OFStringStream_ends;
819 OFSTRINGSTREAM_GETOFSTRING(out, ret)
820 return ret;
821 } else {
822 return "Peer did not provide a certificate or certificate verification is disabled.";
823 }
824 }
825
setTLSProfile(DcmTLSSecurityProfile profile)826 DcmTransportLayerStatus DcmTLSTransportLayer::setTLSProfile(DcmTLSSecurityProfile profile)
827 {
828 return ciphersuites.setTLSProfile(profile);
829 }
830
clearTLSProfile()831 void DcmTLSTransportLayer::clearTLSProfile()
832 {
833 ciphersuites.clearTLSProfile();
834 }
835
addCipherSuite(const char * suite)836 DcmTransportLayerStatus DcmTLSTransportLayer::addCipherSuite(const char *suite)
837 {
838 return ciphersuites.addCipherSuite(suite);
839 }
840
getNativeHandle()841 DcmTLSTransportLayer::native_handle_type DcmTLSTransportLayer::getNativeHandle()
842 {
843 return transportLayerContext;
844 }
845
lookupOpenSSLCertificateFormat(DcmKeyFileFormat fileType)846 int DcmTLSTransportLayer::lookupOpenSSLCertificateFormat(DcmKeyFileFormat fileType)
847 {
848 int result = -1;
849 switch (fileType)
850 {
851 case DCF_Filetype_PEM:
852 result = SSL_FILETYPE_PEM;
853 break;
854 case DCF_Filetype_ASN1:
855 result = SSL_FILETYPE_ASN1;
856 break;
857 }
858 return result;
859 }
860
861
printSupportedCiphersuites(STD_NAMESPACE ostream & os) const862 void DcmTLSTransportLayer::printSupportedCiphersuites(STD_NAMESPACE ostream& os) const
863 {
864 ciphersuites.printSupportedCiphersuites(os);
865 }
866
getListOfCipherSuitesForOpenSSL(OFString & cslist) const867 void DcmTLSTransportLayer::getListOfCipherSuitesForOpenSSL(OFString& cslist) const
868 {
869 ciphersuites.getListOfCipherSuitesForOpenSSL(cslist, (role != NET_REQUESTOR));
870 }
871
getRSAKeySize(X509 * certificate)872 int DcmTLSTransportLayer::getRSAKeySize(X509 *certificate)
873 {
874 if (certificate)
875 {
876 EVP_PKEY *pubkey = X509_get_pubkey(certificate); // creates a copy of the public key
877 if (pubkey && (EVP_PKEY_base_id(pubkey) == EVP_PKEY_RSA))
878 {
879 int certPubKeyBits = EVP_PKEY_bits(pubkey); // RSA public key size, in bits
880 EVP_PKEY_free(pubkey);
881 return certPubKeyBits;
882 }
883 }
884 return 0; // certificate not present or not RSA
885 }
886
checkRSAHashKeyIsSHA2(X509 * certificate)887 const char *DcmTLSTransportLayer::checkRSAHashKeyIsSHA2(X509 *certificate)
888 {
889 if (certificate)
890 {
891 EVP_PKEY *pubkey = X509_get_pubkey(certificate); // creates copy of public key
892 if (pubkey && (EVP_PKEY_base_id(pubkey) == EVP_PKEY_RSA))
893 {
894 int nid = X509_get_signature_nid(certificate);
895 EVP_PKEY_free(pubkey);
896 switch (nid)
897 {
898 case NID_sha256WithRSAEncryption:
899 case NID_sha384WithRSAEncryption:
900 case NID_sha512WithRSAEncryption:
901 return NULL; // hash key uses SHA256 (or better)
902 default:
903 return OBJ_nid2sn(nid); // hash key does not follow BCP 195 recommendation to use SHA256
904 }
905 }
906 }
907 return NULL; // default: everything is OK
908 }
909
loadCertificateFile(const char * fileName,DcmKeyFileFormat fileType)910 X509 *DcmTLSTransportLayer::loadCertificateFile(const char *fileName, DcmKeyFileFormat fileType)
911 {
912 X509 *result = NULL;
913 BIO *in=BIO_new_file(fileName, "rb");
914 if (in)
915 {
916 if (fileType == DCF_Filetype_ASN1)
917 {
918 result=d2i_X509_bio(in,NULL);
919 }
920 else if (fileType == DCF_Filetype_PEM)
921 {
922 result=PEM_read_bio_X509(in, NULL, NULL, NULL);
923 }
924 BIO_free(in);
925 }
926 return result;
927 }
928
initializeOpenSSL()929 void DcmTLSTransportLayer::initializeOpenSSL()
930 {
931 // the call to SSL_library_init was not needed in OpenSSL versions prior to 0.9.8,
932 // but the API has been available at least since 0.9.5.
933 SSL_library_init();
934 SSL_load_error_strings();
935 OpenSSL_add_all_algorithms();
936 }
937
getOpenSSLVersionName()938 const char *DcmTLSTransportLayer::getOpenSSLVersionName()
939 {
940 return OPENSSL_VERSION_TEXT;
941 }
942
943 #else /* WITH_OPENSSL */
944
945 /* make sure that the object file is not completely empty if compiled
946 * without OpenSSL because some linkers might fail otherwise.
947 */
tlslayer_dummy_function()948 DCMTK_DCMTLS_EXPORT void tlslayer_dummy_function()
949 {
950 return;
951 }
952
953 #endif /* WITH_OPENSSL */
954