SecretKeysBasic.java revision 8729:0242fce0f717
1251876Speter/*
2251876Speter * Copyright (c) 2008, 2013, Oracle and/or its affiliates. All rights reserved.
3251876Speter * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4251876Speter *
5251876Speter * This code is free software; you can redistribute it and/or modify it
6251876Speter * under the terms of the GNU General Public License version 2 only, as
7251876Speter * published by the Free Software Foundation.
8251876Speter *
9251876Speter * This code is distributed in the hope that it will be useful, but WITHOUT
10251876Speter * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11251876Speter * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
12251876Speter * version 2 for more details (a copy is included in the LICENSE file that
13251876Speter * accompanied this code).
14251876Speter *
15251876Speter * You should have received a copy of the GNU General Public License version
16251876Speter * 2 along with this work; if not, write to the Free Software Foundation,
17251876Speter * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18251876Speter *
19251876Speter * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20251876Speter * or visit www.oracle.com if you need additional information or have any
21251876Speter * questions.
22251876Speter */
23251876Speter
24251876Speterimport java.io.*;
25251876Speterimport java.util.*;
26251876Speterimport java.security.*;
27251876Speterimport javax.crypto.*;
28251876Speterimport javax.crypto.spec.*;
29251876Speterimport javax.xml.bind.DatatypeConverter;
30251876Speter
31251876Speterpublic class SecretKeysBasic extends PKCS11Test {
32251876Speter
33251876Speter    private static final char SEP = File.separatorChar;
34251876Speter    private static char[] tokenPwd;
35251876Speter    private static final char[] nssPwd =
36251876Speter            new char[]{'t', 'e', 's', 't', '1', '2'};
37251876Speter    private static final char[] solarisPwd =
38251876Speter            new char[]{'p', 'i', 'n'};
39251876Speter    private static SecretKey sk1;
40251876Speter    private static SecretKey sk2;
41251876Speter    private static SecretKey softkey;
42251876Speter    private static KeyStore ks;
43251876Speter    private static final String KS_TYPE = "PKCS11";
44251876Speter    private static Provider provider;
45251876Speter
46251876Speter    public static void main(String[] args) throws Exception {
47251876Speter        main(new SecretKeysBasic());
48251876Speter    }
49251876Speter
50251876Speter    public void main(Provider p) throws Exception {
51251876Speter        this.provider = p;
52251876Speter
53251876Speter        // create secret key
54251876Speter        byte[] keyVal = new byte[16];
55251876Speter        (new SecureRandom()).nextBytes(keyVal);
56251876Speter        // NSS will throw CKR_HOST_MEMORY if calling C_DecryptInit w/
57251876Speter        // (keyVal[0] == 0)
58251876Speter        if (keyVal[0] == 0) {
59251876Speter            keyVal[0] = 1;
60251876Speter        }
61251876Speter        softkey = new SecretKeySpec(keyVal, "AES");
62251876Speter        dumpKey("softkey", softkey);
63251876Speter
64251876Speter        KeyGenerator kg = KeyGenerator.getInstance("DESede", provider);
65251876Speter        sk1 = kg.generateKey();
66251876Speter        dumpKey("skey1", sk1);
67251876Speter        sk2 = kg.generateKey();
68251876Speter        dumpKey("skey2", sk2);
69251876Speter
70251876Speter        String token = System.getProperty("TOKEN");
71251876Speter
72251876Speter        if (token == null || token.length() == 0) {
73251876Speter            System.out.println("Error: missing TOKEN system property");
74251876Speter            throw new Exception("token arg required");
75251876Speter        }
76251876Speter
77251876Speter        if ("nss".equals(token)) {
78251876Speter            tokenPwd = nssPwd;
79251876Speter        } else if ("solaris".equals(token)) {
80251876Speter            tokenPwd = solarisPwd;
81251876Speter        }
82251876Speter
83251876Speter        int testnum = 1;
84251876Speter        doTest();
85251876Speter    }
86251876Speter
87251876Speter    private static boolean checkSecretKeyEntry(String alias,
88251876Speter            SecretKey expected,
89251876Speter            boolean saveBeforeCheck)
90251876Speter            throws Exception {
91251876Speter
92251876Speter        // A bug in NSS 3.12 (Mozilla bug 471665) causes AES key lengths
93251876Speter        // to be read incorrectly.  Checking for improper 16 byte length
94251876Speter        // in key string.
95251876Speter        if (isNSS(provider) && expected.getAlgorithm().equals("AES") &&
96251876Speter                (getNSSVersion() >= 3.12 && getNSSVersion() <= 3.122)) {
97251876Speter            System.out.println("NSS 3.12 bug returns incorrect AES key "+
98251876Speter                    "length breaking key storage. Aborting...");
99251876Speter            return true;
100251876Speter        }
101251876Speter
102251876Speter        if (saveBeforeCheck) {
103251876Speter            ks.setKeyEntry(alias, expected, null, null);
104251876Speter        }
105251876Speter        SecretKey result = (SecretKey) (ks.getKey(alias, null));
106251876Speter        String keyEncFormat = result.getFormat();
107251876Speter        if (keyEncFormat == null) {
108251876Speter            // sensitive or un-extractable keys - verify by encrypt/decrypt
109251876Speter            byte[] data = new byte[64];
110251876Speter            Cipher c =
111251876Speter                    Cipher.getInstance(result.getAlgorithm() + "/CBC/NoPadding",
112251876Speter                    provider);
113251876Speter            c.init(Cipher.ENCRYPT_MODE, expected);
114251876Speter            byte[] encOut = c.doFinal(data);
115251876Speter            c.init(Cipher.DECRYPT_MODE, result, c.getParameters());
116251876Speter            byte[] decOut = c.doFinal(encOut);
117251876Speter            if (!Arrays.equals(data, decOut)) {
118251876Speter                return false;
119251876Speter            }
120251876Speter        } else if (keyEncFormat.toUpperCase().equals("RAW")) {
121251876Speter            if (!Arrays.equals(result.getEncoded(), expected.getEncoded())) {
122251876Speter                dumpKey("\texpected:", expected);
123251876Speter                dumpKey("\treturns:", result);
124251876Speter                return false;
125251876Speter            }
126251876Speter        }
127251876Speter        return true;
128251876Speter    }
129251876Speter
130251876Speter    private static void dumpKey(String info, SecretKey key) {
131251876Speter        System.out.println(info + "> " + key);
132251876Speter        System.out.println("\tALGO=" + key.getAlgorithm());
133251876Speter        if (key.getFormat() != null) {
134251876Speter            System.out.println("\t[" + key.getFormat() + "] VALUE=" +
135251876Speter                    DatatypeConverter.printHexBinary(key.getEncoded()));
136251876Speter        } else {
137251876Speter            System.out.println("\tVALUE=n/a");
138251876Speter        }
139251876Speter    }
140251876Speter
141251876Speter    private static void doTest() throws Exception {
142251876Speter        if (ks == null) {
143251876Speter            ks = KeyStore.getInstance(KS_TYPE, provider);
144251876Speter            ks.load(null, tokenPwd);
145251876Speter        }
146251876Speter
147251876Speter        System.out.println("Number of entries: " + ks.size());
148251876Speter        if (ks.size() != 0) {
149251876Speter            System.out.println("Deleting entries under aliases: ");
150251876Speter            for (Enumeration<String> aliases = ks.aliases();
151251876Speter                    aliases.hasMoreElements();) {
152251876Speter                String alias = aliases.nextElement();
153251876Speter                System.out.println("\t" + alias);
154251876Speter                ks.deleteEntry(alias);
155251876Speter            }
156251876Speter        }
157251876Speter
158251876Speter        String alias = "testSKey";
159251876Speter
160251876Speter        boolean testResult = checkSecretKeyEntry(alias, softkey, true);
161251876Speter        if (!testResult) {
162251876Speter            System.out.println("FAILURE: setKey() w/ softSecretKey failed");
163251876Speter        }
164251876Speter
165251876Speter        if (!checkSecretKeyEntry(alias, sk1, true)) {
166251876Speter            testResult = false;
167251876Speter            System.out.println("FAILURE: setKey() w/ skey1 failed");
168251876Speter        }
169251876Speter        if (!checkSecretKeyEntry(alias, sk2, true)) {
170251876Speter            testResult = false;
171251876Speter            System.out.println("FAILURE: setKey() w/ skey2 failed");
172251876Speter        }
173251876Speter
174251876Speter        ks.store(null);
175251876Speter        System.out.println("Reloading keystore...");
176251876Speter
177251876Speter        ks.load(null, "whatever".toCharArray());
178251876Speter        if (ks.size() != 1) {
179251876Speter            System.out.println("FAILURE: reload#1 ks.size() != 1");
180251876Speter        }
181251876Speter        if (!checkSecretKeyEntry(alias, sk2, false)) {
182251876Speter            testResult = false;
183251876Speter            System.out.println("FAILURE: reload#1 ks entry check failed");
184251876Speter        }
185251876Speter
186251876Speter        ks.deleteEntry(alias);
187251876Speter        ks.store(null);
188251876Speter
189251876Speter        System.out.println("Reloading keystore...");
190251876Speter        ks.load(null, "whatever".toCharArray());
191251876Speter        if (ks.size() != 0) {
192251876Speter            testResult = false;
193251876Speter            System.out.println("FAILURE: reload#2 ks.size() != 0");
194251876Speter        }
195251876Speter        if (!testResult) {
196251876Speter            throw new Exception("One or more test failed!");
197251876Speter        }
198251876Speter    }
199251876Speter}
200251876Speter