| /* | |
| * Copyright (c) 2016, 2024, Oracle and/or its affiliates. All rights reserved. | |
| * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. | |
| * | |
| * This code is free software; you can redistribute it and/or modify it | |
| * under the terms of the GNU General Public License version 2 only, as | |
| * published by the Free Software Foundation. | |
| * | |
| * This code is distributed in the hope that it will be useful, but WITHOUT | |
| * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
| * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
| * version 2 for more details (a copy is included in the LICENSE file that | |
| * accompanied this code). | |
| * | |
| * You should have received a copy of the GNU General Public License version | |
| * 2 along with this work; if not, write to the Free Software Foundation, | |
| * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. | |
| * | |
| * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA | |
| * or visit www.oracle.com if you need additional information or have any | |
| * questions. | |
| */ | |
| /** | |
| * @test | |
| * @bug 8149802 | |
| * @library /test/lib | |
| * @summary Ensure that Signature objects are reset after verification errored out. | |
| */ | |
| import java.util.Arrays; | |
| import java.security.*; | |
| import jdk.test.lib.security.SecurityUtils; | |
| public class ResetAfterException { | |
| public static void main(String[] args) throws Exception { | |
| byte[] data = "data to be signed".getBytes(); | |
| byte[] shortBuffer = new byte[2]; | |
| Provider[] provs = Security.getProviders(); | |
| boolean failed = false; | |
| for (Provider p : provs) { | |
| Signature sig; | |
| try { | |
| sig = Signature.getInstance("SHA256withRSA", p); | |
| } catch (NoSuchAlgorithmException nsae) { | |
| // no support, skip | |
| continue; | |
| } | |
| boolean res = true; | |
| System.out.println("Testing Provider: " + p.getName()); | |
| KeyPairGenerator keyGen = null; | |
| String kpgAlgorithm = "RSA"; | |
| try { | |
| // It's possible that some provider, e.g. SunMSCAPI, | |
| // doesn't work well with keys from other providers | |
| // so we use the same provider to generate key first | |
| keyGen = KeyPairGenerator.getInstance(kpgAlgorithm, p); | |
| } catch (NoSuchAlgorithmException nsae) { | |
| keyGen = KeyPairGenerator.getInstance(kpgAlgorithm); | |
| } | |
| if (keyGen == null) { | |
| throw new RuntimeException("Error: No support for RSA KeyPairGenerator"); | |
| } | |
| keyGen.initialize(SecurityUtils.getTestKeySize(kpgAlgorithm)); | |
| KeyPair keyPair = keyGen.generateKeyPair(); | |
| sig.initSign(keyPair.getPrivate()); | |
| sig.update(data); | |
| byte[] signature = sig.sign(); | |
| // First check signing | |
| try { | |
| sig.update(data); | |
| // sign with short output buffer to cause exception | |
| int len = sig.sign(shortBuffer, 0, shortBuffer.length); | |
| System.out.println("FAIL: Should throw SE with short buffer"); | |
| res = false; | |
| } catch (SignatureException e) { | |
| // expected exception; ignore | |
| System.out.println("Expected Ex for short output buffer: " + e); | |
| } | |
| // Signature object should reset after a failed generation | |
| sig.update(data); | |
| byte[] signature2 = sig.sign(); | |
| if (!Arrays.equals(signature, signature2)) { | |
| System.out.println("FAIL: Generated different signature"); | |
| res = false; | |
| } else { | |
| System.out.println("Generated same signature"); | |
| } | |
| // Now, check signature verification | |
| sig.initVerify(keyPair.getPublic()); | |
| sig.update(data); | |
| try { | |
| // first verify with valid signature bytes | |
| res = sig.verify(signature); | |
| } catch (SignatureException e) { | |
| System.out.println("FAIL: Valid signature rejected"); | |
| e.printStackTrace(); | |
| res = false; | |
| } | |
| try { | |
| sig.update(data); | |
| // verify with short signaure to cause exception | |
| if (sig.verify(shortBuffer)) { | |
| System.out.println("FAIL: Invalid signature verified"); | |
| res = false; | |
| } else { | |
| System.out.println("Invalid signature rejected"); | |
| } | |
| } catch (SignatureException e) { | |
| // expected exception; ignore | |
| System.out.println("Expected Ex for short output buffer: " + e); | |
| } | |
| // Signature object should reset after a failed verification | |
| sig.update(data); | |
| try { | |
| // verify with valid signature bytes again | |
| res = sig.verify(signature); | |
| if (!res) { | |
| System.out.println("FAIL: Valid signature is rejected"); | |
| } else { | |
| System.out.println("Valid signature is accepted"); | |
| } | |
| } catch (GeneralSecurityException e) { | |
| System.out.println("FAIL: Valid signature is rejected"); | |
| e.printStackTrace(); | |
| res = false; | |
| } | |
| failed |= !res; | |
| } | |
| if (failed) { | |
| throw new RuntimeException("One or more test failed"); | |
| } else { | |
| System.out.println("Test Passed"); | |
| } | |
| } | |
| } |