1 package org.bouncycastle.jsse.provider; 2 3 import java.util.Collections; 4 import java.util.HashSet; 5 import java.util.Set; 6 7 import org.bouncycastle.tls.CipherSuite; 8 import org.bouncycastle.tls.CipherType; 9 import org.bouncycastle.tls.EncryptionAlgorithm; 10 import org.bouncycastle.tls.KeyExchangeAlgorithm; 11 import org.bouncycastle.tls.MACAlgorithm; 12 import org.bouncycastle.tls.TlsUtils; 13 import org.bouncycastle.tls.crypto.CryptoHashAlgorithm; 14 15 class CipherSuiteInfo 16 { forCipherSuite(int cipherSuite, String name)17 static CipherSuiteInfo forCipherSuite(int cipherSuite, String name) 18 { 19 if (!name.startsWith("TLS_")) 20 { 21 throw new IllegalArgumentException(); 22 } 23 24 int encryptionAlgorithm = TlsUtils.getEncryptionAlgorithm(cipherSuite); 25 int encryptionAlgorithmType = TlsUtils.getEncryptionAlgorithmType(encryptionAlgorithm); 26 int cryptoHashAlgorithm = getCryptoHashAlgorithm(cipherSuite); 27 int keyExchangeAlgorithm = TlsUtils.getKeyExchangeAlgorithm(cipherSuite); 28 int macAlgorithm = TlsUtils.getMACAlgorithm(cipherSuite); 29 30 Set<String> decompositionX509 = new HashSet<String>(); 31 decomposeKeyExchangeAlgorithm(decompositionX509, keyExchangeAlgorithm); 32 33 Set<String> decompositionTLS = new HashSet<String>(decompositionX509); 34 decomposeEncryptionAlgorithm(decompositionTLS, encryptionAlgorithm); 35 decomposeHashAlgorithm(decompositionTLS, cryptoHashAlgorithm); 36 decomposeMACAlgorithm(decompositionTLS, encryptionAlgorithmType, macAlgorithm); 37 38 boolean isTLSv13 = (KeyExchangeAlgorithm.NULL == keyExchangeAlgorithm); 39 40 return new CipherSuiteInfo(cipherSuite, name, isTLSv13, Collections.unmodifiableSet(decompositionTLS), 41 Collections.unmodifiableSet(decompositionX509)); 42 } 43 44 private final int cipherSuite; 45 private final String name; 46 private final boolean isTLSv13; 47 private final Set<String> decompositionTLS, decompositionX509; 48 CipherSuiteInfo(int cipherSuite, String name, boolean isTLSv13, Set<String> decompositionTLS, Set<String> decompositionX509)49 private CipherSuiteInfo(int cipherSuite, String name, boolean isTLSv13, Set<String> decompositionTLS, 50 Set<String> decompositionX509) 51 { 52 this.cipherSuite = cipherSuite; 53 this.name = name; 54 this.isTLSv13 = isTLSv13; 55 this.decompositionTLS = decompositionTLS; 56 this.decompositionX509 = decompositionX509; 57 } 58 getCipherSuite()59 public int getCipherSuite() 60 { 61 return cipherSuite; 62 } 63 getDecompositionTLS()64 public Set<String> getDecompositionTLS() 65 { 66 return decompositionTLS; 67 } 68 getDecompositionX509()69 public Set<String> getDecompositionX509() 70 { 71 return decompositionX509; 72 } 73 getName()74 public String getName() 75 { 76 return name; 77 } 78 isTLSv13()79 boolean isTLSv13() 80 { 81 return isTLSv13; 82 } 83 addAll(Set<String> decomposition, String... entries)84 private static void addAll(Set<String> decomposition, String... entries) 85 { 86 for (String entry : entries) 87 { 88 decomposition.add(entry); 89 } 90 } 91 decomposeEncryptionAlgorithm(Set<String> decomposition, int encryptionAlgorithm)92 private static void decomposeEncryptionAlgorithm(Set<String> decomposition, int encryptionAlgorithm) 93 { 94 String transformation = getTransformation(encryptionAlgorithm); 95 decomposition.addAll(JcaAlgorithmDecomposer.INSTANCE_JCA.decompose(transformation)); 96 97 switch (encryptionAlgorithm) 98 { 99 case EncryptionAlgorithm._3DES_EDE_CBC: 100 decomposition.add("3DES_EDE_CBC"); 101 break; 102 case EncryptionAlgorithm.AES_128_CBC: 103 decomposition.add("AES_128_CBC"); 104 break; 105 case EncryptionAlgorithm.AES_128_CCM: 106 decomposition.add("AES_128_CCM"); 107 break; 108 case EncryptionAlgorithm.AES_128_CCM_8: 109 decomposition.add("AES_128_CCM_8"); 110 break; 111 case EncryptionAlgorithm.AES_128_GCM: 112 decomposition.add("AES_128_GCM"); 113 break; 114 case EncryptionAlgorithm.AES_256_CBC: 115 decomposition.add("AES_256_CBC"); 116 break; 117 case EncryptionAlgorithm.AES_256_CCM: 118 decomposition.add("AES_256_CCM"); 119 break; 120 case EncryptionAlgorithm.AES_256_CCM_8: 121 decomposition.add("AES_256_CCM_8"); 122 break; 123 case EncryptionAlgorithm.AES_256_GCM: 124 decomposition.add("AES_256_GCM"); 125 break; 126 case EncryptionAlgorithm.ARIA_128_CBC: 127 decomposition.add("ARIA_128_CBC"); 128 break; 129 case EncryptionAlgorithm.ARIA_256_CBC: 130 decomposition.add("ARIA_256_CBC"); 131 break; 132 case EncryptionAlgorithm.ARIA_128_GCM: 133 decomposition.add("ARIA_128_GCM"); 134 break; 135 case EncryptionAlgorithm.ARIA_256_GCM: 136 decomposition.add("ARIA_256_GCM"); 137 break; 138 case EncryptionAlgorithm.CAMELLIA_128_CBC: 139 decomposition.add("CAMELLIA_128_CBC"); 140 break; 141 case EncryptionAlgorithm.CAMELLIA_256_CBC: 142 decomposition.add("CAMELLIA_256_CBC"); 143 break; 144 case EncryptionAlgorithm.CAMELLIA_128_GCM: 145 decomposition.add("CAMELLIA_128_GCM"); 146 break; 147 case EncryptionAlgorithm.CAMELLIA_256_GCM: 148 decomposition.add("CAMELLIA_256_GCM"); 149 break; 150 case EncryptionAlgorithm.CHACHA20_POLY1305: 151 // NOTE: Following SunJSSE, nothing beyond the transformation added above (i.e "ChaCha20-Poly1305") 152 break; 153 case EncryptionAlgorithm.NULL: 154 decomposition.add("C_NULL"); 155 break; 156 case EncryptionAlgorithm.SM4_CBC: 157 decomposition.add("SM4_CBC"); 158 break; 159 case EncryptionAlgorithm.SM4_CCM: 160 decomposition.add("SM4_CCM"); 161 break; 162 case EncryptionAlgorithm.SM4_GCM: 163 decomposition.add("SM4_GCM"); 164 break; 165 default: 166 throw new IllegalArgumentException(); 167 } 168 } 169 decomposeHashAlgorithm(Set<String> decomposition, int cryptoHashAlgorithm)170 private static void decomposeHashAlgorithm(Set<String> decomposition, int cryptoHashAlgorithm) 171 { 172 switch (cryptoHashAlgorithm) 173 { 174 case CryptoHashAlgorithm.sha256: 175 addAll(decomposition, "SHA256", "SHA-256", "HmacSHA256"); 176 break; 177 case CryptoHashAlgorithm.sha384: 178 addAll(decomposition, "SHA384", "SHA-384", "HmacSHA384"); 179 break; 180 // case CryptoHashAlgorithm.sha512: 181 // addAll(decomposition, "SHA512", "SHA-512", "HmacSHA512"); 182 // break; 183 case CryptoHashAlgorithm.sm3: 184 addAll(decomposition, "SM3", "HmacSM3"); 185 break; 186 default: 187 throw new IllegalArgumentException(); 188 } 189 } 190 decomposeKeyExchangeAlgorithm(Set<String> decomposition, int keyExchangeAlgorithm)191 private static void decomposeKeyExchangeAlgorithm(Set<String> decomposition, int keyExchangeAlgorithm) 192 { 193 switch (keyExchangeAlgorithm) 194 { 195 case KeyExchangeAlgorithm.DHE_DSS: 196 addAll(decomposition, "DSA", "DSS", "DH", "DHE", "DiffieHellman", "DHE_DSS"); 197 break; 198 case KeyExchangeAlgorithm.DHE_RSA: 199 addAll(decomposition, "RSA", "DH", "DHE", "DiffieHellman", "DHE_RSA"); 200 break; 201 case KeyExchangeAlgorithm.ECDHE_ECDSA: 202 addAll(decomposition, "ECDHE", "ECDSA", "ECDHE_ECDSA"); 203 break; 204 case KeyExchangeAlgorithm.ECDHE_RSA: 205 addAll(decomposition, "ECDHE", "RSA", "ECDHE_RSA"); 206 break; 207 case KeyExchangeAlgorithm.NULL: 208 // NOTE: TLS 1.3 cipher suites 209 break; 210 case KeyExchangeAlgorithm.RSA: 211 addAll(decomposition, "RSA"); 212 break; 213 default: 214 throw new IllegalArgumentException(); 215 } 216 } 217 decomposeMACAlgorithm(Set<String> decomposition, int cipherType, int macAlgorithm)218 private static void decomposeMACAlgorithm(Set<String> decomposition, int cipherType, int macAlgorithm) 219 { 220 switch (macAlgorithm) 221 { 222 case MACAlgorithm._null: 223 if (CipherType.aead != cipherType) 224 { 225 addAll(decomposition, "M_NULL"); 226 } 227 break; 228 case MACAlgorithm.hmac_md5: 229 addAll(decomposition, "MD5", "HmacMD5"); 230 break; 231 case MACAlgorithm.hmac_sha1: 232 addAll(decomposition, "SHA1", "SHA-1", "HmacSHA1"); 233 break; 234 case MACAlgorithm.hmac_sha256: 235 addAll(decomposition, "SHA256", "SHA-256", "HmacSHA256"); 236 break; 237 case MACAlgorithm.hmac_sha384: 238 addAll(decomposition, "SHA384", "SHA-384", "HmacSHA384"); 239 break; 240 // case MACAlgorithm.hmac_sha512: 241 // addAll(decomposition, "SHA512", "SHA-512", "HmacSHA512"); 242 // break; 243 default: 244 throw new IllegalArgumentException(); 245 } 246 } 247 getCryptoHashAlgorithm(int cipherSuite)248 private static int getCryptoHashAlgorithm(int cipherSuite) 249 { 250 switch (cipherSuite) 251 { 252 case CipherSuite.TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA: 253 case CipherSuite.TLS_DHE_DSS_WITH_AES_128_CBC_SHA: 254 case CipherSuite.TLS_DHE_DSS_WITH_AES_256_CBC_SHA: 255 case CipherSuite.TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA: 256 case CipherSuite.TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA: 257 case CipherSuite.TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA: 258 case CipherSuite.TLS_DHE_RSA_WITH_AES_128_CBC_SHA: 259 case CipherSuite.TLS_DHE_RSA_WITH_AES_256_CBC_SHA: 260 case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA: 261 case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA: 262 case CipherSuite.TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA: 263 case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA: 264 case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA: 265 case CipherSuite.TLS_ECDHE_ECDSA_WITH_NULL_SHA: 266 case CipherSuite.TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA: 267 case CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA: 268 case CipherSuite.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA: 269 case CipherSuite.TLS_ECDHE_RSA_WITH_NULL_SHA: 270 case CipherSuite.TLS_RSA_WITH_3DES_EDE_CBC_SHA: 271 case CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA: 272 case CipherSuite.TLS_RSA_WITH_AES_256_CBC_SHA: 273 case CipherSuite.TLS_RSA_WITH_CAMELLIA_128_CBC_SHA: 274 case CipherSuite.TLS_RSA_WITH_CAMELLIA_256_CBC_SHA: 275 case CipherSuite.TLS_RSA_WITH_NULL_SHA: 276 /* 277 * TODO[jsse] We follow SunJSSE behaviour here, but it's not quite right; these cipher 278 * suites will actually use the legacy PRF based on MD5/SHA1 for TLS 1.1 or earlier. 279 */ 280 return CryptoHashAlgorithm.sha256; 281 282 case CipherSuite.TLS_AES_128_CCM_SHA256: 283 case CipherSuite.TLS_AES_128_CCM_8_SHA256: 284 case CipherSuite.TLS_AES_128_GCM_SHA256: 285 case CipherSuite.TLS_CHACHA20_POLY1305_SHA256: 286 case CipherSuite.TLS_DHE_DSS_WITH_AES_128_CBC_SHA256: 287 case CipherSuite.TLS_DHE_DSS_WITH_AES_128_GCM_SHA256: 288 case CipherSuite.TLS_DHE_DSS_WITH_AES_256_CBC_SHA256: 289 case CipherSuite.TLS_DHE_DSS_WITH_ARIA_128_CBC_SHA256: 290 case CipherSuite.TLS_DHE_DSS_WITH_ARIA_128_GCM_SHA256: 291 case CipherSuite.TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA256: 292 case CipherSuite.TLS_DHE_DSS_WITH_CAMELLIA_128_GCM_SHA256: 293 case CipherSuite.TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA256: 294 case CipherSuite.TLS_DHE_RSA_WITH_AES_128_CBC_SHA256: 295 case CipherSuite.TLS_DHE_RSA_WITH_AES_128_CCM: 296 case CipherSuite.TLS_DHE_RSA_WITH_AES_128_CCM_8: 297 case CipherSuite.TLS_DHE_RSA_WITH_AES_128_GCM_SHA256: 298 case CipherSuite.TLS_DHE_RSA_WITH_AES_256_CBC_SHA256: 299 case CipherSuite.TLS_DHE_RSA_WITH_AES_256_CCM: 300 case CipherSuite.TLS_DHE_RSA_WITH_AES_256_CCM_8: 301 case CipherSuite.TLS_DHE_RSA_WITH_ARIA_128_CBC_SHA256: 302 case CipherSuite.TLS_DHE_RSA_WITH_ARIA_128_GCM_SHA256: 303 case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256: 304 case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_128_GCM_SHA256: 305 case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256: 306 case CipherSuite.TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256: 307 case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256: 308 case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_CCM: 309 case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8: 310 case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256: 311 case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_256_CCM: 312 case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8: 313 case CipherSuite.TLS_ECDHE_ECDSA_WITH_ARIA_128_CBC_SHA256: 314 case CipherSuite.TLS_ECDHE_ECDSA_WITH_ARIA_128_GCM_SHA256: 315 case CipherSuite.TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256: 316 case CipherSuite.TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_GCM_SHA256: 317 case CipherSuite.TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256: 318 case CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256: 319 case CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256: 320 case CipherSuite.TLS_ECDHE_RSA_WITH_ARIA_128_CBC_SHA256: 321 case CipherSuite.TLS_ECDHE_RSA_WITH_ARIA_128_GCM_SHA256: 322 case CipherSuite.TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256: 323 case CipherSuite.TLS_ECDHE_RSA_WITH_CAMELLIA_128_GCM_SHA256: 324 case CipherSuite.TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256: 325 case CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA256: 326 case CipherSuite.TLS_RSA_WITH_AES_128_CCM: 327 case CipherSuite.TLS_RSA_WITH_AES_128_CCM_8: 328 case CipherSuite.TLS_RSA_WITH_AES_128_GCM_SHA256: 329 case CipherSuite.TLS_RSA_WITH_AES_256_CBC_SHA256: 330 case CipherSuite.TLS_RSA_WITH_AES_256_CCM: 331 case CipherSuite.TLS_RSA_WITH_AES_256_CCM_8: 332 case CipherSuite.TLS_RSA_WITH_ARIA_128_CBC_SHA256: 333 case CipherSuite.TLS_RSA_WITH_ARIA_128_GCM_SHA256: 334 case CipherSuite.TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256: 335 case CipherSuite.TLS_RSA_WITH_CAMELLIA_128_GCM_SHA256: 336 case CipherSuite.TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256: 337 case CipherSuite.TLS_RSA_WITH_NULL_SHA256: 338 return CryptoHashAlgorithm.sha256; 339 340 case CipherSuite.TLS_AES_256_GCM_SHA384: 341 case CipherSuite.TLS_DHE_DSS_WITH_AES_256_GCM_SHA384: 342 case CipherSuite.TLS_DHE_DSS_WITH_ARIA_256_CBC_SHA384: 343 case CipherSuite.TLS_DHE_DSS_WITH_ARIA_256_GCM_SHA384: 344 case CipherSuite.TLS_DHE_DSS_WITH_CAMELLIA_256_GCM_SHA384: 345 case CipherSuite.TLS_DHE_RSA_WITH_AES_256_GCM_SHA384: 346 case CipherSuite.TLS_DHE_RSA_WITH_ARIA_256_CBC_SHA384: 347 case CipherSuite.TLS_DHE_RSA_WITH_ARIA_256_GCM_SHA384: 348 case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_256_GCM_SHA384: 349 case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384: 350 case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384: 351 case CipherSuite.TLS_ECDHE_ECDSA_WITH_ARIA_256_CBC_SHA384: 352 case CipherSuite.TLS_ECDHE_ECDSA_WITH_ARIA_256_GCM_SHA384: 353 case CipherSuite.TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384: 354 case CipherSuite.TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_GCM_SHA384: 355 case CipherSuite.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384: 356 case CipherSuite.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384: 357 case CipherSuite.TLS_ECDHE_RSA_WITH_ARIA_256_CBC_SHA384: 358 case CipherSuite.TLS_ECDHE_RSA_WITH_ARIA_256_GCM_SHA384: 359 case CipherSuite.TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384: 360 case CipherSuite.TLS_ECDHE_RSA_WITH_CAMELLIA_256_GCM_SHA384: 361 case CipherSuite.TLS_RSA_WITH_AES_256_GCM_SHA384: 362 case CipherSuite.TLS_RSA_WITH_ARIA_256_CBC_SHA384: 363 case CipherSuite.TLS_RSA_WITH_ARIA_256_GCM_SHA384: 364 case CipherSuite.TLS_RSA_WITH_CAMELLIA_256_GCM_SHA384: 365 return CryptoHashAlgorithm.sha384; 366 367 case CipherSuite.TLS_SM4_CCM_SM3: 368 case CipherSuite.TLS_SM4_GCM_SM3: 369 return CryptoHashAlgorithm.sm3; 370 371 default: 372 throw new IllegalArgumentException(); 373 } 374 } 375 getTransformation(int encryptionAlgorithm)376 private static String getTransformation(int encryptionAlgorithm) 377 { 378 switch (encryptionAlgorithm) 379 { 380 case EncryptionAlgorithm._3DES_EDE_CBC: 381 return "DESede/CBC/NoPadding"; 382 case EncryptionAlgorithm.AES_128_CBC: 383 case EncryptionAlgorithm.AES_256_CBC: 384 return "AES/CBC/NoPadding"; 385 case EncryptionAlgorithm.AES_128_CCM: 386 case EncryptionAlgorithm.AES_128_CCM_8: 387 case EncryptionAlgorithm.AES_256_CCM: 388 case EncryptionAlgorithm.AES_256_CCM_8: 389 return "AES/CCM/NoPadding"; 390 case EncryptionAlgorithm.AES_128_GCM: 391 case EncryptionAlgorithm.AES_256_GCM: 392 return "AES/GCM/NoPadding"; 393 case EncryptionAlgorithm.ARIA_128_CBC: 394 case EncryptionAlgorithm.ARIA_256_CBC: 395 return "ARIA/CBC/NoPadding"; 396 case EncryptionAlgorithm.ARIA_128_GCM: 397 case EncryptionAlgorithm.ARIA_256_GCM: 398 return "ARIA/GCM/NoPadding"; 399 case EncryptionAlgorithm.CAMELLIA_128_CBC: 400 case EncryptionAlgorithm.CAMELLIA_256_CBC: 401 return "Camellia/CBC/NoPadding"; 402 case EncryptionAlgorithm.CAMELLIA_128_GCM: 403 case EncryptionAlgorithm.CAMELLIA_256_GCM: 404 return "Camellia/GCM/NoPadding"; 405 case EncryptionAlgorithm.CHACHA20_POLY1305: 406 return "ChaCha20-Poly1305"; 407 case EncryptionAlgorithm.NULL: 408 return "NULL"; 409 case EncryptionAlgorithm.SM4_CBC: 410 return "SM4/CBC/NoPadding"; 411 case EncryptionAlgorithm.SM4_CCM: 412 return "SM4/CCM/NoPadding"; 413 case EncryptionAlgorithm.SM4_GCM: 414 return "SM4/GCM/NoPadding"; 415 default: 416 throw new IllegalArgumentException(); 417 } 418 } 419 } 420