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