1 /* 2 * Copyright (c) 1997, 2014, 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.InvalidKeyException; 29 import java.security.spec.KeySpec; 30 import java.security.spec.InvalidKeySpecException; 31 import javax.crypto.SecretKey; 32 import javax.crypto.SecretKeyFactorySpi; 33 import javax.crypto.spec.PBEKeySpec; 34 import java.util.HashSet; 35 import java.util.Locale; 36 37 /** 38 * This class implements a key factory for PBE keys according to PKCS#5, 39 * meaning that the password must consist of printable ASCII characters 40 * (values 32 to 126 decimal inclusive) and only the low order 8 bits 41 * of each password character are used. 42 * 43 * @author Jan Luehe 44 * 45 */ 46 abstract class PBEKeyFactory extends SecretKeyFactorySpi { 47 48 private String type; 49 private static HashSet<String> validTypes; 50 51 /** 52 * Simple constructor 53 */ 54 private PBEKeyFactory(String keytype) { 55 type = keytype; 56 } 57 58 static { 59 validTypes = new HashSet<String>(17); 60 validTypes.add("PBEWithMD5AndDES".toUpperCase(Locale.ENGLISH)); 61 validTypes.add("PBEWithSHA1AndDESede".toUpperCase(Locale.ENGLISH)); 62 validTypes.add("PBEWithSHA1AndRC2_40".toUpperCase(Locale.ENGLISH)); 63 validTypes.add("PBEWithSHA1AndRC2_128".toUpperCase(Locale.ENGLISH)); 64 validTypes.add("PBEWithSHA1AndRC4_40".toUpperCase(Locale.ENGLISH)); 65 validTypes.add("PBEWithSHA1AndRC4_128".toUpperCase(Locale.ENGLISH)); 66 // Proprietary algorithm. 67 validTypes.add("PBEWithMD5AndTripleDES".toUpperCase(Locale.ENGLISH)); 68 validTypes.add("PBEWithHmacSHA1AndAES_128".toUpperCase(Locale.ENGLISH)); 69 validTypes.add("PBEWithHmacSHA224AndAES_128".toUpperCase(Locale.ENGLISH)); 70 validTypes.add("PBEWithHmacSHA256AndAES_128".toUpperCase(Locale.ENGLISH)); 71 validTypes.add("PBEWithHmacSHA384AndAES_128".toUpperCase(Locale.ENGLISH)); 72 validTypes.add("PBEWithHmacSHA512AndAES_128".toUpperCase(Locale.ENGLISH)); 73 validTypes.add("PBEWithHmacSHA1AndAES_256".toUpperCase(Locale.ENGLISH)); 74 validTypes.add("PBEWithHmacSHA224AndAES_256".toUpperCase(Locale.ENGLISH)); 75 validTypes.add("PBEWithHmacSHA256AndAES_256".toUpperCase(Locale.ENGLISH)); 76 validTypes.add("PBEWithHmacSHA384AndAES_256".toUpperCase(Locale.ENGLISH)); 77 validTypes.add("PBEWithHmacSHA512AndAES_256".toUpperCase(Locale.ENGLISH)); 78 } 79 80 public static final class PBEWithMD5AndDES 81 extends PBEKeyFactory { 82 public PBEWithMD5AndDES() { 83 super("PBEWithMD5AndDES"); 84 } 85 } 86 87 public static final class PBEWithSHA1AndDESede 88 extends PBEKeyFactory { 89 public PBEWithSHA1AndDESede() { 90 super("PBEWithSHA1AndDESede"); 91 } 92 } 93 94 public static final class PBEWithSHA1AndRC2_40 95 extends PBEKeyFactory { 96 public PBEWithSHA1AndRC2_40() { 97 super("PBEWithSHA1AndRC2_40"); 98 } 99 } 100 101 public static final class PBEWithSHA1AndRC2_128 102 extends PBEKeyFactory { 103 public PBEWithSHA1AndRC2_128() { 104 super("PBEWithSHA1AndRC2_128"); 105 } 106 } 107 108 public static final class PBEWithSHA1AndRC4_40 109 extends PBEKeyFactory { 110 public PBEWithSHA1AndRC4_40() { 111 super("PBEWithSHA1AndRC4_40"); 112 } 113 } 114 115 public static final class PBEWithSHA1AndRC4_128 116 extends PBEKeyFactory { 117 public PBEWithSHA1AndRC4_128() { 118 super("PBEWithSHA1AndRC4_128"); 119 } 120 } 121 122 /* 123 * Private proprietary algorithm for supporting JCEKS. 124 */ 125 public static final class PBEWithMD5AndTripleDES 126 extends PBEKeyFactory { 127 public PBEWithMD5AndTripleDES() { 128 super("PBEWithMD5AndTripleDES"); 129 } 130 } 131 132 public static final class PBEWithHmacSHA1AndAES_128 133 extends PBEKeyFactory { 134 public PBEWithHmacSHA1AndAES_128() { 135 super("PBEWithHmacSHA1AndAES_128"); 136 } 137 } 138 139 public static final class PBEWithHmacSHA224AndAES_128 140 extends PBEKeyFactory { 141 public PBEWithHmacSHA224AndAES_128() { 142 super("PBEWithHmacSHA224AndAES_128"); 143 } 144 } 145 146 public static final class PBEWithHmacSHA256AndAES_128 147 extends PBEKeyFactory { 148 public PBEWithHmacSHA256AndAES_128() { 149 super("PBEWithHmacSHA256AndAES_128"); 150 } 151 } 152 153 public static final class PBEWithHmacSHA384AndAES_128 154 extends PBEKeyFactory { 155 public PBEWithHmacSHA384AndAES_128() { 156 super("PBEWithHmacSHA384AndAES_128"); 157 } 158 } 159 160 public static final class PBEWithHmacSHA512AndAES_128 161 extends PBEKeyFactory { 162 public PBEWithHmacSHA512AndAES_128() { 163 super("PBEWithHmacSHA512AndAES_128"); 164 } 165 } 166 167 public static final class PBEWithHmacSHA1AndAES_256 168 extends PBEKeyFactory { 169 public PBEWithHmacSHA1AndAES_256() { 170 super("PBEWithHmacSHA1AndAES_256"); 171 } 172 } 173 174 public static final class PBEWithHmacSHA224AndAES_256 175 extends PBEKeyFactory { 176 public PBEWithHmacSHA224AndAES_256() { 177 super("PBEWithHmacSHA224AndAES_256"); 178 } 179 } 180 181 public static final class PBEWithHmacSHA256AndAES_256 182 extends PBEKeyFactory { 183 public PBEWithHmacSHA256AndAES_256() { 184 super("PBEWithHmacSHA256AndAES_256"); 185 } 186 } 187 188 public static final class PBEWithHmacSHA384AndAES_256 189 extends PBEKeyFactory { 190 public PBEWithHmacSHA384AndAES_256() { 191 super("PBEWithHmacSHA384AndAES_256"); 192 } 193 } 194 195 public static final class PBEWithHmacSHA512AndAES_256 196 extends PBEKeyFactory { 197 public PBEWithHmacSHA512AndAES_256() { 198 super("PBEWithHmacSHA512AndAES_256"); 199 } 200 } 201 202 /** 203 * Generates a <code>SecretKey</code> object from the provided key 204 * specification (key material). 205 * 206 * @param keySpec the specification (key material) of the secret key 207 * 208 * @return the secret key 209 * 210 * @exception InvalidKeySpecException if the given key specification 211 * is inappropriate for this key factory to produce a public key. 212 */ 213 protected SecretKey engineGenerateSecret(KeySpec keySpec) 214 throws InvalidKeySpecException 215 { 216 if (!(keySpec instanceof PBEKeySpec)) { 217 throw new InvalidKeySpecException("Invalid key spec"); 218 } 219 return new PBEKey((PBEKeySpec)keySpec, type); 220 } 221 222 /** 223 * Returns a specification (key material) of the given key 224 * in the requested format. 225 * 226 * @param key the key 227 * 228 * @param keySpec the requested format in which the key material shall be 229 * returned 230 * 231 * @return the underlying key specification (key material) in the 232 * requested format 233 * 234 * @exception InvalidKeySpecException if the requested key specification is 235 * inappropriate for the given key, or the given key cannot be processed 236 * (e.g., the given key has an unrecognized algorithm or format). 237 */ 238 protected KeySpec engineGetKeySpec(SecretKey key, Class<?> keySpecCl) 239 throws InvalidKeySpecException { 240 if ((key instanceof SecretKey) 241 && (validTypes.contains(key.getAlgorithm().toUpperCase(Locale.ENGLISH))) 242 && (key.getFormat().equalsIgnoreCase("RAW"))) { 243 244 // Check if requested key spec is amongst the valid ones 245 if ((keySpecCl != null) 246 && PBEKeySpec.class.isAssignableFrom(keySpecCl)) { 247 byte[] passwdBytes = key.getEncoded(); 248 char[] passwdChars = new char[passwdBytes.length]; 249 for (int i=0; i<passwdChars.length; i++) 250 passwdChars[i] = (char) (passwdBytes[i] & 0x7f); 251 PBEKeySpec ret = new PBEKeySpec(passwdChars); 252 // password char[] was cloned in PBEKeySpec constructor, 253 // so we can zero it out here 254 java.util.Arrays.fill(passwdChars, ' '); 255 java.util.Arrays.fill(passwdBytes, (byte)0x00); 256 return ret; 257 } else { 258 throw new InvalidKeySpecException("Invalid key spec"); 259 } 260 } else { 261 throw new InvalidKeySpecException("Invalid key " 262 + "format/algorithm"); 263 } 264 } 265 266 /** 267 * Translates a <code>SecretKey</code> object, whose provider may be 268 * unknown or potentially untrusted, into a corresponding 269 * <code>SecretKey</code> object of this key factory. 270 * 271 * @param key the key whose provider is unknown or untrusted 272 * 273 * @return the translated key 274 * 275 * @exception InvalidKeyException if the given key cannot be processed by 276 * this key factory. 277 */ 278 protected SecretKey engineTranslateKey(SecretKey key) 279 throws InvalidKeyException 280 { 281 try { 282 if ((key != null) && 283 (validTypes.contains(key.getAlgorithm().toUpperCase(Locale.ENGLISH))) && 284 (key.getFormat().equalsIgnoreCase("RAW"))) { 285 286 // Check if key originates from this factory 287 if (key instanceof com.sun.crypto.provider.PBEKey) { 288 return key; 289 } 290 291 // Convert key to spec 292 PBEKeySpec pbeKeySpec = (PBEKeySpec)engineGetKeySpec 293 (key, PBEKeySpec.class); 294 295 // Create key from spec, and return it 296 return engineGenerateSecret(pbeKeySpec); 297 } else { 298 throw new InvalidKeyException("Invalid key format/algorithm"); 299 } 300 301 } catch (InvalidKeySpecException ikse) { 302 throw new InvalidKeyException("Cannot translate key: " 303 + ikse.getMessage()); 304 } 305 } 306 }