1 /* 2 * Copyright (c) 1996, 2018, 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.security.*; 29 import java.security.spec.AlgorithmParameterSpec; 30 31 /** 32 * Signature implementation for the SSL/TLS RSA Signature variant with both 33 * MD5 and SHA-1 MessageDigests. Used for explicit RSA server authentication 34 * (RSA signed server key exchange for RSA_EXPORT and DHE_RSA) and RSA client 35 * authentication (RSA signed certificate verify message). 36 * 37 * It conforms to the standard JCA Signature API. It is registered in the 38 * SunJSSE provider to avoid more complicated getInstance() code and 39 * negative interaction with the JCA mechanisms for hardware providers. 40 * 41 * The class should be instantiated via the getInstance() method in this class, 42 * which returns the implementation from the preferred provider. The internal 43 * implementation allows the hashes to be explicitly set, which is required 44 * for RSA client authentication. It can be obtained via the 45 * getInternalInstance() method. 46 * 47 * This class is not thread safe. 48 */ 49 public final class RSASignature extends SignatureSpi { 50 private final Signature rawRsa; 51 private final MessageDigest mdMD5; 52 private final MessageDigest mdSHA; 53 54 public RSASignature() throws NoSuchAlgorithmException { 55 super(); 56 rawRsa = JsseJce.getSignature(JsseJce.SIGNATURE_RAWRSA); 57 this.mdMD5 = JsseJce.getMessageDigest("MD5"); 58 this.mdSHA = JsseJce.getMessageDigest("SHA"); 59 } 60 61 /** 62 * Get an implementation for the RSA signature. 63 * 64 * Follows the standard JCA getInstance() model, so it return the 65 * implementation from the provider with the highest precedence, 66 * which may be this class. 67 */ 68 static Signature getInstance() throws NoSuchAlgorithmException { 69 return JsseJce.getSignature(JsseJce.SIGNATURE_SSLRSA); 70 } 71 72 /** 73 * Get an internal implementation for the RSA signature. 74 * 75 * Used for RSA client authentication, which needs the ability to set 76 * the digests to externally provided values via the setHashes() method. 77 */ 78 static Signature getInternalInstance() 79 throws NoSuchAlgorithmException, NoSuchProviderException { 80 return Signature.getInstance(JsseJce.SIGNATURE_SSLRSA, "SunJSSE"); 81 } 82 83 /** 84 * Set the MD5 and SHA hashes to the provided objects. 85 */ 86 @SuppressWarnings("deprecation") 87 static void setHashes(Signature sig, MessageDigest md5, MessageDigest sha) { 88 sig.setParameter("hashes", new MessageDigest[] {md5, sha}); 89 } 90 91 @Override 92 protected void engineInitVerify(PublicKey publicKey) 93 throws InvalidKeyException { 94 if (publicKey == null) { 95 throw new InvalidKeyException("Public key must not be null"); 96 } 97 mdMD5.reset(); 98 mdSHA.reset(); 99 rawRsa.initVerify(publicKey); 100 } 101 102 @Override 103 protected void engineInitSign(PrivateKey privateKey) 104 throws InvalidKeyException { 105 engineInitSign(privateKey, null); 106 } 107 108 @Override 109 protected void engineInitSign(PrivateKey privateKey, SecureRandom random) 110 throws InvalidKeyException { 111 if (privateKey == null) { 112 throw new InvalidKeyException("Private key must not be null"); 113 } 114 mdMD5.reset(); 115 mdSHA.reset(); 116 rawRsa.initSign(privateKey, random); 117 } 118 119 @Override 120 protected void engineUpdate(byte b) { 121 mdMD5.update(b); 122 mdSHA.update(b); 123 } 124 125 @Override 126 protected void engineUpdate(byte[] b, int off, int len) { 127 mdMD5.update(b, off, len); 128 mdSHA.update(b, off, len); 129 } 130 131 private byte[] getDigest() throws SignatureException { 132 try { 133 byte[] data = new byte[36]; 134 mdMD5.digest(data, 0, 16); 135 mdSHA.digest(data, 16, 20); 136 return data; 137 } catch (DigestException e) { 138 // should never occur 139 throw new SignatureException(e); 140 } 141 } 142 143 @Override 144 protected byte[] engineSign() throws SignatureException { 145 rawRsa.update(getDigest()); 146 return rawRsa.sign(); 147 } 148 149 @Override 150 protected boolean engineVerify(byte[] sigBytes) throws SignatureException { 151 return engineVerify(sigBytes, 0, sigBytes.length); 152 } 153 154 @Override 155 protected boolean engineVerify(byte[] sigBytes, int offset, int length) 156 throws SignatureException { 157 rawRsa.update(getDigest()); 158 return rawRsa.verify(sigBytes, offset, length); 159 } 160 161 @Override 162 @SuppressWarnings("deprecation") 163 protected void engineSetParameter(String param, 164 Object value) throws InvalidParameterException { 165 throw new InvalidParameterException("Parameters not supported"); 166 } 167 168 @Override 169 protected void engineSetParameter(AlgorithmParameterSpec params) 170 throws InvalidAlgorithmParameterException { 171 if (params != null) { 172 throw new InvalidAlgorithmParameterException("No parameters accepted"); 173 } 174 } 175 176 @Override 177 @SuppressWarnings("deprecation") 178 protected Object engineGetParameter( 179 String param) throws InvalidParameterException { 180 throw new InvalidParameterException("Parameters not supported"); 181 } 182 183 @Override 184 protected AlgorithmParameters engineGetParameters() { 185 return null; 186 } 187 }