diff options
-rw-r--r-- | base/common/src/com/netscape/certsrv/request/IRequest.java | 2 | ||||
-rw-r--r-- | base/common/src/com/netscape/cms/servlet/connector/GenerateKeyPairServlet.java | 87 | ||||
-rw-r--r-- | base/kra/src/com/netscape/kra/NetkeyKeygenService.java | 299 | ||||
-rw-r--r-- | base/tps/src/channel/Secure_Channel.cpp | 110 | ||||
-rw-r--r-- | base/tps/src/cms/CertEnroll.cpp | 305 | ||||
-rw-r--r-- | base/tps/src/engine/RA.cpp | 37 | ||||
-rw-r--r-- | base/tps/src/include/channel/Secure_Channel.h | 8 | ||||
-rw-r--r-- | base/tps/src/include/cms/CertEnroll.h | 10 | ||||
-rw-r--r-- | base/tps/src/include/engine/RA.h | 14 | ||||
-rw-r--r-- | base/tps/src/include/main/Buffer.h | 3 | ||||
-rw-r--r-- | base/tps/src/include/processor/RA_Enroll_Processor.h | 68 | ||||
-rw-r--r-- | base/tps/src/main/Buffer.cpp | 10 | ||||
-rw-r--r-- | base/tps/src/main/ObjectSpec.cpp | 13 | ||||
-rw-r--r-- | base/tps/src/processor/RA_Enroll_Processor.cpp | 314 |
14 files changed, 946 insertions, 334 deletions
diff --git a/base/common/src/com/netscape/certsrv/request/IRequest.java b/base/common/src/com/netscape/certsrv/request/IRequest.java index f54352ce1..59ae460e5 100644 --- a/base/common/src/com/netscape/certsrv/request/IRequest.java +++ b/base/common/src/com/netscape/certsrv/request/IRequest.java @@ -153,6 +153,8 @@ public interface IRequest { public final static String NETKEY_ATTR_ENC_PRIVKEY_FLAG ="encryptPrivKey"; public final static String NETKEY_ATTR_USER_CERT = "cert"; public final static String NETKEY_ATTR_KEY_SIZE = "keysize"; + public final static String NETKEY_ATTR_KEY_TYPE = "keytype"; + public final static String NETKEY_ATTR_KEY_EC_CURVE = "eckeycurve"; // requestor type values. public static final String REQUESTOR_EE = "EE"; diff --git a/base/common/src/com/netscape/cms/servlet/connector/GenerateKeyPairServlet.java b/base/common/src/com/netscape/cms/servlet/connector/GenerateKeyPairServlet.java index 2f41efc14..ec9b28cad 100644 --- a/base/common/src/com/netscape/cms/servlet/connector/GenerateKeyPairServlet.java +++ b/base/common/src/com/netscape/cms/servlet/connector/GenerateKeyPairServlet.java @@ -24,6 +24,7 @@ import javax.servlet.*; import javax.servlet.http.*; import java.io.*; +import java.util.Hashtable; import com.netscape.certsrv.common.*; import com.netscape.certsrv.request.*; @@ -55,6 +56,7 @@ public class GenerateKeyPairServlet extends CMSServlet { IPrettyPrintFormat pp = CMS.getPrettyPrintFormat(":"); protected IAuthSubsystem mAuthSubsystem = null; protected ILogger mLogger = CMS.getLogger(); + private Hashtable supportedECCurves_ht = null; /** * Constructs GenerateKeyPair servlet. @@ -67,6 +69,7 @@ public class GenerateKeyPairServlet extends CMSServlet { public void init(ServletConfig config) throws ServletException { super.init(config); mConfig = config; + IConfigStore sconfig = CMS.getConfigStore(); String authority = config.getInitParameter(PROP_AUTHORITY); if (authority != null) @@ -74,6 +77,22 @@ public class GenerateKeyPairServlet extends CMSServlet { CMS.getSubsystem(authority); mAuthSubsystem = (IAuthSubsystem) CMS.getSubsystem(CMS.SUBSYSTEM_AUTH); + + // supported EC cuves by the smart cards + String curveList = null; + try { + curveList = sconfig.getString("kra.keygen.curvelist", + "nistp256,nistp384,nistp521"); + } catch (EBaseException e) { + curveList = "nistp256,nistp384,nistp521"; + } + + supportedECCurves_ht = new Hashtable(); + String[] supportedECCurves = curveList.split(","); + for ( int i = 0; i < supportedECCurves.length; i++) { + supportedECCurves_ht.put(supportedECCurves[i], supportedECCurves[i]); + } + } /** @@ -113,8 +132,10 @@ public class GenerateKeyPairServlet extends CMSServlet { String rCUID = req.getParameter("CUID"); String rUserid = req.getParameter("userid"); String rdesKeyString = req.getParameter("drm_trans_desKey"); - String rArchive = req.getParameter("archive"); - String rKeysize = req.getParameter("keysize"); + String rArchive = req.getParameter("archive"); + String rKeysize = req.getParameter("keysize"); + String rKeytype = req.getParameter("keytype"); + String rKeycurve = req.getParameter("eckeycurve"); if ((rCUID == null) || (rCUID.equals(""))) { CMS.debug("GenerateKeyPairServlet: processServerSideKeygen(): missing request parameter: CUID"); @@ -126,9 +147,29 @@ public class GenerateKeyPairServlet extends CMSServlet { missingParam = true; } - if ((rKeysize == null) || (rKeysize.equals(""))) { - rKeysize = "1024"; // default to 1024 - } + // keysize is for non-EC (EC uses keycurve) + if (!rKeytype.equals("EC") && ((rKeysize == null) || (rKeysize.equals("")))) { + rKeysize = "1024"; // default to 1024 + } + + // if not specified, default to RSA + if ((rKeytype == null) || (rKeytype.equals(""))) { + rKeytype = "RSA"; + } + + if (rKeytype.equals("EC")) { + if ((rKeycurve == null) || (rKeycurve.equals(""))) { + rKeycurve = "nistp256"; + } + // is the specified curve supported? + boolean isSupportedCurve = supportedECCurves_ht.containsKey(rKeycurve); + if (isSupportedCurve == false) { + CMS.debug("GenerateKeyPairServlet: processServerSideKeygen(): unsupported curve:"+ rKeycurve); + missingParam = true; + } else { + CMS.debug("GenerateKeyPairServlet: processServerSideKeygen(): curve to be generated:"+ rKeycurve); + } + } if ((rdesKeyString == null) || (rdesKeyString.equals(""))) { @@ -138,7 +179,7 @@ public class GenerateKeyPairServlet extends CMSServlet { if ((rArchive == null) || (rArchive.equals(""))) { CMS.debug("GenerateKeyPairServlet: processServerSideKeygen(): missing key archival flag 'archive' ,default to true"); - rArchive = "true"; + rArchive = "true"; } String selectedToken = null; @@ -150,17 +191,19 @@ public class GenerateKeyPairServlet extends CMSServlet { thisreq.setExtData(IRequest.NETKEY_ATTR_CUID, rCUID); thisreq.setExtData(IRequest.NETKEY_ATTR_USERID, rUserid); thisreq.setExtData(IRequest.NETKEY_ATTR_DRMTRANS_DES_KEY, rdesKeyString); - thisreq.setExtData(IRequest.NETKEY_ATTR_ARCHIVE_FLAG, rArchive); - thisreq.setExtData(IRequest.NETKEY_ATTR_KEY_SIZE, rKeysize); + thisreq.setExtData(IRequest.NETKEY_ATTR_ARCHIVE_FLAG, rArchive); + thisreq.setExtData(IRequest.NETKEY_ATTR_KEY_SIZE, rKeysize); + thisreq.setExtData(IRequest.NETKEY_ATTR_KEY_TYPE, rKeytype); + thisreq.setExtData(IRequest.NETKEY_ATTR_KEY_EC_CURVE, rKeycurve); queue.processRequest( thisreq ); Integer result = thisreq.getExtDataInInteger(IRequest.RESULT); if (result != null) { - // sighs! tps thinks 0 is good, and DRM thinks 1 is good - if (result.intValue() == 1) - status = "0"; - else - status = result.toString(); + // sighs! tps thinks 0 is good, and DRM thinks 1 is good + if (result.intValue() == 1) + status = "0"; + else + status = result.toString(); } else status = "7"; @@ -183,7 +226,7 @@ public class GenerateKeyPairServlet extends CMSServlet { publicKeyString = thisreq.getExtDataInString("public_key"); wrappedPrivKeyString = thisreq.getExtDataInString("wrappedUserPrivate"); - String ivString = thisreq.getExtDataInString("iv_s"); + String ivString = thisreq.getExtDataInString("iv_s"); /* if (selectedToken == null) @@ -194,12 +237,12 @@ public class GenerateKeyPairServlet extends CMSServlet { else { StringBuffer sb = new StringBuffer(); sb.append("status=0&"); - sb.append("wrapped_priv_key="); - sb.append(wrappedPrivKeyString); - sb.append("&iv_param="); - sb.append(ivString); + sb.append("wrapped_priv_key="); + sb.append(wrappedPrivKeyString); + sb.append("&iv_param="); + sb.append(ivString); sb.append("&public_key="); - sb.append(publicKeyString); + sb.append(publicKeyString); value = sb.toString(); } @@ -267,9 +310,9 @@ public class GenerateKeyPairServlet extends CMSServlet { } // begin Netkey serverSideKeyGen and archival - CMS.debug("GenerateKeyPairServlet: processServerSideKeyGen would be called"); - processServerSideKeyGen(req, resp); - return; + CMS.debug("GenerateKeyPairServlet: processServerSideKeyGen would be called"); + processServerSideKeyGen(req, resp); + return; // end Netkey functions } diff --git a/base/kra/src/com/netscape/kra/NetkeyKeygenService.java b/base/kra/src/com/netscape/kra/NetkeyKeygenService.java index 1310fca76..2731e537c 100644 --- a/base/kra/src/com/netscape/kra/NetkeyKeygenService.java +++ b/base/kra/src/com/netscape/kra/NetkeyKeygenService.java @@ -62,6 +62,9 @@ import com.netscape.certsrv.policy.*; import com.netscape.certsrv.authentication.*; import com.netscape.certsrv.apps.*; import com.netscape.certsrv.apps.CMS; +import com.netscape.cmsutil.crypto.CryptoUtil; +import com.netscape.cms.servlet.key.KeyRecordParser; + //for b64 encoding import org.mozilla.jss.util.Base64OutputStream; @@ -146,7 +149,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 { @@ -165,20 +168,28 @@ public class NetkeyKeygenService implements IService { 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) { + 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"); @@ -188,70 +199,111 @@ 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.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(), /*ECC_curve default*/ keyCurve , + 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); + if (kpAlg == KeyPairAlgorithm.DSA) { + if (pqg == null) { + kpGen.initialize(keySize); + } else { + kpGen.initialize(pqg); + } } else { - kpGen.initialize(pqg); + kpGen.initialize(keySize); } - } 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; + 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(); + /* 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) { @@ -324,7 +376,7 @@ public class NetkeyKeygenService implements IService { byte[] wrapped_des_key; byte iv[] = {0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1}; - String iv_s =""; + String iv_s =""; try { SecureRandom random = SecureRandom.getInstance("SHA1PRNG"); random.nextBytes(iv); @@ -332,33 +384,34 @@ public class NetkeyKeygenService implements IService { CMS.debug("NetkeyKeygenService.serviceRequest: "+ e.toString()); } - IVParameterSpec algParam = new IVParameterSpec(iv); + IVParameterSpec algParam = new IVParameterSpec(iv); wrapped_des_key = null; - boolean archive = true; - PK11SymKey sk= null; - byte[] publicKeyData = null;; - String PubKey = ""; + boolean archive = true; + PK11SymKey sk= null; + byte[] publicKeyData = null;; + String PubKey = ""; String id = request.getRequestId().toString(); if (id != null) { auditArchiveID = id.trim(); } - String rArchive = request.getExtDataInString(IRequest.NETKEY_ATTR_ARCHIVE_FLAG); - if (rArchive.equals("true")) { - archive = true; + String rArchive = request.getExtDataInString(IRequest.NETKEY_ATTR_ARCHIVE_FLAG); + if (rArchive.equals("true")) { + archive = true; CMS.debug("NetkeyKeygenService: serviceRequest " +"archival requested for serverSideKeyGen"); - } else { - archive = false; + } else { + archive = false; CMS.debug("NetkeyKeygenService: serviceRequest " +"archival not requested for serverSideKeyGen"); } 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); - auditSubjectID=rCUID+":"+rUserid; + + String rKeytype = request.getExtDataInString(IRequest.NETKEY_ATTR_KEY_TYPE); + + auditSubjectID=rCUID+":"+rUserid; SessionContext sContext = SessionContext.getContext(); String agentId=""; @@ -381,14 +434,40 @@ public class NetkeyKeygenService implements IService { wrapped_des_key = com.netscape.cmsutil.util.Utils.SpecialDecode(rWrappedDesKeyString); CMS.debug("NetkeyKeygenService: wrapped_des_key specialDecoded"); - // 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 - CMS.debug("NetkeyKeygenService: got keygenToken"); +/* + if ((rKeytype == null) || (rKeytype.equals(""))) { + rKeytype = "RSA"; + } +*/ + + 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 + CMS.debug("NetkeyKeygenService: got keygenToken"); if ((wrapped_des_key != null) && (wrapped_des_key.length > 0)) { @@ -401,8 +480,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); @@ -421,18 +502,20 @@ public class NetkeyKeygenService implements IService { CMS.debug("NetkeyKeygenService: finished generate key pair for " +rCUID+":"+rUserid); try { - publicKeyData = keypair.getPublic().getEncoded(); - if (publicKeyData == null) { - request.setExtData(IRequest.RESULT, Integer.valueOf(4)); - CMS.debug("NetkeyKeygenService: failed getting publickey encoded"); - return false; - } else { - //CMS.debug("NetkeyKeygenService: public key binary length ="+ publicKeyData.length); - PubKey = base64Encode(publicKeyData); - - //CMS.debug("NetkeyKeygenService: public key length =" + PubKey.length()); - request.setExtData("public_key", PubKey); - } + publicKeyData = keypair.getPublic().getEncoded(); + if (publicKeyData == null) { + request.setExtData(IRequest.RESULT, Integer.valueOf(4)); + CMS.debug("NetkeyKeygenService: failed getting publickey encoded"); + return false; + } else { + //CMS.debug("NetkeyKeygenService: public key binary length ="+ publicKeyData.length); + /* 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); + } auditMessage = CMS.getLogMessage( LOGGING_SIGNED_AUDIT_SERVER_SIDE_KEYGEN_REQUEST_PROCESSED_SUCCESS, @@ -558,18 +641,52 @@ public class NetkeyKeygenService implements IService { CMS.debug("NetkeyKeygenService: privatekey recording failed"); return false; } else - CMS.debug("NetkeyKeygenService: got key record"); + CMS.debug("NetkeyKeygenService: got key record"); - // we deal with RSA key only - try { - RSAPublicKey rsaPublicKey = new RSAPublicKey(publicKeyData); + 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); + } - rec.setKeySize(Integer.valueOf(rsaPublicKey.getKeySize())); - } catch (InvalidKeyException e) { - request.setExtData(IRequest.RESULT, Integer.valueOf(11)); - CMS.debug("NetkeyKeygenService: failed:InvalidKeyException"); - return false; - } //?? IKeyRepository storage = mKRA.getKeyRepository(); BigInteger serialNo = storage.getNextSerialNumber(); diff --git a/base/tps/src/channel/Secure_Channel.cpp b/base/tps/src/channel/Secure_Channel.cpp index 50b24ae99..27dfaaebf 100644 --- a/base/tps/src/channel/Secure_Channel.cpp +++ b/base/tps/src/channel/Secure_Channel.cpp @@ -38,6 +38,7 @@ #include "apdu/Read_Object_APDU.h" #include "apdu/Write_Object_APDU.h" #include "apdu/Generate_Key_APDU.h" +#include "apdu/Generate_Key_ECC_APDU.h" #include "apdu/Put_Key_APDU.h" #include "apdu/Delete_File_APDU.h" #include "apdu/Load_File_APDU.h" @@ -142,6 +143,7 @@ int Secure_Channel::ComputeAPDU(APDU *apdu) } } + RA::Debug(LL_PER_PDU,"Secure_Channel::ComputeAPDU","Completed apdu."); rc = 1; loser: if( mac != NULL ) { @@ -180,6 +182,8 @@ Buffer *Secure_Channel::ComputeAPDUMac(APDU *apdu) apdu->SetMAC(*mac); m_icv = *mac; + RA::DebugBuffer("Secure_Channel::ComputeAPDUMac ", "mac", + mac); return mac; } /* EncodeAPDUMac */ @@ -1340,6 +1344,8 @@ int Secure_Channel::StartEnrollment(BYTE p1, BYTE p2, Buffer *wrapped_challenge, { int rc = -1; Generate_Key_APDU *generate_key_apdu = NULL; + Generate_Key_ECC_APDU *generate_key_ecc_apdu = NULL; + APDU_Response *response = NULL; RA_Token_PDU_Request_Msg *token_pdu_request_msg = NULL; RA_Token_PDU_Response_Msg *token_pdu_response_msg = NULL; @@ -1348,9 +1354,19 @@ int Secure_Channel::StartEnrollment(BYTE p1, BYTE p2, Buffer *wrapped_challenge, RA::Debug("Secure_Channel::GenerateKey", "Secure_Channel::GenerateKey"); - generate_key_apdu = new Generate_Key_APDU(p1, p2, alg, keysize, option, - alg, *wrapped_challenge, *key_check); - rc = ComputeAPDU(generate_key_apdu); + + bool isECC = RA::isAlgorithmECC(alg); + + if (isECC) { + generate_key_ecc_apdu = new Generate_Key_ECC_APDU(p1, p2, alg, keysize, option, + alg, *wrapped_challenge, *key_check); + rc = ComputeAPDU(generate_key_ecc_apdu); + } else { + generate_key_apdu = new Generate_Key_APDU(p1, p2, alg, keysize, option, + alg, *wrapped_challenge, *key_check); + rc = ComputeAPDU(generate_key_apdu); + } + if (rc == -1) goto loser; @@ -1358,8 +1374,15 @@ int Secure_Channel::StartEnrollment(BYTE p1, BYTE p2, Buffer *wrapped_challenge, mac = ComputeAPDUMac(generate_key_apdu); generate_key_apdu->SetMAC(*mac); */ - token_pdu_request_msg = new RA_Token_PDU_Request_Msg( - generate_key_apdu); + + if (generate_key_ecc_apdu != NULL ) { + token_pdu_request_msg = new RA_Token_PDU_Request_Msg( + generate_key_ecc_apdu); + } else { + token_pdu_request_msg = new RA_Token_PDU_Request_Msg( + generate_key_apdu); + } + m_session->WriteMsg(token_pdu_request_msg); RA::Debug("Secure_Channel::GenerateKey", "Sent token_pdu_request_msg"); @@ -2177,9 +2200,9 @@ Buffer Secure_Channel::CreatePKCS11CertAttrsBuffer(TokenKeyType key_type, const Buffer b(256); // allocate some space b.resize(7); // this keeps the allocated space around - RA::Debug("Secure_Channel::CreatePKCS11CertAttrs", "id=%s", id); - RA::Debug("Secure_Channel::CreatePKCS11CertAttrs", "label=%s", label); - RA::DebugBuffer("Secure_Channel::CreatePKCS11CertAttrs", "keyid", keyid); + RA::Debug("Secure_Channel::CreatePKCS11CertAttrsBuffer", "id=%s", id); + RA::Debug("Secure_Channel::CreatePKCS11CertAttrsBuffer", "label=%s", label); + RA::DebugBuffer("Secure_Channel::CreatePKCS11CertAttrsBuffer", "keyid", keyid); AppendAttribute(b, CKA_LABEL, strlen(label), (BYTE*)label); // hash of pubk AppendAttribute(b, CKA_ID, keyid->size(), (BYTE*)*keyid); @@ -2301,6 +2324,7 @@ mine: M 00020001010000000100010100000100 M 00040000000000000000000403000000 */ + Buffer Secure_Channel::CreatePKCS11PriKeyAttrsBuffer(TokenKeyType key_type, const char *id, const char *label, Buffer *keyid, Buffer *modulus, const char *opType, const char *tokenType, const char *keyTypePrefix) { @@ -2383,6 +2407,39 @@ int Secure_Channel::CreatePKCS11PriKeyAttrs(TokenKeyType key_type, const char *i } /* CreatePKCS11PriKeyAttrs */ +Buffer Secure_Channel::CreatePKCS11ECCPriKeyAttrsBuffer(TokenKeyType type, const char *id, const char *label, Buffer *keyid, + SECKEYECParams *ecParams, const char *opType, const char *tokenType, const char *keyTypePrefix) +{ + + BYTE keytype[8] = { 3,0,0,0 }; + BYTE p11class[4] = { 3,0,0,0 }; + + Buffer b(256); // allocate some space + b.resize(7); // this keeps the allocated space around + + if (label != NULL) + RA::Debug("Secure_Channel::CreatePKCS11ECCPriKeyAttrsBuffer", "label=%s", label); + if (keyid != NULL) + RA::DebugBuffer("Secure_Channel::CreatePKCS11ECCPriKeyAttrsBuffer", "keyid", keyid); + if (id != NULL) + RA::Debug("Secure_Channel::CreatePKCS11ECCPriKeyAttrsBuffer", "id=%s",id); + + AppendAttribute(b,CKA_KEY_TYPE, 4, keytype); + AppendAttribute(b,CKA_CLASS, 4, p11class ); + // hash of pubk + AppendAttribute(b,CKA_ID, keyid->size(), (BYTE*)*keyid); + + AppendAttribute(b,CKA_EC_PARAMS, ecParams->len, ecParams->data); + AppendKeyCapabilities(b, opType, tokenType, keyTypePrefix, "private"); + + FinalizeBuffer(b, id); + + RA::DebugBuffer("Secure_Channel::CreatePKCS11ECCPriKeyAttrsBuffer", "buffer", &b); + + return b; + +} + /* Public Key: (k1) CKA_PUBLIC_EXPONENT(0x0122) @@ -2461,6 +2518,43 @@ Buffer Secure_Channel::CreatePKCS11PubKeyAttrsBuffer(TokenKeyType key_type, cons return b; } /* CreatePKCS11PubKeyAttrs */ + +Buffer Secure_Channel::CreatePKCS11ECCPubKeyAttrsBuffer(TokenKeyType key_type, const char *id, const char *label, Buffer *keyid, + SECKEYECPublicKey *publicKey, SECKEYECParams *ecParams, const char *opType, const char *tokenType, const char *keyTypePrefix) +{ + BYTE p11class[4] = { 2,0,0,0 }; + // BYTE ZERO[1] = { 0 }; + // BYTE ONE[1] = { 1 }; + // char configname[256]; + + BYTE keytype[4] = { 3,0,0,0 }; + Buffer b(256); // allocate some space + b.resize(7); // this keeps the allocated space around + + if (label != NULL) + RA::Debug("Secure_Channel::CreatePKCS11ECCPubAttrsBuffer", "label=%s", label); + if (keyid != NULL) + RA::DebugBuffer("Secure_Channel::CreatePKCS11ECCPubAttrsBuffer", "keyid", keyid); + + // XXX TUES + // hash of pubk + AppendAttribute(b,CKA_ID, keyid->size(), (BYTE*)*keyid); + AppendAttribute(b, CKA_CLASS, 4, p11class ); // type of object + AppendAttribute(b,CKA_KEY_TYPE, 4, keytype); // CKK_EC key type + AppendAttribute(b,CKA_EC_PARAMS, ecParams->len, (BYTE *) ecParams->data); + AppendAttribute(b, CKA_EC_POINT, publicKey->publicValue.len, (BYTE *) publicKey->publicValue.data); + + AppendKeyCapabilities(b, opType, tokenType, keyTypePrefix, "public"); + + FinalizeBuffer(b, id); + + RA::DebugBuffer("Secure_Channel::CreatePKCS11ECCPubAttrsBuffer", "buffer", &b); + + return b; +} /* CreatePKCS11ECCPubKeyAttrs */ + + + int Secure_Channel::CreatePKCS11PubKeyAttrs(TokenKeyType key_type, const char *id, const char *label, Buffer *keyid, Buffer *exponent, Buffer *modulus, const char *opType, const char *tokenType, const char *keyTypePrefix) { diff --git a/base/tps/src/cms/CertEnroll.cpp b/base/tps/src/cms/CertEnroll.cpp index 89990d021..fb2852d9b 100644 --- a/base/tps/src/cms/CertEnroll.cpp +++ b/base/tps/src/cms/CertEnroll.cpp @@ -19,6 +19,7 @@ // --- END COPYRIGHT BLOCK --- #include <string.h> +#include <assert.h> #include "main/RA_Session.h" #include "main/RA_Msg.h" @@ -35,6 +36,7 @@ #include "base64.h" #include "nssb64.h" #include "prlock.h" +#include "secoidt.h" #include "main/Memory.h" @@ -49,6 +51,131 @@ ReturnStatus verifyProof(SECKEYPublicKey* , SECItem* , #define TOKENDB_PUBLIC #endif /* !XP_WIN32 */ +//ECC curve information + +typedef struct curveNameTagPairStr { + char *curveName; + SECOidTag curveOidTag; +} CurveNameTagPair; + + +static CurveNameTagPair nameTagPair[] = +{ + { "prime192v1", SEC_OID_ANSIX962_EC_PRIME192V1 }, + { "prime192v2", SEC_OID_ANSIX962_EC_PRIME192V2 }, + { "prime192v3", SEC_OID_ANSIX962_EC_PRIME192V3 }, + { "prime239v1", SEC_OID_ANSIX962_EC_PRIME239V1 }, + { "prime239v2", SEC_OID_ANSIX962_EC_PRIME239V2 }, + { "prime239v3", SEC_OID_ANSIX962_EC_PRIME239V3 }, + { "prime256v1", SEC_OID_ANSIX962_EC_PRIME256V1 }, + + { "secp112r1", SEC_OID_SECG_EC_SECP112R1}, + { "secp112r2", SEC_OID_SECG_EC_SECP112R2}, + { "secp128r1", SEC_OID_SECG_EC_SECP128R1}, + { "secp128r2", SEC_OID_SECG_EC_SECP128R2}, + { "secp160k1", SEC_OID_SECG_EC_SECP160K1}, + { "secp160r1", SEC_OID_SECG_EC_SECP160R1}, + { "secp160r2", SEC_OID_SECG_EC_SECP160R2}, + { "secp192k1", SEC_OID_SECG_EC_SECP192K1}, + { "secp192r1", SEC_OID_ANSIX962_EC_PRIME192V1 }, + { "nistp192", SEC_OID_ANSIX962_EC_PRIME192V1 }, + { "secp224k1", SEC_OID_SECG_EC_SECP224K1}, + { "secp224r1", SEC_OID_SECG_EC_SECP224R1}, + { "nistp224", SEC_OID_SECG_EC_SECP224R1}, + { "secp256k1", SEC_OID_SECG_EC_SECP256K1}, + { "secp256r1", SEC_OID_ANSIX962_EC_PRIME256V1 }, + { "nistp256", SEC_OID_ANSIX962_EC_PRIME256V1 }, + { "secp384r1", SEC_OID_SECG_EC_SECP384R1}, + { "nistp384", SEC_OID_SECG_EC_SECP384R1}, + { "secp521r1", SEC_OID_SECG_EC_SECP521R1}, + { "nistp521", SEC_OID_SECG_EC_SECP521R1}, + + { "c2pnb163v1", SEC_OID_ANSIX962_EC_C2PNB163V1 }, + { "c2pnb163v2", SEC_OID_ANSIX962_EC_C2PNB163V2 }, + { "c2pnb163v3", SEC_OID_ANSIX962_EC_C2PNB163V3 }, + { "c2pnb176v1", SEC_OID_ANSIX962_EC_C2PNB176V1 }, + { "c2tnb191v1", SEC_OID_ANSIX962_EC_C2TNB191V1 }, + { "c2tnb191v2", SEC_OID_ANSIX962_EC_C2TNB191V2 }, + { "c2tnb191v3", SEC_OID_ANSIX962_EC_C2TNB191V3 }, + { "c2onb191v4", SEC_OID_ANSIX962_EC_C2ONB191V4 }, + { "c2onb191v5", SEC_OID_ANSIX962_EC_C2ONB191V5 }, + { "c2pnb208w1", SEC_OID_ANSIX962_EC_C2PNB208W1 }, + { "c2tnb239v1", SEC_OID_ANSIX962_EC_C2TNB239V1 }, + { "c2tnb239v2", SEC_OID_ANSIX962_EC_C2TNB239V2 }, + { "c2tnb239v3", SEC_OID_ANSIX962_EC_C2TNB239V3 }, + { "c2onb239v4", SEC_OID_ANSIX962_EC_C2ONB239V4 }, + { "c2onb239v5", SEC_OID_ANSIX962_EC_C2ONB239V5 }, + { "c2pnb272w1", SEC_OID_ANSIX962_EC_C2PNB272W1 }, + { "c2pnb304w1", SEC_OID_ANSIX962_EC_C2PNB304W1 }, + { "c2tnb359v1", SEC_OID_ANSIX962_EC_C2TNB359V1 }, + { "c2pnb368w1", SEC_OID_ANSIX962_EC_C2PNB368W1 }, + { "c2tnb431r1", SEC_OID_ANSIX962_EC_C2TNB431R1 }, + + { "sect113r1", SEC_OID_SECG_EC_SECT113R1}, + { "sect113r2", SEC_OID_SECG_EC_SECT113R2}, + { "sect131r1", SEC_OID_SECG_EC_SECT131R1}, + { "sect131r2", SEC_OID_SECG_EC_SECT131R2}, + { "sect163k1", SEC_OID_SECG_EC_SECT163K1}, + { "nistk163", SEC_OID_SECG_EC_SECT163K1}, + { "sect163r1", SEC_OID_SECG_EC_SECT163R1}, + { "sect163r2", SEC_OID_SECG_EC_SECT163R2}, + { "nistb163", SEC_OID_SECG_EC_SECT163R2}, + { "sect193r1", SEC_OID_SECG_EC_SECT193R1}, + { "sect193r2", SEC_OID_SECG_EC_SECT193R2}, + { "sect233k1", SEC_OID_SECG_EC_SECT233K1}, + { "nistk233", SEC_OID_SECG_EC_SECT233K1}, + { "sect233r1", SEC_OID_SECG_EC_SECT233R1}, + { "nistb233", SEC_OID_SECG_EC_SECT233R1}, + { "sect239k1", SEC_OID_SECG_EC_SECT239K1}, + { "sect283k1", SEC_OID_SECG_EC_SECT283K1}, + { "nistk283", SEC_OID_SECG_EC_SECT283K1}, + { "sect283r1", SEC_OID_SECG_EC_SECT283R1}, + { "nistb283", SEC_OID_SECG_EC_SECT283R1}, + { "sect409k1", SEC_OID_SECG_EC_SECT409K1}, + { "nistk409", SEC_OID_SECG_EC_SECT409K1}, + { "sect409r1", SEC_OID_SECG_EC_SECT409R1}, + { "nistb409", SEC_OID_SECG_EC_SECT409R1}, + { "sect571k1", SEC_OID_SECG_EC_SECT571K1}, + { "nistk571", SEC_OID_SECG_EC_SECT571K1}, + { "sect571r1", SEC_OID_SECG_EC_SECT571R1}, + { "nistb571", SEC_OID_SECG_EC_SECT571R1}, + +}; + +SECKEYECParams * +CertEnroll::encode_ec_params(char *curve) +{ + SECKEYECParams *ecparams; + SECOidData *oidData = NULL; + SECOidTag curveOidTag = SEC_OID_UNKNOWN; /* default */ + int i, numCurves; + + if (curve && *curve) { + numCurves = sizeof(nameTagPair)/sizeof(CurveNameTagPair); + for (i = 0; ((i < numCurves) && (curveOidTag == SEC_OID_UNKNOWN)); + i++) { + if (PL_strcmp(curve, nameTagPair[i].curveName) == 0) + curveOidTag = nameTagPair[i].curveOidTag; + } + } + + if ((curveOidTag == SEC_OID_UNKNOWN) || + (oidData = SECOID_FindOIDByTag(curveOidTag)) == NULL) { + return NULL; + } + + ecparams = SECITEM_AllocItem(NULL, NULL, (2 + oidData->oid.len)); + + if (!ecparams) + return NULL; + + ecparams->data[0] = SEC_ASN1_OBJECT_ID; + ecparams->data[1] = oidData->oid.len; + memcpy(ecparams->data + 2, oidData->oid.data, oidData->oid.len); + + return ecparams; +} + /** * Constructs handle for Certificate Enrollment */ @@ -328,8 +455,20 @@ Buffer * CertEnroll::EnrollCertificate( * Short Exponent Length * * Byte[] Exponent + * + * + * ECC KeyBlob Format (ECC Public Key) + * ---------------------------------- + * + * Byte Encoding (0 for plaintext) * - * + * Byte Key Type (10 for ECC public) + * + * Short Key Length (256, 384, 521 high byte first) + * + * Byte[] Key (W) + * + * * Signature Format (Proof) * --------------------------------------- * @@ -369,7 +508,7 @@ Buffer * CertEnroll::EnrollCertificate( ******/ SECKEYPublicKey *CertEnroll::ParsePublicKeyBlob(unsigned char *blob, - Buffer *challenge) + Buffer *challenge, bool isECC) { char configname[5000]; SECKEYPublicKey *pk = NULL; @@ -404,7 +543,7 @@ SECKEYPublicKey *CertEnroll::ParsePublicKeyBlob(unsigned char *blob, pkeyb_len = (unsigned short) ((len0 << 8) | (len1 & 0xFF)); RA::Debug(LL_PER_PDU, "CertEnroll::ParsePublicKeyBlob", - "pkeyb_len =%d",pkeyb_len); + "pkeyb_len =%d isECC: %d",pkeyb_len, isECC); if (pkeyb_len <= 0) { RA::Error("CertEnroll::ParsePublicKeyBlob", "public key blob length = %d", pkeyb_len); @@ -431,51 +570,112 @@ SECKEYPublicKey *CertEnroll::ParsePublicKeyBlob(unsigned char *blob, // convert pkeyb to pkey // 1 byte encoding, 1 byte key type, 2 bytes key length, then the key + + // for ECC + unsigned short ecc_pkey_len = 0; + // ecc key blob + unsigned char *eccpb = NULL; + + // for RSA + unsigned short mod_len = 0; + unsigned short exp_len = 0; + // public key mod blob + unsigned char * modb = NULL; + // public key exp blob + unsigned char * expb = NULL; + unsigned short pkey_offset = 4; - // now, convert lengths for modulus and exponent len0 = pkeyb[pkey_offset]; len1 = pkeyb[pkey_offset + 1]; - unsigned short mod_len = (len0 << 8 | len1); - len0 = pkeyb[pkey_offset + 2 + mod_len]; - len1 = pkeyb[pkey_offset + 2 + mod_len + 1]; - unsigned short exp_len = (len0 << 8 | len1); + if (!isECC) { + // now, convert lengths for modulus and exponent + mod_len = (len0 << 8 | len1); + len0 = pkeyb[pkey_offset + 2 + mod_len]; + len1 = pkeyb[pkey_offset + 2 + mod_len + 1]; + exp_len = (len0 << 8 | len1); - // public key mod blob - unsigned char * modb = &pkeyb[pkey_offset + 2]; + modb = &pkeyb[pkey_offset + 2]; + expb = &pkeyb[pkey_offset + 2 + mod_len + 2]; - // public key exp blob - unsigned char * expb = &pkeyb[pkey_offset + 2 + mod_len + 2]; + } else { + ecc_pkey_len = (len0 << 8 | len1); + eccpb = &pkeyb[pkey_offset + 2]; + } // construct SECItem - SECItem siMod; - siMod.type = (SECItemType) 0; - siMod.data = (unsigned char *) modb; - siMod.len = mod_len; + // for RSA + SECItem siMod; SECItem siExp; - siExp.type = (SECItemType) 0; - siExp.data = (unsigned char *)expb; - siExp.len = exp_len; - - // construct SECKEYRSAPublicKeyStr SECKEYRSAPublicKeyStr rsa_pks; - rsa_pks.modulus = siMod; - rsa_pks.publicExponent = siExp; - // construct SECKEYPublicKey - // this is to be returned + // for ECC + SECItem eccValue; + SECKEYECPublicKeyStr ecc_pks; + SECKEYECParams *ecc_key_params = NULL; + pk = (SECKEYPublicKey *) malloc(sizeof(SECKEYPublicKey)); - pk->keyType = rsaKey; - pk->pkcs11Slot = NULL; - pk->pkcs11ID = CK_INVALID_HANDLE; - pk->u.rsa = rsa_pks; + + assert(pk); + + if (!isECC) { + + siMod.type = (SECItemType) 0; + siMod.data = (unsigned char *) modb; + siMod.len = mod_len; + + siExp.type = (SECItemType) 0; + siExp.data = (unsigned char *)expb; + siExp.len = exp_len; + + // construct SECKEYRSAPublicKeyStr + rsa_pks.modulus = siMod; + rsa_pks.publicExponent = siExp; + + pk->keyType = rsaKey; + pk->pkcs11Slot = NULL; + pk->pkcs11ID = CK_INVALID_HANDLE; + pk->u.rsa = rsa_pks; + } else { + // ECC + len0 = blob[pkeyb_len_offset +4]; + len1 = blob[pkeyb_len_offset +5]; + int keyCurveSize = (len0 << 8 | len1); + + RA::Debug(LL_PER_PDU, "CertEnroll::ParsePublicKeyBlob", + "keyCurveSize =%d",keyCurveSize); + + char curve[56] = ""; + snprintf(curve, 56, "nistp%d",keyCurveSize ); + + ecc_key_params = encode_ec_params(curve); + + if (ecc_key_params == NULL) { + free(pk); + pk = NULL; + return NULL; + } + + eccValue.type = (SECItemType) 0; + eccValue.data = (unsigned char *) eccpb; + eccValue.len = ecc_pkey_len; + + ecc_pks.size = keyCurveSize; + ecc_pks.publicValue = eccValue; + ecc_pks.DEREncodedParams = *ecc_key_params; + + pk->keyType = ecKey; + pk->pkcs11Slot = NULL; + pk->pkcs11ID = CK_INVALID_HANDLE; + pk->u.ec = ecc_pks; + } PR_snprintf((char *)configname, 256, "general.verifyProof"); int verifyProofEnable = RA::GetConfigStore()->GetConfigAsInt(configname, 0x1); if (verifyProofEnable) { - rs = verifyProof(pk, &siProof, pkeyb_len, pkeyb, challenge); + rs = verifyProof(pk, &siProof, pkeyb_len, pkeyb, challenge, isECC); if (rs.status == PR_FAILURE) { RA::Error("CertEnroll::ParsePublicKeyBlob", "verify proof failed"); @@ -487,6 +687,32 @@ SECKEYPublicKey *CertEnroll::ParsePublicKeyBlob(unsigned char *blob, return pk; } +/* + * for debugging tokens + * -- list out all tokens and thier login status + */ +static SECStatus +ListModules(void) +{ + PK11SlotList *list; + PK11SlotListElement *le; + + /* get them all! */ + list = PK11_GetAllTokens(CKM_INVALID_MECHANISM,PR_FALSE,PR_FALSE,NULL); + if (list == NULL) return SECFailure; + + /* look at each slot*/ + for (le = list->head ; le; le = le->next) { + RA::Debug( LL_PER_PDU, "CertEnroll::ListModules", + " slot: %s\n, loggedIn? %d, token: %s\n", PK11_GetSlotName(le->slot), + (PK11_IsLoggedIn(le->slot, NULL) == PR_TRUE)? 1:0, + PK11_GetTokenName(le->slot)); + } + PK11_FreeSlotList(list); + + return SECSuccess; +} + /** * verify the proof. @@ -502,18 +728,24 @@ SECKEYPublicKey *CertEnroll::ParsePublicKeyBlob(unsigned char *blob, */ ReturnStatus CertEnroll::verifyProof(SECKEYPublicKey* pk, SECItem* siProof, unsigned short pkeyb_len, unsigned char* pkeyb, - Buffer* challenge) { + Buffer* challenge, bool isECC) { ReturnStatus rs; VFYContext * vc = NULL; rs.statusNum = ::VRFY_SUCCESS; rs.status = PR_SUCCESS; + // ListModules(); + // verify proof (signature) RA::Debug(LL_PER_PDU, "CertEnroll::verifyProof", "verify proof begins"); - vc = VFY_CreateContext(pk, siProof, SEC_OID_ISO_SHA_WITH_RSA_SIGNATURE, NULL); + if(isECC) { + vc = VFY_CreateContext(pk, siProof, SEC_OID_ANSIX962_ECDSA_SHA1_SIGNATURE , NULL); + } else { + vc = VFY_CreateContext(pk, siProof, SEC_OID_ISO_SHA_WITH_RSA_SIGNATURE, NULL); + } if (vc == NULL) { RA::Error("CertEnroll::verifyProof", @@ -530,14 +762,15 @@ ReturnStatus CertEnroll::verifyProof(SECKEYPublicKey* pk, SECItem* siProof, int i =0; for (i = 0; i<pkeyb_len; i++) { proof[i] = pkeyb[i]; + RA::Debug(LL_PER_PDU,"CertEnroll::VerifyProof", "proof[%d]=%x", i, proof[i]); } - // RA::DebugBuffer("CertEnroll::VerifyProof","VerifyProof:: challenge =", challenge); + RA::DebugBuffer("CertEnroll::VerifyProof","VerifyProof:: challenge =", challenge); unsigned char* chal = (unsigned char *)(BYTE *) (*challenge); unsigned int j = 0; for (j=0; j < challenge->size(); i++, j++) { proof[i] = chal[j]; - // RA::Debug(LL_PER_PDU, "CertEnroll::VerifyProof","proof[%d]= %x", - // i, proof[i]); + RA::Debug(LL_PER_PDU, "CertEnroll::VerifyProof","proof[%d]= %x", + i, proof[i]); } SECStatus vs = VFY_Begin(vc); @@ -547,7 +780,7 @@ ReturnStatus CertEnroll::verifyProof(SECKEYPublicKey* pk, SECItem* siProof, vs = VFY_End(vc); if (vs == SECFailure) { RA::Error("CertEnroll::verifyProof", - "VFY_End() failed pkeyb_len=%d challenge_size=%d", pkeyb_len, challenge->size()); + "VFY_End() failed pkeyb_len=%d challenge_size=%d error=%d", pkeyb_len, challenge->size(),PR_GetError()); rs.statusNum = ::VFY_UPDATE_FAILURE; rs.status = PR_FAILURE; } diff --git a/base/tps/src/engine/RA.cpp b/base/tps/src/engine/RA.cpp index f8c64f306..2502cf259 100644 --- a/base/tps/src/engine/RA.cpp +++ b/base/tps/src/engine/RA.cpp @@ -1302,7 +1302,7 @@ void RA::ServerSideKeyGen(RA_Session *session, const char* cuid, char **publicKey_s, char **wrappedPrivateKey_s, char **ivParam_s, const char *connId, - bool archive, int keysize) + bool archive, int keysize, bool isECC) { const char *FN="RA::ServerSideKeyGen"; @@ -1372,8 +1372,27 @@ void RA::ServerSideKeyGen(RA_Session *session, const char* cuid, RA::Debug(LL_PER_CONNECTION, FN, "wrappedDESKey_s=%s", wrappedDESKey_s); - PR_snprintf((char *)body, MAX_BODY_LEN, - "archive=%s&CUID=%s&userid=%s&keysize=%d&drm_trans_desKey=%s",archive?"true":"false",cuid, userid, keysize, wrappedDESKey_s); + if (isECC) { + char *eckeycurve = NULL; + if (keysize == 521) { + eckeycurve = "nistp521"; + } else if (keysize == 384) { + eckeycurve = "nistp384"; + } else if (keysize == 256) { + eckeycurve = "nistp256"; + } else { + RA::Debug(LL_PER_CONNECTION, FN, + "unrecognized ECC keysize %d, setting to nistp256", keysize); + keysize = 256; + eckeycurve = "nistp256"; + } + PR_snprintf((char *)body, MAX_BODY_LEN, + "archive=%s&CUID=%s&userid=%s&keytype=EC&eckeycurve=%s&drm_trans_desKey=%s",archive?"true":"false",cuid, userid, eckeycurve, wrappedDESKey_s); + } else { + PR_snprintf((char *)body, MAX_BODY_LEN, + "archive=%s&CUID=%s&userid=%s&keysize=%d&keytype=RSA&drm_trans_desKey=%s",archive?"true":"false",cuid, userid, keysize, wrappedDESKey_s); + } + RA::Debug(LL_PER_CONNECTION, FN, "sending to DRM: query=%s", body); @@ -3680,6 +3699,18 @@ loser: return newKey; } +bool RA::isAlgorithmECC(BYTE alg) +{ + bool result = false; + + if (alg == ALG_EC_F2M || alg == ALG_EC_FP) + result = true; + + RA::Debug(LL_PER_SERVER, "RA::isAlgorithmECC", " alg: %d result: %d", alg, result); + + return result; +} + bool RA::transition_allowed(int oldState, int newState) { /* parse the allowed transitions string and look for old:new */ diff --git a/base/tps/src/include/channel/Secure_Channel.h b/base/tps/src/include/channel/Secure_Channel.h index bac072407..e67f8ebaf 100644 --- a/base/tps/src/include/channel/Secure_Channel.h +++ b/base/tps/src/include/channel/Secure_Channel.h @@ -125,10 +125,18 @@ class Secure_Channel : public Channel int CreatePKCS11CertAttrs(TokenKeyType type, const char *id, const char *label, Buffer *keyid); Buffer CreatePKCS11PriKeyAttrsBuffer(TokenKeyType type, const char *id, const char *label, Buffer *keyid, Buffer *modulus, const char *opType, const char *tokenType, const char *keyTypePrefix); + + Buffer CreatePKCS11ECCPriKeyAttrsBuffer(TokenKeyType type, const char *id, const char *label, Buffer *keyid, + SECKEYECParams *ecParams, const char *opType, const char *tokenType, const char *keyTypePrefix); + int CreatePKCS11PriKeyAttrs(TokenKeyType type, const char *id, const char *label, Buffer *keyid, Buffer *modulus, const char *opType, const char *tokenType, const char *keyTypePrefix); Buffer CreatePKCS11PubKeyAttrsBuffer(TokenKeyType type, const char *id, const char *label, Buffer *keyid, Buffer *exponent, Buffer *modulus, const char *opType, const char *tokenType, const char *keyTypePrefix); + + Buffer CreatePKCS11ECCPubKeyAttrsBuffer(TokenKeyType key_type, const char *id, const char *label, Buffer *keyid, SECKEYECPublicKey *publicKey, + SECKEYECParams *ecParams, const char *opType, const char *tokenType, const char *keyTypePrefix); + int CreatePKCS11PubKeyAttrs(TokenKeyType type, const char *id, const char *label, Buffer *keyid, Buffer *exponent, Buffer *modulus, const char *opType, const char *tokenType, const char *keyTypePrefix); APDU_Response *SendTokenAPU(APDU *apdu); diff --git a/base/tps/src/include/cms/CertEnroll.h b/base/tps/src/include/cms/CertEnroll.h index 442e28e8c..4f06961d5 100644 --- a/base/tps/src/include/cms/CertEnroll.h +++ b/base/tps/src/include/cms/CertEnroll.h @@ -55,8 +55,9 @@ class CertEnroll TOKENDB_PUBLIC CertEnroll(); TOKENDB_PUBLIC ~CertEnroll(); + SECKEYPublicKey *ParsePublicKeyBlob(unsigned char * /*blob*/, - Buffer * /*challenge*/); + Buffer * /*challenge*/, bool isECC); Buffer *EnrollCertificate(SECKEYPublicKey * /*pk_parsed*/, const char *profileId, const char * /*uid*/, @@ -64,12 +65,15 @@ class CertEnroll char *error_msg, SECItem** encodedPublicKeyInfo = NULL); ReturnStatus verifyProof(SECKEYPublicKey* /*pk*/, SECItem* /*siProof*/, - unsigned short /*pkeyb_len*/, unsigned char* /*pkeyb*/, - Buffer* /*challenge*/); + unsigned short /*pkeyb_len*/, unsigned char* /*pkeyb*/, + Buffer* /*challenge*/, bool /*isECC*/); TOKENDB_PUBLIC Buffer *RenewCertificate(PRUint64 serialno, const char *connid, const char *profileId, char *error_msg); TOKENDB_PUBLIC int RevokeCertificate(const char *reason, const char *serialno, const char *connid, char *&status); TOKENDB_PUBLIC int UnrevokeCertificate(const char *serialno, const char *connid, char *&status); PSHttpResponse * sendReqToCA(const char *servlet, const char *parameters, const char *connid); Buffer * parseResponse(PSHttpResponse * /*resp*/); + + SECKEYECParams * encode_ec_params(char *curve); + }; #endif /* CERTENROLL_H */ diff --git a/base/tps/src/include/engine/RA.h b/base/tps/src/include/engine/RA.h index ea04aa4d5..3ec0143d8 100644 --- a/base/tps/src/include/engine/RA.h +++ b/base/tps/src/include/engine/RA.h @@ -80,6 +80,13 @@ enum RA_Log_Level { LL_ALL_DATA_IN_PDU = 9 }; +enum RA_Algs { + ALG_RSA = 1, + ALG_RSA_CRT = 2, + ALG_DSA = 3, + ALG_EC_F2M = 4, + ALG_EC_FP = 5 +}; #ifdef XP_WIN32 #define TPS_PUBLIC __declspec(dllexport) @@ -125,12 +132,12 @@ class RA char** kek_kekSessionKey_s, char **keycheck_s, const char *connId); - static void ServerSideKeyGen(RA_Session *session, const char* cuid, + static void ServerSideKeyGen(RA_Session *session, const char* cuid, const char *userid, char* kekSessionKey_s, - char **publickey_s, + char **publickey_s, char **wrappedPrivateKey_s, char **ivParam_s, const char *connId, - bool archive, int keysize); + bool archive, int keysize, bool isECC); static void RecoverKey(RA_Session *session, const char* cuid, const char *userid, char* kekSessionKey_s, char *cert_s, char **publickey_s, @@ -368,6 +375,7 @@ class RA static void CleanupPublishers(); static int Failover(HttpConnection *&conn, int len); + static bool isAlgorithmECC(BYTE algorithm); TPS_PUBLIC static SECCertificateUsage getCertificateUsage(const char *certusage); TPS_PUBLIC static bool verifySystemCertByNickname(const char *nickname, const char *certUsage); TPS_PUBLIC static bool verifySystemCerts(); diff --git a/base/tps/src/include/main/Buffer.h b/base/tps/src/include/main/Buffer.h index 4fa7af6df..e3f08925e 100644 --- a/base/tps/src/include/main/Buffer.h +++ b/base/tps/src/include/main/Buffer.h @@ -167,6 +167,9 @@ class Buffer { */ TPS_PUBLIC void replace(unsigned int i, const BYTE* cpy, unsigned int n); + TPS_PUBLIC unsigned char* getBuf(); + TPS_PUBLIC unsigned int getLen(); + /** * returns a hex version of the buffer */ diff --git a/base/tps/src/include/processor/RA_Enroll_Processor.h b/base/tps/src/include/processor/RA_Enroll_Processor.h index b78d33f36..373465064 100644 --- a/base/tps/src/include/processor/RA_Enroll_Processor.h +++ b/base/tps/src/include/processor/RA_Enroll_Processor.h @@ -50,40 +50,40 @@ class RA_Enroll_Processor : public RA_Processor { - public: - TPS_PUBLIC RA_Enroll_Processor(); - TPS_PUBLIC ~RA_Enroll_Processor(); - public: - int ParsePublicKeyBlob(unsigned char *blob, - unsigned char *challenge, - SECKEYPublicKey *pk); - RA_Status DoEnrollment(AuthParams *login, RA_Session *session, - CERTCertificate **certificates, - char **origins, - char **ktypes, - int pkcs11obj, - PKCS11Obj * pkcs_objx, - NameValueSet *extensions, - int index, int keyTypeNum, - int start_progress, - int end_progress, - Secure_Channel *channel, Buffer *wrapped_challenge, - const char *tokenType, - const char *keyType, - Buffer *key_check, - Buffer *plaintext_challenge, - const char *cuid, - const char *msn, - const char *khex, - TokenKeyType key_type, - const char *profileId, - const char *userid, - const char *cert_id, - const char *publisher_id, - const char *cert_attr_id, - const char *pri_attr_id, - const char *pub_attr_id, - BYTE se_p1, BYTE se_p2, int keysize, const char *connid, const char *keyTypePrefix,char * applet_version); + public: + TPS_PUBLIC RA_Enroll_Processor(); + TPS_PUBLIC ~RA_Enroll_Processor(); + public: + int ParsePublicKeyBlob(unsigned char *blob, + unsigned char *challenge, + SECKEYPublicKey *pk); + RA_Status DoEnrollment(AuthParams *login, RA_Session *session, + CERTCertificate **certificates, + char **origins, + char **ktypes, + int pkcs11obj, + PKCS11Obj * pkcs_objx, + NameValueSet *extensions, + int index, int keyTypeNum, + int start_progress, + int end_progress, + Secure_Channel *channel, Buffer *wrapped_challenge, + const char *tokenType, + const char *keyType, + Buffer *key_check, + Buffer *plaintext_challenge, + const char *cuid, + const char *msn, + const char *khex, + TokenKeyType key_type, + const char *profileId, + const char *userid, + const char *cert_id, + const char *publisher_id, + const char *cert_attr_id, + const char *pri_attr_id, + const char *pub_attr_id, + BYTE se_p1, BYTE se_p2, BYTE algorithm, int keysize, const char *connid, const char *keyTypePrefix,char * applet_version); bool DoRenewal(const char *connid, const char *profileId, diff --git a/base/tps/src/main/Buffer.cpp b/base/tps/src/main/Buffer.cpp index 2a547feea..94311fc50 100644 --- a/base/tps/src/main/Buffer.cpp +++ b/base/tps/src/main/Buffer.cpp @@ -222,6 +222,16 @@ Buffer::string() return s; } +TPS_PUBLIC unsigned char* +Buffer::getBuf() { + return (unsigned char *) buf; +} + +TPS_PUBLIC unsigned int +Buffer::getLen() { + return len; +} + TPS_PUBLIC char * Buffer::toHex() { diff --git a/base/tps/src/main/ObjectSpec.cpp b/base/tps/src/main/ObjectSpec.cpp index 2896a85f0..b339fcfa6 100644 --- a/base/tps/src/main/ObjectSpec.cpp +++ b/base/tps/src/main/ObjectSpec.cpp @@ -190,6 +190,7 @@ void ObjectSpec::ParseAttributes(char *objectID, ObjectSpec *ObjectSpec, Buffer case CKA_KEY_TYPE: type = DATATYPE_INTEGER; data = b->substr(curpos+6, 4); + found = 1; /* build by PKCS11 */ break; case CKA_CLASS: @@ -208,6 +209,18 @@ void ObjectSpec::ParseAttributes(char *objectID, ObjectSpec *ObjectSpec, Buffer data = b->substr(curpos+6, 4); /* build by PKCS11 */ break; + + case CKA_EC_PARAMS: + type = DATATYPE_STRING; + data = b->substr(curpos+6, attribute_size); + found = 1; + break; + + case CKA_EC_POINT: + type = DATATYPE_STRING; + data = b->substr(curpos+6, attribute_size); + found = 1; + break; default: RA::Debug("ObjectSpec::ParseKeyBlob", "skipped attribute_id = %lx", diff --git a/base/tps/src/processor/RA_Enroll_Processor.cpp b/base/tps/src/processor/RA_Enroll_Processor.cpp index ba751646e..874720685 100644 --- a/base/tps/src/processor/RA_Enroll_Processor.cpp +++ b/base/tps/src/processor/RA_Enroll_Processor.cpp @@ -184,7 +184,7 @@ RA_Status RA_Enroll_Processor::DoEnrollment(AuthParams *login, RA_Session *sessi const char *cert_attr_id, const char *pri_attr_id, const char *pub_attr_id, - BYTE se_p1, BYTE se_p2, int keysize, const char *connid, const char *keyTypePrefix,char * applet_version) + BYTE se_p1, BYTE se_p2, BYTE algorithm, int keysize, const char *connid, const char *keyTypePrefix,char * applet_version) { RA_Status status = STATUS_NO_ERROR; int rc = -1; @@ -231,6 +231,9 @@ RA_Status RA_Enroll_Processor::DoEnrollment(AuthParams *login, RA_Session *sessi RA::Debug(LL_PER_CONNECTION,FN, "Start of keygen/certificate enrollment"); + bool isECC = RA::isAlgorithmECC(algorithm); + SECKEYECParams *eccParams = NULL; + // get key version for audit logs if (channel != NULL) { if( keyVersion != NULL ) { @@ -288,8 +291,8 @@ RA_Status RA_Enroll_Processor::DoEnrollment(AuthParams *login, RA_Session *sessi (progress_block_size * 15/100) /* progress */, "PROGRESS_KEY_GENERATION"); - if (key_type == KEY_TYPE_ENCRYPTION) {// do serverSide keygen? - + if (key_type == KEY_TYPE_ENCRYPTION) { + // do serverSide keygen? PR_snprintf((char *)configname, 256, "%s.serverKeygen.enable", keyTypePrefix); RA::Debug(LL_PER_CONNECTION,FN, "looking for config %s", configname); @@ -300,57 +303,58 @@ RA_Status RA_Enroll_Processor::DoEnrollment(AuthParams *login, RA_Session *sessi if (serverKeygen) { RA::Debug(LL_PER_CONNECTION,FN, - "Private key is to be generated on server"); + "Private key is to be generated on server"); PR_snprintf((char *)configname, 256, "%s.serverKeygen.drm.conn", keyTypePrefix); RA::Debug(LL_PER_CONNECTION,FN, - "looking for config %s", configname); + "looking for config %s", configname); drmconnid = RA::GetConfigStore()->GetConfigAsString(configname); PR_snprintf((char *)configname, 256, "%s.serverKeygen.archive", keyTypePrefix); bool archive = RA::GetConfigStore()->GetConfigAsBool(configname, true); RA::Debug(LL_PER_CONNECTION,FN, - "calling ServerSideKeyGen with userid =%s, archive=%s", userid, archive? "true":"false"); + "calling ServerSideKeyGen with userid =%s, archive=%s", userid, archive? "true":"false"); RA::ServerSideKeyGen(session, cuid, userid, channel->getDrmWrappedDESKey(), &pKey, &wrappedPrivKey, &ivParam, drmconnid, - archive, keysize); + archive, keysize, isECC); if (pKey == NULL) { - RA::Error(LL_PER_CONNECTION,FN, - "Failed to generate key on server. Please check DRM."); - RA::Debug(LL_PER_CONNECTION,FN, - "ServerSideKeyGen called, pKey is NULL"); - status = STATUS_ERROR_MAC_ENROLL_PDU; + RA::Error(LL_PER_CONNECTION,FN, + "Failed to generate key on server. Please check DRM."); + RA::Debug(LL_PER_CONNECTION,FN, + "ServerSideKeyGen called, pKey is NULL"); + status = STATUS_ERROR_MAC_ENROLL_PDU; PR_snprintf(audit_msg, 512, "ServerSideKeyGen called, failed to generate key on server"); - goto loser; - } else - RA::Debug(LL_PER_CONNECTION,FN, - "key value = %s", pKey); + goto loser; + } else { + RA::Debug(LL_PER_CONNECTION,FN, + "key value = %s", pKey); + } if (wrappedPrivKey == NULL) { - RA::Debug(LL_PER_CONNECTION,FN, - "ServerSideKeyGen called, wrappedPrivKey is NULL"); - status = STATUS_ERROR_MAC_ENROLL_PDU; + RA::Debug(LL_PER_CONNECTION,FN, + "ServerSideKeyGen called, wrappedPrivKey is NULL"); + status = STATUS_ERROR_MAC_ENROLL_PDU; PR_snprintf(audit_msg, 512, "ServerSideKeyGen called, wrappedPrivKey is NULL"); - goto loser; - } else - RA::Debug(LL_PER_CONNECTION,FN, - "wrappedPrivKey = %s", wrappedPrivKey); + goto loser; + } else { + RA::Debug(LL_PER_CONNECTION,FN, + "wrappedPrivKey = %s", wrappedPrivKey); + } if (ivParam == NULL) { - RA::Debug(LL_PER_CONNECTION,FN, - "ServerSideKeyGen called, ivParam is NULL"); - status = STATUS_ERROR_MAC_ENROLL_PDU; + RA::Debug(LL_PER_CONNECTION,FN, + "ServerSideKeyGen called, ivParam is NULL"); + status = STATUS_ERROR_MAC_ENROLL_PDU; PR_snprintf(audit_msg, 512, "ServerSideKeyGen called, ivParam is NULL"); - goto loser; + goto loser; } else - RA::Debug(LL_PER_CONNECTION,FN, - "ivParam = %s", ivParam); + RA::Debug(LL_PER_CONNECTION,FN, "ivParam = %s", ivParam); /* * the following code converts b64-encoded public key info into SECKEYPublicKey @@ -359,39 +363,47 @@ RA_Status RA_Enroll_Processor::DoEnrollment(AuthParams *login, RA_Session *sessi SECItem der; CERTSubjectPublicKeyInfo* spki = NULL; + Buffer *decodePubKey = Util::URLDecode(pKey); + char *pKey_ascii = NULL; + if (decodePubKey != NULL) { + pKey_ascii = + BTOA_DataToAscii(decodePubKey->getBuf(), decodePubKey->size()); + + } else { + PR_snprintf(audit_msg, 512, "ServerSideKeyGen: failed to URL decode public key"); + goto loser; + } + der.type = (SECItemType) 0; /* initialize it, since convertAsciiToItem does not set it */ - rv = ATOB_ConvertAsciiToItem (&der, pKey); + rv = ATOB_ConvertAsciiToItem (&der, pKey_ascii); if (rv != SECSuccess){ - RA::Debug(LL_PER_CONNECTION,FN, - "failed to convert b64 private key to binary"); - SECITEM_FreeItem(&der, PR_FALSE); - status = STATUS_ERROR_MAC_ENROLL_PDU; - PR_snprintf(audit_msg, 512, "ServerSideKeyGen: failed to convert b64 private key to binary"); - goto loser; - }else { - RA::Debug(LL_PER_CONNECTION,FN, - "decoded private key as: secitem (len=%d)",der.len); - - spki = SECKEY_DecodeDERSubjectPublicKeyInfo(&der); - - if (spki != NULL) { - RA::Debug(LL_PER_CONNECTION,FN, - "Successfully decoded DER SubjectPublicKeyInfo structure"); - pk_p = SECKEY_ExtractPublicKey(spki); - if (pk_p != NULL) - RA::Debug(LL_PER_CONNECTION,FN, - "Successfully extracted public key from SPKI structure"); - else - RA::Debug(LL_PER_CONNECTION,FN, - "Failed to extract public key from SPKI"); - } else { - RA::Debug(LL_PER_CONNECTION,FN, - "Failed to decode SPKI structure"); - } + RA::Debug(LL_PER_CONNECTION,FN, + "failed to convert b64 public key to binary"); + SECITEM_FreeItem(&der, PR_FALSE); + status = STATUS_ERROR_MAC_ENROLL_PDU; + PR_snprintf(audit_msg, 512, "ServerSideKeyGen: failed to convert b64 public key to binary"); + goto loser; + } else { + RA::Debug(LL_PER_CONNECTION,FN, + "decoded public key as: secitem (len=%d)",der.len); + + spki = SECKEY_DecodeDERSubjectPublicKeyInfo(&der); + + if (spki != NULL) { + RA::Debug(LL_PER_CONNECTION,FN, + "Successfully decoded DER SubjectPublicKeyInfo structure"); + pk_p = SECKEY_ExtractPublicKey(spki); + if (pk_p != NULL) + RA::Debug(LL_PER_CONNECTION,FN, "Successfully extracted public key from SPKI structure"); + else + RA::Debug(LL_PER_CONNECTION,FN, "Failed to extract public key from SPKI"); + } else { + RA::Debug(LL_PER_CONNECTION,FN, + "Failed to decode SPKI structure"); + } - SECITEM_FreeItem(&der, PR_FALSE); - SECKEY_DestroySubjectPublicKeyInfo(spki); - + SECITEM_FreeItem(&der, PR_FALSE); + SECKEY_DestroySubjectPublicKeyInfo(spki); } } else { //generate keys on token @@ -404,6 +416,11 @@ RA_Status RA_Enroll_Processor::DoEnrollment(AuthParams *login, RA_Session *sessi if(key_check && key_check->size()) alg = 0x81; + + if (isECC) { + alg = algorithm; + } + len = channel->StartEnrollment( se_p1, se_p2, wrapped_challenge, @@ -412,7 +429,7 @@ RA_Status RA_Enroll_Processor::DoEnrollment(AuthParams *login, RA_Session *sessi 0x00 /* option */); RA::Debug(LL_PER_CONNECTION,FN, - "channel->StartEnrollment returned length of public key blob: len=%d", len); + "channel->StartEnrollment returned length of public key blob: len=%d", len); StatusUpdate(session, extensions, start_progress + (index * progress_block_size) + @@ -460,6 +477,8 @@ RA_Status RA_Enroll_Processor::DoEnrollment(AuthParams *login, RA_Session *sessi plaintext_challenge); + // We have received the public key blob for ECC + // send status update to the client StatusUpdate(session, extensions, start_progress + (index * progress_block_size) + @@ -471,7 +490,7 @@ RA_Status RA_Enroll_Processor::DoEnrollment(AuthParams *login, RA_Session *sessi pk_p = certEnroll->ParsePublicKeyBlob( (unsigned char *)(BYTE *)*public_key /*blob*/, - plaintext_challenge); + plaintext_challenge, isECC); if (pk_p == NULL) { RA::Error(LL_PER_CONNECTION,FN, @@ -550,8 +569,10 @@ RA_Status RA_Enroll_Processor::DoEnrollment(AuthParams *login, RA_Session *sessi goto loser; } - si_mod = pk_p->u.rsa.modulus; - modulus = new Buffer((BYTE*) si_mod.data, si_mod.len); + if (!isECC) { + si_mod = pk_p->u.rsa.modulus; + modulus = new Buffer((BYTE*) si_mod.data, si_mod.len); + } /* * RFC 3279 @@ -569,14 +590,14 @@ RA_Status RA_Enroll_Processor::DoEnrollment(AuthParams *login, RA_Session *sessi si_kid = PK11_MakeIDFromPubKey(&spkix->subjectPublicKey); spkix->subjectPublicKey.len <<= 3; - keyid = new Buffer((BYTE*) si_kid->data, si_kid->len); - si_exp = pk_p->u.rsa.publicExponent; - exponent = new Buffer((BYTE*) si_exp.data, si_exp.len); - - RA::Debug(LL_PER_CONNECTION,FN, - "Keyid, modulus and exponent have been extracted from public key"); + if (!isECC) { + si_exp = pk_p->u.rsa.publicExponent; + exponent = new Buffer((BYTE*) si_exp.data, si_exp.len); + RA::Debug(LL_PER_CONNECTION,FN, + "Keyid, modulus and exponent have been extracted from public key"); + } SECKEY_DestroySubjectPublicKeyInfo(spkix); @@ -788,67 +809,77 @@ RA_Status RA_Enroll_Processor::DoEnrollment(AuthParams *login, RA_Session *sessi /* write certificate from CA to netkey */ if (pkcs11obj_enable) { - ObjectSpec *objSpec = - ObjectSpec::ParseFromTokenData( - (cert_id[0] << 24) + - (cert_id[1] << 16), - cert); - pkcs_objx->AddObjectSpec(objSpec); + ObjectSpec *objSpec = + ObjectSpec::ParseFromTokenData( + (cert_id[0] << 24) + + (cert_id[1] << 16), + cert); + pkcs_objx->AddObjectSpec(objSpec); } else { - RA::Debug(LL_PER_CONNECTION,FN, - "About to create certificate object on token"); - rc = channel->CreateCertificate(cert_id, cert); - if (rc == -1) { - RA::Error(LL_PER_CONNECTION,FN, - "Failed to create certificate object on token"); - status = STATUS_ERROR_MAC_ENROLL_PDU; - PR_snprintf(audit_msg, 512, "Failed to create certificate object on token"); - goto loser; - } + RA::Debug(LL_PER_CONNECTION,FN, + "About to create certificate object on token"); + rc = channel->CreateCertificate(cert_id, cert); + if (rc == -1) { + RA::Error(LL_PER_CONNECTION,FN, + "Failed to create certificate object on token"); + status = STATUS_ERROR_MAC_ENROLL_PDU; + PR_snprintf(audit_msg, 512, "Failed to create certificate object on token"); + goto loser; + } } // build label PR_snprintf((char *)configname, 256, "%s.%s.keyGen.%s.label", - OP_PREFIX, tokenType, keyType); + OP_PREFIX, tokenType, keyType); RA::Debug(LL_PER_CONNECTION,FN, - "label '%s'", configname); + "label '%s'", configname); pattern = RA::GetConfigStore()->GetConfigAsString(configname); label = MapPattern(&nv, (char *) pattern); if (pkcs11obj_enable) { - Buffer b = channel->CreatePKCS11CertAttrsBuffer( - key_type, cert_attr_id, label, keyid); - ObjectSpec *objSpec = - ObjectSpec::ParseFromTokenData( - (cert_attr_id[0] << 24) + - (cert_attr_id[1] << 16), - &b); - pkcs_objx->AddObjectSpec(objSpec); + Buffer b = channel->CreatePKCS11CertAttrsBuffer( + key_type, cert_attr_id, label, keyid); + ObjectSpec *objSpec = + ObjectSpec::ParseFromTokenData( + (cert_attr_id[0] << 24) + + (cert_attr_id[1] << 16), + &b); + pkcs_objx->AddObjectSpec(objSpec); } else { - RA::Debug(LL_PER_CONNECTION,FN, - "About to create PKCS#11 certificate Attributes"); - rc = channel->CreatePKCS11CertAttrs(key_type, cert_attr_id, label, keyid); - if (rc == -1) { - RA::Error(LL_PER_CONNECTION,FN, - "PKCS11 Certificate attributes creation failed"); - status = STATUS_ERROR_MAC_ENROLL_PDU; + RA::Debug(LL_PER_CONNECTION,FN, + "About to create PKCS#11 certificate Attributes"); + rc = channel->CreatePKCS11CertAttrs(key_type, cert_attr_id, label, keyid); + if (rc == -1) { + RA::Error(LL_PER_CONNECTION,FN, + "PKCS11 Certificate attributes creation failed"); + status = STATUS_ERROR_MAC_ENROLL_PDU; PR_snprintf(audit_msg, 512, "PKCS11 Certificate attributes creation failed"); - goto loser; - } + goto loser; + } } if (pkcs11obj_enable) { - RA::Debug(LL_PER_CONNECTION,FN, - "Create PKCS11 Private Key Attributes Buffer"); - Buffer b = channel->CreatePKCS11PriKeyAttrsBuffer(key_type, - pri_attr_id, label, keyid, modulus, OP_PREFIX, - tokenType, keyTypePrefix); - ObjectSpec *objSpec = - ObjectSpec::ParseFromTokenData( - (pri_attr_id[0] << 24) + - (pri_attr_id[1] << 16), - &b); - pkcs_objx->AddObjectSpec(objSpec); + RA::Debug(LL_PER_CONNECTION,FN, + "Create PKCS11 Private Key Attributes Buffer"); + + Buffer b; + if (!isECC) { + b = channel->CreatePKCS11PriKeyAttrsBuffer(key_type, + pri_attr_id, label, keyid, modulus, OP_PREFIX, + tokenType, keyTypePrefix); + + } else { //isECC + eccParams = &pk_p->u.ec.DEREncodedParams; + b = channel->CreatePKCS11ECCPriKeyAttrsBuffer(key_type, + pri_attr_id, label, keyid, eccParams, OP_PREFIX, + tokenType, keyTypePrefix); + } + ObjectSpec *objSpec = + ObjectSpec::ParseFromTokenData( + (pri_attr_id[0] << 24) + + (pri_attr_id[1] << 16), + &b); + pkcs_objx->AddObjectSpec(objSpec); } else { RA::Debug(LL_PER_CONNECTION,FN, "Create PKCS11 Private Key Attributes"); @@ -863,27 +894,34 @@ RA_Status RA_Enroll_Processor::DoEnrollment(AuthParams *login, RA_Session *sessi } if (pkcs11obj_enable) { - Buffer b = channel->CreatePKCS11PubKeyAttrsBuffer(key_type, - pub_attr_id, label, keyid, - exponent, modulus, OP_PREFIX, tokenType, keyTypePrefix); - ObjectSpec *objSpec = - ObjectSpec::ParseFromTokenData( - (pub_attr_id[0] << 24) + - (pub_attr_id[1] << 16), - &b); - pkcs_objx->AddObjectSpec(objSpec); + Buffer b; + if (!isECC) { + b = channel->CreatePKCS11PubKeyAttrsBuffer(key_type, + pub_attr_id, label, keyid, + exponent, modulus, OP_PREFIX, tokenType, keyTypePrefix); + } else { + b = channel->CreatePKCS11ECCPubKeyAttrsBuffer(key_type, + pub_attr_id, label, keyid,&pk_p->u.ec, eccParams, + OP_PREFIX, tokenType, keyTypePrefix); + } + ObjectSpec *objSpec = + ObjectSpec::ParseFromTokenData( + (pub_attr_id[0] << 24) + + (pub_attr_id[1] << 16), + &b); + pkcs_objx->AddObjectSpec(objSpec); } else { - RA::Debug(LL_PER_CONNECTION,FN, - "Create PKCS11 Public Key Attributes"); - rc = channel->CreatePKCS11PubKeyAttrs(key_type, pub_attr_id, label, keyid, + RA::Debug(LL_PER_CONNECTION,FN, + "Create PKCS11 Public Key Attributes"); + rc = channel->CreatePKCS11PubKeyAttrs(key_type, pub_attr_id, label, keyid, exponent, modulus, OP_PREFIX, tokenType, keyTypePrefix); - if (rc == -1) { - RA::Error(LL_PER_CONNECTION,FN, - "PKCS11 public key attributes creation failed"); - status = STATUS_ERROR_MAC_ENROLL_PDU; + if (rc == -1) { + RA::Error(LL_PER_CONNECTION,FN, + "PKCS11 public key attributes creation failed"); + status = STATUS_ERROR_MAC_ENROLL_PDU; PR_snprintf(audit_msg, 512, "PKCS11 public key attributes creation failed"); - goto loser; - } + goto loser; + } } RA::Debug(LL_PER_CONNECTION,FN, "End of keygen/certificate enrollment"); @@ -983,10 +1021,13 @@ loser: } if (pk_p != NULL) { if (serverKeygen) { + RA::Debug(LL_PER_CONNECTION,FN,"DoEnrollment about to call SECKEY_DestroyPublicKey on pk_p"); SECKEY_DestroyPublicKey(pk_p); } else { + RA::Debug(LL_PER_CONNECTION,FN,"DoEnrollment about to call free on pk_p"); free(pk_p); } + pk_p = NULL; } return status; @@ -3063,6 +3104,11 @@ bool RA_Enroll_Processor::GenerateCertificate(AuthParams *login, int keyTypeNum, PR_snprintf((char *)configname, 256, "%s.keySize", keyTypePrefix); int keySize = RA::GetConfigStore()->GetConfigAsInt(configname, 1024); + + PR_snprintf((char *)configname, 256, "%s.alg", keyTypePrefix); + //Default RSA_CRT=2 + BYTE algorithm = (BYTE) RA::GetConfigStore()->GetConfigAsInt(configname, 2); + PR_snprintf((char *)configname, 256, "%s.publisherId", keyTypePrefix); const char *publisherId = RA::GetConfigStore()->GetConfigAsString(configname, NULL); @@ -3113,7 +3159,7 @@ bool RA_Enroll_Processor::GenerateCertificate(AuthParams *login, int keyTypeNum, msn, khex, (TokenKeyType)keyTypeEnum, profileId, userid, certId,publisherId, certAttrId, priKeyAttrId, pubKeyAttrId, (keyUser << 4)+priKeyNumber, - (keyUsage << 4)+pubKeyNumber, keySize, caconnid, keyTypePrefix,(char *)final_applet_version); + (keyUsage << 4)+pubKeyNumber, algorithm, keySize, caconnid, keyTypePrefix,(char *)final_applet_version); if (o_status != STATUS_NO_ERROR) { r = false; |