1 /* 2 * 3 * Copyright (C) 2018-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: DcmTLSCiphersuiteHandler 20 * 21 */ 22 23 #ifndef TLSCIPHR_H 24 #define TLSCIPHR_H 25 26 #include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */ 27 28 #ifdef WITH_OPENSSL 29 30 #include "dcmtk/ofstd/ofstring.h" /* for class OFString */ 31 #include "dcmtk/ofstd/ofstream.h" /* for class ostream */ 32 #include "dcmtk/ofstd/ofvector.h" /* for class OFVector */ 33 #include "dcmtk/dcmtls/tlsdefin.h" /* for DCMTK_DCMTLS_EXPORT */ 34 #include "dcmtk/dcmnet/dcmlayer.h" /* for DcmTransportLayerStatus */ 35 36 // include this file in doxygen documentation 37 38 /** @file tlsciphr.h 39 * @brief type definitions and classes for TLS ciphersuites 40 */ 41 42 /** This enum describes DICOM TLS Security Profiles, which are the basis 43 * for the selection of supported ciphersuites when using DICOM over TLS. 44 * @remark This enum is only available if DCMTK is compiled with 45 * OpenSSL support enabled. 46 */ 47 enum DcmTLSSecurityProfile 48 { 49 /// No security profile, start with an empty list of ciphersuites 50 TSP_Profile_None, 51 52 /** DICOM Basic TLS Secure Transport Connection Profile (retired), 53 * using the ciphersuite TLS_RSA_WITH_3DES_EDE_CBC_SHA and TLS 1.0 or newer. 54 */ 55 TSP_Profile_Basic, 56 57 /** DICOM AES TLS Secure Transport Connection Profile (retired), 58 * using the ciphersuites TLS_RSA_WITH_AES_128_CBC_SHA and TLS_RSA_WITH_3DES_EDE_CBC_SHA, 59 * and TLS 1.0 or newer. 60 */ 61 TSP_Profile_AES, 62 63 /** DICOM BCP 195 TLS Profile, based on RFC 7525. 64 * This profile tries to negotiate TLS 1.2 or newer, but may fall back to previous 65 * protocol versions up to TLS 1.0. It supports four TLS 1.2 specific ciphersuites 66 * (TLS_DHE_RSA_WITH_AES_128_GCM_SHA256, TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, 67 * TLS_DHE_RSA_WITH_AES_256_GCM_SHA384, TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) 68 * but also the ciphersuites of the AES and Basic Profile, thus providing 69 * backward compatibility with older implementations while offering much 70 * better security when used with implementations also supporting one of the 71 * BCP 195 profiles. 72 */ 73 TSP_Profile_BCP195, 74 75 /** DICOM Non-downgrading BCP 195 TLS Profile, based on RFC 7525. 76 * This profile only negotiates TLS 1.2 or newer, and will not fall back to 77 * previous TLS versions. It supports four ciphersuites: 78 * TLS_DHE_RSA_WITH_AES_128_GCM_SHA256, TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, 79 * TLS_DHE_RSA_WITH_AES_256_GCM_SHA384, TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384. 80 * It does not provide backwards compatibility with the older Basic and AES profiles, 81 * and thus guarantees the higher security level of BCP 195. 82 */ 83 TSP_Profile_BCP195_ND, 84 85 /** DICOM Extended BCP 195 TLS Profile, based on RFC 7525. 86 * This profile only negotiates TLS 1.2, and will not fall back to 87 * previous TLS versions. It does NOT support TLS 1.3. 88 * It supports the same set of ciphersuites as TSP_Profile_BCP195_ND, 89 * plus TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 and TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256. 90 * The other ciphersuites suggested by the profile (see DICOM Part 15, section B.11) 91 * are not supported in OpenSSL 1.0.1 to 1.1.0. 92 * This profile requires DHE keys of at least 2048 bits and ECDHE keys of at least 256 bits. 93 * It does not provide backwards compatibility with the older Basic and AES profiles, 94 * and thus guarantees the higher security level of BCP 195. 95 */ 96 TSP_Profile_BCP195_Extended, 97 98 /** IHE ATNA Profile for Unencrypted In-house Communication (retired). 99 * This profile uses the ciphersuite SSL_RSA_WITH_NULL_SHA and TLS 1.0 or newer. 100 * This ciphersuite offers peer authentication and integrity of communication, 101 * but no encryption (i.e. no confidentiality), and is thus only suitable for use 102 * over a secure infrastructure. This was used in older versions of the 103 * IHE Audit Trail and Node Authentication (ATNA) integration profile, 104 * but has been retired. 105 */ 106 TSP_Profile_IHE_ATNA_Unencrypted 107 108 }; 109 110 111 /** This enum describes the minimum SSL/TLS protocol version required 112 * for a certain ciphersuite. 113 * @remark this enum is only available if DCMTK is compiled with 114 * OpenSSL support enabled. 115 */ 116 enum DcmTLSCipherProtocolVersion 117 { 118 /// Secure Socket Layer (SSL) version 3 or newer 119 TPV_SSLv3, 120 /// Transport Layer Security (TLS) version 1.2 or newer 121 TPV_TLSv12 122 }; 123 124 125 /** This enum describes the key exchange protocol used in a certain 126 * TLS ciphersuite. 127 * @remark this enum is only available if DCMTK is compiled with 128 * OpenSSL support enabled. 129 */ 130 enum DcmTLSCipherKeyExchange 131 { 132 /// Static RSA key exchange 133 TKE_RSA, 134 135 /// Elliptic Curve Diffie–Hellman 136 TKE_ECDH, 137 138 /// Fixed ECDH with ECDSA-signed certificates 139 TKE_ECDH_ECDSA, 140 141 /// Fixed ECDH with RSA signatures 142 TKE_ECDH_RSA, 143 144 /// Diffie–Hellman key exchange 145 TKE_DH 146 147 }; 148 149 150 /** This enum describes the authentication mechanism 151 * used in a certain TLS ciphersuite. 152 * @remark this enum is only available if DCMTK is compiled with 153 * OpenSSL support enabled. 154 */ 155 enum DcmTLSCipherAuthentication 156 { 157 /// Digital Signature Standard 158 TCA_DSS, 159 160 /// Elliptic Curve Diffie–Hellman 161 TCA_ECDH, 162 163 /// Elliptic Curve Digital Signature Algorithm 164 TCA_ECDSA, 165 166 /// RSA 167 TCA_RSA 168 }; 169 170 171 /** This enum describes the symmetric encryption algorithm 172 * (bulk cipher) used in a certain TLS ciphersuite. 173 * @remark this enum is only available if DCMTK is compiled with 174 * OpenSSL support enabled. 175 */ 176 enum DcmTLSCipherEncryption 177 { 178 /// No encryption 179 TCE_None, 180 181 /// Triple DES in Cipher Block Chaining (CBC) mode 182 TCE_3DES, 183 184 /// Advanced Encryption Standard (AES) in Cipher Block Chaining (CBC) mode 185 TCE_AES, 186 187 /// Advanced Encryption Standard (AES) in Galois/Counter Mode (GCM) 188 TCE_AESGCM, 189 190 /// Camellia (RFC 3713) in Cipher Block Chaining (CBC) mode 191 TCE_Camellia, 192 193 /// ChaCha20-Poly1305 in Galois/Counter Mode (GCM) 194 TCE_ChaCha20 195 }; 196 197 198 /** This enum describes the message authentication code (MAC) 199 * used in a certain TLS ciphersuite. 200 * @remark this enum is only available if DCMTK is compiled with 201 * OpenSSL support enabled. 202 */ 203 enum DcmTLSCipherMAC 204 { 205 /// Secure Hash Algorithm SHA-1 206 TCM_SHA1, 207 208 /// Secure Hash Algorithm SHA-2 in 256 bit mode 209 TCM_SHA256, 210 211 /// Secure Hash Algorithm SHA-2 in 384 bit mode 212 TCM_SHA384, 213 214 /// Authenticated Encryption with Associated Data (AEAD) 215 TCM_AEAD 216 217 }; 218 219 220 /** This helper class manages the list of TLS ciphersuites supported by DCMTK, 221 * translates DcmTLSSecurityProfile enums into the corresponding sets of 222 * ciphersuites, and permits translation between the official TLS ciphersuite 223 * names (as used in DCMTK) and the corresponding internal OpenSSL name. 224 * @remark This class is only available if DCMTK is compiled with 225 * OpenSSL support enabled. 226 */ 227 class DCMTK_DCMTLS_EXPORT DcmTLSCiphersuiteHandler 228 { 229 public: 230 231 /** constructor. The constructor assumes that the OpenSSL library 232 * has already been initialized. This should be ensured prior to creating 233 * any DcmTLSCiphersuiteHandler instance by calling 234 * DcmTLSTransportLayer::initializeOpenSSL(). This only needs to be done once. 235 */ 236 DcmTLSCiphersuiteHandler(); 237 238 /// destructor 239 virtual ~DcmTLSCiphersuiteHandler(); 240 241 /** replace the current list of ciphersuites by the list of ciphersuites 242 * for the given profile. 243 * @param profile TLS Security Profile 244 * @return TCS_ok if successful, an error code otherwise 245 */ 246 DcmTransportLayerStatus setTLSProfile(DcmTLSSecurityProfile profile); 247 248 /** return the currently selected TLS profile 249 * @return currently selected TLS profile 250 */ getTLSProfile()251 DcmTLSSecurityProfile getTLSProfile() const 252 { 253 return currentProfile; 254 } 255 256 /** clear the current list of ciphersuites. Equivalent to 257 * calling setTLSProfile(TSP_Profile_None). 258 */ 259 void clearTLSProfile(); 260 261 /** adds a ciphersuite to the list of ciphersuites for TLS negotiation. 262 * It is the responsibility of the user to ensure that the added ciphersuite 263 * does not break the rules of the selected profile. Use with care! 264 * @param suite TLS ciphersuite name, in the official TLS name form. 265 * @return TCS_ok if successful, an error code otherwise 266 */ 267 DcmTransportLayerStatus addCipherSuite(const char *suite); 268 269 /** returns a string in OpenSSL syntax that contains the currently defined 270 * list of TLS ciphersuites. 271 * @param cslist The list of ciphersuites in OpenSSL syntax is written to this string. 272 * @param isServer true if the list of cipher suites is intended for 273 * a TLS server. In this case, the list of ciphersuites will be reordered 274 * from strongest to weakest, as recommended by BCP 195. 275 */ 276 void getListOfCipherSuitesForOpenSSL(OFString& cslist, OFBool isServer) const; 277 278 /** returns the set of flags that need to be activated in OpenSSL 279 * depending on the selected TLS profile. 280 * @return flags for openssl 281 */ 282 long getTLSOptions() const; 283 284 /** checks if the 3DES ciphersuite TLS_RSA_WITH_3DES_EDE_CBC_SHA 285 * is supported by the underlying OpenSSL library (which newer versions 286 * only do if compiled with "weak ciphers" enabled). 287 * @return true if we support 3DES, false otherwise 288 */ 289 OFBool cipher3DESsupported() const; 290 291 /** checks if the unencrypted ciphersuite TLS_RSA_WITH_NULL_SHA 292 * is supported by the underlying OpenSSL library (which newer versions 293 * only do if compiled with "weak ciphers" enabled). 294 * @return true if we support unencrypted TLS, false otherwise 295 */ 296 OFBool cipherNULLsupported() const; 297 298 /** checks if TLS 1.3 is enabled (permitted) for the currently selected 299 * TLS security profile. Note that this does not imply that the underlying 300 * OpenSSL library version actually supports TLS 1.3. That is checked elsewhere. 301 * @return true if we support TLS 1.3, false otherwise 302 */ 303 OFBool isTLS13Enabled() const; 304 305 /** print a list of supported ciphersuites to the given output stream 306 * @param os output stream 307 */ 308 void printSupportedCiphersuites(STD_NAMESPACE ostream& os) const; 309 310 /** returns the number of known ciphersuites. 311 * @return number of known ciphersuites 312 */ 313 static size_t getNumberOfCipherSuites(); 314 315 /** looks up the index of the given ciphersuite by name 316 * @param tlsCipherSuiteName ciphersuite name in RFC 2246 form 317 * @returns index into list of ciphersuites, DcmTLSCiphersuiteHandler::unknownCipherSuiteIndex if ciphersuite unknown 318 */ 319 static size_t lookupCiphersuite(const char *tlsCipherSuiteName); 320 321 /** looks up the index of the given ciphersuite by OpenSSL name 322 * @param tlsCipherSuiteName ciphersuite name in the form used by OpenSSL 323 * @returns index into list of ciphersuites, DcmTLSCiphersuiteHandler::unknownCipherSuiteIndex if ciphersuite unknown 324 */ 325 static size_t lookupCiphersuiteByOpenSSLName(const char *opensslCipherSuiteName); 326 327 /** returns a ciphersuite name in RFC 2246 (TLS) form 328 * @param idx index, must be < getNumberOfCipherSuites() 329 * @return ciphersuite name 330 */ 331 static const char *getTLSCipherSuiteName(size_t idx); 332 333 /** returns a ciphersuite name in OpenSSL form 334 * @param idx index, must be < getNumberOfCipherSuites() 335 * @return ciphersuite name 336 */ 337 static const char *getOpenSSLCipherSuiteName(size_t idx); 338 339 /** returns the minimum SSL/TLS version required for the ciphersuite with the given index 340 * @param idx index, must be < getNumberOfCipherSuites() 341 * @return minimum SSL/TLS version required 342 */ 343 static DcmTLSCipherProtocolVersion getCipherSuiteProtocolVersion(size_t idx); 344 345 /** returns the key exchange protocol used by the ciphersuite with the given index 346 * @param idx index, must be < getNumberOfCipherSuites() 347 * @return key exchange protocol 348 */ 349 static DcmTLSCipherKeyExchange getCipherSuiteKeyExchange(size_t idx); 350 351 /** returns the authentication algorithm used by the ciphersuite with the given index 352 * @param idx index, must be < getNumberOfCipherSuites() 353 * @return authentication algorithm 354 */ 355 static DcmTLSCipherAuthentication getCipherSuiteAuthentication(size_t idx); 356 357 /** returns the encryption algorithm used by the ciphersuite with the given index 358 * @param idx index, must be < getNumberOfCipherSuites() 359 * @return minimum SSL/TLS version required 360 */ 361 static DcmTLSCipherEncryption getCipherSuiteEncryption(size_t idx); 362 363 /** returns the message authentication code (MAC) algorithm used by the ciphersuite with the given index 364 * @param idx index, must be < getNumberOfCipherSuites() 365 * @return message authentication code (MAC) algorithm 366 */ 367 static DcmTLSCipherMAC getCipherSuiteMAC(size_t idx); 368 369 /** returns the symmetric key size used by the ciphersuite with the given index 370 * @param idx index, must be < getNumberOfCipherSuites() 371 * @return symmetric key size, in bits 372 */ 373 static size_t getCipherSuiteKeySize(size_t idx); 374 375 /** returns the effective symmetric key size (i.e. security level) of the ciphersuite with the given index. 376 * BCP 195 (2015) recommends that no ciphersuites with an effective key size of less than 112 bits should be used anymore with TLS. 377 * @param idx index, must be < getNumberOfCipherSuites() 378 * @return effective symmetric key size, in bits 379 */ 380 static size_t getCipherSuiteEffectiveKeySize(size_t idx); 381 382 /** look up the name of the given security profile 383 * @return name of security profile, never NULL. 384 */ 385 static const char *lookupProfileName(DcmTLSSecurityProfile profile); 386 387 /// constant returned by findOpenSSLCipherSuiteName() if ciphersuite name is unknown 388 static const size_t unknownCipherSuiteIndex; 389 390 private: 391 392 /// private undefined copy constructor 393 DcmTLSCiphersuiteHandler(const DcmTLSCiphersuiteHandler&); 394 395 /// private undefined assignment operator 396 DcmTLSCiphersuiteHandler& operator=(const DcmTLSCiphersuiteHandler&); 397 398 /** determine the set of ciphersuites that are supported both by DCMTK 399 * and the OpenSSL library we are currently using 400 */ 401 void determineSupportedCiphers(); 402 403 /** add ciphersuite by name, print error if unsupported 404 * @param name ciphersuite name in RFC 2246 form 405 * @return TCS_ok if successful, an error code otherwise 406 */ 407 DcmTransportLayerStatus addRequiredCipherSuite(const char *name); 408 409 /** add 3DES ciphersuite, print warning if unsupported 410 */ 411 void addOptional3DESCipherSuite(); 412 413 /// current list of ciphersuites 414 OFVector<size_t> ciphersuiteList; 415 416 /// currently selected DICOM TLS security profile 417 DcmTLSSecurityProfile currentProfile; 418 419 /// indicator whether TLS 1.3 is enabled or disabled for the current profile 420 OFBool tls13_enabled; 421 422 /** an array of booleans indicating which ciphersuites known to DCMTK are 423 * actually supported by the OpenSSL library we are using. 424 */ 425 OFBool *ciphersuiteSupported; 426 }; 427 428 #endif /* WITH_OPENSSL */ 429 #endif /* TLSCIPHR_H */ 430