1 /**
2 * Hooks for application level policies on TLS connections
3 * 
4 * Copyright:
5 * (C) 2004-2006,2013 Jack Lloyd
6 * (C) 2014-2015 Etienne Cimon
7 *
8 * License:
9 * Botan is released under the Simplified BSD License (see LICENSE.md)
10 */
11 module botan.tls.policy;
12 
13 import botan.constants;
14 static if (BOTAN_HAS_TLS):
15 
16 import botan.tls.version_;
17 import botan.tls.ciphersuite;
18 import botan.cert.x509.x509cert;
19 import botan.pubkey.algo.dl_group;
20 import botan.tls.ciphersuite;
21 import botan.tls.magic;
22 import botan.tls.exceptn;
23 import memutils.dictionarylist;
24 import std.datetime;
25 import std.algorithm : uniq, sort;
26 import std.array : array, Appender;
27 import std.conv : to;
28 import botan.utils.types;
29 public import botan.tls.extensions;
30 
31 /**
32 * TLSPolicy Base Class
33 * Inherit and overload as desired to suit local policy concerns
34 */
35 class TLSPolicy
36 {
37 public:
38 	Vector!HandshakeExtensionType enabledExtensions() const {
39 		return Vector!HandshakeExtensionType([TLSEXT_SAFE_RENEGOTIATION,
40 				TLSEXT_SERVER_NAME_INDICATION,
41 				TLSEXT_EC_POINT_FORMATS,
42 				TLSEXT_USABLE_ELLIPTIC_CURVES,
43 				TLSEXT_EXTENDED_MASTER_SECRET,
44 				TLSEXT_SESSION_TICKET,
45 				TLSEXT_SIGNATURE_ALGORITHMS,
46 				//TLSEXT_STATUS_REQUEST,
47 				//TLSEXT_NPN,
48 				//TLSEXT_SIGNED_CERT_TIMESTAMP,
49 				TLSEXT_ALPN,
50 				TLSEXT_CHANNEL_ID,
51 				TLSEXT_SRP_IDENTIFIER,
52 				TLSEXT_HEARTBEAT_SUPPORT,
53 				TLSEXT_MAX_FRAGMENT_LENGTH]);
54 	}
55 
56     /**
57     * Returns a list of ciphers we are willing to negotiate, in
58     * order of preference.
59     */
60     Vector!string allowedCiphers() const
61     {
62         return Vector!string([
63 			"AES-128/GCM",
64             "AES-256/GCM",
65 			"ChaCha20Poly1305",
66             "AES-256/CCM",
67             "AES-128/CCM",
68             "AES-256/CCM-8",
69             "AES-128/CCM-8",
70             "Camellia-256/GCM",
71             "Camellia-128/GCM",
72             "AES-256",
73             "AES-128",
74             "Camellia-256",
75             "Camellia-128",
76             "SEED",
77             "3DES",
78             "RC4",
79         ]);
80     }
81 
82     /**
83     * Returns a list of hash algorithms we are willing to use for
84     * signatures, in order of preference.
85     */
86     Vector!string allowedSignatureHashes() const
87     {
88         return Vector!string([
89 			"SHA-256",
90             "SHA-512",
91             "SHA-384",
92             "SHA-224",
93             "SHA-1",
94             "MD5",
95         ]);
96     }
97 
98 
99     /**
100     * Returns a list of MAC algorithms we are willing to use.
101     */
102     Vector!string allowedMacs() const
103     {
104         return Vector!string([
105             "AEAD",
106             "SHA-384",
107             "SHA-256",
108             "SHA-1",
109             "MD5",
110         ]);
111     }
112 
113     /**
114     * Returns a list of key exchange algorithms we are willing to
115     * use, in order of preference. Allowed values: DH, empty string
116     * (representing RSA using server certificate key)
117     */
118     Vector!string allowedKeyExchangeMethods() const
119     {
120         return Vector!string([
121             //"SRP_SHA",
122             //"ECDHE_PSK",
123             //"DHE_PSK",
124             //"PSK",
125 			"RSA",
126 			"ECDH",
127             "DH",
128         ]);
129     }
130 
131     /**
132     * Returns a list of signature algorithms we are willing to
133     * use, in order of preference. Allowed values RSA and DSA.
134     */
135     Vector!string allowedSignatureMethods() const
136     {
137         return Vector!string([
138 			"RSA",
139 			"ECDSA",
140             "DSA",
141             //""
142         ]);
143     }
144 
145     /**
146     * Return list of ECC curves we are willing to use in order of preference
147     */
148     Vector!string allowedEccCurves() const
149     {
150         return Vector!string([
151 			"x25519",
152             "brainpool512r1",
153             "brainpool384r1",
154             "brainpool256r1",
155             "secp521r1",
156             "secp384r1",
157             "secp256r1",
158             "secp256k1",
159             "secp224r1",
160             "secp224k1",
161             "secp192r1",
162             "secp192k1",
163             "secp160r2",
164             "secp160r1",
165             "secp160k1",
166         ]);
167     }
168 
169     /**
170     * Returns a list of compression algorithms we are willing to use,
171     * in order of preference. Allowed values any value of
172     * Compression_Method.
173     *
174     * @note Compression is not currently supported
175     */
176     Vector!ubyte compression() const
177     {
178         return Vector!ubyte([NO_COMPRESSION]);
179     }
180 
181 
182     /**
183     * Choose an elliptic curve to use
184     */
185 	string chooseCurve(in Vector!string curve_names) const
186 	{
187 		const Vector!string our_curves = allowedEccCurves();
188 		for (size_t i = 0; i != our_curves.length; ++i) 
189 			if (valueExists(curve_names, our_curves[i])) 
190 				return our_curves[i];
191 		
192 		return ""; // no shared curve
193 	}
194 
195     /**
196     * Attempt to negotiate the use of the heartbeat extension
197     */
198     bool negotiateHeartbeatSupport() const
199     {
200         return false;
201     }
202 
203     /**
204     * Allow renegotiation even if the counterparty doesn't
205     * support the secure renegotiation extension.
206     *
207     * Notes:
208     *  Changing this to true exposes you to injected plaintext attacks. 
209     *  Read RFC 5746 for background.
210     */
211     bool allowInsecureRenegotiation() const { return false; }
212 
213     /**
214      * The protocol dictates that the first 32 bits of the random
215      * field are the current time in seconds. However this allows
216      * client fingerprinting attacks. Set to false to disable, in
217      * which case random bytes will be used instead.
218      */
219     bool includeTimeInHelloRandom() const { return false; }
220 
221     /**
222     * Allow servers to initiate a new handshake
223     */
224     bool allowServerInitiatedRenegotiation() const
225     {
226         return true;
227     }
228 
229     /**
230     * Return the group to use for ephemeral Diffie-Hellman key agreement
231     */
232     DLGroup dhGroup() const
233     {
234         return DLGroup("modp/ietf/2048");
235     }
236 
237     /**
238     * Return the minimum DH group size we're willing to use
239     */
240     size_t minimumDhGroupSize() const
241     {
242         return 1024;
243     }
244 
245     /**
246     * If this function returns false, unknown SRP/PSK identifiers
247     * will be rejected with an unknown_psk_identifier alert as soon
248     * as the non-existence is identified. Otherwise, a false
249     * identifier value will be used and the protocol allowed to
250     * proceed, causing the handshake to eventually fail without
251     * revealing that the username does not exist on this system.
252     */
253     bool hideUnknownUsers() const { return false; }
254 
255     /**
256     * Return the allowed lifetime of a session ticket. If 0, session
257     * tickets do not expire until the session ticket key rolls over.
258     * Expired session tickets cannot be used to resume a session.
259     */
260     Duration sessionTicketLifetime() const
261     {
262         return 24.hours; // 1 day
263     }
264 
265     /**
266     * Returns: true if and only if we are willing to accept this version
267     * Default accepts only TLS, so if you want to enable DTLS override
268     * in your application.
269     */
270     bool acceptableProtocolVersion(TLSProtocolVersion _version) const
271     {
272         if (_version.isDatagramProtocol())
273             return (_version >= TLSProtocolVersion.DTLS_V12);
274         
275         return (_version >= TLSProtocolVersion.TLS_V10);
276     }
277     /**
278      * Returns the more recent protocol version we are willing to
279      * use, for either TLS or DTLS depending on datagram param.
280      * Shouldn't ever need to override this unless you want to allow
281      * a user to disable use of TLS v1.2 (which is *not recommended*)
282      */
283     TLSProtocolVersion latestSupportedVersion(bool datagram) const
284     {
285         if (datagram)
286             return TLSProtocolVersion.latestDtlsVersion();
287         else
288             return TLSProtocolVersion.latestTlsVersion();
289     }
290 
291     /**
292      * When offering this version, should we send a fallback SCSV?
293      * Default returns true iff version is the latest version the
294      * policy allows, exists to allow override in case of interop problems.
295      */
296     bool sendFallbackSCSV(in TLSProtocolVersion _version) const
297     {
298         return _version == latestSupportedVersion(_version.isDatagramProtocol());
299     }
300 
301     /**
302      * Allows policy to reject any ciphersuites which are undesirable
303      * for whatever reason without having to reimplement ciphersuite_list
304      */
305     bool acceptableCiphersuite(in TLSCiphersuite) const
306     {
307         return true;
308     }
309 
310     /**
311     * Returns: true if servers should choose the ciphersuite matching
312     *            their highest preference, rather than the clients.
313     *            Has no effect on client side.
314     */
315     bool serverUsesOwnCiphersuitePreferences() const { return true; }
316 
317     /**
318     * Return allowed ciphersuites, in order of preference
319     */
320     Vector!ushort ciphersuiteList(TLSProtocolVersion _version, bool have_srp) const
321     {
322         Vector!string ciphers = allowedCiphers();
323         Vector!string macs = allowedMacs();
324         Vector!string kex = allowedKeyExchangeMethods();
325         Vector!string sigs = allowedSignatureMethods();
326         
327         CiphersuitePreferenceOrdering order = CiphersuitePreferenceOrdering(ciphers, macs, kex, sigs);
328         
329         Vector!(TLSCiphersuite) ciphersuites;
330 		ciphersuites.reserve(64);
331 		auto cipher_suites = TLSCiphersuite.allKnownCiphersuites();
332 		foreach (const ref TLSCiphersuite suite; cipher_suites)
333         {
334             if (!acceptableCiphersuite(suite))
335                 continue;
336             
337             if (!have_srp && suite.kexAlgo() == "SRP_SHA")
338                 continue;
339             
340             if (_version.isDatagramProtocol() && suite.cipherAlgo() == "RC4")
341                 continue;
342             
343             if (!_version.supportsAeadModes() && suite.macAlgo() == "AEAD")
344                 continue;
345             
346             if (!valueExists(kex, suite.kexAlgo()))
347                 continue; // unsupported key exchange
348             
349             if (!valueExists(ciphers, suite.cipherAlgo()))
350                 continue; // unsupported cipher
351             
352             if (!valueExists(macs, suite.macAlgo()))
353                 continue; // unsupported MAC algo
354             
355             if (!valueExists(sigs, suite.sigAlgo()))
356             {
357                 // allow if it's an empty sig algo and we want to use PSK
358                 if (suite.sigAlgo() != "" || !suite.pskCiphersuite())
359                     continue;
360             }
361             
362             // OK, allow it:
363             ciphersuites ~= suite;
364         }
365         
366         if (ciphersuites.length == 0)
367             throw new LogicError("TLSPolicy does not allow any available cipher suite");
368         Vector!ushort ciphersuite_codes;
369 		auto ciphersuites_ordered = ciphersuites[].uniq.array.sort!((a,b){ return order.compare(a, b); }).array.to!(TLSCiphersuite[]);
370 		foreach (TLSCiphersuite i; ciphersuites_ordered)
371             ciphersuite_codes.pushBack(i.ciphersuiteCode());
372         return ciphersuite_codes;
373     }
374 
375     ~this() {}
376 }
377 
378 /**
379 * NSA Suite B 128-bit security level (see @rfc 6460)
380 */
381 class NSASuiteB128 : TLSPolicy
382 {
383 public:
384     override Vector!string allowedCiphers() const
385     { return Vector!string(["AES-128/GCM"]); }
386 
387     override Vector!string allowedSignatureHashes() const
388     { return Vector!string(["SHA-256"]); }
389 
390     override Vector!string allowedMacs() const
391     { return Vector!string(["AEAD"]); }
392 
393     override Vector!string allowedKeyExchangeMethods() const
394     { return Vector!string(["ECDH"]); }
395 
396     override Vector!string allowedSignatureMethods() const
397     { return Vector!string(["ECDSA"]); }
398 
399     override Vector!string allowedEccCurves() const
400     { return Vector!string(["secp256r1"]); }
401 
402     override bool acceptableProtocolVersion(TLSProtocolVersion _version) const
403     { return _version == TLSProtocolVersion.TLS_V12; }
404 }
405 
406 /**
407 * TLSPolicy for DTLS. We require DTLS v1.2 and an AEAD mode
408 */
409 class DatagramPolicy : TLSPolicy
410 {
411 public:
412     override Vector!string allowedMacs() const
413     { return Vector!string(["AEAD"]); }
414 
415     override bool acceptableProtocolVersion(TLSProtocolVersion _version) const
416     { return _version == TLSProtocolVersion.DTLS_V12; }
417 }
418 
419 
420 private:
421 
422 struct CiphersuitePreferenceOrdering
423 {
424 public:
425     this(ref Vector!string ciphers, ref Vector!string macs, ref Vector!string kex, ref Vector!string sigs)
426     {
427         m_ciphers = ciphers.dup();
428         m_macs = macs.dup();
429         m_kex = kex.dup(); 
430         m_sigs = sigs.dup();
431     }
432     
433     bool compare(U : TLSCiphersuite)(in TLSCiphersuite a, auto ref U b) const
434     {
435         if (a.kexAlgo() != b.kexAlgo())
436         {
437             for (size_t i = 0; i != m_kex.length; ++i)
438             {
439                 if (a.kexAlgo() == m_kex[i])
440                     return true;
441                 if (b.kexAlgo() == m_kex[i])
442                     return false;
443             }
444         }
445         
446         if (a.cipherAlgo() != b.cipherAlgo())
447         {
448             for (size_t i = 0; i != m_ciphers.length; ++i)
449             {
450                 if (a.cipherAlgo() == m_ciphers[i])
451                     return true;
452                 if (b.cipherAlgo() == m_ciphers[i])
453                     return false;
454             }
455         }
456         
457         if (a.cipherKeylen() != b.cipherKeylen())
458         {
459             if (a.cipherKeylen() < b.cipherKeylen())
460                 return false;
461             if (a.cipherKeylen() > b.cipherKeylen())
462                 return true;
463         }
464         
465         if (a.sigAlgo() != b.sigAlgo())
466         {
467             for (size_t i = 0; i != m_sigs.length; ++i)
468             {
469                 if (a.sigAlgo() == m_sigs[i])
470                     return true;
471                 if (b.sigAlgo() == m_sigs[i])
472                     return false;
473             }
474         }
475         
476         if (a.macAlgo() != b.macAlgo())
477         {
478             for (size_t i = 0; i != m_macs.length; ++i)
479             {
480                 if (a.macAlgo() == m_macs[i])
481                     return true;
482                 if (b.macAlgo() == m_macs[i])
483                     return false;
484             }
485         }
486         
487         return false; // equal (?!?)
488     }
489 private:
490     Vector!string m_ciphers, m_macs, m_kex, m_sigs;
491 }