Path: blob/master/test/jdk/javax/security/auth/Destroyable/KeyDestructionTest.java
41153 views
/*1* Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation.7*8* This code is distributed in the hope that it will be useful, but WITHOUT9* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or10* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License11* version 2 for more details (a copy is included in the LICENSE file that12* accompanied this code).13*14* You should have received a copy of the GNU General Public License version15* 2 along with this work; if not, write to the Free Software Foundation,16* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.17*18* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA19* or visit www.oracle.com if you need additional information or have any20* questions.21*/2223/*24* @test25* @bug 626341926* @summary No way to clean the memory for a java.security.Key27*/2829import java.security.*;30import java.util.*;31import javax.crypto.*;32import javax.security.auth.Destroyable;33import javax.security.auth.DestroyFailedException;3435public class KeyDestructionTest {36public static void main(String[] args) throws Exception {37KeyPair keypair = generateKeyPair("RSA", 1024);3839// Check keys that support and have implemented key destruction40testKeyDestruction(new MyDestroyableSecretKey());41testKeyDestruction(new MyDestroyablePrivateKey());4243// Check keys that support but have not implemented key destruction44testNoKeyDestruction(generateSecretKey("AES", 128));45testNoKeyDestruction(keypair.getPrivate());4647// Check keys that do not support key destruction48try {49testKeyDestruction(keypair.getPublic());50} catch (UnsupportedOperationException uoe) {51// not an error52System.out.println(keypair.getPublic().getClass().getName() +53" keys do not support key destruction");54}5556System.out.println("PASSED.");57}5859// Check the behaviour of a key that implements key destruction60private static void testKeyDestruction(Key key) throws Exception {61String klass = key.getClass().getName();62boolean hasUsable = key instanceof Usable;6364try {65key.getAlgorithm();66key.getFormat();67if (allZero(key.getEncoded())) {68throw new Exception("error: key destroyed prematurely");69}70} catch (IllegalStateException ise) {71throw new Exception("error: unexpected ISE", ise);72}7374if (hasUsable) {75((Usable) key).useKey();76}7778destroyKey(key);7980try {81if (hasUsable) {82((Usable) key).useKey();83}84} catch (IllegalStateException ise) {85// not an error86}8788try {89key.getAlgorithm();90key.getFormat();91if (!allZero(key.getEncoded())) {92throw new Exception("error: key destroyed incorrectly");93}94} catch (IllegalStateException ise) {95// not an error96}9798System.out.println("A " + klass +99" key has been successfully destroyed");100}101102// Check the behaviour of a key that does not implement key destruction103private static void testNoKeyDestruction(Destroyable key)104throws Exception {105String klass = key.getClass().getName();106107if (key.isDestroyed()) {108throw new Exception("error: a " + klass +109" key has been unexpectedly destroyed");110}111try {112key.destroy();113} catch (DestroyFailedException dfe) {114// not an error115116if (key.isDestroyed()) {117throw new Exception("error: a " + klass +118" key has been unexpectedly destroyed");119}120System.out.println(klass + " keys are not destroyable");121return;122}123throw new Exception("error: key may been unexpectedly destroyed");124}125126private static KeyPair generateKeyPair(String algorithm, int size)127throws NoSuchAlgorithmException {128KeyPairGenerator generator = KeyPairGenerator.getInstance(algorithm);129generator.initialize(size);130return generator.genKeyPair();131}132133private static SecretKey generateSecretKey(String algorithm, int size)134throws NoSuchAlgorithmException {135KeyGenerator generator = KeyGenerator.getInstance(algorithm);136generator.init(size);137return generator.generateKey();138}139140private static void destroyKey(Key key) throws Exception {141String klass = key.getClass().getName();142143if (!(key instanceof Destroyable)) {144throw new UnsupportedOperationException();145}146147Destroyable dKey = (Destroyable) key;148if (dKey.isDestroyed()) {149throw new Exception("error: a " + klass +150" key has already been destroyed");151}152dKey.destroy();153if (!dKey.isDestroyed()) {154throw new Exception("error: a " + klass +155" key has NOT been destroyed");156}157}158159private static boolean allZero(byte[] bytes) {160int count = 0;161for (byte b : bytes) {162if (b == 0x00) {163count++;164}165}166return (bytes.length == count);167}168}169170interface Usable {171public void useKey();172}173174class MyDestroyableSecretKey implements SecretKey, Usable {175private byte[] encoded = new byte[]{0x0F, 0x1F, 0x2F, 0x3F}; // non-zero176private boolean isDestroyed = false;177178@Override179public void useKey() {180if (isDestroyed) {181throw new IllegalStateException();182}183}184185@Override186public String getAlgorithm() {187return "MyDestroyableSecretKey algorithm";188}189190@Override191public String getFormat() {192return "MyDestroyableSecretKey format";193}194195@Override196public byte[] getEncoded() {197return this.encoded;198}199200@Override201public void destroy() throws DestroyFailedException {202if (!this.isDestroyed) {203Arrays.fill(encoded, (byte) 0);204this.isDestroyed = true;205}206}207208@Override209public boolean isDestroyed() {210return this.isDestroyed;211}212}213214class MyDestroyablePrivateKey implements PrivateKey, Usable {215private byte[] encoded = new byte[]{0x4F, 0x5F, 0x6F, 0x7F}; // non-zero216private boolean isDestroyed = false;217218@Override219public void useKey() {220if (isDestroyed) {221throw new IllegalStateException();222}223}224225@Override226public String getAlgorithm() {227return "MyDestroyablePrivateKey algorithm";228}229230@Override231public String getFormat() {232return "MyDestroyablePrivateKey format";233}234235@Override236public byte[] getEncoded() {237return this.encoded;238}239240@Override241public void destroy() throws DestroyFailedException {242if (!this.isDestroyed) {243Arrays.fill(encoded, (byte) 0);244this.isDestroyed = true;245}246}247248@Override249public boolean isDestroyed() {250return this.isDestroyed;251}252}253254255