1 /* 2 * Copyright (c) 2019, 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. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 */ 23 24 /* 25 * @test 26 * @bug 8216039 27 * @summary Ensure the BC provider-reselection workaround in Signature class 28 * functions correctly 29 * @modules java.base/sun.security.util 30 * @run main/othervm SignatureGetInstance 31 */ 32 import java.security.*; 33 import java.security.interfaces.*; 34 import java.security.spec.*; 35 import sun.security.util.SignatureUtil; 36 37 public class SignatureGetInstance { 38 39 private static final String SIGALG = "RSASSA-PSS"; 40 41 public static void main(String[] args) throws Exception { 42 Provider testProvider = new TestProvider(); 43 // put test provider before SunRsaSign provider 44 Security.insertProviderAt(testProvider, 1); 45 //Security.addProvider(testProvider); 46 KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA"); 47 KeyPair kp = kpg.generateKeyPair(); 48 49 MyPrivKey testPriv = new MyPrivKey(); 50 MyPubKey testPub = new MyPubKey(); 51 52 testDblInit(testPriv, testPub, true, "TestProvider"); 53 testDblInit(kp.getPrivate(), kp.getPublic(), true, "SunRsaSign"); 54 testDblInit(testPriv, kp.getPublic(), false, null); 55 testDblInit(kp.getPrivate(), testPub, false, null); 56 57 testSetAndInit(null, testPriv, true); 58 testSetAndInit(null, testPub, true); 59 testSetAndInit(null, kp.getPrivate(), true); 60 testSetAndInit(null, kp.getPublic(), true); 61 62 String provName = "SunRsaSign"; 63 testSetAndInit(provName, testPriv, false); 64 testSetAndInit(provName, testPub, false); 65 testSetAndInit(provName, kp.getPrivate(), true); 66 testSetAndInit(provName, kp.getPublic(), true); 67 68 provName = "TestProvider"; 69 testSetAndInit(provName, testPriv, true); 70 testSetAndInit(provName, testPub, true); 71 testSetAndInit(provName, kp.getPrivate(), false); 72 testSetAndInit(provName, kp.getPublic(), false); 73 74 System.out.println("Test Passed"); 75 } 76 77 private static void checkName(Signature s, String name) { 78 if (name != null && 79 !(name.equals(s.getProvider().getName()))) { 80 throw new RuntimeException("Fail: provider name mismatch"); 81 } 82 } 83 84 private static void testDblInit(PrivateKey key1, PublicKey key2, 85 boolean shouldPass, String expectedProvName) throws Exception { 86 Signature sig = Signature.getInstance(SIGALG); 87 SignatureUtil.initSignWithParam(sig, key1, PSSParameterSpec.DEFAULT, null); 88 try { 89 sig.initVerify(key2); 90 if (!shouldPass) { 91 throw new RuntimeException("Fail: should throw InvalidKeyException"); 92 } 93 checkName(sig, expectedProvName); 94 } catch (InvalidKeyException ike) { 95 if (shouldPass) { 96 System.out.println("Fail: Unexpected InvalidKeyException"); 97 throw ike; 98 } 99 } 100 } 101 102 private static void testSetAndInit(String provName, Key key, 103 boolean shouldPass) throws Exception { 104 Signature sig; 105 if (provName == null) { 106 sig = Signature.getInstance(SIGALG); 107 } else { 108 sig = Signature.getInstance(SIGALG, provName); 109 } 110 AlgorithmParameterSpec params = PSSParameterSpec.DEFAULT; 111 boolean doSign = (key instanceof PrivateKey); 112 try { 113 if (doSign) { 114 SignatureUtil.initSignWithParam(sig, (PrivateKey)key, params, null); 115 } else { 116 SignatureUtil.initVerifyWithParam(sig, (PublicKey)key, params); 117 } 118 if (!shouldPass) { 119 throw new RuntimeException("Fail: should throw InvalidKeyException"); 120 } 121 checkName(sig, provName); 122 // check that the earlier parameter is still there 123 if (sig.getParameters() == null) { 124 throw new RuntimeException("Fail: parameters not preserved"); 125 } 126 } catch (InvalidKeyException ike) { 127 if (shouldPass) { 128 System.out.println("Fail: Unexpected InvalidKeyException"); 129 throw ike; 130 } 131 } 132 } 133 134 // Test provider which only accepts its own Key objects 135 // Registered to be more preferred than SunRsaSign provider 136 // for testing deferred provider selection 137 public static class TestProvider extends Provider { 138 TestProvider() { 139 super("TestProvider", "1.0", "provider for SignatureGetInstance"); 140 put("Signature.RSASSA-PSS", 141 "SignatureGetInstance$MySigImpl"); 142 } 143 } 144 145 public static class MyPrivKey implements PrivateKey { 146 public String getAlgorithm() { return "RSASSA-PSS"; } 147 public String getFormat() { return "MyOwn"; } 148 public byte[] getEncoded() { return null; } 149 } 150 151 public static class MyPubKey implements PublicKey { 152 public String getAlgorithm() { return "RSASSA-PSS"; } 153 public String getFormat() { return "MyOwn"; } 154 public byte[] getEncoded() { return null; } 155 } 156 157 public static class MySigImpl extends SignatureSpi { 158 // simulate BC behavior of only using params set before init calls 159 AlgorithmParameterSpec initParamSpec = null; 160 AlgorithmParameterSpec paramSpec = null; 161 162 public MySigImpl() { 163 super(); 164 } 165 166 @Override 167 protected void engineInitVerify(PublicKey publicKey) 168 throws InvalidKeyException { 169 if (!(publicKey instanceof MyPubKey)) { 170 throw new InvalidKeyException("Must be MyPubKey"); 171 } 172 initParamSpec = paramSpec; 173 } 174 175 @Override 176 protected void engineInitSign(PrivateKey privateKey) 177 throws InvalidKeyException { 178 if (!(privateKey instanceof MyPrivKey)) { 179 throw new InvalidKeyException("Must be MyPrivKey"); 180 } 181 initParamSpec = paramSpec; 182 } 183 184 @Override 185 protected void engineUpdate(byte b) throws SignatureException { 186 } 187 188 @Override 189 protected void engineUpdate(byte[] b, int off, int len) 190 throws SignatureException { 191 } 192 193 @Override 194 protected byte[] engineSign() 195 throws SignatureException { 196 return new byte[0]; 197 } 198 199 @Override 200 protected boolean engineVerify(byte[] sigBytes) 201 throws SignatureException { 202 return false; 203 } 204 205 @Override 206 @Deprecated 207 protected void engineSetParameter(String param, Object value) 208 throws InvalidParameterException { 209 } 210 211 @Override 212 protected void engineSetParameter(AlgorithmParameterSpec params) 213 throws InvalidAlgorithmParameterException { 214 paramSpec = params; 215 } 216 217 @Override 218 @Deprecated 219 protected AlgorithmParameters engineGetParameter(String param) 220 throws InvalidParameterException { 221 return null; 222 } 223 224 @Override 225 protected AlgorithmParameters engineGetParameters() { 226 if (initParamSpec != null) { 227 try { 228 AlgorithmParameters ap = 229 AlgorithmParameters.getInstance("RSASSA-PSS"); 230 ap.init(initParamSpec); 231 return ap; 232 } catch (Exception e) { 233 throw new RuntimeException(e); 234 } 235 } 236 return null; 237 } 238 } 239 }