1 /*
   2  * Copyright (c) 2015, 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.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 package sun.security.ssl;
  27 
  28 import java.util.HashSet;
  29 import java.util.Set;
  30 import sun.security.util.AlgorithmDecomposer;
  31 import static sun.security.ssl.CipherSuite.*;
  32 import static sun.security.ssl.CipherSuite.KeyExchange.*;
  33 
  34 /**
  35  * The class decomposes standard SSL/TLS cipher suites into sub-elements.
  36  */
  37 class SSLAlgorithmDecomposer extends AlgorithmDecomposer {
  38 
  39     // indicates that only certification path algorithms need to be used
  40     private final boolean onlyX509;
  41 
  42     SSLAlgorithmDecomposer(boolean onlyX509) {
  43         this.onlyX509 = onlyX509;
  44     }
  45 
  46     SSLAlgorithmDecomposer() {
  47         this(false);
  48     }
  49 
  50     private Set<String> decomposes(CipherSuite.KeyExchange keyExchange) {
  51         Set<String> components = new HashSet<>();
  52         switch (keyExchange) {
  53             case K_NULL:
  54                 if (!onlyX509) {
  55                     components.add("K_NULL");
  56                 }
  57                 break;
  58             case K_RSA:
  59                 components.add("RSA");
  60                 break;
  61             case K_RSA_EXPORT:
  62                 components.add("RSA");
  63                 components.add("RSA_EXPORT");
  64                 break;
  65             case K_DH_RSA:
  66                 components.add("RSA");
  67                 components.add("DH");
  68                 components.add("DiffieHellman");
  69                 components.add("DH_RSA");
  70                 break;
  71             case K_DH_DSS:
  72                 components.add("DSA");
  73                 components.add("DSS");
  74                 components.add("DH");
  75                 components.add("DiffieHellman");
  76                 components.add("DH_DSS");
  77                 break;
  78             case K_DHE_DSS:
  79                 components.add("DSA");
  80                 components.add("DSS");
  81                 components.add("DH");
  82                 components.add("DHE");
  83                 components.add("DiffieHellman");
  84                 components.add("DHE_DSS");
  85                 break;
  86             case K_DHE_RSA:
  87                 components.add("RSA");
  88                 components.add("DH");
  89                 components.add("DHE");
  90                 components.add("DiffieHellman");
  91                 components.add("DHE_RSA");
  92                 break;
  93             case K_DH_ANON:
  94                 if (!onlyX509) {
  95                     components.add("ANON");
  96                     components.add("DH");
  97                     components.add("DiffieHellman");
  98                     components.add("DH_ANON");
  99                 }
 100                 break;
 101             case K_ECDH_ECDSA:
 102                 components.add("ECDH");
 103                 components.add("ECDSA");
 104                 components.add("ECDH_ECDSA");
 105                 break;
 106             case K_ECDH_RSA:
 107                 components.add("ECDH");
 108                 components.add("RSA");
 109                 components.add("ECDH_RSA");
 110                 break;
 111             case K_ECDHE_ECDSA:
 112                 components.add("ECDHE");
 113                 components.add("ECDSA");
 114                 components.add("ECDHE_ECDSA");
 115                 break;
 116             case K_ECDHE_RSA:
 117                 components.add("ECDHE");
 118                 components.add("RSA");
 119                 components.add("ECDHE_RSA");
 120                 break;
 121             case K_ECDH_ANON:
 122                 if (!onlyX509) {
 123                     components.add("ECDH");
 124                     components.add("ANON");
 125                     components.add("ECDH_ANON");
 126                 }
 127                 break;
 128             case K_KRB5:
 129                 if (!onlyX509) {
 130                     components.add("KRB5");
 131                 }
 132                 break;
 133             case K_KRB5_EXPORT:
 134                 if (!onlyX509) {
 135                     components.add("KRB5_EXPORT");
 136                 }
 137                 break;
 138             default:
 139                 // ignore
 140             }
 141 
 142         return components;
 143     }
 144 
 145     private Set<String> decomposes(CipherSuite.BulkCipher bulkCipher) {
 146         Set<String> components = new HashSet<>();
 147 
 148         if (bulkCipher.transformation != null) {
 149             components.addAll(super.decompose(bulkCipher.transformation));
 150         }
 151 
 152         if (bulkCipher == B_NULL) {
 153             components.add("C_NULL");
 154         } else if (bulkCipher == B_RC2_40) {
 155             components.add("RC2_CBC_40");
 156         } else if (bulkCipher == B_RC4_40) {
 157             components.add("RC4_40");
 158         } else if (bulkCipher == B_RC4_128) {
 159             components.add("RC4_128");
 160         } else if (bulkCipher == B_DES_40) {
 161             components.add("DES40_CBC");
 162             components.add("DES_CBC_40");
 163         } else if (bulkCipher == B_DES) {
 164             components.add("DES_CBC");
 165         } else if (bulkCipher == B_3DES) {
 166             components.add("3DES_EDE_CBC");
 167         } else if (bulkCipher == B_AES_128) {
 168             components.add("AES_128_CBC");
 169         } else if (bulkCipher == B_AES_256) {
 170             components.add("AES_256_CBC");
 171         } else if (bulkCipher == B_AES_128_GCM) {
 172             components.add("AES_128_GCM");
 173         } else if (bulkCipher == B_AES_256_GCM) {
 174             components.add("AES_256_GCM");
 175         }
 176 
 177         return components;
 178     }
 179 
 180     private Set<String> decomposes(CipherSuite.MacAlg macAlg,
 181             BulkCipher cipher) {
 182         Set<String> components = new HashSet<>();
 183 
 184         if (macAlg == M_NULL
 185                 && cipher.cipherType != CipherType.AEAD_CIPHER) {
 186             components.add("M_NULL");
 187         } else if (macAlg == M_MD5) {
 188             components.add("MD5");
 189             components.add("HmacMD5");
 190         } else if (macAlg == M_SHA) {
 191             components.add("SHA1");
 192             components.add("SHA-1");
 193             components.add("HmacSHA1");
 194         } else if (macAlg == M_SHA256) {
 195             components.add("SHA256");
 196             components.add("SHA-256");
 197             components.add("HmacSHA256");
 198         } else if (macAlg == M_SHA384) {
 199             components.add("SHA384");
 200             components.add("SHA-384");
 201             components.add("HmacSHA384");
 202         }
 203 
 204         return components;
 205     }
 206 
 207     private Set<String> decompose(KeyExchange keyExchange, BulkCipher cipher,
 208             MacAlg macAlg) {
 209         Set<String> components = new HashSet<>();
 210 
 211         if (keyExchange != null) {
 212             components.addAll(decomposes(keyExchange));
 213         }
 214 
 215         if (onlyX509) {
 216             // Certification path algorithm constraints do not apply
 217             // to cipher and macAlg.
 218             return components;
 219         }
 220 
 221         if (cipher != null) {
 222             components.addAll(decomposes(cipher));
 223         }
 224 
 225         if (macAlg != null) {
 226             components.addAll(decomposes(macAlg, cipher));
 227         }
 228 
 229         return components;
 230     }
 231 
 232     @Override
 233     public Set<String> decompose(String algorithm) {
 234         if (algorithm.startsWith("SSL_") || algorithm.startsWith("TLS_")) {
 235             CipherSuite cipherSuite = null;
 236             try {
 237                 cipherSuite = CipherSuite.valueOf(algorithm);
 238             } catch (IllegalArgumentException iae) {
 239                 // ignore: unknown or unsupported ciphersuite
 240             }
 241 
 242             if (cipherSuite != null) {
 243                 return decompose(cipherSuite.keyExchange, cipherSuite.cipher,
 244                         cipherSuite.macAlg);
 245             }
 246         }
 247 
 248         return super.decompose(algorithm);
 249     }
 250 
 251 }