Path: blob/master/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11RSAKeyFactory.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.interfaces.*;31import java.security.spec.*;3233import sun.security.rsa.RSAPublicKeyImpl;34import sun.security.rsa.RSAPrivateCrtKeyImpl;35import sun.security.rsa.RSAUtil.KeyType;36import static sun.security.pkcs11.TemplateManager.*;37import sun.security.pkcs11.wrapper.*;38import static sun.security.pkcs11.wrapper.PKCS11Constants.*;3940import sun.security.rsa.RSAKeyFactory;4142/**43* RSA KeyFactory implementation.44*45* @author Andreas Sterbenz46* @since 1.547*/48final class P11RSAKeyFactory extends P11KeyFactory {4950P11RSAKeyFactory(Token token, String algorithm) {51super(token, algorithm);52}5354PublicKey implTranslatePublicKey(PublicKey key) throws InvalidKeyException {55try {56if (key instanceof RSAPublicKey) {57RSAPublicKey rsaKey = (RSAPublicKey)key;58return generatePublic(59rsaKey.getModulus(),60rsaKey.getPublicExponent()61);62} else {63// let SunRsaSign provider parse for us, then recurse64key = RSAPublicKeyImpl.newKey(KeyType.RSA, key.getFormat(),65key.getEncoded());66return implTranslatePublicKey(key);67}68} catch (PKCS11Exception e) {69throw new InvalidKeyException("Could not create RSA public key", e);70}71}7273PrivateKey implTranslatePrivateKey(PrivateKey key)74throws InvalidKeyException {75try {76if (key instanceof RSAPrivateCrtKey) {77RSAPrivateCrtKey rsaKey = (RSAPrivateCrtKey)key;78return generatePrivate(79rsaKey.getModulus(),80rsaKey.getPublicExponent(),81rsaKey.getPrivateExponent(),82rsaKey.getPrimeP(),83rsaKey.getPrimeQ(),84rsaKey.getPrimeExponentP(),85rsaKey.getPrimeExponentQ(),86rsaKey.getCrtCoefficient()87);88} else if (key instanceof RSAPrivateKey) {89RSAPrivateKey rsaKey = (RSAPrivateKey)key;90return generatePrivate(91rsaKey.getModulus(),92rsaKey.getPrivateExponent()93);94} else {95// let SunRsaSign provider parse for us, then recurse96key = RSAPrivateCrtKeyImpl.newKey(KeyType.RSA, key.getFormat(),97key.getEncoded());98return implTranslatePrivateKey(key);99}100} catch (PKCS11Exception e) {101throw new InvalidKeyException("Could not create RSA private key", e);102}103}104105// see JCA spec106protected PublicKey engineGeneratePublic(KeySpec keySpec)107throws InvalidKeySpecException {108token.ensureValid();109if (keySpec instanceof X509EncodedKeySpec) {110try {111PublicKey key = RSAPublicKeyImpl.newKey(KeyType.RSA, "X.509",112((X509EncodedKeySpec)keySpec).getEncoded());113return implTranslatePublicKey(key);114} catch (InvalidKeyException e) {115throw new InvalidKeySpecException116("Could not create RSA public key", e);117}118}119if (keySpec instanceof RSAPublicKeySpec == false) {120throw new InvalidKeySpecException("Only RSAPublicKeySpec and "121+ "X509EncodedKeySpec supported for RSA public keys");122}123try {124RSAPublicKeySpec rs = (RSAPublicKeySpec)keySpec;125return generatePublic(126rs.getModulus(),127rs.getPublicExponent()128);129} catch (PKCS11Exception | InvalidKeyException e) {130throw new InvalidKeySpecException131("Could not create RSA public key", e);132}133}134135// see JCA spec136protected PrivateKey engineGeneratePrivate(KeySpec keySpec)137throws InvalidKeySpecException {138token.ensureValid();139if (keySpec instanceof PKCS8EncodedKeySpec) {140try {141PrivateKey key = RSAPrivateCrtKeyImpl.newKey(KeyType.RSA,142"PKCS#8", ((PKCS8EncodedKeySpec)keySpec).getEncoded());143return implTranslatePrivateKey(key);144} catch (GeneralSecurityException e) {145throw new InvalidKeySpecException146("Could not create RSA private key", e);147}148}149try {150if (keySpec instanceof RSAPrivateCrtKeySpec) {151RSAPrivateCrtKeySpec rs = (RSAPrivateCrtKeySpec)keySpec;152return generatePrivate(153rs.getModulus(),154rs.getPublicExponent(),155rs.getPrivateExponent(),156rs.getPrimeP(),157rs.getPrimeQ(),158rs.getPrimeExponentP(),159rs.getPrimeExponentQ(),160rs.getCrtCoefficient()161);162} else if (keySpec instanceof RSAPrivateKeySpec) {163RSAPrivateKeySpec rs = (RSAPrivateKeySpec)keySpec;164return generatePrivate(165rs.getModulus(),166rs.getPrivateExponent()167);168} else {169throw new InvalidKeySpecException("Only RSAPrivate(Crt)KeySpec "170+ "and PKCS8EncodedKeySpec supported for RSA private keys");171}172} catch (PKCS11Exception | InvalidKeyException e) {173throw new InvalidKeySpecException174("Could not create RSA private key", e);175}176}177178private PublicKey generatePublic(BigInteger n, BigInteger e)179throws PKCS11Exception, InvalidKeyException {180RSAKeyFactory.checkKeyLengths(n.bitLength(), e, -1, 64 * 1024);181CK_ATTRIBUTE[] attributes = new CK_ATTRIBUTE[] {182new CK_ATTRIBUTE(CKA_CLASS, CKO_PUBLIC_KEY),183new CK_ATTRIBUTE(CKA_KEY_TYPE, CKK_RSA),184new CK_ATTRIBUTE(CKA_MODULUS, n),185new CK_ATTRIBUTE(CKA_PUBLIC_EXPONENT, e),186};187attributes = token.getAttributes188(O_IMPORT, CKO_PUBLIC_KEY, CKK_RSA, attributes);189Session session = null;190try {191session = token.getObjSession();192long keyID = token.p11.C_CreateObject(session.id(), attributes);193return P11Key.publicKey194(session, keyID, "RSA", n.bitLength(), attributes);195} finally {196token.releaseSession(session);197}198}199200private PrivateKey generatePrivate(BigInteger n, BigInteger d)201throws PKCS11Exception, InvalidKeyException {202RSAKeyFactory.checkKeyLengths(n.bitLength(), null, -1, 64 * 1024);203CK_ATTRIBUTE[] attributes = new CK_ATTRIBUTE[] {204new CK_ATTRIBUTE(CKA_CLASS, CKO_PRIVATE_KEY),205new CK_ATTRIBUTE(CKA_KEY_TYPE, CKK_RSA),206new CK_ATTRIBUTE(CKA_MODULUS, n),207new CK_ATTRIBUTE(CKA_PRIVATE_EXPONENT, d),208};209attributes = token.getAttributes210(O_IMPORT, CKO_PRIVATE_KEY, CKK_RSA, attributes);211Session session = null;212try {213session = token.getObjSession();214long keyID = token.p11.C_CreateObject(session.id(), attributes);215return P11Key.privateKey216(session, keyID, "RSA", n.bitLength(), attributes);217} finally {218token.releaseSession(session);219}220}221222private PrivateKey generatePrivate(BigInteger n, BigInteger e,223BigInteger d, BigInteger p, BigInteger q, BigInteger pe,224BigInteger qe, BigInteger coeff) throws PKCS11Exception,225InvalidKeyException {226RSAKeyFactory.checkKeyLengths(n.bitLength(), e, -1, 64 * 1024);227CK_ATTRIBUTE[] attributes = new CK_ATTRIBUTE[] {228new CK_ATTRIBUTE(CKA_CLASS, CKO_PRIVATE_KEY),229new CK_ATTRIBUTE(CKA_KEY_TYPE, CKK_RSA),230new CK_ATTRIBUTE(CKA_MODULUS, n),231new CK_ATTRIBUTE(CKA_PUBLIC_EXPONENT, e),232new CK_ATTRIBUTE(CKA_PRIVATE_EXPONENT, d),233new CK_ATTRIBUTE(CKA_PRIME_1, p),234new CK_ATTRIBUTE(CKA_PRIME_2, q),235new CK_ATTRIBUTE(CKA_EXPONENT_1, pe),236new CK_ATTRIBUTE(CKA_EXPONENT_2, qe),237new CK_ATTRIBUTE(CKA_COEFFICIENT, coeff),238};239attributes = token.getAttributes240(O_IMPORT, CKO_PRIVATE_KEY, CKK_RSA, attributes);241Session session = null;242try {243session = token.getObjSession();244long keyID = token.p11.C_CreateObject(session.id(), attributes);245return P11Key.privateKey246(session, keyID, "RSA", n.bitLength(), attributes);247} finally {248token.releaseSession(session);249}250}251252<T extends KeySpec> T implGetPublicKeySpec(P11Key key, Class<T> keySpec,253Session[] session) throws PKCS11Exception, InvalidKeySpecException {254if (keySpec.isAssignableFrom(RSAPublicKeySpec.class)) {255session[0] = token.getObjSession();256CK_ATTRIBUTE[] attributes = new CK_ATTRIBUTE[] {257new CK_ATTRIBUTE(CKA_MODULUS),258new CK_ATTRIBUTE(CKA_PUBLIC_EXPONENT),259};260long keyID = key.getKeyID();261try {262token.p11.C_GetAttributeValue(session[0].id(), keyID, attributes);263} finally {264key.releaseKeyID();265}266KeySpec spec = new RSAPublicKeySpec(267attributes[0].getBigInteger(),268attributes[1].getBigInteger()269);270return keySpec.cast(spec);271} else { // X.509 handled in superclass272throw new InvalidKeySpecException("Only RSAPublicKeySpec and "273+ "X509EncodedKeySpec supported for RSA public keys");274}275}276277<T extends KeySpec> T implGetPrivateKeySpec(P11Key key, Class<T> keySpec,278Session[] session) throws PKCS11Exception, InvalidKeySpecException {279if (key.sensitive || !key.extractable) {280throw new InvalidKeySpecException("Key is sensitive or not extractable");281}282// If the key is both extractable and not sensitive, then when it was converted into a P11Key283// it was also converted into subclass of RSAPrivateKey which encapsulates all of the logic284// necessary to retrieve the attributes we need. This sub-class will also cache these attributes285// so that we do not need to query them more than once.286// Rather than rewrite this logic and make possibly slow calls to the token, we'll just use287// that existing logic.288if (keySpec.isAssignableFrom(RSAPrivateCrtKeySpec.class)) {289// All supported keyspecs (other than PKCS8EncodedKeySpec) descend from RSAPrivateCrtKeySpec290if (key instanceof RSAPrivateCrtKey) {291RSAPrivateCrtKey crtKey = (RSAPrivateCrtKey)key;292return keySpec.cast(new RSAPrivateCrtKeySpec(293crtKey.getModulus(),294crtKey.getPublicExponent(),295crtKey.getPrivateExponent(),296crtKey.getPrimeP(),297crtKey.getPrimeQ(),298crtKey.getPrimeExponentP(),299crtKey.getPrimeExponentQ(),300crtKey.getCrtCoefficient(),301crtKey.getParams()302));303} else { // RSAPrivateKey (non-CRT)304if (!keySpec.isAssignableFrom(RSAPrivateKeySpec.class)) {305throw new InvalidKeySpecException306("RSAPrivateCrtKeySpec can only be used with CRT keys");307}308309if (!(key instanceof RSAPrivateKey)) {310// We should never reach here as P11Key.privateKey() should always produce an instance311// of RSAPrivateKey when the RSA key is both extractable and non-sensitive.312throw new InvalidKeySpecException313("Key must be an instance of RSAPrivateKeySpec. Was " + key.getClass());314}315316// fall through to RSAPrivateKey (non-CRT)317RSAPrivateKey rsaKey = (RSAPrivateKey) key;318return keySpec.cast(new RSAPrivateKeySpec(319rsaKey.getModulus(),320rsaKey.getPrivateExponent(),321rsaKey.getParams()322));323}324} else { // PKCS#8 handled in superclass325throw new InvalidKeySpecException("Only RSAPrivate(Crt)KeySpec "326+ "and PKCS8EncodedKeySpec supported for RSA private keys");327}328}329330KeyFactory implGetSoftwareFactory() throws GeneralSecurityException {331return KeyFactory.getInstance("RSA", P11Util.getSunRsaSignProvider());332}333334}335336337