Path: blob/master/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11KeyFactory.java
41154 views
/*1* Copyright (c) 2003, 2021, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation. Oracle designates this7* particular file as subject to the "Classpath" exception as provided8* by Oracle in the LICENSE file that accompanied this code.9*10* This code is distributed in the hope that it will be useful, but WITHOUT11* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or12* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License13* version 2 for more details (a copy is included in the LICENSE file that14* accompanied this code).15*16* You should have received a copy of the GNU General Public License version17* 2 along with this work; if not, write to the Free Software Foundation,18* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.19*20* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA21* or visit www.oracle.com if you need additional information or have any22* questions.23*/2425package sun.security.pkcs11;2627import java.security.*;28import java.security.spec.*;2930import sun.security.pkcs11.wrapper.PKCS11Exception;3132/**33* KeyFactory base class. Provides common infrastructure for the RSA, DSA,34* and DH implementations.35*36* The subclasses support conversion between keys and keyspecs37* using X.509, PKCS#8, and their individual algorithm specific formats,38* assuming keys are extractable.39*40* @author Andreas Sterbenz41* @since 1.542*/43abstract class P11KeyFactory extends KeyFactorySpi {4445// token instance46final Token token;4748// algorithm name, currently one of RSA, DSA, DH49final String algorithm;5051P11KeyFactory(Token token, String algorithm) {52super();53this.token = token;54this.algorithm = algorithm;55}5657/**58* Convert an arbitrary key of algorithm into a P11Key of token.59* Used by P11Signature.init() and RSACipher.init().60*/61static P11Key convertKey(Token token, Key key, String algorithm)62throws InvalidKeyException {63return (P11Key)token.getKeyFactory(algorithm).engineTranslateKey(key);64}6566// see JCA spec67protected final <T extends KeySpec> T engineGetKeySpec(Key key, Class<T> keySpec)68throws InvalidKeySpecException {69token.ensureValid();70if ((key == null) || (keySpec == null)) {71throw new InvalidKeySpecException72("key and keySpec must not be null");73}74// delegate to our Java based providers for PKCS#8 and X.50975if (keySpec.isAssignableFrom(PKCS8EncodedKeySpec.class)76|| keySpec.isAssignableFrom(X509EncodedKeySpec.class)) {77try {78return implGetSoftwareFactory().getKeySpec(key, keySpec);79} catch (GeneralSecurityException e) {80throw new InvalidKeySpecException("Could not encode key", e);81}82}83// first translate into a key of this token, if it is not already84P11Key p11Key;85try {86p11Key = (P11Key)engineTranslateKey(key);87} catch (InvalidKeyException e) {88throw new InvalidKeySpecException("Could not convert key", e);89}90Session[] session = new Session[1];91try {92if (p11Key.isPublic()) {93return implGetPublicKeySpec(p11Key, keySpec, session);94} else {95return implGetPrivateKeySpec(p11Key, keySpec, session);96}97} catch (PKCS11Exception e) {98throw new InvalidKeySpecException("Could not generate KeySpec", e);99} finally {100session[0] = token.releaseSession(session[0]);101}102}103104// see JCA spec105protected final Key engineTranslateKey(Key key) throws InvalidKeyException {106token.ensureValid();107if (key == null) {108throw new InvalidKeyException("Key must not be null");109}110if (key.getAlgorithm().equals(this.algorithm) == false) {111throw new InvalidKeyException112("Key algorithm must be " + algorithm);113}114if (key instanceof P11Key) {115P11Key p11Key = (P11Key)key;116if (p11Key.token == token) {117// already a key of this token, no need to translate118return key;119}120}121P11Key p11Key = token.privateCache.get(key);122if (p11Key != null) {123return p11Key;124}125if (key instanceof PublicKey) {126PublicKey publicKey = implTranslatePublicKey((PublicKey)key);127token.privateCache.put(key, (P11Key)publicKey);128return publicKey;129} else if (key instanceof PrivateKey) {130PrivateKey privateKey = implTranslatePrivateKey((PrivateKey)key);131token.privateCache.put(key, (P11Key)privateKey);132return privateKey;133} else {134throw new InvalidKeyException135("Key must be instance of PublicKey or PrivateKey");136}137}138139abstract <T extends KeySpec> T implGetPublicKeySpec(P11Key key, Class<T> keySpec,140Session[] session) throws PKCS11Exception, InvalidKeySpecException;141142abstract <T extends KeySpec> T implGetPrivateKeySpec(P11Key key, Class<T> keySpec,143Session[] session) throws PKCS11Exception, InvalidKeySpecException;144145abstract PublicKey implTranslatePublicKey(PublicKey key)146throws InvalidKeyException;147148abstract PrivateKey implTranslatePrivateKey(PrivateKey key)149throws InvalidKeyException;150151abstract KeyFactory implGetSoftwareFactory() throws GeneralSecurityException;152153}154155156