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             = Utils.getBoolProperty("fullCases");
  34 
  35     public static final boolean FULL_CIPHER_SUITES
  36             = Utils.getBoolProperty("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 
 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 
 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             FULL_CASES ? PROTOCOLS : PROTOCOLS,
 133             FULL_CASES ? 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 
 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
 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 
 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 
 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 }