Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/share/classes/sun/security/ssl/JsseJce.java
38830 views
/*1* Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation. Oracle designates this7* particular file as subject to the "Classpath" exception as provided8* by Oracle in the LICENSE file that accompanied this code.9*10* This code is distributed in the hope that it will be useful, but WITHOUT11* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or12* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License13* version 2 for more details (a copy is included in the LICENSE file that14* accompanied this code).15*16* You should have received a copy of the GNU General Public License version17* 2 along with this work; if not, write to the Free Software Foundation,18* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.19*20* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA21* or visit www.oracle.com if you need additional information or have any22* questions.23*/2425package sun.security.ssl;2627import java.math.BigInteger;28import java.security.*;29import java.security.interfaces.RSAPublicKey;30import java.security.spec.*;31import java.util.*;32import javax.crypto.*;33import sun.security.jca.ProviderList;34import sun.security.jca.Providers;35import static sun.security.ssl.SunJSSE.cryptoProvider;36import sun.security.util.ECUtil;37import static sun.security.util.SecurityConstants.PROVIDER_VER;3839/**40* This class contains a few static methods for interaction with the JCA/JCE41* to obtain implementations, etc.42*43* @author Andreas Sterbenz44*/45final class JsseJce {46static final boolean ALLOW_ECC =47Utilities.getBooleanProperty("com.sun.net.ssl.enableECC", true);4849private static final ProviderList fipsProviderList;5051// Flag indicating whether Kerberos crypto is available.52// If true, then all the Kerberos-based crypto we need is available.53private final static boolean kerberosAvailable;54static {55boolean temp;56try {57AccessController.doPrivileged(58new PrivilegedExceptionAction<Void>() {59@Override60public Void run() throws Exception {61// Test for Kerberos using the bootstrap class loader62Class.forName("sun.security.krb5.PrincipalName", true,63null);64return null;65}66});67temp = true;6869} catch (Exception e) {70temp = false;71}72kerberosAvailable = temp;73}7475static {76// force FIPS flag initialization77// Because isFIPS() is synchronized and cryptoProvider is not modified78// after it completes, this also eliminates the need for any further79// synchronization when accessing cryptoProvider80if (SunJSSE.isFIPS() == false) {81fipsProviderList = null;82} else {83// Setup a ProviderList that can be used by the trust manager84// during certificate chain validation. All the crypto must be85// from the FIPS provider, but we also allow the required86// certificate related services from the SUN provider.87Provider sun = Security.getProvider("SUN");88if (sun == null) {89throw new RuntimeException90("FIPS mode: SUN provider must be installed");91}92Provider sunCerts = new SunCertificates(sun);93fipsProviderList = ProviderList.newList(cryptoProvider, sunCerts);94}95}9697private static final class SunCertificates extends Provider {98private static final long serialVersionUID = -3284138292032213752L;99100SunCertificates(final Provider p) {101super("SunCertificates", PROVIDER_VER, "SunJSSE internal");102AccessController.doPrivileged(new PrivilegedAction<Object>() {103@Override104public Object run() {105// copy certificate related services from the Sun provider106for (Map.Entry<Object,Object> entry : p.entrySet()) {107String key = (String)entry.getKey();108if (key.startsWith("CertPathValidator.")109|| key.startsWith("CertPathBuilder.")110|| key.startsWith("CertStore.")111|| key.startsWith("CertificateFactory.")) {112put(key, entry.getValue());113}114}115return null;116}117});118}119}120121/**122* JCE transformation string for RSA with PKCS#1 v1.5 padding.123* Can be used for encryption, decryption, signing, verifying.124*/125static final String CIPHER_RSA_PKCS1 = "RSA/ECB/PKCS1Padding";126127/**128* JCE transformation string for the stream cipher RC4.129*/130static final String CIPHER_RC4 = "RC4";131132/**133* JCE transformation string for DES in CBC mode without padding.134*/135static final String CIPHER_DES = "DES/CBC/NoPadding";136137/**138* JCE transformation string for (3-key) Triple DES in CBC mode139* without padding.140*/141static final String CIPHER_3DES = "DESede/CBC/NoPadding";142143/**144* JCE transformation string for AES in CBC mode145* without padding.146*/147static final String CIPHER_AES = "AES/CBC/NoPadding";148149/**150* JCE transformation string for AES in GCM mode151* without padding.152*/153static final String CIPHER_AES_GCM = "AES/GCM/NoPadding";154155/**156* JCA identifier string for DSA, i.e. a DSA with SHA-1.157*/158static final String SIGNATURE_DSA = "DSA";159160/**161* JCA identifier string for ECDSA, i.e. a ECDSA with SHA-1.162*/163static final String SIGNATURE_ECDSA = "SHA1withECDSA";164165/**166* JCA identifier string for Raw DSA, i.e. a DSA signature without167* hashing where the application provides the SHA-1 hash of the data.168* Note that the standard name is "NONEwithDSA" but we use "RawDSA"169* for compatibility.170*/171static final String SIGNATURE_RAWDSA = "RawDSA";172173/**174* JCA identifier string for Raw ECDSA, i.e. a DSA signature without175* hashing where the application provides the SHA-1 hash of the data.176*/177static final String SIGNATURE_RAWECDSA = "NONEwithECDSA";178179/**180* JCA identifier string for Raw RSA, i.e. a RSA PKCS#1 v1.5 signature181* without hashing where the application provides the hash of the data.182* Used for RSA client authentication with a 36 byte hash.183*/184static final String SIGNATURE_RAWRSA = "NONEwithRSA";185186/**187* JCA identifier string for the SSL/TLS style RSA Signature. I.e.188* an signature using RSA with PKCS#1 v1.5 padding signing a189* concatenation of an MD5 and SHA-1 digest.190*/191static final String SIGNATURE_SSLRSA = "MD5andSHA1withRSA";192193private JsseJce() {194// no instantiation of this class195}196197static boolean isEcAvailable() {198return EcAvailability.isAvailable;199}200201static boolean isKerberosAvailable() {202return kerberosAvailable;203}204205/**206* Return an JCE cipher implementation for the specified algorithm.207*/208static Cipher getCipher(String transformation)209throws NoSuchAlgorithmException {210try {211if (cryptoProvider == null) {212return Cipher.getInstance(transformation);213} else {214return Cipher.getInstance(transformation, cryptoProvider);215}216} catch (NoSuchPaddingException e) {217throw new NoSuchAlgorithmException(e);218}219}220221/**222* Return an JCA signature implementation for the specified algorithm.223* The algorithm string should be one of the constants defined224* in this class.225*/226static Signature getSignature(String algorithm)227throws NoSuchAlgorithmException {228if (cryptoProvider == null) {229return Signature.getInstance(algorithm);230} else {231// reference equality232if (algorithm == SIGNATURE_SSLRSA) {233// The SunPKCS11 provider currently does not support this234// special algorithm. We allow a fallback in this case because235// the SunJSSE implementation does the actual crypto using236// a NONEwithRSA signature obtained from the cryptoProvider.237if (cryptoProvider.getService("Signature", algorithm) == null) {238// Calling Signature.getInstance() and catching the239// exception would be cleaner, but exceptions are a little240// expensive. So we check directly via getService().241try {242return Signature.getInstance(algorithm, "SunJSSE");243} catch (NoSuchProviderException e) {244throw new NoSuchAlgorithmException(e);245}246}247}248return Signature.getInstance(algorithm, cryptoProvider);249}250}251252static KeyGenerator getKeyGenerator(String algorithm)253throws NoSuchAlgorithmException {254if (cryptoProvider == null) {255return KeyGenerator.getInstance(algorithm);256} else {257return KeyGenerator.getInstance(algorithm, cryptoProvider);258}259}260261static KeyPairGenerator getKeyPairGenerator(String algorithm)262throws NoSuchAlgorithmException {263if (cryptoProvider == null) {264return KeyPairGenerator.getInstance(algorithm);265} else {266return KeyPairGenerator.getInstance(algorithm, cryptoProvider);267}268}269270static KeyAgreement getKeyAgreement(String algorithm)271throws NoSuchAlgorithmException {272if (cryptoProvider == null) {273return KeyAgreement.getInstance(algorithm);274} else {275return KeyAgreement.getInstance(algorithm, cryptoProvider);276}277}278279static Mac getMac(String algorithm)280throws NoSuchAlgorithmException {281if (cryptoProvider == null) {282return Mac.getInstance(algorithm);283} else {284return Mac.getInstance(algorithm, cryptoProvider);285}286}287288static KeyFactory getKeyFactory(String algorithm)289throws NoSuchAlgorithmException {290if (cryptoProvider == null) {291return KeyFactory.getInstance(algorithm);292} else {293return KeyFactory.getInstance(algorithm, cryptoProvider);294}295}296297static AlgorithmParameters getAlgorithmParameters(String algorithm)298throws NoSuchAlgorithmException {299if (cryptoProvider == null) {300return AlgorithmParameters.getInstance(algorithm);301} else {302return AlgorithmParameters.getInstance(algorithm, cryptoProvider);303}304}305306static SecureRandom getSecureRandom() throws KeyManagementException {307if (cryptoProvider == null) {308return new SecureRandom();309}310// Try "PKCS11" first. If that is not supported, iterate through311// the provider and return the first working implementation.312try {313return SecureRandom.getInstance("PKCS11", cryptoProvider);314} catch (NoSuchAlgorithmException e) {315// ignore316}317for (Provider.Service s : cryptoProvider.getServices()) {318if (s.getType().equals("SecureRandom")) {319try {320return SecureRandom.getInstance(321s.getAlgorithm(), cryptoProvider);322} catch (NoSuchAlgorithmException ee) {323// ignore324}325}326}327throw new KeyManagementException("FIPS mode: no SecureRandom "328+ " implementation found in provider " + cryptoProvider.getName());329}330331static MessageDigest getMD5() {332return getMessageDigest("MD5");333}334335static MessageDigest getSHA() {336return getMessageDigest("SHA");337}338339static MessageDigest getMessageDigest(String algorithm) {340try {341if (cryptoProvider == null) {342return MessageDigest.getInstance(algorithm);343} else {344return MessageDigest.getInstance(algorithm, cryptoProvider);345}346} catch (NoSuchAlgorithmException e) {347throw new RuntimeException348("Algorithm " + algorithm + " not available", e);349}350}351352static int getRSAKeyLength(PublicKey key) {353BigInteger modulus;354if (key instanceof RSAPublicKey) {355modulus = ((RSAPublicKey)key).getModulus();356} else {357RSAPublicKeySpec spec = getRSAPublicKeySpec(key);358modulus = spec.getModulus();359}360return modulus.bitLength();361}362363static RSAPublicKeySpec getRSAPublicKeySpec(PublicKey key) {364if (key instanceof RSAPublicKey) {365RSAPublicKey rsaKey = (RSAPublicKey)key;366return new RSAPublicKeySpec(rsaKey.getModulus(),367rsaKey.getPublicExponent());368}369try {370KeyFactory factory = JsseJce.getKeyFactory("RSA");371return factory.getKeySpec(key, RSAPublicKeySpec.class);372} catch (Exception e) {373throw new RuntimeException(e);374}375}376377static ECParameterSpec getECParameterSpec(String namedCurveOid) {378return ECUtil.getECParameterSpec(cryptoProvider, namedCurveOid);379}380381static String getNamedCurveOid(ECParameterSpec params) {382return ECUtil.getCurveName(cryptoProvider, params);383}384385static ECPoint decodePoint(byte[] encoded, EllipticCurve curve)386throws java.io.IOException {387return ECUtil.decodePoint(encoded, curve);388}389390static byte[] encodePoint(ECPoint point, EllipticCurve curve) {391return ECUtil.encodePoint(point, curve);392}393394// In FIPS mode, set thread local providers; otherwise a no-op.395// Must be paired with endFipsProvider.396static Object beginFipsProvider() {397if (fipsProviderList == null) {398return null;399} else {400return Providers.beginThreadProviderList(fipsProviderList);401}402}403404static void endFipsProvider(Object o) {405if (fipsProviderList != null) {406Providers.endThreadProviderList((ProviderList)o);407}408}409410411// lazy initialization holder class idiom for static default parameters412//413// See Effective Java Second Edition: Item 71.414private static class EcAvailability {415// Is EC crypto available?416private static final boolean isAvailable;417418static {419boolean mediator = true;420try {421JsseJce.getSignature(SIGNATURE_ECDSA);422JsseJce.getSignature(SIGNATURE_RAWECDSA);423JsseJce.getKeyAgreement("ECDH");424JsseJce.getKeyFactory("EC");425JsseJce.getKeyPairGenerator("EC");426JsseJce.getAlgorithmParameters("EC");427} catch (Exception e) {428mediator = false;429}430431isAvailable = mediator;432}433}434}435436437