1 /*
2  * Copyright (c) 2017, 2019, Oracle and/or its affiliates. All rights reserved.
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * This code is free software; you can redistribute it and/or modify it
6  * under the terms of the GNU General Public License version 2 only, as
7  * published by the Free Software Foundation.
8  *
9  * This code is distributed in the hope that it will be useful, but WITHOUT
10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
12  * version 2 for more details (a copy is included in the LICENSE file that
13  * accompanied this code).
14  *
15  * You should have received a copy of the GNU General Public License version
16  * 2 along with this work; if not, write to the Free Software Foundation,
17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18  *
19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20  * or visit www.oracle.com if you need additional information or have any
21  * questions.
22  */
23 
24 import java.util.ArrayList;
25 import java.util.List;
26 
27 /*
28  * The TLS communication use case.
29  */
30 public class UseCase {
31 
32     private static final boolean FULL_CASES
33             = Boolean.getBoolean("fullCases");
34 
35     public static final boolean FULL_CIPHER_SUITES
36             = Boolean.getBoolean("fullCipherSuites");
37 
38     public static final Protocol[] PROTOCOLS = new Protocol[] {
39             Protocol.TLSV1,
40             Protocol.TLSV1_1,
41             Protocol.TLSV1_2,
42             Protocol.TLSV1_3 };
43 
44     public static final CipherSuite[] CIPHER_SUITES = new CipherSuite[] {
45             CipherSuite.TLS_AES_128_GCM_SHA256,
46             CipherSuite.TLS_AES_256_GCM_SHA384,
47             CipherSuite.TLS_CHACHA20_POLY1305_SHA256,
48             CipherSuite.TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256,
49             CipherSuite.TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256,
50             CipherSuite.TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256,
51             CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384,
52             CipherSuite.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384,
53             CipherSuite.TLS_RSA_WITH_AES_256_CBC_SHA256,
54             CipherSuite.TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384,
55             CipherSuite.TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384,
56             CipherSuite.TLS_DHE_RSA_WITH_AES_256_CBC_SHA256,
57             CipherSuite.TLS_DHE_DSS_WITH_AES_256_CBC_SHA256,
58             CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA,
59             CipherSuite.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,
60             CipherSuite.TLS_RSA_WITH_AES_256_CBC_SHA,
61             CipherSuite.TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA,
62             CipherSuite.TLS_ECDH_RSA_WITH_AES_256_CBC_SHA,
63             CipherSuite.TLS_DHE_RSA_WITH_AES_256_CBC_SHA,
64             CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256,
65             CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256,
66             CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA256,
67             CipherSuite.TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256,
68             CipherSuite.TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256,
69             CipherSuite.TLS_DHE_RSA_WITH_AES_128_CBC_SHA256,
70             CipherSuite.TLS_DHE_DSS_WITH_AES_128_CBC_SHA256,
71             CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA,
72             CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,
73             CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA,
74             CipherSuite.TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA,
75             CipherSuite.TLS_DHE_RSA_WITH_AES_128_CBC_SHA,
76             CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,
77             CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
78             CipherSuite.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
79             CipherSuite.TLS_RSA_WITH_AES_256_GCM_SHA384,
80             CipherSuite.TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384,
81             CipherSuite.TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384,
82             CipherSuite.TLS_DHE_RSA_WITH_AES_256_GCM_SHA384,
83             CipherSuite.TLS_DHE_DSS_WITH_AES_256_GCM_SHA384,
84             CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
85             CipherSuite.TLS_RSA_WITH_AES_128_GCM_SHA256,
86             CipherSuite.TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256,
87             CipherSuite.TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256,
88             CipherSuite.TLS_DHE_RSA_WITH_AES_128_GCM_SHA256,
89             CipherSuite.TLS_DHE_DSS_WITH_AES_128_GCM_SHA256 };
90 
91     public static final CipherSuite[] MANDATORY_CIPHER_SUITES = new CipherSuite[] {
92             CipherSuite.TLS_AES_128_GCM_SHA256,
93             CipherSuite.TLS_CHACHA20_POLY1305_SHA256,
94             CipherSuite.TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256,
95             CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA,
96             CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA,
97             CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,
98             CipherSuite.TLS_RSA_WITH_AES_256_CBC_SHA256,
99             CipherSuite.TLS_DHE_DSS_WITH_AES_256_CBC_SHA256,
100             CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384,
101             CipherSuite.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 };
102 
103     enum ServerName {
104 
105         NONE(null),
106         EXAMPLE("EXAMPLE");
107 
108         final String name;
109 
ServerName(String name)110         private ServerName(String name) {
111             this.name = name;
112         }
113     }
114 
115     enum AppProtocol {
116 
117         NONE(null, null),
118         EXAMPLE(new String[] { Utils.HTTP_2, Utils.HTTP_1_1 }, Utils.HTTP_2);
119 
120         final String[] appProtocols;
121 
122         // Expected negotiated application protocol
123         final String negoAppProtocol;
124 
AppProtocol(String[] appProtocols, String negoAppProtocol)125         private AppProtocol(String[] appProtocols, String negoAppProtocol) {
126             this.appProtocols = appProtocols;
127             this.negoAppProtocol = negoAppProtocol;
128         }
129     }
130 
131     private static final Object[][] PARAMS = new Object[][] {
132             PROTOCOLS,
133             FULL_CASES || FULL_CIPHER_SUITES ? CIPHER_SUITES : MANDATORY_CIPHER_SUITES,
134             FULL_CASES ? new Boolean[] { false, true } : new Boolean[] { true },
135             FULL_CASES
136                     ? new ServerName[] { ServerName.NONE, ServerName.EXAMPLE }
137                     : new ServerName[] { ServerName.EXAMPLE },
138             FULL_CASES
139                     ? new AppProtocol[] {
140                             AppProtocol.NONE,
141                             AppProtocol.EXAMPLE }
142                     : new AppProtocol[] {
143                             AppProtocol.EXAMPLE } };
144 
145     public final Protocol protocol;
146     public final CipherSuite cipherSuite;
147     public final Boolean clientAuth;
148     public final ServerName serverName;
149     public final AppProtocol appProtocol;
150 
151     public final boolean negativeCase;
152 
UseCase( Protocol protocol, CipherSuite cipherSuite, boolean clientAuth, ServerName serverName, AppProtocol appProtocol)153     public UseCase(
154             Protocol protocol,
155             CipherSuite cipherSuite,
156             boolean clientAuth,
157             ServerName serverName,
158             AppProtocol appProtocol) {
159         this.protocol = protocol;
160         this.cipherSuite = cipherSuite;
161         this.clientAuth = clientAuth;
162         this.serverName = serverName;
163         this.appProtocol = appProtocol;
164 
165         negativeCase = !cipherSuite.supportedByProtocol(protocol);
166     }
167 
168     @Override
toString()169     public String toString() {
170         return Utils.join(Utils.PARAM_DELIMITER,
171                 "Protocol=" + protocol.name,
172                 "CipherSuite=" + cipherSuite,
173                 "ClientAuth=" + clientAuth,
174                 "ServerName=" + serverName,
175                 "AppProtocols=" + appProtocol);
176     }
177 
getAllUseCases()178     public static List<UseCase> getAllUseCases() {
179         List<UseCase> useCases = new ArrayList<>();
180         getUseCases(PARAMS, 0, new Object[PARAMS.length], useCases);
181         return useCases;
182     }
183 
getUseCases(Object[][] params, int index, Object[] currentValues, List<UseCase> useCases)184     private static void getUseCases(Object[][] params, int index,
185             Object[] currentValues, List<UseCase> useCases) {
186         if (index == params.length) {
187             Protocol protocol = (Protocol) currentValues[0];
188             CipherSuite cipherSuite = (CipherSuite) currentValues[1];
189 
190             UseCase useCase = new UseCase(
191                     protocol,
192                     cipherSuite,
193                     (Boolean) currentValues[2],
194                     (ServerName) currentValues[3],
195                     (AppProtocol) currentValues[4]);
196             useCases.add(useCase);
197         } else {
198             Object[] values = params[index];
199             for (int i = 0; i < values.length; i++) {
200                 currentValues[index] = values[i];
201                 getUseCases(params, index + 1, currentValues, useCases);
202             }
203         }
204     }
205 }
206