1 /*
2  * Copyright (c) 2003, 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.  Oracle designates this
8  * particular file as subject to the "Classpath" exception as provided
9  * by Oracle in the LICENSE file that accompanied this code.
10  *
11  * This code is distributed in the hope that it will be useful, but WITHOUT
12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14  * version 2 for more details (a copy is included in the LICENSE file that
15  * accompanied this code).
16  *
17  * You should have received a copy of the GNU General Public License version
18  * 2 along with this work; if not, write to the Free Software Foundation,
19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20  *
21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22  * or visit www.oracle.com if you need additional information or have any
23  * questions.
24  */
25 
26 package com.sun.crypto.provider;
27 
28 import java.security.*;
29 import java.security.spec.AlgorithmParameterSpec;
30 
31 import javax.crypto.*;
32 import javax.crypto.spec.SecretKeySpec;
33 
34 /**
35  * KeyGeneratore core implementation and individual key generator
36  * implementations. Because of US export regulations, we cannot use
37  * subclassing to achieve code sharing between the key generator
38  * implementations for our various algorithms. Instead, we have the
39  * core implementation in this KeyGeneratorCore class, which is used
40  * by the individual implementations. See those further down in this
41  * file.
42  *
43  * @since   1.5
44  * @author  Andreas Sterbenz
45  */
46 final class KeyGeneratorCore {
47 
48     // algorithm name to use for the generator keys
49     private final String name;
50 
51     // default key size in bits
52     private final int defaultKeySize;
53 
54     // current key size in bits
55     private int keySize;
56 
57     // PRNG to use
58     private SecureRandom random;
59 
60     /**
61      * Construct a new KeyGeneratorCore object with the specified name
62      * and defaultKeySize. Initialize to default key size in case the
63      * application does not call any of the init() methods.
64      */
KeyGeneratorCore(String name, int defaultKeySize)65     KeyGeneratorCore(String name, int defaultKeySize) {
66         this.name = name;
67         this.defaultKeySize = defaultKeySize;
68         implInit(null);
69     }
70 
71     // implementation for engineInit(), see JCE doc
72     // reset keySize to default
implInit(SecureRandom random)73     void implInit(SecureRandom random) {
74         this.keySize = defaultKeySize;
75         this.random = random;
76     }
77 
78     // implementation for engineInit(), see JCE doc
79     // we do not support any parameters
implInit(AlgorithmParameterSpec params, SecureRandom random)80     void implInit(AlgorithmParameterSpec params, SecureRandom random)
81             throws InvalidAlgorithmParameterException {
82         throw new InvalidAlgorithmParameterException
83             (name + " key generation does not take any parameters");
84     }
85 
86     // implementation for engineInit(), see JCE doc
87     // we enforce a general 40 bit minimum key size for security
implInit(int keysize, SecureRandom random)88     void implInit(int keysize, SecureRandom random) {
89         if (keysize < 40) {
90             throw new InvalidParameterException
91                 ("Key length must be at least 40 bits");
92         }
93         this.keySize = keysize;
94         this.random = random;
95     }
96 
97     // implementation for engineInit(), see JCE doc
98     // generate the key
implGenerateKey()99     SecretKey implGenerateKey() {
100         if (random == null) {
101             random = SunJCE.getRandom();
102         }
103         byte[] b = new byte[(keySize + 7) >> 3];
104         random.nextBytes(b);
105         return new SecretKeySpec(b, name);
106     }
107 
108     // nested static classes for the HmacSHA-2 family of key generator
109     abstract static class HmacSHA2KG extends KeyGeneratorSpi {
110         private final KeyGeneratorCore core;
HmacSHA2KG(String algoName, int len)111         protected HmacSHA2KG(String algoName, int len) {
112             core = new KeyGeneratorCore(algoName, len);
113         }
114         @Override
engineInit(SecureRandom random)115         protected void engineInit(SecureRandom random) {
116             core.implInit(random);
117         }
118         @Override
engineInit(AlgorithmParameterSpec params, SecureRandom random)119         protected void engineInit(AlgorithmParameterSpec params,
120                 SecureRandom random) throws InvalidAlgorithmParameterException {
121             core.implInit(params, random);
122         }
123         @Override
engineInit(int keySize, SecureRandom random)124         protected void engineInit(int keySize, SecureRandom random) {
125             core.implInit(keySize, random);
126         }
127         @Override
engineGenerateKey()128         protected SecretKey engineGenerateKey() {
129             return core.implGenerateKey();
130         }
131 
132         public static final class SHA224 extends HmacSHA2KG {
SHA224()133             public SHA224() {
134                 super("HmacSHA224", 224);
135             }
136         }
137         public static final class SHA256 extends HmacSHA2KG {
SHA256()138             public SHA256() {
139                 super("HmacSHA256", 256);
140             }
141         }
142         public static final class SHA384 extends HmacSHA2KG {
SHA384()143             public SHA384() {
144                 super("HmacSHA384", 384);
145             }
146         }
147         public static final class SHA512 extends HmacSHA2KG {
SHA512()148             public SHA512() {
149                 super("HmacSHA512", 512);
150             }
151         }
152     }
153 
154     // nested static class for the RC2 key generator
155     public static final class RC2KeyGenerator extends KeyGeneratorSpi {
156         private final KeyGeneratorCore core;
RC2KeyGenerator()157         public RC2KeyGenerator() {
158             core = new KeyGeneratorCore("RC2", 128);
159         }
160         @Override
engineInit(SecureRandom random)161         protected void engineInit(SecureRandom random) {
162             core.implInit(random);
163         }
164         @Override
engineInit(AlgorithmParameterSpec params, SecureRandom random)165         protected void engineInit(AlgorithmParameterSpec params,
166                 SecureRandom random) throws InvalidAlgorithmParameterException {
167             core.implInit(params, random);
168         }
169         @Override
engineInit(int keySize, SecureRandom random)170         protected void engineInit(int keySize, SecureRandom random) {
171             if ((keySize < 40) || (keySize > 1024)) {
172                 throw new InvalidParameterException("Key length for RC2"
173                     + " must be between 40 and 1024 bits");
174             }
175             core.implInit(keySize, random);
176         }
177         @Override
engineGenerateKey()178         protected SecretKey engineGenerateKey() {
179             return core.implGenerateKey();
180         }
181     }
182 
183     // nested static class for the ARCFOUR (RC4) key generator
184     public static final class ARCFOURKeyGenerator extends KeyGeneratorSpi {
185         private final KeyGeneratorCore core;
ARCFOURKeyGenerator()186         public ARCFOURKeyGenerator() {
187             core = new KeyGeneratorCore("ARCFOUR", 128);
188         }
189         @Override
engineInit(SecureRandom random)190         protected void engineInit(SecureRandom random) {
191             core.implInit(random);
192         }
193         @Override
engineInit(AlgorithmParameterSpec params, SecureRandom random)194         protected void engineInit(AlgorithmParameterSpec params,
195                 SecureRandom random) throws InvalidAlgorithmParameterException {
196             core.implInit(params, random);
197         }
198         @Override
engineInit(int keySize, SecureRandom random)199         protected void engineInit(int keySize, SecureRandom random) {
200             if ((keySize < 40) || (keySize > 1024)) {
201                 throw new InvalidParameterException("Key length for ARCFOUR"
202                     + " must be between 40 and 1024 bits");
203             }
204             core.implInit(keySize, random);
205         }
206         @Override
engineGenerateKey()207         protected SecretKey engineGenerateKey() {
208             return core.implGenerateKey();
209         }
210     }
211 
212     // nested static class for the ChaCha20 key generator
213     public static final class ChaCha20KeyGenerator extends KeyGeneratorSpi {
214         private final KeyGeneratorCore core;
ChaCha20KeyGenerator()215         public ChaCha20KeyGenerator() {
216             core = new KeyGeneratorCore("ChaCha20", 256);
217         }
218         @Override
engineInit(SecureRandom random)219         protected void engineInit(SecureRandom random) {
220             core.implInit(random);
221         }
222         @Override
engineInit(AlgorithmParameterSpec params, SecureRandom random)223         protected void engineInit(AlgorithmParameterSpec params,
224                 SecureRandom random) throws InvalidAlgorithmParameterException {
225             core.implInit(params, random);
226         }
227         @Override
engineInit(int keySize, SecureRandom random)228         protected void engineInit(int keySize, SecureRandom random) {
229             if (keySize != 256) {
230                 throw new InvalidParameterException(
231                         "Key length for ChaCha20 must be 256 bits");
232             }
233             core.implInit(keySize, random);
234         }
235         @Override
engineGenerateKey()236         protected SecretKey engineGenerateKey() {
237             return core.implGenerateKey();
238         }
239     }
240 }
241