1 /* 2 * Copyright (c) 2015, 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. 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 import java.security.*; 25 import java.security.spec.*; 26 import jdk.test.lib.RandomFactory; 27 28 /* 29 * @test 30 * @bug 8050374 8181048 8146293 31 * @key randomness 32 * @summary This test validates signature verification 33 * Signature.verify(byte[], int, int). The test uses RandomFactory to 34 * get random set of clear text data to sign. After the signature 35 * generation, the test tries to verify signature with the above API 36 * and passing in different signature offset (0, 33, 66, 99). 37 * @library /test/lib 38 * @build jdk.test.lib.RandomFactory 39 * @run main Offsets SUN NONEwithDSA 40 * @run main Offsets SUN SHA1withDSA 41 * @run main Offsets SUN SHA224withDSA 42 * @run main Offsets SUN SHA256withDSA 43 * @run main Offsets SunRsaSign SHA224withRSA 44 * @run main Offsets SunRsaSign SHA256withRSA 45 * @run main Offsets SunRsaSign SHA384withRSA 46 * @run main Offsets SunRsaSign SHA512withRSA 47 * @run main Offsets SunRsaSign SHA512/224withRSA 48 * @run main Offsets SunRsaSign SHA512/256withRSA 49 */ 50 public class Offsets { 51 52 private final int size; 53 private final byte[] cleartext; 54 private final PublicKey pubkey; 55 private final Signature signature; 56 private final byte[] signed; 57 Offsets(Signature signature, PublicKey pubkey, PrivateKey privkey, int size, byte[] cleartext)58 private Offsets(Signature signature, PublicKey pubkey, PrivateKey privkey, 59 int size, byte[] cleartext) throws InvalidKeyException, 60 SignatureException { 61 System.out.println("Testing signature " + signature.getAlgorithm()); 62 this.pubkey = pubkey; 63 this.signature = signature; 64 this.size = size; 65 this.cleartext = cleartext; 66 67 String sigAlg = signature.getAlgorithm(); 68 signature.initSign(privkey); 69 signature.update(cleartext, 0, size); 70 signed = signature.sign(); 71 } 72 getDataSize()73 int getDataSize() { 74 return size; 75 } 76 getSignatureLength()77 int getSignatureLength() { 78 return signed.length; 79 } 80 shiftSignData(int offset)81 byte[] shiftSignData(int offset) { 82 byte[] testSignData = new byte[offset + signed.length]; 83 System.arraycopy(signed, 0, testSignData, offset, 84 signed.length); 85 return testSignData; 86 } 87 verifySignature(byte[] sigData, int sigOffset, int sigLength, int updateOffset, int updateLength)88 boolean verifySignature(byte[] sigData, int sigOffset, int sigLength, 89 int updateOffset, int updateLength) 90 throws InvalidKeyException, SignatureException { 91 signature.initVerify(pubkey); 92 signature.update(cleartext, updateOffset, updateLength); 93 return signature.verify(sigData, sigOffset, sigLength); 94 } 95 init(String provider, String algorithm)96 static Offsets init(String provider, String algorithm) 97 throws NoSuchAlgorithmException, NoSuchProviderException, 98 InvalidKeyException, SignatureException { 99 // fill the cleartext data with random bytes 100 byte[] cleartext = new byte[100]; 101 RandomFactory.getRandom().nextBytes(cleartext); 102 103 // NONEwith requires input to be of 20 bytes 104 int size = algorithm.contains("NONEwith") ? 20 : 100; 105 106 // create signature instance 107 Signature signature = Signature.getInstance(algorithm, provider); 108 109 String keyAlgo; 110 int keySize = 2048; 111 if (algorithm.contains("RSA")) { 112 keyAlgo = "RSA"; 113 } else if (algorithm.contains("ECDSA")) { 114 keyAlgo = "EC"; 115 keySize = 256; 116 } else if (algorithm.contains("DSA")) { 117 keyAlgo = "DSA"; 118 if (algorithm.startsWith("SHAwith") || 119 algorithm.startsWith("SHA1with")) { 120 keySize = 1024; 121 } 122 } else { 123 throw new RuntimeException("Test doesn't support this signature " 124 + "algorithm: " + algorithm); 125 } 126 KeyPairGenerator kpg = null; 127 // first try matching provider, fallback to most preferred if none available 128 try { 129 kpg = KeyPairGenerator.getInstance(keyAlgo, provider); 130 } catch (NoSuchAlgorithmException nsae) { 131 kpg = KeyPairGenerator.getInstance(keyAlgo); 132 } 133 kpg.initialize(keySize); 134 KeyPair kp = kpg.generateKeyPair(); 135 PublicKey pubkey = kp.getPublic(); 136 PrivateKey privkey = kp.getPrivate(); 137 138 return new Offsets(signature, pubkey, privkey, size, cleartext); 139 } 140 main(String[] args)141 public static void main(String[] args) throws NoSuchAlgorithmException, 142 InvalidKeyException, SignatureException { 143 if (args.length < 2) { 144 throw new RuntimeException("Wrong parameters"); 145 } 146 147 boolean result = true; 148 try { 149 Offsets test = init(args[0], args[1]); 150 151 // We are trying 3 different offsets, data size has nothing to do 152 // with signature length 153 for (int chunk = 3; chunk > 0; chunk--) { 154 int signOffset = test.getDataSize() / chunk; 155 156 System.out.println("Running test with offset " + signOffset); 157 byte[] signData = test.shiftSignData(signOffset); 158 159 boolean success = test.verifySignature(signData, signOffset, 160 test.getSignatureLength(), 0, test.getDataSize()); 161 162 if (success) { 163 System.out.println("Successfully verified with offset " 164 + signOffset); 165 } else { 166 System.out.println("Verification failed with offset " 167 + signOffset); 168 result = false; 169 } 170 } 171 172 // save signature to offset 0 173 byte[] signData = test.shiftSignData(0); 174 175 // Negative tests 176 177 // Test signature offset 0. 178 // Wrong test data will be passed to update, 179 // so signature verification should fail. 180 for (int chunk = 3; chunk > 0; chunk--) { 181 int dataOffset = (test.getDataSize() - 1) / chunk; 182 boolean success; 183 try { 184 success = test.verifySignature(signData, 0, 185 test.getSignatureLength(), dataOffset, 186 (test.getDataSize() - dataOffset)); 187 } catch (SignatureException e) { 188 // Since we are trying different data size, it can throw 189 // SignatureException 190 success = false; 191 } 192 193 if (!success) { 194 System.out.println("Signature verification failed " 195 + "as expected, with data offset " + dataOffset 196 + " and length " 197 + (test.getDataSize() - dataOffset)); 198 } else { 199 System.out.println("Signature verification " 200 + "should not succeed, with data offset " 201 + dataOffset + " and length " 202 + (test.getDataSize() - dataOffset)); 203 result = false; 204 } 205 } 206 207 // Tests with manipulating offset and length 208 result &= Offsets.checkFailure(test, signData, -1, 209 test.getSignatureLength()); 210 211 result &= Offsets.checkFailure(test, signData, 0, 212 test.getSignatureLength() - 1); 213 214 result &= Offsets.checkFailure(test, signData, 215 test.getSignatureLength() + 1, test.getSignatureLength()); 216 217 result &= Offsets.checkFailure(test, signData, 0, 218 test.getSignatureLength() + 1); 219 220 result &= Offsets.checkFailure(test, signData, 0, 0); 221 222 result &= Offsets.checkFailure(test, signData, 0, -1); 223 224 result &= Offsets.checkFailure(test, signData, 225 2147483646, test.getSignatureLength()); 226 227 result &= Offsets.checkFailure(test, null, 0, 228 test.getSignatureLength()); 229 } catch (NoSuchProviderException nspe) { 230 System.out.println("No such provider: " + nspe); 231 } 232 233 if (!result) { 234 throw new RuntimeException("Some test cases failed"); 235 } 236 } 237 checkFailure(Offsets test, byte[] signData, int offset, int length)238 static boolean checkFailure(Offsets test, byte[] signData, int offset, 239 int length) { 240 boolean success; 241 try { 242 success = test.verifySignature(signData, offset, length, 0, 243 test.getDataSize()); 244 } catch (IllegalArgumentException | SignatureException e) { 245 System.out.println("Expected exception: " + e); 246 success = false; 247 } catch (InvalidKeyException e) { 248 System.out.println("Unexpected exception: " + e); 249 return false; 250 } 251 252 if (!success) { 253 System.out.println("Signature verification failed as expected, " 254 + "with signature offset " + offset + " and length " 255 + length); 256 return true; 257 } else { 258 System.out.println("Signature verification should not succeed, " 259 + "with signature offset " + offset + " and length " 260 + length); 261 return false; 262 } 263 } 264 265 } 266