1 /*
2  * Copyright (c) 2003, 2020, 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 Hmac key generator
109     abstract static class HmacKG extends KeyGeneratorSpi {
110         private final KeyGeneratorCore core;
HmacKG(String algoName, int len)111         protected HmacKG(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 HmacKG {
SHA224()133             public SHA224() {
134                 super("HmacSHA224", 224);
135             }
136         }
137         public static final class SHA256 extends HmacKG {
SHA256()138             public SHA256() {
139                 super("HmacSHA256", 256);
140             }
141         }
142         public static final class SHA384 extends HmacKG {
SHA384()143             public SHA384() {
144                 super("HmacSHA384", 384);
145             }
146         }
147         public static final class SHA512 extends HmacKG {
SHA512()148             public SHA512() {
149                 super("HmacSHA512", 512);
150             }
151         }
152         public static final class SHA512_224 extends HmacKG {
SHA512_224()153             public SHA512_224() {
154                 super("HmacSHA512/224", 224);
155             }
156         }
157         public static final class SHA512_256 extends HmacKG {
SHA512_256()158             public SHA512_256() {
159                 super("HmacSHA512/256", 256);
160             }
161         }
162         public static final class SHA3_224 extends HmacKG {
SHA3_224()163             public SHA3_224() {
164                 super("HmacSHA3-224", 224);
165             }
166         }
167         public static final class SHA3_256 extends HmacKG {
SHA3_256()168             public SHA3_256() {
169                 super("HmacSHA3-256", 256);
170             }
171         }
172         public static final class SHA3_384 extends HmacKG {
SHA3_384()173             public SHA3_384() {
174                 super("HmacSHA3-384", 384);
175             }
176         }
177         public static final class SHA3_512 extends HmacKG {
SHA3_512()178             public SHA3_512() {
179                 super("HmacSHA3-512", 512);
180             }
181         }
182     }
183 
184     // nested static class for the RC2 key generator
185     public static final class RC2KeyGenerator extends KeyGeneratorSpi {
186         private final KeyGeneratorCore core;
RC2KeyGenerator()187         public RC2KeyGenerator() {
188             core = new KeyGeneratorCore("RC2", 128);
189         }
190         @Override
engineInit(SecureRandom random)191         protected void engineInit(SecureRandom random) {
192             core.implInit(random);
193         }
194         @Override
engineInit(AlgorithmParameterSpec params, SecureRandom random)195         protected void engineInit(AlgorithmParameterSpec params,
196                 SecureRandom random) throws InvalidAlgorithmParameterException {
197             core.implInit(params, random);
198         }
199         @Override
engineInit(int keySize, SecureRandom random)200         protected void engineInit(int keySize, SecureRandom random) {
201             if ((keySize < 40) || (keySize > 1024)) {
202                 throw new InvalidParameterException("Key length for RC2"
203                     + " must be between 40 and 1024 bits");
204             }
205             core.implInit(keySize, random);
206         }
207         @Override
engineGenerateKey()208         protected SecretKey engineGenerateKey() {
209             return core.implGenerateKey();
210         }
211     }
212 
213     // nested static class for the ARCFOUR (RC4) key generator
214     public static final class ARCFOURKeyGenerator extends KeyGeneratorSpi {
215         private final KeyGeneratorCore core;
ARCFOURKeyGenerator()216         public ARCFOURKeyGenerator() {
217             core = new KeyGeneratorCore("ARCFOUR", 128);
218         }
219         @Override
engineInit(SecureRandom random)220         protected void engineInit(SecureRandom random) {
221             core.implInit(random);
222         }
223         @Override
engineInit(AlgorithmParameterSpec params, SecureRandom random)224         protected void engineInit(AlgorithmParameterSpec params,
225                 SecureRandom random) throws InvalidAlgorithmParameterException {
226             core.implInit(params, random);
227         }
228         @Override
engineInit(int keySize, SecureRandom random)229         protected void engineInit(int keySize, SecureRandom random) {
230             if ((keySize < 40) || (keySize > 1024)) {
231                 throw new InvalidParameterException("Key length for ARCFOUR"
232                     + " must be between 40 and 1024 bits");
233             }
234             core.implInit(keySize, random);
235         }
236         @Override
engineGenerateKey()237         protected SecretKey engineGenerateKey() {
238             return core.implGenerateKey();
239         }
240     }
241 
242     // nested static class for the ChaCha20 key generator
243     public static final class ChaCha20KeyGenerator extends KeyGeneratorSpi {
244         private final KeyGeneratorCore core;
ChaCha20KeyGenerator()245         public ChaCha20KeyGenerator() {
246             core = new KeyGeneratorCore("ChaCha20", 256);
247         }
248         @Override
engineInit(SecureRandom random)249         protected void engineInit(SecureRandom random) {
250             core.implInit(random);
251         }
252         @Override
engineInit(AlgorithmParameterSpec params, SecureRandom random)253         protected void engineInit(AlgorithmParameterSpec params,
254                 SecureRandom random) throws InvalidAlgorithmParameterException {
255             core.implInit(params, random);
256         }
257         @Override
engineInit(int keySize, SecureRandom random)258         protected void engineInit(int keySize, SecureRandom random) {
259             if (keySize != 256) {
260                 throw new InvalidParameterException(
261                         "Key length for ChaCha20 must be 256 bits");
262             }
263             core.implInit(keySize, random);
264         }
265         @Override
engineGenerateKey()266         protected SecretKey engineGenerateKey() {
267             return core.implGenerateKey();
268         }
269     }
270 }
271