diff options
author | Ade Lee <alee@redhat.com> | 2017-05-01 15:56:58 -0400 |
---|---|---|
committer | Ade Lee <alee@redhat.com> | 2017-05-06 10:06:27 -0400 |
commit | f84bfab30647ae1492fcdca0a026bfa4d91350c9 (patch) | |
tree | faeed0006dcc71a9d068241b1b2f56e0b83d45be | |
parent | f26b3aaee1cf36941f387b464b937ffee1403048 (diff) | |
download | pki-f84bfab30647ae1492fcdca0a026bfa4d91350c9.tar.gz pki-f84bfab30647ae1492fcdca0a026bfa4d91350c9.tar.xz pki-f84bfab30647ae1492fcdca0a026bfa4d91350c9.zip |
Make sure generated asym keys are extractable
In HSMs, we were not able to retrieve asym keys that were
generated from the AsymKeyGenService, because the right
flags were not set (ie. set like in the server side
keygen case).
To do this, I extracted the key generation function from
NetKeygenService to KeyRecoveryAuthority, so that it could
be used by both services.
Bugzilla BZ# 1386303
Change-Id: I13b5f4b602217a685acada94091e91df75e25eff
4 files changed, 213 insertions, 196 deletions
diff --git a/base/common/src/com/netscape/certsrv/kra/IKeyRecoveryAuthority.java b/base/common/src/com/netscape/certsrv/kra/IKeyRecoveryAuthority.java index a12d7738d..4f709e9af 100644 --- a/base/common/src/com/netscape/certsrv/kra/IKeyRecoveryAuthority.java +++ b/base/common/src/com/netscape/certsrv/kra/IKeyRecoveryAuthority.java @@ -17,12 +17,15 @@ // --- END COPYRIGHT BLOCK --- package com.netscape.certsrv.kra; +import java.security.KeyPair; import java.util.Enumeration; import java.util.Hashtable; import java.util.Vector; import org.dogtagpki.legacy.policy.IPolicyProcessor; import org.mozilla.jss.crypto.CryptoToken; +import org.mozilla.jss.crypto.KeyPairGeneratorSpi; +import org.mozilla.jss.crypto.PQGParams; import com.netscape.certsrv.base.EBaseException; import com.netscape.certsrv.base.ISubsystem; @@ -337,4 +340,18 @@ public interface IKeyRecoveryAuthority extends ISubsystem { * @return */ public boolean isRetrievalSynchronous(String realm); + + /** + * Generate an asymmetric key pair. + * + * @param alg + * @param keySize + * @param keyCurve + * @param pqg + * @param usageList - RSA only for now + * @return key pair + * @throws EBaseException + */ + public KeyPair generateKeyPair(String alg, int keySize, String keyCurve, + PQGParams pqg, KeyPairGeneratorSpi.Usage[] usageList) throws EBaseException; } diff --git a/base/kra/src/com/netscape/kra/AsymKeyGenService.java b/base/kra/src/com/netscape/kra/AsymKeyGenService.java index 95289721a..7351d50be 100644 --- a/base/kra/src/com/netscape/kra/AsymKeyGenService.java +++ b/base/kra/src/com/netscape/kra/AsymKeyGenService.java @@ -19,14 +19,10 @@ package com.netscape.kra; import java.math.BigInteger; import java.security.KeyPair; -import java.security.NoSuchAlgorithmException; import org.mozilla.jss.crypto.CryptoToken; -import org.mozilla.jss.crypto.KeyPairAlgorithm; -import org.mozilla.jss.crypto.KeyPairGenerator; import org.mozilla.jss.crypto.KeyPairGeneratorSpi; import org.mozilla.jss.crypto.PrivateKey; -import org.mozilla.jss.crypto.TokenException; import com.netscape.certsrv.apps.CMS; import com.netscape.certsrv.base.EBaseException; @@ -42,7 +38,6 @@ import com.netscape.certsrv.request.IRequest; import com.netscape.certsrv.request.IService; import com.netscape.certsrv.request.RequestId; import com.netscape.certsrv.security.IStorageKeyUnit; -import com.netscape.cms.servlet.key.KeyRequestDAO; import com.netscape.cmscore.dbs.KeyRecord; import netscape.security.util.WrappingParams; @@ -132,8 +127,6 @@ public class AsymKeyGenService implements IService { CMS.debug("AsymKeyGenService.serviceRequest. Request id: " + request.getRequestId()); CMS.debug("AsymKeyGenService.serviceRequest algorithm: " + algorithm); - KeyPairAlgorithm keyPairAlgorithm = KeyRequestDAO.ASYMKEY_GEN_ALGORITHMS.get(algorithm.toUpperCase()); - String owner = request.getExtDataInString(IRequest.ATTR_REQUEST_OWNER); String auditSubjectID = owner; @@ -141,16 +134,18 @@ public class AsymKeyGenService implements IService { CryptoToken token = kra.getKeygenToken(); // Generating the asymmetric keys - KeyPairGenerator keyPairGen = null; KeyPair kp = null; try { - keyPairGen = token.getKeyPairGenerator(keyPairAlgorithm); - keyPairGen.initialize(keySize); - if (usageList != null) - keyPairGen.setKeyPairUsages(usageList, usageList); - kp = keyPairGen.genKeyPair(); - } catch (NoSuchAlgorithmException | TokenException e) { + kp = kra.generateKeyPair( + algorithm.toUpperCase(), + keySize, + null, // keyCurve for ECC, not yet supported + null, // PQG not yet supported + usageList + ); + + } catch (EBaseException e) { CMS.debugStackTrace(); auditAsymKeyGenRequestProcessed(auditSubjectID, ILogger.FAILURE, request.getRequestId(), clientKeyId, null, "Failed to generate Asymmetric key"); diff --git a/base/kra/src/com/netscape/kra/KeyRecoveryAuthority.java b/base/kra/src/com/netscape/kra/KeyRecoveryAuthority.java index ec920e682..54953d1b1 100644 --- a/base/kra/src/com/netscape/kra/KeyRecoveryAuthority.java +++ b/base/kra/src/com/netscape/kra/KeyRecoveryAuthority.java @@ -20,6 +20,10 @@ package com.netscape.kra; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.math.BigInteger; +import java.security.InvalidAlgorithmParameterException; +import java.security.InvalidParameterException; +import java.security.KeyPair; +import java.security.NoSuchAlgorithmException; import java.security.cert.CertificateEncodingException; import java.security.cert.CertificateException; import java.security.cert.X509Certificate; @@ -32,6 +36,12 @@ import org.dogtagpki.legacy.kra.KRAPolicy; import org.dogtagpki.legacy.policy.IPolicyProcessor; import org.mozilla.jss.NoSuchTokenException; import org.mozilla.jss.crypto.CryptoToken; +import org.mozilla.jss.crypto.KeyPairAlgorithm; +import org.mozilla.jss.crypto.KeyPairGenerator; +import org.mozilla.jss.crypto.KeyPairGeneratorSpi; +import org.mozilla.jss.crypto.PQGParamGenException; +import org.mozilla.jss.crypto.PQGParams; +import org.mozilla.jss.crypto.TokenException; import com.netscape.certsrv.apps.CMS; import com.netscape.certsrv.authority.IAuthority; @@ -1816,4 +1826,178 @@ public class KeyRecoveryAuthority implements IAuthority, IKeyService, IKeyRecove return agents; } + + public KeyPair generateKeyPair(String alg, int keySize, String keyCurve, + PQGParams pqg, KeyPairGeneratorSpi.Usage[] usageList) throws EBaseException { + KeyPairAlgorithm kpAlg = null; + + if (alg.equals("RSA")) + kpAlg = KeyPairAlgorithm.RSA; + else if (alg.equals("EC")) + kpAlg = KeyPairAlgorithm.EC; + else + kpAlg = KeyPairAlgorithm.DSA; + + try { + KeyPair kp = generateKeyPair(kpAlg, keySize, keyCurve, pqg, usageList); + + return kp; + } catch (InvalidParameterException e) { + throw new EBaseException(CMS.getUserMessage("CMS_BASE_INVALID_KEYSIZE_PARAMS", + "" + keySize)); + } catch (PQGParamGenException e) { + throw new EBaseException(CMS.getUserMessage("CMS_BASE_PQG_GEN_FAILED")); + } catch (NoSuchAlgorithmException e) { + throw new EBaseException(CMS.getUserMessage("CMS_BASE_ALG_NOT_SUPPORTED", + kpAlg.toString())); + } catch (TokenException e) { + throw new EBaseException(CMS.getUserMessage("CMS_BASE_TOKEN_ERROR_1", e.toString())); + } catch (InvalidAlgorithmParameterException e) { + throw new EBaseException(CMS.getUserMessage("CMS_BASE_ALG_NOT_SUPPORTED", "DSA")); + } + } + + public KeyPair generateKeyPair( + KeyPairAlgorithm kpAlg, int keySize, String keyCurve, PQGParams pqg, + KeyPairGeneratorSpi.Usage[] usageList ) + throws NoSuchAlgorithmException, TokenException, InvalidAlgorithmParameterException, + InvalidParameterException, PQGParamGenException { + + CryptoToken token = getKeygenToken(); + + CMS.debug("NetkeyKeygenService: key pair is to be generated on slot: " + token.getName()); + + /* + make it temporary so can work with HSM + netHSM works with + temporary == true + sensitive == <do not specify> + extractable == <do not specify> + LunaSA2 works with + temporary == true + sensitive == true + extractable == true + */ + KeyPairGenerator kpGen = token.getKeyPairGenerator(kpAlg); + IConfigStore config = CMS.getConfigStore(); + IConfigStore kgConfig = config.getSubStore("kra.keygen"); + boolean tp = false; + boolean sp = false; + boolean ep = false; + if ((kgConfig != null) && (!kgConfig.equals(""))) { + try { + tp = kgConfig.getBoolean("temporaryPairs", false); + sp = kgConfig.getBoolean("sensitivePairs", false); + ep = kgConfig.getBoolean("extractablePairs", false); + CMS.debug("NetkeyKeygenService: found config store: kra.keygen"); + // by default, let nethsm work + if ((tp == false) && (sp == false) && (ep == false)) { + if (kpAlg == KeyPairAlgorithm.EC) { + // set to what works for nethsm + tp = true; + sp = false; + ep = true; + } else + tp = true; + } + } catch (Exception e) { + CMS.debug("NetkeyKeygenService: kgConfig.getBoolean failed"); + // by default, let nethsm work + tp = true; + } + } else { + // by default, let nethsm work + CMS.debug("NetkeyKeygenService: cannot find config store: kra.keygen, assume temporaryPairs==true"); + if (kpAlg == KeyPairAlgorithm.EC) { + // set to what works for nethsm + tp = true; + sp = false; + ep = true; + } else { + tp = true; + } + } + + if (kpAlg == KeyPairAlgorithm.EC) { + + boolean isECDHE = false; + KeyPair pair = null; + + // used with isECDHE == true + org.mozilla.jss.crypto.KeyPairGeneratorSpi.Usage usages_mask_ECDSA[] = { + org.mozilla.jss.crypto.KeyPairGeneratorSpi.Usage.DERIVE + }; + + // used with isECDHE == false + org.mozilla.jss.crypto.KeyPairGeneratorSpi.Usage usages_mask_ECDH[] = { + org.mozilla.jss.crypto.KeyPairGeneratorSpi.Usage.SIGN, + org.mozilla.jss.crypto.KeyPairGeneratorSpi.Usage.SIGN_RECOVER + }; + + try { + pair = CryptoUtil.generateECCKeyPair(token.getName(), + keyCurve /*ECC_curve default*/, + null, + (isECDHE==true) ? usages_mask_ECDSA: usages_mask_ECDH, + tp /*temporary*/, sp? 1:0 /*sensitive*/, ep? 1:0 /*extractable*/); + CMS.debug("NetkeyKeygenService: after key pair generation" ); + } catch (Exception e) { + CMS.debug("NetkeyKeygenService: key pair generation with exception:"+e.toString()); + } + return pair; + + } else { // !EC + //only specified to "true" will it be set + if (tp == true) { + CMS.debug("NetkeyKeygenService: setting temporaryPairs to true"); + kpGen.temporaryPairs(true); + } + + if (sp == true) { + CMS.debug("NetkeyKeygenService: setting sensitivePairs to true"); + kpGen.sensitivePairs(true); + } + + if (ep == true) { + CMS.debug("NetkeyKeygenService: setting extractablePairs to true"); + kpGen.extractablePairs(true); + } + + if (kpAlg == KeyPairAlgorithm.DSA) { + if (pqg == null) { + kpGen.initialize(keySize); + } else { + kpGen.initialize(pqg); + } + } else { + kpGen.initialize(keySize); + } + + if (usageList != null) + kpGen.setKeyPairUsages(usageList, usageList); + + if (pqg == null) { + KeyPair kp = null; + synchronized (new Object()) { + CMS.debug("NetkeyKeygenService: key pair generation begins"); + kp = kpGen.genKeyPair(); + CMS.debug("NetkeyKeygenService: key pair generation done"); + addEntropy(true); + } + return kp; + } else { + // DSA + KeyPair kp = null; + + /* no DSA for now... netkey prototype + do { + // 602548 NSS bug - to overcome it, we use isBadDSAKeyPair + kp = kpGen.genKeyPair(); + } + while (isBadDSAKeyPair(kp)); + */ + return kp; + } + } + } } diff --git a/base/kra/src/com/netscape/kra/NetkeyKeygenService.java b/base/kra/src/com/netscape/kra/NetkeyKeygenService.java index e09eb420c..f068a4a81 100644 --- a/base/kra/src/com/netscape/kra/NetkeyKeygenService.java +++ b/base/kra/src/com/netscape/kra/NetkeyKeygenService.java @@ -23,11 +23,8 @@ import java.io.FilterOutputStream; import java.io.IOException; import java.io.PrintStream; import java.math.BigInteger; -import java.security.InvalidAlgorithmParameterException; import java.security.InvalidKeyException; -import java.security.InvalidParameterException; import java.security.KeyPair; -import java.security.NoSuchAlgorithmException; import java.security.SecureRandom; import org.mozilla.jss.asn1.ASN1Util; @@ -35,21 +32,15 @@ import org.mozilla.jss.crypto.CryptoToken; import org.mozilla.jss.crypto.EncryptionAlgorithm; import org.mozilla.jss.crypto.IVParameterSpec; import org.mozilla.jss.crypto.KeyGenAlgorithm; -import org.mozilla.jss.crypto.KeyPairAlgorithm; -import org.mozilla.jss.crypto.KeyPairGenerator; import org.mozilla.jss.crypto.KeyWrapAlgorithm; -import org.mozilla.jss.crypto.PQGParamGenException; -import org.mozilla.jss.crypto.PQGParams; import org.mozilla.jss.crypto.PrivateKey; import org.mozilla.jss.crypto.SymmetricKey; -import org.mozilla.jss.crypto.TokenException; import org.mozilla.jss.pkcs11.PK11SymKey; import org.mozilla.jss.pkix.crmf.PKIArchiveOptions; import org.mozilla.jss.util.Base64OutputStream; import com.netscape.certsrv.apps.CMS; import com.netscape.certsrv.base.EBaseException; -import com.netscape.certsrv.base.IConfigStore; import com.netscape.certsrv.base.MetaInfo; import com.netscape.certsrv.base.SessionContext; import com.netscape.certsrv.dbs.keydb.IKeyRecord; @@ -122,177 +113,6 @@ public class NetkeyKeygenService implements IService { return archOpts; } - public KeyPair generateKeyPair( - KeyPairAlgorithm kpAlg, int keySize, String keyCurve, PQGParams pqg) - throws NoSuchAlgorithmException, TokenException, InvalidAlgorithmParameterException, - InvalidParameterException, PQGParamGenException { - - CryptoToken token = mKRA.getKeygenToken(); - - CMS.debug("NetkeyKeygenService: key pair is to be generated on slot: " + token.getName()); - - /* - make it temporary so can work with HSM - netHSM works with - temporary == true - sensitive == <do not specify> - extractable == <do not specify> - LunaSA2 works with - temporary == true - sensitive == true - extractable == true - */ - KeyPairGenerator kpGen = token.getKeyPairGenerator(kpAlg); - IConfigStore config = CMS.getConfigStore(); - IConfigStore kgConfig = config.getSubStore("kra.keygen"); - boolean tp = false; - boolean sp = false; - boolean ep = false; - if ((kgConfig != null) && (!kgConfig.equals(""))) { - try { - tp = kgConfig.getBoolean("temporaryPairs", false); - sp = kgConfig.getBoolean("sensitivePairs", false); - ep = kgConfig.getBoolean("extractablePairs", false); - CMS.debug("NetkeyKeygenService: found config store: kra.keygen"); - // by default, let nethsm work - if ((tp == false) && (sp == false) && (ep == false)) { - if (kpAlg == KeyPairAlgorithm.EC) { - // set to what works for nethsm - tp = true; - sp = false; - ep = true; - } else - tp = true; - } - } catch (Exception e) { - CMS.debug("NetkeyKeygenService: kgConfig.getBoolean failed"); - // by default, let nethsm work - tp = true; - } - } else { - // by default, let nethsm work - CMS.debug("NetkeyKeygenService: cannot find config store: kra.keygen, assume temporaryPairs==true"); - if (kpAlg == KeyPairAlgorithm.EC) { - // set to what works for nethsm - tp = true; - sp = false; - ep = true; - } else { - tp = true; - } - } - - if (kpAlg == KeyPairAlgorithm.EC) { - - boolean isECDHE = false; - KeyPair pair = null; - - // used with isECDHE == true - org.mozilla.jss.crypto.KeyPairGeneratorSpi.Usage usages_mask_ECDSA[] = { - org.mozilla.jss.crypto.KeyPairGeneratorSpi.Usage.DERIVE - }; - - // used with isECDHE == false - org.mozilla.jss.crypto.KeyPairGeneratorSpi.Usage usages_mask_ECDH[] = { - org.mozilla.jss.crypto.KeyPairGeneratorSpi.Usage.SIGN, - org.mozilla.jss.crypto.KeyPairGeneratorSpi.Usage.SIGN_RECOVER - }; - - try { - pair = CryptoUtil.generateECCKeyPair(token.getName(), - keyCurve /*ECC_curve default*/, - null, - (isECDHE==true) ? usages_mask_ECDSA: usages_mask_ECDH, - tp /*temporary*/, sp? 1:0 /*sensitive*/, ep? 1:0 /*extractable*/); - CMS.debug("NetkeyKeygenService: after key pair generation" ); - } catch (Exception e) { - CMS.debug("NetkeyKeygenService: key pair generation with exception:"+e.toString()); - } - return pair; - - } else { // !EC - //only specified to "true" will it be set - if (tp == true) { - CMS.debug("NetkeyKeygenService: setting temporaryPairs to true"); - kpGen.temporaryPairs(true); - } - - if (sp == true) { - CMS.debug("NetkeyKeygenService: setting sensitivePairs to true"); - kpGen.sensitivePairs(true); - } - - if (ep == true) { - CMS.debug("NetkeyKeygenService: setting extractablePairs to true"); - kpGen.extractablePairs(true); - } - - if (kpAlg == KeyPairAlgorithm.DSA) { - if (pqg == null) { - kpGen.initialize(keySize); - } else { - kpGen.initialize(pqg); - } - } else { - kpGen.initialize(keySize); - } - - if (pqg == null) { - KeyPair kp = null; - synchronized (new Object()) { - CMS.debug("NetkeyKeygenService: key pair generation begins"); - kp = kpGen.genKeyPair(); - CMS.debug("NetkeyKeygenService: key pair generation done"); - mKRA.addEntropy(true); - } - return kp; - } else { - // DSA - KeyPair kp = null; - - /* no DSA for now... netkey prototype - do { - // 602548 NSS bug - to overcome it, we use isBadDSAKeyPair - kp = kpGen.genKeyPair(); - } - while (isBadDSAKeyPair(kp)); - */ - return kp; - } - } - } - - public KeyPair generateKeyPair(String alg, - int keySize, String keyCurve, PQGParams pqg) throws EBaseException { - - KeyPairAlgorithm kpAlg = null; - - if (alg.equals("RSA")) - kpAlg = KeyPairAlgorithm.RSA; - else if (alg.equals("EC")) - kpAlg = KeyPairAlgorithm.EC; - else - kpAlg = KeyPairAlgorithm.DSA; - - try { - KeyPair kp = generateKeyPair(kpAlg, keySize, keyCurve, pqg); - - return kp; - } catch (InvalidParameterException e) { - throw new EBaseException(CMS.getUserMessage("CMS_BASE_INVALID_KEYSIZE_PARAMS", - "" + keySize)); - } catch (PQGParamGenException e) { - throw new EBaseException(CMS.getUserMessage("CMS_BASE_PQG_GEN_FAILED")); - } catch (NoSuchAlgorithmException e) { - throw new EBaseException(CMS.getUserMessage("CMS_BASE_ALG_NOT_SUPPORTED", - kpAlg.toString())); - } catch (TokenException e) { - throw new EBaseException(CMS.getUserMessage("CMS_BASE_TOKEN_ERROR_1", e.toString())); - } catch (InvalidAlgorithmParameterException e) { - throw new EBaseException(CMS.getUserMessage("CMS_BASE_ALG_NOT_SUPPORTED", "DSA")); - } - } - private static String base64Encode(byte[] bytes) throws IOException { // All this streaming is lame, but Base64OutputStream needs a // PrintStream @@ -430,10 +250,11 @@ public class NetkeyKeygenService implements IService { CMS.debug("NetkeyKeygenService: about to generate key pair"); - keypair = generateKeyPair(rKeytype /* rKeytype: "RSA" or "EC" */, + keypair = mKRA.generateKeyPair(rKeytype /* rKeytype: "RSA" or "EC" */, keysize /*Integer.parseInt(len)*/, rKeycurve /* for "EC" only */, - null /*pqgParams*/); + null /*pqgParams*/, + null /* usageList*/); if (keypair == null) { CMS.debug("NetkeyKeygenService: failed generating key pair for " + rCUID + ":" + rUserid); |