diff options
author | cfu <cfu@c9f7a03b-bd48-0410-a16d-cbbf54688b0b> | 2011-10-21 16:52:03 +0000 |
---|---|---|
committer | cfu <cfu@c9f7a03b-bd48-0410-a16d-cbbf54688b0b> | 2011-10-21 16:52:03 +0000 |
commit | 93a2f2630e5c10b3e1744df4daf8f0291203b17b (patch) | |
tree | 2f003e11d822cbe3420bf9faa8b41498e8063135 /pki/base/kra | |
parent | 47995409e791ce27c142586fe85b3a42d0e58721 (diff) | |
download | pki-93a2f2630e5c10b3e1744df4daf8f0291203b17b.tar.gz pki-93a2f2630e5c10b3e1744df4daf8f0291203b17b.tar.xz pki-93a2f2630e5c10b3e1744df4daf8f0291203b17b.zip |
Bug 737122 - DRM: during archiving and recovering, wrapping unwrapping keys should be done in the token
git-svn-id: svn+ssh://svn.fedorahosted.org/svn/pki/trunk@2273 c9f7a03b-bd48-0410-a16d-cbbf54688b0b
Diffstat (limited to 'pki/base/kra')
3 files changed, 266 insertions, 42 deletions
diff --git a/pki/base/kra/src/com/netscape/kra/EncryptionUnit.java b/pki/base/kra/src/com/netscape/kra/EncryptionUnit.java index 0fc5ff610..422eb3a35 100644 --- a/pki/base/kra/src/com/netscape/kra/EncryptionUnit.java +++ b/pki/base/kra/src/com/netscape/kra/EncryptionUnit.java @@ -147,6 +147,10 @@ public abstract class EncryptionUnit implements IEncryptionUnit { CMS.getLogger().log(ILogger.EV_SYSTEM, null, ILogger.S_KRA, ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_KRA_ENCRYPTION_INTERNAL", e.toString())); Debug.trace("EncryptionUnit::encryptInternalPrivate " + e.toString()); return null; + } catch (Exception e) { + CMS.getLogger().log(ILogger.EV_SYSTEM, null, ILogger.S_KRA, ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_KRA_ENCRYPTION_INTERNAL", e.toString())); + Debug.trace("EncryptionUnit::encryptInternalPrivate " + e.toString()); + return null; } } @@ -158,31 +162,27 @@ public abstract class EncryptionUnit implements IEncryptionUnit { CMS.debug("EncryptionUnit.wrap"); CryptoToken token = getToken(); - CryptoToken internalToken = getInternalToken(); // (1) generate session key org.mozilla.jss.crypto.KeyGenerator kg = token.getKeyGenerator(KeyGenAlgorithm.DES3); // internalToken.getKeyGenerator(KeyGenAlgorithm.DES3); - SymmetricKey.Usage usages[] = new SymmetricKey.Usage[3]; - usages[0] = SymmetricKey.Usage.ENCRYPT; - usages[1] = SymmetricKey.Usage.WRAP; - usages[2] = SymmetricKey.Usage.UNWRAP; + SymmetricKey.Usage usages[] = new SymmetricKey.Usage[2]; + usages[0] = SymmetricKey.Usage.WRAP; + usages[1] = SymmetricKey.Usage.UNWRAP; kg.setKeyUsages(usages); kg.temporaryKeys(true); SymmetricKey sk = kg.generate(); - CMS.debug("EncryptionUnit:wrap() session key generated on slot: "+token.getName()); + CMS.debug("EncryptionUnit:wrap() session key generated on slot: "+token.getName()); // (2) wrap private key with session key // KeyWrapper wrapper = internalToken.getKeyWrapper( KeyWrapper wrapper = token.getKeyWrapper( KeyWrapAlgorithm.DES3_CBC_PAD); - CMS.debug("EncryptionUnit:wrap() got key wrapper"); wrapper.initWrap(sk, IV); - CMS.debug("EncryptionUnit:wrap() key wrapper initialized"); byte pri[] = wrapper.wrap(priKey); - CMS.debug("EncryptionUnit:wrap() privKey wrapped"); + CMS.debug("EncryptionUnit:wrap() privKey wrapped"); // (3) wrap session with transport public KeyWrapper rsaWrap = token.getKeyWrapper( @@ -190,7 +190,7 @@ public abstract class EncryptionUnit implements IEncryptionUnit { rsaWrap.initWrap(getPublicKey(), null); byte session[] = rsaWrap.wrap(sk); - CMS.debug("EncryptionUnit:wrap() sessin key wrapped"); + CMS.debug("EncryptionUnit:wrap() sessin key wrapped"); // use MY own structure for now: // SEQUENCE { @@ -230,6 +230,10 @@ public abstract class EncryptionUnit implements IEncryptionUnit { CMS.getLogger().log(ILogger.EV_SYSTEM, null, ILogger.S_KRA, ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_KRA_ENCRYPTION_WRAP", e.toString())); Debug.trace("EncryptionUnit::wrap " + e.toString()); return null; + } catch (Exception e) { + CMS.getLogger().log(ILogger.EV_SYSTEM, null, ILogger.S_KRA, ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_KRA_ENCRYPTION_WRAP", e.toString())); + Debug.trace("EncryptionUnit::wrap " + e.toString()); + return null; } } @@ -241,13 +245,11 @@ public abstract class EncryptionUnit implements IEncryptionUnit { { try { CryptoToken token = getToken(); - CryptoToken internalToken = getInternalToken(); // (1) unwrap the session - CMS.debug("EncryptionUnit::unwrap_sym() on slot: "+token.getName()); PrivateKey priKey = getPrivateKey(); String priKeyAlgo = priKey.getAlgorithm(); - CMS.debug("EncryptionUnit::unwrap_sym() private key algo: " + priKeyAlgo); + CMS.debug("EncryptionUnit::unwrap_sym() private key algo: " + priKeyAlgo); KeyWrapper keyWrapper = null; if (priKeyAlgo.equals("EC")) { keyWrapper = token.getKeyWrapper(KeyWrapAlgorithm.AES_ECB); @@ -259,6 +261,8 @@ public abstract class EncryptionUnit implements IEncryptionUnit { SymmetricKey sk = keyWrapper.unwrapSymmetric(encSymmKey, SymmetricKey.DES3, usage, 0); + CMS.debug("EncryptionUnit::unwrap_sym() unwrapped on slot: " + +token.getName()); return sk; } catch (Exception e) { CMS.debug("EncryptionUnit::unwrap_sym() error:" + @@ -288,7 +292,6 @@ public abstract class EncryptionUnit implements IEncryptionUnit { CMS.debug("EncryptionUnit.decryptExternalPrivate"); CryptoToken token = getToken(); - CryptoToken internalToken = getInternalToken(); // (1) unwrap the session KeyWrapper rsaWrap = token.getKeyWrapper( @@ -331,6 +334,10 @@ public abstract class EncryptionUnit implements IEncryptionUnit { CMS.getLogger().log(ILogger.EV_SYSTEM, null, ILogger.S_KRA, ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_KRA_ENCRYPTION_EXTERNAL", e.toString())); Debug.trace("EncryptionUnit::decryptExternalPrivate " + e.toString()); return null; + } catch (Exception e) { + CMS.getLogger().log(ILogger.EV_SYSTEM, null, ILogger.S_KRA, ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_KRA_ENCRYPTION_EXTERNAL", e.toString())); + Debug.trace("EncryptionUnit::decryptExternalPrivate " + e.toString()); + return null; } } @@ -340,13 +347,11 @@ public abstract class EncryptionUnit implements IEncryptionUnit { */ public PrivateKey unwrap(byte encSymmKey[], String symmAlgOID, byte symmAlgParams[], - byte encValue[], PublicKey pubKey) + byte encValue[], PublicKey pubKey) throws EBaseException { try { CryptoToken token = getToken(); - CryptoToken internalToken = getInternalToken(); - CMS.debug("EncryptionUnit.unwrap symAlgParams: " + new String(symmAlgParams)); // (1) unwrap the session KeyWrapper rsaWrap = token.getKeyWrapper( KeyWrapAlgorithm.RSA); @@ -363,8 +368,18 @@ public abstract class EncryptionUnit implements IEncryptionUnit { wrapper.initUnwrap(sk, new IVParameterSpec( symmAlgParams)); - PrivateKey pk = wrapper.unwrapPrivate(encValue, - PrivateKey.RSA, pubKey); + + PrivateKey.Type keytype = null; + String alg = pubKey.getAlgorithm(); + if (alg.equals("DSA")) { + keytype = PrivateKey.DSA; + } else if (alg.equals("EC")) { + keytype = PrivateKey.EC; + } else { + keytype = PrivateKey.RSA; + } + PrivateKey pk = wrapper.unwrapTemporaryPrivate(encValue, + keytype , pubKey); return pk; } catch (TokenException e) { @@ -383,6 +398,9 @@ public abstract class EncryptionUnit implements IEncryptionUnit { CMS.getLogger().log(ILogger.EV_SYSTEM, null, ILogger.S_KRA, ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_KRA_ENCRYPTION_UNWRAP", e.toString())); Debug.trace("EncryptionUnit::unwrap " + e.toString()); return null; + } catch (Exception e) { + CMS.debug("EncryptionUnit.unwrap : Exception:"+e.toString()); + return null; } } @@ -399,10 +417,9 @@ public abstract class EncryptionUnit implements IEncryptionUnit { byte pri[] = dPri.getOctetString(); CryptoToken token = getToken(); - CryptoToken internalToken = getInternalToken(); // (1) unwrap the session - CMS.debug("decryptInternalPrivate(): getting key wrapper on slot:"+ token.getName()); + CMS.debug("decryptInternalPrivate(): getting key wrapper on slot:"+ token.getName()); KeyWrapper rsaWrap = token.getKeyWrapper( KeyWrapAlgorithm.RSA); @@ -444,6 +461,10 @@ public abstract class EncryptionUnit implements IEncryptionUnit { CMS.getLogger().log(ILogger.EV_SYSTEM, null, ILogger.S_KRA, ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_KRA_ENCRYPTION_DECRYPT", e.toString())); Debug.trace("EncryptionUnit::decryptInternalPrivate " + e.toString()); return null; + } catch (Exception e) { + CMS.getLogger().log(ILogger.EV_SYSTEM, null, ILogger.S_KRA, ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_KRA_ENCRYPTION_DECRYPT", e.toString())); + Debug.trace("EncryptionUnit::decryptInternalPrivate " + e.toString()); + return null; } } diff --git a/pki/base/kra/src/com/netscape/kra/EnrollmentService.java b/pki/base/kra/src/com/netscape/kra/EnrollmentService.java index 239cfef0d..2dfc188d2 100644 --- a/pki/base/kra/src/com/netscape/kra/EnrollmentService.java +++ b/pki/base/kra/src/com/netscape/kra/EnrollmentService.java @@ -20,6 +20,7 @@ package com.netscape.kra; import java.util.StringTokenizer; import java.util.Vector; +import java.util.Arrays; import java.io.IOException; import java.io.ByteArrayInputStream; import java.math.BigInteger; @@ -31,6 +32,7 @@ import java.security.cert.CertificateException; import netscape.security.util.*; import netscape.security.util.BigInt; import netscape.security.x509.*; +import org.mozilla.jss.CryptoManager; import org.mozilla.jss.asn1.*; import org.mozilla.jss.pkix.cms.*; import org.mozilla.jss.pkix.cms.EnvelopedData; @@ -69,7 +71,8 @@ import com.netscape.certsrv.apps.CMS; * in the internal database for long term storage. * <P> * - * @author thomask + * @author thomask (original) + * @author cfu (non-RSA keys; private keys secure handling); * @version $Revision$, $Date$ */ public class EnrollmentService implements IService { diff --git a/pki/base/kra/src/com/netscape/kra/RecoveryService.java b/pki/base/kra/src/com/netscape/kra/RecoveryService.java index 7f6137ffd..5e0c77e25 100644 --- a/pki/base/kra/src/com/netscape/kra/RecoveryService.java +++ b/pki/base/kra/src/com/netscape/kra/RecoveryService.java @@ -50,7 +50,9 @@ import org.mozilla.jss.asn1.*; import org.mozilla.jss.crypto.PBEAlgorithm; import org.mozilla.jss.pkcs12.*; import org.mozilla.jss.pkix.primitive.*; - +import org.mozilla.jss.pkcs11.PK11RSAPublicKey; +import org.mozilla.jss.crypto.PrivateKey; +import org.mozilla.jss.crypto.CryptoToken; /** * A class represents recovery request processor. There @@ -63,7 +65,8 @@ import org.mozilla.jss.pkix.primitive.*; * End Entity recovery will send RA or CA a response where * stores the recovered key. * - * @author thomask + * @author thomask (original) + * @author cfu (non-RSA keys; private keys secure handling); * @version $Revision$, $Date$ */ public class RecoveryService implements IService { @@ -113,6 +116,23 @@ public class RecoveryService implements IService { */ public boolean serviceRequest(IRequest request) throws EBaseException { + CryptoManager cm = null; + IConfigStore config = null; + String tokName = ""; + CryptoToken ct = null; + Boolean allowEncDecrypt_recovery = false; + + try { + cm = CryptoManager.getInstance(); + config = CMS.getConfigStore(); + tokName = config.getString("kra.storageUnit.hardware", "internal"); + CMS.debug("RecoveryService: tokenName="+tokName); + ct = cm.getTokenByName(tokName); + allowEncDecrypt_recovery = config.getBoolean("kra.allowEncDecrypt.recovery", false); + } catch (Exception e) { + throw new EBaseException(CMS.getUserMessage("CMS_BASE_CERT_ERROR", e.toString())); + } + IStatsSubsystem statsSub = (IStatsSubsystem)CMS.getSubsystem("stats"); if (statsSub != null) { statsSub.startTiming("recovery", true /* main action */); @@ -164,6 +184,13 @@ public class RecoveryService implements IService { } } + boolean isRSA = true; + String keyAlg = x509cert.getPublicKey().getAlgorithm(); + if (keyAlg != null) { + CMS.debug("RecoveryService: publicKey alg ="+keyAlg); + if (!keyAlg.equals("RSA")) isRSA = false; + } + // Unwrap the archived private key byte privateKeyData[] = null; X509Certificate transportCert = @@ -173,28 +200,41 @@ public class RecoveryService implements IService { if (statsSub != null) { statsSub.startTiming("recover_key"); } - privateKeyData = recoverKey(params, keyRecord); + + PrivateKey privKey = null; + if (allowEncDecrypt_recovery == true) { + privateKeyData = recoverKey(params, keyRecord); + } else { + privKey= recoverKey(params, keyRecord, isRSA); + } if (statsSub != null) { statsSub.endTiming("recover_key"); } - if (statsSub != null) { - statsSub.startTiming("verify_key"); - } - if (verifyKeyPair(pubData, privateKeyData) == false) { - mKRA.log(ILogger.LL_FAILURE, - CMS.getLogMessage("CMSCORE_KRA_PUBLIC_NOT_FOUND")); - throw new EKRAException( - CMS.getUserMessage("CMS_KRA_INVALID_PUBLIC_KEY")); - } - if (statsSub != null) { - statsSub.endTiming("verify_key"); + if ((isRSA == true) && (allowEncDecrypt_recovery == true)) { + if (statsSub != null) { + statsSub.startTiming("verify_key"); + } + // verifyKeyPair() is RSA-centric + if (verifyKeyPair(pubData, privateKeyData) == false) { + mKRA.log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSCORE_KRA_PUBLIC_NOT_FOUND")); + throw new EKRAException( + CMS.getUserMessage("CMS_KRA_INVALID_PUBLIC_KEY")); + } + if (statsSub != null) { + statsSub.endTiming("verify_key"); + } } if (statsSub != null) { statsSub.startTiming("create_p12"); } - createPFX(request, params, privateKeyData); + if (allowEncDecrypt_recovery == true) { + createPFX(request, params, privateKeyData); + } else { + createPFX(request, params, privKey, ct); + } if (statsSub != null) { statsSub.endTiming("create_p12"); } @@ -260,6 +300,9 @@ public class RecoveryService implements IService { return true; } + /* + * verifyKeyPair()- RSA-centric key verification + */ public boolean verifyKeyPair(byte publicKeyData[], byte privateKeyData[]) { try { @@ -299,9 +342,166 @@ public class RecoveryService implements IService { return false; } } + + /** + * Recovers key. (using unwrapping/wrapping on token) + * - used when allowEncDecrypt_recovery is false + */ + public synchronized PrivateKey recoverKey(Hashtable request, KeyRecord keyRecord, boolean isRSA) + throws EBaseException { + + if (!isRSA) { + CMS.debug("RecoverService: recoverKey: currently, non-RSA keys are not supported when allowEncDecrypt_ is false"); + throw new EKRAException(CMS.getUserMessage("CMS_KRA_RECOVERY_FAILED_1", "key type not supported")); + } + try { + if (CMS.getConfigStore().getBoolean("kra.keySplitting")) { + Credential creds[] = (Credential[]) + request.get(ATTR_AGENT_CREDENTIALS); + + mStorageUnit.login(creds); + } + + /* wrapped retrieve session key and private key */ + DerValue val = new DerValue(keyRecord.getPrivateKeyData()); + DerInputStream in = val.data; + DerValue dSession = in.getDerValue(); + byte session[] = dSession.getOctetString(); + DerValue dPri = in.getDerValue(); + byte pri[] = dPri.getOctetString(); + + /* debug */ + byte publicKeyData[] = keyRecord.getPublicKeyData(); + PublicKey pubkey = null; + try { + pubkey = X509Key.parsePublicKey (new DerValue(publicKeyData)); + } catch (Exception e) { + CMS.debug("RecoverService: after parsePublicKey:"+e.toString()); + throw new EKRAException(CMS.getUserMessage("CMS_KRA_RECOVERY_FAILED_1", "pubic key parsing failure")); + } + byte iv[] = {0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1}; + PrivateKey privKey = + mStorageUnit.unwrap( + session, + keyRecord.getAlgorithm(), + iv, + pri, + (PublicKey) pubkey); + + if (privKey == null) { + mKRA.log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_KRA_PRIVATE_KEY_NOT_FOUND")); + throw new EKRAException(CMS.getUserMessage("CMS_KRA_RECOVERY_FAILED_1", "private key unwrapping failure")); + } + if (CMS.getConfigStore().getBoolean("kra.keySplitting")) { + mStorageUnit.logout(); + } + return privKey; + } catch (Exception e) { + CMS.debug("RecoverService: recoverKey() failed with allowEncDecrypt_recovery=false:"+e.toString()); + throw new EKRAException(CMS.getUserMessage("CMS_KRA_RECOVERY_FAILED_1", "recoverKey() failed with allowEncDecrypt_recovery=false:"+e.toString())); + } + } + + + /** + * Creates a PFX (PKCS12) file. (the unwrapping/wrapping way) + * - used when allowEncDecrypt_recovery is false + * + * @param request CRMF recovery request + * @param priKey private key handle + * @exception EBaseException failed to create P12 file + */ + public void createPFX(IRequest request, Hashtable params, + PrivateKey priKey, CryptoToken ct) throws EBaseException { + try { + // create p12 + X509Certificate x509cert = + request.getExtDataInCert(ATTR_USER_CERT); + String pwd = (String) params.get(ATTR_TRANSPORT_PWD); + + // add certificate + mKRA.log(ILogger.LL_INFO, "KRA adds certificate to P12"); + SEQUENCE encSafeContents = new SEQUENCE(); + ASN1Value cert = new OCTET_STRING(x509cert.getEncoded()); + String nickname = request.getExtDataInString(ATTR_NICKNAME); + + if (nickname == null) { + nickname = x509cert.getSubjectDN().toString(); + } + byte localKeyId[] = createLocalKeyId(x509cert); + SET certAttrs = createBagAttrs( + nickname, localKeyId); + // attributes: user friendly name, Local Key ID + SafeBag certBag = new SafeBag(SafeBag.CERT_BAG, + new CertBag(CertBag.X509_CERT_TYPE, cert), + certAttrs); + + encSafeContents.addElement(certBag); + + // add key + mKRA.log(ILogger.LL_INFO, "KRA adds key to P12"); + org.mozilla.jss.util.Password pass = new + org.mozilla.jss.util.Password( + pwd.toCharArray()); + + SEQUENCE safeContents = new SEQUENCE(); + PasswordConverter passConverter = new + PasswordConverter(); + byte salt[] = {0x01, 0x01, 0x01, 0x01}; + + ASN1Value key = EncryptedPrivateKeyInfo.createPBE( + PBEAlgorithm.PBE_SHA1_DES3_CBC, + pass, salt, 1, passConverter, priKey, ct); + + SET keyAttrs = createBagAttrs( + x509cert.getSubjectDN().toString(), + localKeyId); + + SafeBag keyBag = new SafeBag( + SafeBag.PKCS8_SHROUDED_KEY_BAG, key, + keyAttrs); // ?? + + safeContents.addElement(keyBag); + + // build contents + AuthenticatedSafes authSafes = new + AuthenticatedSafes(); + + authSafes.addSafeContents( + safeContents + ); + authSafes.addSafeContents( + encSafeContents + ); + + // authSafes.addEncryptedSafeContents( + // authSafes.DEFAULT_KEY_GEN_ALG, + // pass, null, 1, + // encSafeContents); + PFX pfx = new PFX(authSafes); + + pfx.computeMacData(pass, null, 5); // ?? + ByteArrayOutputStream fos = new + ByteArrayOutputStream(); + + pfx.encode(fos); + pass.clear(); + + // put final PKCS12 into volatile request + params.put(ATTR_PKCS12, fos.toByteArray()); + } catch (Exception e) { + mKRA.log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_KRA_CONSTRUCT_P12", e.toString())); + throw new EKRAException(CMS.getUserMessage("CMS_KRA_PKCS12_FAILED_1", e.toString())); + } + + // update request + mKRA.getRequestQueue().updateRequest(request); + } + /** * Recovers key. + * - used when allowEncDecrypt_recovery is true */ public synchronized byte[] recoverKey(Hashtable request, KeyRecord keyRecord) throws EBaseException { @@ -328,6 +528,7 @@ public class RecoveryService implements IService { /** * Creates a PFX (PKCS12) file. + * - used when allowEncDecrypt_recovery is true * * @param request CRMF recovery request * @param priData decrypted private key (PrivateKeyInfo) @@ -335,12 +536,11 @@ public class RecoveryService implements IService { */ public void createPFX(IRequest request, Hashtable params, byte priData[]) throws EBaseException { - // create p12 - X509Certificate x509cert = - request.getExtDataInCert(ATTR_USER_CERT); - String pwd = (String) params.get(ATTR_TRANSPORT_PWD); - try { + // create p12 + X509Certificate x509cert = + request.getExtDataInCert(ATTR_USER_CERT); + String pwd = (String) params.get(ATTR_TRANSPORT_PWD); // add certificate mKRA.log(ILogger.LL_INFO, "KRA adds certificate to P12"); |