1 /* |
1 /* |
2 * Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved. |
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. |
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
4 * |
4 * |
5 * This code is free software; you can redistribute it and/or modify it |
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 |
6 * under the terms of the GNU General Public License version 2 only, as |
7 * published by the Free Software Foundation. Oracle designates this |
7 * published by the Free Software Foundation. Oracle designates this |
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
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 |
22 * or visit www.oracle.com if you need additional information or have any |
23 * questions. |
23 * questions. |
24 */ |
24 */ |
25 |
25 |
26 |
|
27 package sun.security.ssl; |
26 package sun.security.ssl; |
28 |
27 |
29 import java.security.*; |
28 import java.security.*; |
|
29 import java.security.spec.AlgorithmParameterSpec; |
30 |
30 |
31 /** |
31 /** |
32 * Signature implementation for the SSL/TLS RSA Signature variant with both |
32 * Signature implementation for the SSL/TLS RSA Signature variant with both |
33 * MD5 and SHA-1 MessageDigests. Used for explicit RSA server authentication |
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 |
34 * (RSA signed server key exchange for RSA_EXPORT and DHE_RSA) and RSA client |
43 * implementation allows the hashes to be explicitly set, which is required |
43 * implementation allows the hashes to be explicitly set, which is required |
44 * for RSA client authentication. It can be obtained via the |
44 * for RSA client authentication. It can be obtained via the |
45 * getInternalInstance() method. |
45 * getInternalInstance() method. |
46 * |
46 * |
47 * This class is not thread safe. |
47 * This class is not thread safe. |
48 * |
|
49 */ |
48 */ |
50 public final class RSASignature extends SignatureSpi { |
49 public final class RSASignature extends SignatureSpi { |
51 |
|
52 private final Signature rawRsa; |
50 private final Signature rawRsa; |
53 private MessageDigest md5, sha; |
51 private final MessageDigest mdMD5; |
54 |
52 private final MessageDigest mdSHA; |
55 // flag indicating if the MessageDigests are in reset state |
|
56 private boolean isReset; |
|
57 |
53 |
58 public RSASignature() throws NoSuchAlgorithmException { |
54 public RSASignature() throws NoSuchAlgorithmException { |
59 super(); |
55 super(); |
60 rawRsa = JsseJce.getSignature(JsseJce.SIGNATURE_RAWRSA); |
56 rawRsa = JsseJce.getSignature(JsseJce.SIGNATURE_RAWRSA); |
61 isReset = true; |
57 this.mdMD5 = JsseJce.getMessageDigest("MD5"); |
|
58 this.mdSHA = JsseJce.getMessageDigest("SHA"); |
62 } |
59 } |
63 |
60 |
64 /** |
61 /** |
65 * Get an implementation for the RSA signature. Follows the standard |
62 * Get an implementation for the RSA signature. |
66 * JCA getInstance() model, so it return the implementation from the |
63 * |
67 * provider with the highest precedence, which may be this class. |
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. |
68 */ |
67 */ |
69 static Signature getInstance() throws NoSuchAlgorithmException { |
68 static Signature getInstance() throws NoSuchAlgorithmException { |
70 return JsseJce.getSignature(JsseJce.SIGNATURE_SSLRSA); |
69 return JsseJce.getSignature(JsseJce.SIGNATURE_SSLRSA); |
71 } |
70 } |
72 |
71 |
73 /** |
72 /** |
74 * Get an internal implementation for the RSA signature. Used for RSA |
73 * Get an internal implementation for the RSA signature. |
75 * client authentication, which needs the ability to set the digests |
74 * |
76 * to externally provided values via the setHashes() method. |
75 * Used for RSA client authentication, which needs the ability to set |
|
76 * the digests to externally provided values via the setHashes() method. |
77 */ |
77 */ |
78 static Signature getInternalInstance() |
78 static Signature getInternalInstance() |
79 throws NoSuchAlgorithmException, NoSuchProviderException { |
79 throws NoSuchAlgorithmException, NoSuchProviderException { |
80 return Signature.getInstance(JsseJce.SIGNATURE_SSLRSA, "SunJSSE"); |
80 return Signature.getInstance(JsseJce.SIGNATURE_SSLRSA, "SunJSSE"); |
81 } |
81 } |
86 @SuppressWarnings("deprecation") |
86 @SuppressWarnings("deprecation") |
87 static void setHashes(Signature sig, MessageDigest md5, MessageDigest sha) { |
87 static void setHashes(Signature sig, MessageDigest md5, MessageDigest sha) { |
88 sig.setParameter("hashes", new MessageDigest[] {md5, sha}); |
88 sig.setParameter("hashes", new MessageDigest[] {md5, sha}); |
89 } |
89 } |
90 |
90 |
91 /** |
|
92 * Reset the MessageDigests unless they are already reset. |
|
93 */ |
|
94 private void reset() { |
|
95 if (isReset == false) { |
|
96 md5.reset(); |
|
97 sha.reset(); |
|
98 isReset = true; |
|
99 } |
|
100 } |
|
101 |
|
102 private static void checkNull(Key key) throws InvalidKeyException { |
|
103 if (key == null) { |
|
104 throw new InvalidKeyException("Key must not be null"); |
|
105 } |
|
106 } |
|
107 |
|
108 @Override |
91 @Override |
109 protected void engineInitVerify(PublicKey publicKey) |
92 protected void engineInitVerify(PublicKey publicKey) |
110 throws InvalidKeyException { |
93 throws InvalidKeyException { |
111 checkNull(publicKey); |
94 if (publicKey == null) { |
112 reset(); |
95 throw new InvalidKeyException("Public key must not be null"); |
|
96 } |
|
97 mdMD5.reset(); |
|
98 mdSHA.reset(); |
113 rawRsa.initVerify(publicKey); |
99 rawRsa.initVerify(publicKey); |
114 } |
100 } |
115 |
101 |
116 @Override |
102 @Override |
117 protected void engineInitSign(PrivateKey privateKey) |
103 protected void engineInitSign(PrivateKey privateKey) |
120 } |
106 } |
121 |
107 |
122 @Override |
108 @Override |
123 protected void engineInitSign(PrivateKey privateKey, SecureRandom random) |
109 protected void engineInitSign(PrivateKey privateKey, SecureRandom random) |
124 throws InvalidKeyException { |
110 throws InvalidKeyException { |
125 checkNull(privateKey); |
111 if (privateKey == null) { |
126 reset(); |
112 throw new InvalidKeyException("Private key must not be null"); |
|
113 } |
|
114 mdMD5.reset(); |
|
115 mdSHA.reset(); |
127 rawRsa.initSign(privateKey, random); |
116 rawRsa.initSign(privateKey, random); |
128 } |
|
129 |
|
130 // lazily initialize the MessageDigests |
|
131 private void initDigests() { |
|
132 if (md5 == null) { |
|
133 md5 = JsseJce.getMD5(); |
|
134 sha = JsseJce.getSHA(); |
|
135 } |
|
136 } |
117 } |
137 |
118 |
138 @Override |
119 @Override |
139 protected void engineUpdate(byte b) { |
120 protected void engineUpdate(byte b) { |
140 initDigests(); |
121 mdMD5.update(b); |
141 isReset = false; |
122 mdSHA.update(b); |
142 md5.update(b); |
|
143 sha.update(b); |
|
144 } |
123 } |
145 |
124 |
146 @Override |
125 @Override |
147 protected void engineUpdate(byte[] b, int off, int len) { |
126 protected void engineUpdate(byte[] b, int off, int len) { |
148 initDigests(); |
127 mdMD5.update(b, off, len); |
149 isReset = false; |
128 mdSHA.update(b, off, len); |
150 md5.update(b, off, len); |
|
151 sha.update(b, off, len); |
|
152 } |
129 } |
153 |
130 |
154 private byte[] getDigest() throws SignatureException { |
131 private byte[] getDigest() throws SignatureException { |
155 try { |
132 try { |
156 initDigests(); |
|
157 byte[] data = new byte[36]; |
133 byte[] data = new byte[36]; |
158 md5.digest(data, 0, 16); |
134 mdMD5.digest(data, 0, 16); |
159 sha.digest(data, 16, 20); |
135 mdSHA.digest(data, 16, 20); |
160 isReset = true; |
|
161 return data; |
136 return data; |
162 } catch (DigestException e) { |
137 } catch (DigestException e) { |
163 // should never occur |
138 // should never occur |
164 throw new SignatureException(e); |
139 throw new SignatureException(e); |
165 } |
140 } |
183 return rawRsa.verify(sigBytes, offset, length); |
158 return rawRsa.verify(sigBytes, offset, length); |
184 } |
159 } |
185 |
160 |
186 @Override |
161 @Override |
187 @SuppressWarnings("deprecation") |
162 @SuppressWarnings("deprecation") |
188 protected void engineSetParameter(String param, Object value) |
163 protected void engineSetParameter(String param, |
189 throws InvalidParameterException { |
164 Object value) throws InvalidParameterException { |
190 if (param.equals("hashes") == false) { |
165 throw new InvalidParameterException("Parameters not supported"); |
191 throw new InvalidParameterException |
166 } |
192 ("Parameter not supported: " + param); |
167 |
|
168 @Override |
|
169 protected void engineSetParameter(AlgorithmParameterSpec params) |
|
170 throws InvalidAlgorithmParameterException { |
|
171 if (params != null) { |
|
172 throw new InvalidAlgorithmParameterException("No parameters accepted"); |
193 } |
173 } |
194 if (value instanceof MessageDigest[] == false) { |
|
195 throw new InvalidParameterException |
|
196 ("value must be MessageDigest[]"); |
|
197 } |
|
198 MessageDigest[] digests = (MessageDigest[])value; |
|
199 md5 = digests[0]; |
|
200 sha = digests[1]; |
|
201 } |
174 } |
202 |
175 |
203 @Override |
176 @Override |
204 @SuppressWarnings("deprecation") |
177 @SuppressWarnings("deprecation") |
205 protected Object engineGetParameter(String param) |
178 protected Object engineGetParameter( |
206 throws InvalidParameterException { |
179 String param) throws InvalidParameterException { |
207 throw new InvalidParameterException("Parameters not supported"); |
180 throw new InvalidParameterException("Parameters not supported"); |
208 } |
181 } |
209 |
182 |
|
183 @Override |
|
184 protected AlgorithmParameters engineGetParameters() { |
|
185 return null; |
|
186 } |
210 } |
187 } |