1 /* 2 * Copyright (c) 2003, 2011, 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.security.*; 29 import java.security.spec.*; 30 31 import sun.security.pkcs11.wrapper.PKCS11Exception; 32 33 /** 34 * KeyFactory base class. Provides common infrastructure for the RSA, DSA, 35 * and DH implementations. 36 * 37 * The subclasses support conversion between keys and keyspecs 38 * using X.509, PKCS#8, and their individual algorithm specific formats, 39 * assuming keys are extractable. 40 * 41 * @author Andreas Sterbenz 42 * @since 1.5 43 */ 44 abstract class P11KeyFactory extends KeyFactorySpi { 45 46 // token instance 47 final Token token; 48 49 // algorithm name, currently one of RSA, DSA, DH 50 final String algorithm; 51 52 P11KeyFactory(Token token, String algorithm) { 53 super(); 54 this.token = token; 55 this.algorithm = algorithm; 56 } 57 58 /** 59 * Convert an arbitrary key of algorithm into a P11Key of token. 60 * Used by P11Signature.init() and RSACipher.init(). 61 */ 62 static P11Key convertKey(Token token, Key key, String algorithm) 63 throws InvalidKeyException { 64 return (P11Key)token.getKeyFactory(algorithm).engineTranslateKey(key); 65 } 66 67 // see JCA spec 68 protected final <T extends KeySpec> T engineGetKeySpec(Key key, Class<T> keySpec) 69 throws InvalidKeySpecException { 70 token.ensureValid(); 71 if ((key == null) || (keySpec == null)) { 72 throw new InvalidKeySpecException 73 ("key and keySpec must not be null"); 74 } 75 // delegate to our Java based providers for PKCS#8 and X.509 76 if (PKCS8EncodedKeySpec.class.isAssignableFrom(keySpec) 77 || X509EncodedKeySpec.class.isAssignableFrom(keySpec)) { 78 try { 79 return implGetSoftwareFactory().getKeySpec(key, keySpec); 80 } catch (GeneralSecurityException e) { 81 throw new InvalidKeySpecException("Could not encode key", e); 82 } 83 } 84 // first translate into a key of this token, if it is not already 85 P11Key p11Key; 86 try { 87 p11Key = (P11Key)engineTranslateKey(key); 88 } catch (InvalidKeyException e) { 89 throw new InvalidKeySpecException("Could not convert key", e); 90 } 91 Session[] session = new Session[1]; 92 try { 93 if (p11Key.isPublic()) { 94 return implGetPublicKeySpec(p11Key, keySpec, session); 95 } else { 96 return implGetPrivateKeySpec(p11Key, keySpec, session); 97 } 98 } catch (PKCS11Exception e) { 99 throw new InvalidKeySpecException("Could not generate KeySpec", e); 100 } finally { 101 session[0] = token.releaseSession(session[0]); 102 } 103 } 104 105 // see JCA spec 106 protected final Key engineTranslateKey(Key key) throws InvalidKeyException { 107 token.ensureValid(); 108 if (key == null) { 109 throw new InvalidKeyException("Key must not be null"); 110 } 111 if (key.getAlgorithm().equals(this.algorithm) == false) { 112 throw new InvalidKeyException 113 ("Key algorithm must be " + algorithm); 114 } 115 if (key instanceof P11Key) { 116 P11Key p11Key = (P11Key)key; 117 if (p11Key.token == token) { 118 // already a key of this token, no need to translate 119 return key; 120 } 121 } 122 P11Key p11Key = token.privateCache.get(key); 123 if (p11Key != null) { 124 return p11Key; 125 } 126 if (key instanceof PublicKey) { 127 PublicKey publicKey = implTranslatePublicKey((PublicKey)key); 128 token.privateCache.put(key, (P11Key)publicKey); 129 return publicKey; 130 } else if (key instanceof PrivateKey) { 131 PrivateKey privateKey = implTranslatePrivateKey((PrivateKey)key); 132 token.privateCache.put(key, (P11Key)privateKey); 133 return privateKey; 134 } else { 135 throw new InvalidKeyException 136 ("Key must be instance of PublicKey or PrivateKey"); 137 } 138 } 139 140 abstract <T extends KeySpec> T implGetPublicKeySpec(P11Key key, Class<T> keySpec, 141 Session[] session) throws PKCS11Exception, InvalidKeySpecException; 142 143 abstract <T extends KeySpec> T implGetPrivateKeySpec(P11Key key, Class<T> keySpec, 144 Session[] session) throws PKCS11Exception, InvalidKeySpecException; 145 146 abstract PublicKey implTranslatePublicKey(PublicKey key) 147 throws InvalidKeyException; 148 149 abstract PrivateKey implTranslatePrivateKey(PrivateKey key) 150 throws InvalidKeyException; 151 152 abstract KeyFactory implGetSoftwareFactory() throws GeneralSecurityException; 153 154 }