Path: blob/master/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11DHKeyFactory.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.math.BigInteger;2829import java.security.*;30import java.security.spec.*;3132import javax.crypto.interfaces.*;33import javax.crypto.spec.*;3435import static sun.security.pkcs11.TemplateManager.*;36import sun.security.pkcs11.wrapper.*;37import static sun.security.pkcs11.wrapper.PKCS11Constants.*;3839/**40* DH KeyFactory implementation.41*42* @author Andreas Sterbenz43* @since 1.544*/45final class P11DHKeyFactory extends P11KeyFactory {4647P11DHKeyFactory(Token token, String algorithm) {48super(token, algorithm);49}5051PublicKey implTranslatePublicKey(PublicKey key) throws InvalidKeyException {52try {53if (key instanceof DHPublicKey) {54DHPublicKey dhKey = (DHPublicKey)key;55DHParameterSpec params = dhKey.getParams();56return generatePublic(57dhKey.getY(),58params.getP(),59params.getG()60);61} else if ("X.509".equals(key.getFormat())) {62// let SunJCE provider parse for us, then recurse63try {64KeyFactory factory = implGetSoftwareFactory();65key = (PublicKey)factory.translateKey(key);66return implTranslatePublicKey(key);67} catch (GeneralSecurityException e) {68throw new InvalidKeyException("Could not translate key", e);69}70} else {71throw new InvalidKeyException("PublicKey must be instance "72+ "of DHPublicKey or have X.509 encoding");73}74} catch (PKCS11Exception e) {75throw new InvalidKeyException("Could not create DH public key", e);76}77}7879PrivateKey implTranslatePrivateKey(PrivateKey key)80throws InvalidKeyException {81try {82if (key instanceof DHPrivateKey) {83DHPrivateKey dhKey = (DHPrivateKey)key;84DHParameterSpec params = dhKey.getParams();85return generatePrivate(86dhKey.getX(),87params.getP(),88params.getG()89);90} else if ("PKCS#8".equals(key.getFormat())) {91// let SunJCE provider parse for us, then recurse92try {93KeyFactory factory = implGetSoftwareFactory();94key = (PrivateKey)factory.translateKey(key);95return implTranslatePrivateKey(key);96} catch (GeneralSecurityException e) {97throw new InvalidKeyException("Could not translate key", e);98}99} else {100throw new InvalidKeyException("PrivateKey must be instance "101+ "of DHPrivateKey or have PKCS#8 encoding");102}103} catch (PKCS11Exception e) {104throw new InvalidKeyException("Could not create DH private key", e);105}106}107108// see JCA spec109protected PublicKey engineGeneratePublic(KeySpec keySpec)110throws InvalidKeySpecException {111token.ensureValid();112if (keySpec instanceof X509EncodedKeySpec) {113try {114KeyFactory factory = implGetSoftwareFactory();115PublicKey key = factory.generatePublic(keySpec);116return implTranslatePublicKey(key);117} catch (GeneralSecurityException e) {118throw new InvalidKeySpecException119("Could not create DH public key", e);120}121}122if (keySpec instanceof DHPublicKeySpec == false) {123throw new InvalidKeySpecException("Only DHPublicKeySpec and "124+ "X509EncodedKeySpec supported for DH public keys");125}126try {127DHPublicKeySpec ds = (DHPublicKeySpec)keySpec;128return generatePublic(129ds.getY(),130ds.getP(),131ds.getG()132);133} catch (PKCS11Exception e) {134throw new InvalidKeySpecException135("Could not create DH public key", e);136}137}138139// see JCA spec140protected PrivateKey engineGeneratePrivate(KeySpec keySpec)141throws InvalidKeySpecException {142token.ensureValid();143if (keySpec instanceof PKCS8EncodedKeySpec) {144try {145KeyFactory factory = implGetSoftwareFactory();146PrivateKey key = factory.generatePrivate(keySpec);147return implTranslatePrivateKey(key);148} catch (GeneralSecurityException e) {149throw new InvalidKeySpecException150("Could not create DH private key", e);151}152}153if (keySpec instanceof DHPrivateKeySpec == false) {154throw new InvalidKeySpecException("Only DHPrivateKeySpec and "155+ "PKCS8EncodedKeySpec supported for DH private keys");156}157try {158DHPrivateKeySpec ds = (DHPrivateKeySpec)keySpec;159return generatePrivate(160ds.getX(),161ds.getP(),162ds.getG()163);164} catch (PKCS11Exception e) {165throw new InvalidKeySpecException166("Could not create DH private key", e);167}168}169170private PublicKey generatePublic(BigInteger y, BigInteger p, BigInteger g)171throws PKCS11Exception {172CK_ATTRIBUTE[] attributes = new CK_ATTRIBUTE[] {173new CK_ATTRIBUTE(CKA_CLASS, CKO_PUBLIC_KEY),174new CK_ATTRIBUTE(CKA_KEY_TYPE, CKK_DH),175new CK_ATTRIBUTE(CKA_VALUE, y),176new CK_ATTRIBUTE(CKA_PRIME, p),177new CK_ATTRIBUTE(CKA_BASE, g),178};179attributes = token.getAttributes180(O_IMPORT, CKO_PUBLIC_KEY, CKK_DH, attributes);181Session session = null;182try {183session = token.getObjSession();184long keyID = token.p11.C_CreateObject(session.id(), attributes);185return P11Key.publicKey186(session, keyID, "DH", p.bitLength(), attributes);187} finally {188token.releaseSession(session);189}190}191192private PrivateKey generatePrivate(BigInteger x, BigInteger p,193BigInteger g) throws PKCS11Exception {194CK_ATTRIBUTE[] attributes = new CK_ATTRIBUTE[] {195new CK_ATTRIBUTE(CKA_CLASS, CKO_PRIVATE_KEY),196new CK_ATTRIBUTE(CKA_KEY_TYPE, CKK_DH),197new CK_ATTRIBUTE(CKA_VALUE, x),198new CK_ATTRIBUTE(CKA_PRIME, p),199new CK_ATTRIBUTE(CKA_BASE, g),200};201attributes = token.getAttributes202(O_IMPORT, CKO_PRIVATE_KEY, CKK_DH, attributes);203Session session = null;204try {205session = token.getObjSession();206long keyID = token.p11.C_CreateObject(session.id(), attributes);207return P11Key.privateKey208(session, keyID, "DH", p.bitLength(), attributes);209} finally {210token.releaseSession(session);211}212}213214<T extends KeySpec> T implGetPublicKeySpec(P11Key key, Class<T> keySpec,215Session[] session) throws PKCS11Exception, InvalidKeySpecException {216if (keySpec.isAssignableFrom(DHPublicKeySpec.class)) {217session[0] = token.getObjSession();218CK_ATTRIBUTE[] attributes = new CK_ATTRIBUTE[] {219new CK_ATTRIBUTE(CKA_VALUE),220new CK_ATTRIBUTE(CKA_PRIME),221new CK_ATTRIBUTE(CKA_BASE),222};223long keyID = key.getKeyID();224try {225token.p11.C_GetAttributeValue(session[0].id(), keyID, attributes);226} finally {227key.releaseKeyID();228}229KeySpec spec = new DHPublicKeySpec(230attributes[0].getBigInteger(),231attributes[1].getBigInteger(),232attributes[2].getBigInteger()233);234return keySpec.cast(spec);235} else { // X.509 handled in superclass236throw new InvalidKeySpecException("Only DHPublicKeySpec and "237+ "X509EncodedKeySpec supported for DH public keys");238}239}240241<T extends KeySpec> T implGetPrivateKeySpec(P11Key key, Class<T> keySpec,242Session[] session) throws PKCS11Exception, InvalidKeySpecException {243if (keySpec.isAssignableFrom(DHPrivateKeySpec.class)) {244session[0] = token.getObjSession();245CK_ATTRIBUTE[] attributes = new CK_ATTRIBUTE[] {246new CK_ATTRIBUTE(CKA_VALUE),247new CK_ATTRIBUTE(CKA_PRIME),248new CK_ATTRIBUTE(CKA_BASE),249};250long keyID = key.getKeyID();251try {252token.p11.C_GetAttributeValue(session[0].id(), keyID, attributes);253} finally {254key.releaseKeyID();255}256KeySpec spec = new DHPrivateKeySpec(257attributes[0].getBigInteger(),258attributes[1].getBigInteger(),259attributes[2].getBigInteger()260);261return keySpec.cast(spec);262} else { // PKCS#8 handled in superclass263throw new InvalidKeySpecException("Only DHPrivateKeySpec "264+ "and PKCS8EncodedKeySpec supported for DH private keys");265}266}267268KeyFactory implGetSoftwareFactory() throws GeneralSecurityException {269return KeyFactory.getInstance("DH", P11Util.getSunJceProvider());270}271272}273274275