1 /* 2 * Copyright (c) 2003, 2019, 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 sun.security.pkcs11; 27 28 import java.util.*; 29 30 import java.security.*; 31 import java.security.spec.*; 32 33 import javax.crypto.*; 34 import javax.crypto.spec.*; 35 36 import static sun.security.pkcs11.TemplateManager.*; 37 import sun.security.pkcs11.wrapper.*; 38 import static sun.security.pkcs11.wrapper.PKCS11Constants.*; 39 40 /** 41 * SecretKeyFactory implementation class. This class currently supports 42 * DES, DESede, AES, ARCFOUR, and Blowfish. 43 * 44 * @author Andreas Sterbenz 45 * @since 1.5 46 */ 47 final class P11SecretKeyFactory extends SecretKeyFactorySpi { 48 49 // token instance 50 private final Token token; 51 52 // algorithm name 53 private final String algorithm; 54 P11SecretKeyFactory(Token token, String algorithm)55 P11SecretKeyFactory(Token token, String algorithm) { 56 super(); 57 this.token = token; 58 this.algorithm = algorithm; 59 } 60 61 private static final Map<String,Long> keyTypes; 62 63 static { 64 keyTypes = new HashMap<String,Long>(); 65 addKeyType("RC4", CKK_RC4); 66 addKeyType("ARCFOUR", CKK_RC4); 67 addKeyType("DES", CKK_DES); 68 addKeyType("DESede", CKK_DES3); 69 addKeyType("AES", CKK_AES); 70 addKeyType("Blowfish", CKK_BLOWFISH); 71 72 // we don't implement RC2 or IDEA, but we want to be able to generate 73 // keys for those SSL/TLS ciphersuites. 74 addKeyType("RC2", CKK_RC2); 75 addKeyType("IDEA", CKK_IDEA); 76 77 addKeyType("TlsPremasterSecret", PCKK_TLSPREMASTER); 78 addKeyType("TlsRsaPremasterSecret", PCKK_TLSRSAPREMASTER); 79 addKeyType("TlsMasterSecret", PCKK_TLSMASTER); 80 addKeyType("Generic", CKK_GENERIC_SECRET); 81 } 82 addKeyType(String name, long id)83 private static void addKeyType(String name, long id) { 84 Long l = Long.valueOf(id); 85 keyTypes.put(name, l); 86 keyTypes.put(name.toUpperCase(Locale.ENGLISH), l); 87 } 88 89 // returns the PKCS11 key type of the specified algorithm 90 // no psuedo KeyTypes getPKCS11KeyType(String algorithm)91 static long getPKCS11KeyType(String algorithm) { 92 long kt = getKeyType(algorithm); 93 if (kt == -1 || kt > PCKK_ANY) { 94 kt = CKK_GENERIC_SECRET; 95 } 96 return kt; 97 } 98 99 // returns direct lookup result of keyTypes using algorithm getKeyType(String algorithm)100 static long getKeyType(String algorithm) { 101 Long l = keyTypes.get(algorithm); 102 if (l == null) { 103 algorithm = algorithm.toUpperCase(Locale.ENGLISH); 104 l = keyTypes.get(algorithm); 105 if (l == null) { 106 if (algorithm.startsWith("HMAC")) { 107 return PCKK_HMAC; 108 } else if (algorithm.startsWith("SSLMAC")) { 109 return PCKK_SSLMAC; 110 } 111 } 112 } 113 return (l != null) ? l.longValue() : -1; 114 } 115 116 /** 117 * Convert an arbitrary key of algorithm into a P11Key of provider. 118 * Used in engineTranslateKey(), P11Cipher.init(), and P11Mac.init(). 119 */ convertKey(Token token, Key key, String algo)120 static P11Key convertKey(Token token, Key key, String algo) 121 throws InvalidKeyException { 122 return convertKey(token, key, algo, null); 123 } 124 125 /** 126 * Convert an arbitrary key of algorithm w/ custom attributes into a 127 * P11Key of provider. 128 * Used in P11KeyStore.storeSkey. 129 */ convertKey(Token token, Key key, String algo, CK_ATTRIBUTE[] extraAttrs)130 static P11Key convertKey(Token token, Key key, String algo, 131 CK_ATTRIBUTE[] extraAttrs) 132 throws InvalidKeyException { 133 token.ensureValid(); 134 if (key == null) { 135 throw new InvalidKeyException("Key must not be null"); 136 } 137 if (key instanceof SecretKey == false) { 138 throw new InvalidKeyException("Key must be a SecretKey"); 139 } 140 long algoType; 141 if (algo == null) { 142 algo = key.getAlgorithm(); 143 algoType = getKeyType(algo); 144 } else { 145 algoType = getKeyType(algo); 146 long keyAlgorithmType = getKeyType(key.getAlgorithm()); 147 if (algoType != keyAlgorithmType) { 148 if ((algoType == PCKK_HMAC) || (algoType == PCKK_SSLMAC)) { 149 // ignore key algorithm for MACs 150 } else { 151 throw new InvalidKeyException 152 ("Key algorithm must be " + algo); 153 } 154 } 155 } 156 if (key instanceof P11Key) { 157 P11Key p11Key = (P11Key)key; 158 if (p11Key.token == token) { 159 if (extraAttrs != null) { 160 P11Key newP11Key = null; 161 Session session = null; 162 long p11KeyID = p11Key.getKeyID(); 163 try { 164 session = token.getObjSession(); 165 long newKeyID = token.p11.C_CopyObject(session.id(), 166 p11KeyID, extraAttrs); 167 newP11Key = (P11Key) (P11Key.secretKey(session, 168 newKeyID, p11Key.algorithm, p11Key.keyLength, 169 extraAttrs)); 170 } catch (PKCS11Exception p11e) { 171 throw new InvalidKeyException 172 ("Cannot duplicate the PKCS11 key", p11e); 173 } finally { 174 p11Key.releaseKeyID(); 175 token.releaseSession(session); 176 } 177 p11Key = newP11Key; 178 } 179 return p11Key; 180 } 181 } 182 P11Key p11Key = token.secretCache.get(key); 183 if (p11Key != null) { 184 return p11Key; 185 } 186 if ("RAW".equalsIgnoreCase(key.getFormat()) == false) { 187 throw new InvalidKeyException("Encoded format must be RAW"); 188 } 189 byte[] encoded = key.getEncoded(); 190 p11Key = createKey(token, encoded, algo, algoType, extraAttrs); 191 token.secretCache.put(key, p11Key); 192 return p11Key; 193 } 194 fixDESParity(byte[] key, int offset)195 static void fixDESParity(byte[] key, int offset) { 196 for (int i = 0; i < 8; i++) { 197 int b = key[offset] & 0xfe; 198 b |= (Integer.bitCount(b) & 1) ^ 1; 199 key[offset++] = (byte)b; 200 } 201 } 202 createKey(Token token, byte[] encoded, String algorithm, long keyType, CK_ATTRIBUTE[] extraAttrs)203 private static P11Key createKey(Token token, byte[] encoded, 204 String algorithm, long keyType, CK_ATTRIBUTE[] extraAttrs) 205 throws InvalidKeyException { 206 int n = encoded.length << 3; 207 int keyLength = n; 208 try { 209 switch ((int)keyType) { 210 case (int)CKK_DES: 211 keyLength = 212 P11KeyGenerator.checkKeySize(CKM_DES_KEY_GEN, n, token); 213 fixDESParity(encoded, 0); 214 break; 215 case (int)CKK_DES3: 216 keyLength = 217 P11KeyGenerator.checkKeySize(CKM_DES3_KEY_GEN, n, token); 218 fixDESParity(encoded, 0); 219 fixDESParity(encoded, 8); 220 if (keyLength == 112) { 221 keyType = CKK_DES2; 222 } else { 223 keyType = CKK_DES3; 224 fixDESParity(encoded, 16); 225 } 226 break; 227 case (int)CKK_AES: 228 keyLength = 229 P11KeyGenerator.checkKeySize(CKM_AES_KEY_GEN, n, token); 230 break; 231 case (int)CKK_RC4: 232 keyLength = 233 P11KeyGenerator.checkKeySize(CKM_RC4_KEY_GEN, n, token); 234 break; 235 case (int)CKK_BLOWFISH: 236 keyLength = 237 P11KeyGenerator.checkKeySize(CKM_BLOWFISH_KEY_GEN, n, 238 token); 239 break; 240 case (int)CKK_GENERIC_SECRET: 241 case (int)PCKK_TLSPREMASTER: 242 case (int)PCKK_TLSRSAPREMASTER: 243 case (int)PCKK_TLSMASTER: 244 keyType = CKK_GENERIC_SECRET; 245 break; 246 case (int)PCKK_SSLMAC: 247 case (int)PCKK_HMAC: 248 if (n == 0) { 249 throw new InvalidKeyException 250 ("MAC keys must not be empty"); 251 } 252 keyType = CKK_GENERIC_SECRET; 253 break; 254 default: 255 throw new InvalidKeyException("Unknown algorithm " + 256 algorithm); 257 } 258 } catch (InvalidAlgorithmParameterException iape) { 259 throw new InvalidKeyException("Invalid key for " + algorithm, 260 iape); 261 } catch (ProviderException pe) { 262 throw new InvalidKeyException("Could not create key", pe); 263 } 264 Session session = null; 265 try { 266 CK_ATTRIBUTE[] attributes; 267 if (extraAttrs != null) { 268 attributes = new CK_ATTRIBUTE[3 + extraAttrs.length]; 269 System.arraycopy(extraAttrs, 0, attributes, 3, 270 extraAttrs.length); 271 } else { 272 attributes = new CK_ATTRIBUTE[3]; 273 } 274 attributes[0] = new CK_ATTRIBUTE(CKA_CLASS, CKO_SECRET_KEY); 275 attributes[1] = new CK_ATTRIBUTE(CKA_KEY_TYPE, keyType); 276 attributes[2] = new CK_ATTRIBUTE(CKA_VALUE, encoded); 277 attributes = token.getAttributes 278 (O_IMPORT, CKO_SECRET_KEY, keyType, attributes); 279 session = token.getObjSession(); 280 long keyID = token.p11.C_CreateObject(session.id(), attributes); 281 P11Key p11Key = (P11Key)P11Key.secretKey 282 (session, keyID, algorithm, keyLength, attributes); 283 return p11Key; 284 } catch (PKCS11Exception e) { 285 throw new InvalidKeyException("Could not create key", e); 286 } finally { 287 token.releaseSession(session); 288 } 289 } 290 291 // see JCE spec engineGenerateSecret(KeySpec keySpec)292 protected SecretKey engineGenerateSecret(KeySpec keySpec) 293 throws InvalidKeySpecException { 294 token.ensureValid(); 295 if (keySpec == null) { 296 throw new InvalidKeySpecException("KeySpec must not be null"); 297 } 298 if (keySpec instanceof SecretKeySpec) { 299 try { 300 Key key = convertKey(token, (SecretKey)keySpec, algorithm); 301 return (SecretKey)key; 302 } catch (InvalidKeyException e) { 303 throw new InvalidKeySpecException(e); 304 } 305 } else if (algorithm.equalsIgnoreCase("DES")) { 306 if (keySpec instanceof DESKeySpec) { 307 byte[] keyBytes = ((DESKeySpec)keySpec).getKey(); 308 keySpec = new SecretKeySpec(keyBytes, "DES"); 309 return engineGenerateSecret(keySpec); 310 } 311 } else if (algorithm.equalsIgnoreCase("DESede")) { 312 if (keySpec instanceof DESedeKeySpec) { 313 byte[] keyBytes = ((DESedeKeySpec)keySpec).getKey(); 314 keySpec = new SecretKeySpec(keyBytes, "DESede"); 315 return engineGenerateSecret(keySpec); 316 } 317 } 318 throw new InvalidKeySpecException 319 ("Unsupported spec: " + keySpec.getClass().getName()); 320 } 321 getKeyBytes(SecretKey key)322 private byte[] getKeyBytes(SecretKey key) throws InvalidKeySpecException { 323 try { 324 key = engineTranslateKey(key); 325 if ("RAW".equalsIgnoreCase(key.getFormat()) == false) { 326 throw new InvalidKeySpecException 327 ("Could not obtain key bytes"); 328 } 329 byte[] k = key.getEncoded(); 330 return k; 331 } catch (InvalidKeyException e) { 332 throw new InvalidKeySpecException(e); 333 } 334 } 335 336 // see JCE spec engineGetKeySpec(SecretKey key, Class<?> keySpec)337 protected KeySpec engineGetKeySpec(SecretKey key, Class<?> keySpec) 338 throws InvalidKeySpecException { 339 token.ensureValid(); 340 if ((key == null) || (keySpec == null)) { 341 throw new InvalidKeySpecException 342 ("key and keySpec must not be null"); 343 } 344 if (SecretKeySpec.class.isAssignableFrom(keySpec)) { 345 return new SecretKeySpec(getKeyBytes(key), algorithm); 346 } else if (algorithm.equalsIgnoreCase("DES")) { 347 try { 348 if (DESKeySpec.class.isAssignableFrom(keySpec)) { 349 return new DESKeySpec(getKeyBytes(key)); 350 } 351 } catch (InvalidKeyException e) { 352 throw new InvalidKeySpecException(e); 353 } 354 } else if (algorithm.equalsIgnoreCase("DESede")) { 355 try { 356 if (DESedeKeySpec.class.isAssignableFrom(keySpec)) { 357 return new DESedeKeySpec(getKeyBytes(key)); 358 } 359 } catch (InvalidKeyException e) { 360 throw new InvalidKeySpecException(e); 361 } 362 } 363 throw new InvalidKeySpecException 364 ("Unsupported spec: " + keySpec.getName()); 365 } 366 367 // see JCE spec engineTranslateKey(SecretKey key)368 protected SecretKey engineTranslateKey(SecretKey key) 369 throws InvalidKeyException { 370 return (SecretKey)convertKey(token, key, algorithm); 371 } 372 373 } 374