1/*
2 * Copyright (C) 2010 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package libcore.javax.crypto;
18
19import java.security.Provider;
20import java.security.SecureRandom;
21import java.security.Security;
22import java.util.HashMap;
23import java.util.Map;
24import java.util.List;
25import java.util.ArrayList;
26import java.util.Set;
27import javax.crypto.KeyGenerator;
28import javax.crypto.SecretKey;
29import junit.framework.TestCase;
30
31public class KeyGeneratorTest extends TestCase {
32
33    private static boolean isUnsupported(KeyGenerator kg) {
34        // Don't bother testing "Sun..." KeyGenerators
35        return (kg.getAlgorithm().startsWith("Sun"));
36    }
37
38    public void test_getInstance() throws Exception {
39        Provider[] providers = Security.getProviders();
40        for (Provider provider : providers) {
41            Set<Provider.Service> services = provider.getServices();
42            for (Provider.Service service : services) {
43                String type = service.getType();
44                if (!type.equals("KeyGenerator")) {
45                    continue;
46                }
47
48                // Do not test AndroidKeyStore's KeyGenerator. It cannot be initialized without
49                // providing AndroidKeyStore-specific algorithm parameters.
50                // It's OKish not to test AndroidKeyStore's KeyGenerator here because it's tested
51                // by cts/tests/test/keystore.
52                if ("AndroidKeyStore".equals(provider.getName())) {
53                    continue;
54                }
55
56                String algorithm = service.getAlgorithm();
57                try {
58                    // KeyGenerator.getInstance(String)
59                    KeyGenerator kg1 = KeyGenerator.getInstance(algorithm);
60                    assertEquals(algorithm, kg1.getAlgorithm());
61                    test_KeyGenerator(kg1);
62
63                    // KeyGenerator.getInstance(String, Provider)
64                    KeyGenerator kg2 = KeyGenerator.getInstance(algorithm, provider);
65                    assertEquals(algorithm, kg2.getAlgorithm());
66                    assertEquals(provider, kg2.getProvider());
67                    test_KeyGenerator(kg2);
68
69                    // KeyGenerator.getInstance(String, String)
70                    KeyGenerator kg3 = KeyGenerator.getInstance(algorithm, provider.getName());
71                    assertEquals(algorithm, kg3.getAlgorithm());
72                    assertEquals(provider, kg3.getProvider());
73                    test_KeyGenerator(kg3);
74                } catch (Exception e) {
75                    throw new Exception("Problem testing KeyPairGenerator." + algorithm, e);
76                }
77            }
78        }
79    }
80
81    private static final Map<String, List<Integer>> KEY_SIZES
82            = new HashMap<String, List<Integer>>();
83    private static void putKeySize(String algorithm, int keySize) {
84        algorithm = algorithm.toUpperCase();
85        List<Integer> keySizes = KEY_SIZES.get(algorithm);
86        if (keySizes == null) {
87            keySizes = new ArrayList<Integer>();
88            KEY_SIZES.put(algorithm, keySizes);
89        }
90        keySizes.add(keySize);
91    }
92    private static List<Integer> getKeySizes(String algorithm) throws Exception {
93        algorithm = algorithm.toUpperCase();
94        List<Integer> keySizes = KEY_SIZES.get(algorithm);
95        if (keySizes == null) {
96            throw new Exception("Unknown key sizes for KeyGenerator." + algorithm);
97        }
98        return keySizes;
99    }
100    static {
101        putKeySize("AES", 128);
102        putKeySize("AES", 192);
103        putKeySize("AES", 256);
104        putKeySize("ARC4", 1024);
105        putKeySize("ARC4", 40);
106        putKeySize("ARC4", 41);
107        putKeySize("ARCFOUR", 1024);
108        putKeySize("ARCFOUR", 40);
109        putKeySize("ARCFOUR", 41);
110        putKeySize("Blowfish", 32);
111        putKeySize("Blowfish", 32+8);
112        putKeySize("Blowfish", 448);
113        putKeySize("DES", 56);
114        putKeySize("DESede", 112);
115        putKeySize("DESede", 168);
116        putKeySize("RC2", 40);
117        putKeySize("RC2", 41);
118        putKeySize("RC2", 1024);
119        putKeySize("RC4", 40);
120        putKeySize("RC4", 41);
121        putKeySize("RC4", 1024);
122        putKeySize("HmacMD5", 1);
123        putKeySize("HmacMD5", 1025);
124        putKeySize("HmacSHA1", 1);
125        putKeySize("HmacSHA1", 1025);
126        putKeySize("HmacSHA224", 40);
127        putKeySize("HmacSHA224", 1025);
128        putKeySize("HmacSHA256", 40);
129        putKeySize("HmacSHA256", 1025);
130        putKeySize("HmacSHA384", 40);
131        putKeySize("HmacSHA384", 1025);
132        putKeySize("HmacSHA512", 40);
133        putKeySize("HmacSHA512", 1025);
134    }
135
136    private void test_KeyGenerator(KeyGenerator kg) throws Exception {
137        if (isUnsupported(kg)) {
138            return;
139        }
140
141        kg.init((SecureRandom) null);
142        test_SecretKey(kg, kg.generateKey());
143
144        kg.init(new SecureRandom());
145        test_SecretKey(kg, kg.generateKey());
146
147        String algorithm = kg.getAlgorithm();
148        List<Integer> keySizes = getKeySizes(algorithm);
149        for (int keySize : keySizes) {
150            kg.init(keySize);
151            test_SecretKey(kg, kg.generateKey());
152
153            kg.init(keySize, (SecureRandom) null);
154            test_SecretKey(kg, kg.generateKey());
155
156            kg.init(keySize, new SecureRandom());
157            test_SecretKey(kg, kg.generateKey());
158        }
159    }
160
161    private void test_SecretKey(KeyGenerator kg, SecretKey sk) throws Exception {
162        assertNotNull(sk);
163        assertEquals(kg.getAlgorithm().toUpperCase(), sk.getAlgorithm().toUpperCase());
164        assertNotNull(sk.getEncoded());
165        assertNotNull(sk.getFormat());
166    }
167}
168