From 6257d326cca9e55f9d6898bb2b227f22485322b7 Mon Sep 17 00:00:00 2001 From: Christina Fu Date: Tue, 18 Sep 2012 14:47:17 -0700 Subject: https://fedorahosted.org/pki/ticket/304 TMS ECC infrastructure (enrollment with client-side and server-side key generation, and key archival) --- .../src/com/netscape/kra/NetkeyKeygenService.java | 235 +++++++++++++++------ 1 file changed, 174 insertions(+), 61 deletions(-) (limited to 'base/kra/src') diff --git a/base/kra/src/com/netscape/kra/NetkeyKeygenService.java b/base/kra/src/com/netscape/kra/NetkeyKeygenService.java index 1fdf9f74e..f0eec6a26 100644 --- a/base/kra/src/com/netscape/kra/NetkeyKeygenService.java +++ b/base/kra/src/com/netscape/kra/NetkeyKeygenService.java @@ -32,6 +32,7 @@ import java.security.SecureRandom; import netscape.security.provider.RSAPublicKey; +import org.mozilla.jss.asn1.ASN1Util; import org.mozilla.jss.crypto.Cipher; import org.mozilla.jss.crypto.CryptoToken; import org.mozilla.jss.crypto.EncryptionAlgorithm; @@ -52,7 +53,9 @@ 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; import com.netscape.certsrv.dbs.keydb.IKeyRepository; import com.netscape.certsrv.kra.IKeyRecoveryAuthority; import com.netscape.certsrv.logging.ILogger; @@ -60,8 +63,10 @@ import com.netscape.certsrv.request.IRequest; import com.netscape.certsrv.request.IService; import com.netscape.certsrv.security.IStorageKeyUnit; import com.netscape.certsrv.security.ITransportKeyUnit; +import com.netscape.cms.servlet.key.KeyRecordParser; import com.netscape.cmscore.dbs.KeyRecord; import com.netscape.cmscore.util.Debug; +import com.netscape.cmsutil.crypto.CryptoUtil; /** * A class representing keygen/archival request procesor for requests @@ -133,7 +138,7 @@ public class NetkeyKeygenService implements IService { } public KeyPair generateKeyPair( - KeyPairAlgorithm kpAlg, int keySize, PQGParams pqg) + KeyPairAlgorithm kpAlg, int keySize, String keyCurve, PQGParams pqg) throws NoSuchAlgorithmException, TokenException, InvalidAlgorithmParameterException, InvalidParameterException, PQGParamGenException { @@ -158,15 +163,22 @@ public class NetkeyKeygenService implements IService { boolean tp = false; boolean sp = false; boolean ep = false; - if (kgConfig != null) { + 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)) { - tp = true; - } + 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 @@ -175,68 +187,110 @@ public class NetkeyKeygenService implements IService { } else { // by default, let nethsm work CMS.debug("NetkeyKeygenService: cannot find config store: kra.keygen, assume temporaryPairs==true"); - tp = true; - } - /* 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); + if (kpAlg == KeyPairAlgorithm.EC) { + // set to what works for nethsm + tp = true; + sp = false; + ep = true; } else { - kpGen.initialize(pqg); + tp = true; } - } 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); + 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 kp; - } else { - // DSA - KeyPair kp = null; + return pair; - /* no DSA for now... netkey prototype - do { - // 602548 NSS bug - to overcome it, we use isBadDSAKeyPair - kp = kpGen.genKeyPair(); + } 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; } - while (isBadDSAKeyPair(kp)); - */ - return kp; } } public KeyPair generateKeyPair(String alg, - int keySize, PQGParams pqg) throws EBaseException { + 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, pqg); + KeyPair kp = generateKeyPair(kpAlg, keySize, keyCurve, pqg); return kp; } catch (InvalidParameterException e) { @@ -338,8 +392,8 @@ public class NetkeyKeygenService implements IService { String rCUID = request.getExtDataInString(IRequest.NETKEY_ATTR_CUID); String rUserid = request.getExtDataInString(IRequest.NETKEY_ATTR_USERID); - String rKeysize = request.getExtDataInString(IRequest.NETKEY_ATTR_KEY_SIZE); - int keysize = Integer.parseInt(rKeysize); + String rKeytype = request.getExtDataInString(IRequest.NETKEY_ATTR_KEY_TYPE); + auditSubjectID = rCUID + ":" + rUserid; SessionContext sContext = SessionContext.getContext(); @@ -362,13 +416,34 @@ public class NetkeyKeygenService implements IService { wrapped_des_key = com.netscape.cmsutil.util.Utils.SpecialDecode(rWrappedDesKeyString); CMS.debug("NetkeyKeygenService: wrapped_des_key specialDecoded"); + + if ((rKeytype == null) || (rKeytype.equals(""))) { + CMS.debug("NetkeyKeygenService: serviceRequest: key type is null"); + rKeytype = "RSA"; + } else + CMS.debug("NetkeyKeygenService: serviceRequest: key type = "+ rKeytype); + + /* for EC, keysize is ignored, only key curve is used */ + String rKeysize = "2048"; + int keysize = 2048; + String rKeycurve = "nistp256"; + if (rKeytype.equals("EC")) { + rKeycurve = request.getExtDataInString(IRequest.NETKEY_ATTR_KEY_EC_CURVE); + if ((rKeycurve == null) || (rKeycurve.equals(""))) { + rKeycurve = "nistp256"; + } + } else { + rKeysize = request.getExtDataInString(IRequest.NETKEY_ATTR_KEY_SIZE); + keysize = Integer.parseInt(rKeysize); + } + // get the token for generating user keys CryptoToken keygenToken = mKRA.getKeygenToken(); if (keygenToken == null) { CMS.debug("NetkeyKeygenService: failed getting keygenToken"); request.setExtData(IRequest.RESULT, Integer.valueOf(10)); return false; - } else + } else CMS.debug("NetkeyKeygenService: got keygenToken"); if ((wrapped_des_key != null) && @@ -382,8 +457,10 @@ public class NetkeyKeygenService implements IService { CMS.debug("NetkeyKeygenService: about to generate key pair"); - keypair = generateKeyPair("RSA"/*alg*/, - keysize /*Integer.parseInt(len)*/, null /*pqgParams*/); + keypair = generateKeyPair(rKeytype /* rKeytype: "RSA" or "EC" */, + keysize /*Integer.parseInt(len)*/, + rKeycurve /* for "EC" only */, + null /*pqgParams*/); if (keypair == null) { CMS.debug("NetkeyKeygenService: failed generating key pair for " + rCUID + ":" + rUserid); @@ -409,7 +486,9 @@ public class NetkeyKeygenService implements IService { return false; } else { //CMS.debug("NetkeyKeygenService: public key binary length ="+ publicKeyData.length); - PubKey = base64Encode(publicKeyData); + /* url encode */ + PubKey = com.netscape.cmsutil.util.Utils.SpecialEncode(publicKeyData); + CMS.debug("NetkeyKeygenService: EC PubKey special encoded"); //CMS.debug("NetkeyKeygenService: public key length =" + PubKey.length()); request.setExtData("public_key", PubKey); @@ -536,16 +615,50 @@ public class NetkeyKeygenService implements IService { CMS.debug("NetkeyKeygenService: got key record"); - // we deal with RSA key only - try { - RSAPublicKey rsaPublicKey = new RSAPublicKey(publicKeyData); - - rec.setKeySize(Integer.valueOf(rsaPublicKey.getKeySize())); - } catch (InvalidKeyException e) { - request.setExtData(IRequest.RESULT, Integer.valueOf(11)); - CMS.debug("NetkeyKeygenService: failed:InvalidKeyException"); - return false; + if (rKeytype.equals("RSA")) { + try { + RSAPublicKey rsaPublicKey = new RSAPublicKey(publicKeyData); + + rec.setKeySize(Integer.valueOf(rsaPublicKey.getKeySize())); + } catch (InvalidKeyException e) { + request.setExtData(IRequest.RESULT, Integer.valueOf(11)); + CMS.debug("NetkeyKeygenService: failed:InvalidKeyException"); + return false; + } + } else if (rKeytype.equals("EC")) { + CMS.debug("NetkeyKeygenService: alg is EC"); + String oidDescription = "UNDETERMINED"; + // for KeyRecordParser + MetaInfo metaInfo = new MetaInfo(); + + try { + byte curve[] = + ASN1Util.getECCurveBytesByX509PublicKeyBytes(publicKeyData, + false /* without tag and size */); + if (curve.length != 0) { + oidDescription = ASN1Util.getOIDdescription(curve); + } else { + /* this is to be used by derdump */ + byte curveTS[] = + ASN1Util.getECCurveBytesByX509PublicKeyBytes(publicKeyData, + true /* with tag and size */); + if (curveTS.length != 0) { + oidDescription = CMS.BtoA(curveTS); + } + } + } catch (Exception e) { + CMS.debug("NetkeyKeygenService: ASN1Util.getECCurveBytesByX509PublicKeyByte() throws exception: "+ e.toString()); + CMS.debug("NetkeyKeygenService: exception allowed. continue"); + } + + metaInfo.set(KeyRecordParser.OUT_KEY_EC_CURVE, + oidDescription); + + rec.set(IKeyRecord.ATTR_META_INFO, metaInfo); + // key size does not apply to EC; + rec.setKeySize(-1); } + //?? IKeyRepository storage = mKRA.getKeyRepository(); BigInteger serialNo = storage.getNextSerialNumber(); -- cgit