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             "brainpool512r1",
152             "brainpool384r1",
153             "brainpool256r1",
154             "secp521r1",
155             "secp384r1",
156             "secp256r1",
157             "secp256k1",
158             "secp224r1",
159             "secp224k1",
160             "secp192r1",
161             "secp192k1",
162             "secp160r2",
163             "secp160r1",
164             "secp160k1",
165         ]);
166     }
167 
168     /**
169     * Returns a list of compression algorithms we are willing to use,
170     * in order of preference. Allowed values any value of
171     * Compression_Method.
172     *
173     * @note Compression is not currently supported
174     */
175     Vector!ubyte compression() const
176     {
177         return Vector!ubyte([NO_COMPRESSION]);
178     }
179 
180 
181     /**
182     * Choose an elliptic curve to use
183     */
184 	string chooseCurve(in Vector!string curve_names) const
185 	{
186 		const Vector!string our_curves = allowedEccCurves();
187 		for (size_t i = 0; i != our_curves.length; ++i) 
188 			if (valueExists(curve_names, our_curves[i])) 
189 				return our_curves[i];
190 		
191 		return ""; // no shared curve
192 	}
193 
194     /**
195     * Attempt to negotiate the use of the heartbeat extension
196     */
197     bool negotiateHeartbeatSupport() const
198     {
199         return false;
200     }
201 
202     /**
203     * Allow renegotiation even if the counterparty doesn't
204     * support the secure renegotiation extension.
205     *
206     * Notes:
207     *  Changing this to true exposes you to injected plaintext attacks. 
208     *  Read RFC 5746 for background.
209     */
210     bool allowInsecureRenegotiation() const { return false; }
211 
212     /**
213      * The protocol dictates that the first 32 bits of the random
214      * field are the current time in seconds. However this allows
215      * client fingerprinting attacks. Set to false to disable, in
216      * which case random bytes will be used instead.
217      */
218     bool includeTimeInHelloRandom() const { return false; }
219 
220     /**
221     * Allow servers to initiate a new handshake
222     */
223     bool allowServerInitiatedRenegotiation() const
224     {
225         return true;
226     }
227 
228     /**
229     * Return the group to use for ephemeral Diffie-Hellman key agreement
230     */
231     DLGroup dhGroup() const
232     {
233         return DLGroup("modp/ietf/2048");
234     }
235 
236     /**
237     * Return the minimum DH group size we're willing to use
238     */
239     size_t minimumDhGroupSize() const
240     {
241         return 1024;
242     }
243 
244     /**
245     * If this function returns false, unknown SRP/PSK identifiers
246     * will be rejected with an unknown_psk_identifier alert as soon
247     * as the non-existence is identified. Otherwise, a false
248     * identifier value will be used and the protocol allowed to
249     * proceed, causing the handshake to eventually fail without
250     * revealing that the username does not exist on this system.
251     */
252     bool hideUnknownUsers() const { return false; }
253 
254     /**
255     * Return the allowed lifetime of a session ticket. If 0, session
256     * tickets do not expire until the session ticket key rolls over.
257     * Expired session tickets cannot be used to resume a session.
258     */
259     Duration sessionTicketLifetime() const
260     {
261         return 24.hours; // 1 day
262     }
263 
264     /**
265     * Returns: true if and only if we are willing to accept this version
266     * Default accepts only TLS, so if you want to enable DTLS override
267     * in your application.
268     */
269     bool acceptableProtocolVersion(TLSProtocolVersion _version) const
270     {
271         if (_version.isDatagramProtocol())
272             return (_version >= TLSProtocolVersion.DTLS_V12);
273         
274         return (_version >= TLSProtocolVersion.TLS_V10);
275     }
276     /**
277      * Returns the more recent protocol version we are willing to
278      * use, for either TLS or DTLS depending on datagram param.
279      * Shouldn't ever need to override this unless you want to allow
280      * a user to disable use of TLS v1.2 (which is *not recommended*)
281      */
282     TLSProtocolVersion latestSupportedVersion(bool datagram) const
283     {
284         if (datagram)
285             return TLSProtocolVersion.latestDtlsVersion();
286         else
287             return TLSProtocolVersion.latestTlsVersion();
288     }
289 
290     /**
291      * When offering this version, should we send a fallback SCSV?
292      * Default returns true iff version is the latest version the
293      * policy allows, exists to allow override in case of interop problems.
294      */
295     bool sendFallbackSCSV(in TLSProtocolVersion _version) const
296     {
297         return _version == latestSupportedVersion(_version.isDatagramProtocol());
298     }
299 
300     /**
301      * Allows policy to reject any ciphersuites which are undesirable
302      * for whatever reason without having to reimplement ciphersuite_list
303      */
304     bool acceptableCiphersuite(in TLSCiphersuite) const
305     {
306         return true;
307     }
308 
309     /**
310     * Returns: true if servers should choose the ciphersuite matching
311     *            their highest preference, rather than the clients.
312     *            Has no effect on client side.
313     */
314     bool serverUsesOwnCiphersuitePreferences() const { return true; }
315 
316     /**
317     * Return allowed ciphersuites, in order of preference
318     */
319     Vector!ushort ciphersuiteList(TLSProtocolVersion _version, bool have_srp) const
320     {
321         Vector!string ciphers = allowedCiphers();
322         Vector!string macs = allowedMacs();
323         Vector!string kex = allowedKeyExchangeMethods();
324         Vector!string sigs = allowedSignatureMethods();
325         
326         CiphersuitePreferenceOrdering order = CiphersuitePreferenceOrdering(ciphers, macs, kex, sigs);
327         
328         Vector!(TLSCiphersuite) ciphersuites;
329 		ciphersuites.reserve(64);
330 		auto cipher_suites = TLSCiphersuite.allKnownCiphersuites();
331 		foreach (const ref TLSCiphersuite suite; cipher_suites)
332         {
333             if (!acceptableCiphersuite(suite))
334                 continue;
335             
336             if (!have_srp && suite.kexAlgo() == "SRP_SHA")
337                 continue;
338             
339             if (_version.isDatagramProtocol() && suite.cipherAlgo() == "RC4")
340                 continue;
341             
342             if (!_version.supportsAeadModes() && suite.macAlgo() == "AEAD")
343                 continue;
344             
345             if (!valueExists(kex, suite.kexAlgo()))
346                 continue; // unsupported key exchange
347             
348             if (!valueExists(ciphers, suite.cipherAlgo()))
349                 continue; // unsupported cipher
350             
351             if (!valueExists(macs, suite.macAlgo()))
352                 continue; // unsupported MAC algo
353             
354             if (!valueExists(sigs, suite.sigAlgo()))
355             {
356                 // allow if it's an empty sig algo and we want to use PSK
357                 if (suite.sigAlgo() != "" || !suite.pskCiphersuite())
358                     continue;
359             }
360             
361             // OK, allow it:
362             ciphersuites ~= suite;
363         }
364         
365         if (ciphersuites.length == 0)
366             throw new LogicError("TLSPolicy does not allow any available cipher suite");
367         Vector!ushort ciphersuite_codes;
368 		auto ciphersuites_ordered = ciphersuites[].uniq.array.sort!((a,b){ return order.compare(a, b); }).array.to!(TLSCiphersuite[]);
369 		foreach (TLSCiphersuite i; ciphersuites_ordered)
370             ciphersuite_codes.pushBack(i.ciphersuiteCode());
371         return ciphersuite_codes;
372     }
373 
374     ~this() {}
375 }
376 
377 /**
378 * NSA Suite B 128-bit security level (see @rfc 6460)
379 */
380 class NSASuiteB128 : TLSPolicy
381 {
382 public:
383     override Vector!string allowedCiphers() const
384     { return Vector!string(["AES-128/GCM"]); }
385 
386     override Vector!string allowedSignatureHashes() const
387     { return Vector!string(["SHA-256"]); }
388 
389     override Vector!string allowedMacs() const
390     { return Vector!string(["AEAD"]); }
391 
392     override Vector!string allowedKeyExchangeMethods() const
393     { return Vector!string(["ECDH"]); }
394 
395     override Vector!string allowedSignatureMethods() const
396     { return Vector!string(["ECDSA"]); }
397 
398     override Vector!string allowedEccCurves() const
399     { return Vector!string(["secp256r1"]); }
400 
401     override bool acceptableProtocolVersion(TLSProtocolVersion _version) const
402     { return _version == TLSProtocolVersion.TLS_V12; }
403 }
404 
405 /**
406 * TLSPolicy for DTLS. We require DTLS v1.2 and an AEAD mode
407 */
408 class DatagramPolicy : TLSPolicy
409 {
410 public:
411     override Vector!string allowedMacs() const
412     { return Vector!string(["AEAD"]); }
413 
414     override bool acceptableProtocolVersion(TLSProtocolVersion _version) const
415     { return _version == TLSProtocolVersion.DTLS_V12; }
416 }
417 
418 
419 private:
420 
421 struct CiphersuitePreferenceOrdering
422 {
423 public:
424     this(ref Vector!string ciphers, ref Vector!string macs, ref Vector!string kex, ref Vector!string sigs)
425     {
426         m_ciphers = ciphers.dup();
427         m_macs = macs.dup();
428         m_kex = kex.dup(); 
429         m_sigs = sigs.dup();
430     }
431     
432     bool compare(U : TLSCiphersuite)(in TLSCiphersuite a, auto ref U b) const
433     {
434         if (a.kexAlgo() != b.kexAlgo())
435         {
436             for (size_t i = 0; i != m_kex.length; ++i)
437             {
438                 if (a.kexAlgo() == m_kex[i])
439                     return true;
440                 if (b.kexAlgo() == m_kex[i])
441                     return false;
442             }
443         }
444         
445         if (a.cipherAlgo() != b.cipherAlgo())
446         {
447             for (size_t i = 0; i != m_ciphers.length; ++i)
448             {
449                 if (a.cipherAlgo() == m_ciphers[i])
450                     return true;
451                 if (b.cipherAlgo() == m_ciphers[i])
452                     return false;
453             }
454         }
455         
456         if (a.cipherKeylen() != b.cipherKeylen())
457         {
458             if (a.cipherKeylen() < b.cipherKeylen())
459                 return false;
460             if (a.cipherKeylen() > b.cipherKeylen())
461                 return true;
462         }
463         
464         if (a.sigAlgo() != b.sigAlgo())
465         {
466             for (size_t i = 0; i != m_sigs.length; ++i)
467             {
468                 if (a.sigAlgo() == m_sigs[i])
469                     return true;
470                 if (b.sigAlgo() == m_sigs[i])
471                     return false;
472             }
473         }
474         
475         if (a.macAlgo() != b.macAlgo())
476         {
477             for (size_t i = 0; i != m_macs.length; ++i)
478             {
479                 if (a.macAlgo() == m_macs[i])
480                     return true;
481                 if (b.macAlgo() == m_macs[i])
482                     return false;
483             }
484         }
485         
486         return false; // equal (?!?)
487     }
488 private:
489     Vector!string m_ciphers, m_macs, m_kex, m_sigs;
490 }