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