diff options
Diffstat (limited to 'pki/base/kra/src')
6 files changed, 965 insertions, 219 deletions
diff --git a/pki/base/kra/src/com/netscape/kra/ArchiveOptions.java b/pki/base/kra/src/com/netscape/kra/ArchiveOptions.java new file mode 100644 index 000000000..c4650f17e --- /dev/null +++ b/pki/base/kra/src/com/netscape/kra/ArchiveOptions.java @@ -0,0 +1,154 @@ +// --- BEGIN COPYRIGHT BLOCK --- +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; version 2 of the License. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// (C) 2007 Red Hat, Inc. +// All rights reserved. +// --- END COPYRIGHT BLOCK --- +package com.netscape.kra; + +import java.io.ByteArrayInputStream; +import java.io.IOException; + +import org.mozilla.jss.asn1.ANY; +import org.mozilla.jss.asn1.BIT_STRING; +import org.mozilla.jss.asn1.InvalidBERException; +import org.mozilla.jss.asn1.OCTET_STRING; +import org.mozilla.jss.asn1.SET; +import org.mozilla.jss.pkix.cms.EncryptedContentInfo; +import org.mozilla.jss.pkix.cms.EnvelopedData; +import org.mozilla.jss.pkix.cms.RecipientInfo; +import org.mozilla.jss.pkix.crmf.EncryptedKey; +import org.mozilla.jss.pkix.crmf.EncryptedValue; +import org.mozilla.jss.pkix.crmf.PKIArchiveOptions; +import org.mozilla.jss.pkix.primitive.AlgorithmIdentifier; + +import com.netscape.certsrv.apps.CMS; +import com.netscape.certsrv.base.EBaseException; + +class ArchiveOptions { + private String mSymmAlgOID = null; + private byte mSymmAlgParams[] = null; + private byte mEncSymmKey[] = null; + private byte mEncValue[] = null; + + public ArchiveOptions(PKIArchiveOptions opts) throws EBaseException { + try { + EncryptedKey key = opts.getEncryptedKey(); + ANY enveloped_val = null; + EncryptedValue val = null; + AlgorithmIdentifier symmAlg = null; + + if (key.getType() == org.mozilla.jss.pkix.crmf.EncryptedKey.ENVELOPED_DATA) { + CMS.debug("EnrollService: ArchiveOptions() EncryptedKey type= ENVELOPED_DATA"); + // this is the new RFC4211 EncryptedKey that should + // have EnvelopedData to replace the deprecated EncryptedValue + enveloped_val = key.getEnvelopedData(); + byte[] env_b = enveloped_val.getEncoded(); + EnvelopedData.Template env_template = new EnvelopedData.Template(); + EnvelopedData env_data = + (EnvelopedData) env_template.decode(new ByteArrayInputStream(env_b)); + EncryptedContentInfo eCI = env_data.getEncryptedContentInfo(); + symmAlg = eCI.getContentEncryptionAlgorithm(); + mSymmAlgOID = symmAlg.getOID().toString(); + mSymmAlgParams = + ((OCTET_STRING) ((ANY) symmAlg.getParameters()).decodeWith(OCTET_STRING.getTemplate())) + .toByteArray(); + + SET recipients = env_data.getRecipientInfos(); + if (recipients.size() <= 0) { + CMS.debug("EnrollService: ArchiveOptions() - missing recipient information "); + throw new EBaseException(CMS.getUserMessage("CMS_BASE_INVALID_ATTRIBUTE", + "[PKIArchiveOptions] missing recipient information ")); + } + //check recpient - later + //we only handle one recipient here anyways. so, either the key + //can be decrypted or it can't. No risk here. + RecipientInfo ri = (RecipientInfo) recipients.elementAt(0); + OCTET_STRING key_o = ri.getEncryptedKey(); + mEncSymmKey = key_o.toByteArray(); + + OCTET_STRING oString = eCI.getEncryptedContent(); + BIT_STRING encVal = new BIT_STRING(oString.toByteArray(), 0); + mEncValue = encVal.getBits(); + CMS.debug("EnrollService: ArchiveOptions() EncryptedKey type= ENVELOPED_DATA done"); + } else if (key.getType() == org.mozilla.jss.pkix.crmf.EncryptedKey.ENCRYPTED_VALUE) { + CMS.debug("EnrollService: ArchiveOptions() EncryptedKey type= ENCRYPTED_VALUE"); + // this is deprecated: EncryptedValue + val = key.getEncryptedValue(); + symmAlg = val.getSymmAlg(); + mSymmAlgOID = symmAlg.getOID().toString(); + mSymmAlgParams = + ((OCTET_STRING) ((ANY) symmAlg.getParameters()).decodeWith(OCTET_STRING.getTemplate())) + .toByteArray(); + BIT_STRING encSymmKey = val.getEncSymmKey(); + + mEncSymmKey = encSymmKey.getBits(); + BIT_STRING encVal = val.getEncValue(); + + mEncValue = encVal.getBits(); + CMS.debug("EnrollService: ArchiveOptions() EncryptedKey type= ENCRYPTED_VALUE done"); + } else { + CMS.debug("EnrollService: ArchiveOptions() invalid EncryptedKey type"); + throw new EBaseException(CMS.getUserMessage("CMS_BASE_INVALID_ATTRIBUTE", "[PKIArchiveOptions] type " + + key.getType())); + } + + } catch (InvalidBERException e) { + CMS.debug("EnrollService: ArchiveOptions(): " + e.toString()); + throw new EBaseException(CMS.getUserMessage("CMS_BASE_INVALID_ATTRIBUTE", + "[PKIArchiveOptions]" + e.toString())); + } catch (IOException e) { + CMS.debug("EnrollService: ArchiveOptions(): " + e.toString()); + throw new EBaseException("ArchiveOptions() exception caught: " + + e.toString()); + } catch (Exception e) { + CMS.debug("EnrollService: ArchiveOptions(): " + e.toString()); + throw new EBaseException("ArchiveOptions() exception caught: " + + e.toString()); + } + + } + + static public ArchiveOptions toArchiveOptions(byte options[]) throws + EBaseException { + ByteArrayInputStream bis = new ByteArrayInputStream(options); + PKIArchiveOptions archOpts = null; + + try { + archOpts = (PKIArchiveOptions) + (new PKIArchiveOptions.Template()).decode(bis); + } catch (Exception e) { + throw new EBaseException("Failed to decode input PKIArchiveOptions."); + } + + return new ArchiveOptions(archOpts); + + } + + public String getSymmAlgOID() { + return mSymmAlgOID; + } + + public byte[] getSymmAlgParams() { + return mSymmAlgParams; + } + + public byte[] getEncSymmKey() { + return mEncSymmKey; + } + + public byte[] getEncValue() { + return mEncValue; + } +} diff --git a/pki/base/kra/src/com/netscape/kra/EncryptionUnit.java b/pki/base/kra/src/com/netscape/kra/EncryptionUnit.java index d90afd726..32c17b08a 100644 --- a/pki/base/kra/src/com/netscape/kra/EncryptionUnit.java +++ b/pki/base/kra/src/com/netscape/kra/EncryptionUnit.java @@ -54,6 +54,7 @@ import com.netscape.cmscore.util.Debug; * @author thomask * @version $Revision$, $Date$ */ +@SuppressWarnings("deprecation") public abstract class EncryptionUnit implements IEncryptionUnit { /* Establish one constant IV for base class, to be used for @@ -168,96 +169,13 @@ public abstract class EncryptionUnit implements IEncryptionUnit { } } - /** - * Wraps the data using transport public key. - */ - public byte[] wrap(PrivateKey priKey) throws EBaseException { - try { - - CMS.debug("EncryptionUnit.wrap"); - CryptoToken token = getToken(); - - // (1) generate session key - org.mozilla.jss.crypto.KeyGenerator kg = - token.getKeyGenerator(KeyGenAlgorithm.DES3); - // internalToken.getKeyGenerator(KeyGenAlgorithm.DES3); - 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()); - - // (2) wrap private key with session key - // KeyWrapper wrapper = internalToken.getKeyWrapper( - KeyWrapper wrapper = token.getKeyWrapper( - KeyWrapAlgorithm.DES3_CBC_PAD); - - wrapper.initWrap(sk, IV); - byte pri[] = wrapper.wrap(priKey); - CMS.debug("EncryptionUnit:wrap() privKey wrapped"); - - // (3) wrap session with transport public - KeyWrapper rsaWrap = token.getKeyWrapper( - KeyWrapAlgorithm.RSA); - - rsaWrap.initWrap(getPublicKey(), null); - byte session[] = rsaWrap.wrap(sk); - CMS.debug("EncryptionUnit:wrap() sessin key wrapped"); - - // use MY own structure for now: - // SEQUENCE { - // encryptedSession OCTET STRING, - // encryptedPrivate OCTET STRING - // } - - DerOutputStream tmp = new DerOutputStream(); - DerOutputStream out = new DerOutputStream(); - - tmp.putOctetString(session); - tmp.putOctetString(pri); - out.write(DerValue.tag_Sequence, tmp); - - return out.toByteArray(); - } catch (TokenException 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; - } catch (NoSuchAlgorithmException 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; - } catch (CharConversionException 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; - } catch (InvalidAlgorithmParameterException 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; - } catch (InvalidKeyException 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; - } catch (IOException 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; - } 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; - } + public byte[] wrap(PrivateKey privKey) throws EBaseException { + return _wrap(privKey,null); } + public byte[] wrap(SymmetricKey symmKey) throws EBaseException { + return _wrap(null,symmKey); + } /** * External unwrapping. Unwraps the data using * the transport private key. @@ -367,13 +285,70 @@ public abstract class EncryptionUnit implements IEncryptionUnit { } /** + * External unwrapping. Unwraps the symmetric key using + * the transport private key. + */ + public SymmetricKey unwrap_symmetric(byte encSymmKey[], + String symmAlgOID, byte symmAlgParams[], + byte encValue[]) + throws EBaseException { + try { + CryptoToken token = getToken(); + + // (1) unwrap the session + KeyWrapper rsaWrap = token.getKeyWrapper( + KeyWrapAlgorithm.RSA); + + rsaWrap.initUnwrap(getPrivateKey(), null); + SymmetricKey sk = rsaWrap.unwrapSymmetric(encSymmKey, + SymmetricKey.DES3, SymmetricKey.Usage.UNWRAP, + 0); + + // (2) unwrap the sym key + KeyWrapper wrapper = token.getKeyWrapper( + KeyWrapAlgorithm.DES3_CBC_PAD // XXX + ); + + wrapper.initUnwrap(sk, new IVParameterSpec( + symmAlgParams)); + + SymmetricKey symKey = wrapper.unwrapSymmetric(encValue, SymmetricKey.DES3, SymmetricKey.Usage.DECRYPT, 0); + + return symKey; + } catch (TokenException e) { + 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 (NoSuchAlgorithmException e) { + 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 (InvalidAlgorithmParameterException e) { + 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 (InvalidKeyException e) { + 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; + } + } + + /** * External unwrapping. Unwraps the data using * the transport private key. */ public PrivateKey unwrap(byte encSymmKey[], - String symmAlgOID, byte symmAlgParams[], - byte encValue[], PublicKey pubKey) - throws EBaseException { + String symmAlgOID, byte symmAlgParams[], + byte encValue[], PublicKey pubKey) + throws EBaseException { try { CryptoToken token = getToken(); @@ -389,12 +364,12 @@ public abstract class EncryptionUnit implements IEncryptionUnit { // (2) unwrap the pri KeyWrapper wrapper = token.getKeyWrapper( KeyWrapAlgorithm.DES3_CBC_PAD // XXX - ); + ); wrapper.initUnwrap(sk, new IVParameterSpec( symmAlgParams)); - PrivateKey.Type keytype = null; + PrivateKey.Type keytype = null; String alg = pubKey.getAlgorithm(); if (alg.equals("DSA")) { keytype = PrivateKey.DSA; @@ -404,35 +379,36 @@ public abstract class EncryptionUnit implements IEncryptionUnit { keytype = PrivateKey.RSA; } PrivateKey pk = wrapper.unwrapTemporaryPrivate(encValue, - keytype, pubKey); + keytype , pubKey); return pk; } catch (TokenException e) { - CMS.getLogger().log(ILogger.EV_SYSTEM, null, ILogger.S_KRA, ILogger.LL_FAILURE, - CMS.getLogMessage("CMSCORE_KRA_ENCRYPTION_UNWRAP", e.toString())); + 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 (NoSuchAlgorithmException e) { - CMS.getLogger().log(ILogger.EV_SYSTEM, null, ILogger.S_KRA, ILogger.LL_FAILURE, - CMS.getLogMessage("CMSCORE_KRA_ENCRYPTION_UNWRAP", e.toString())); + 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 (InvalidAlgorithmParameterException e) { - CMS.getLogger().log(ILogger.EV_SYSTEM, null, ILogger.S_KRA, ILogger.LL_FAILURE, - CMS.getLogMessage("CMSCORE_KRA_ENCRYPTION_UNWRAP", e.toString())); + 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 (InvalidKeyException e) { - CMS.getLogger().log(ILogger.EV_SYSTEM, null, ILogger.S_KRA, ILogger.LL_FAILURE, - CMS.getLogMessage("CMSCORE_KRA_ENCRYPTION_UNWRAP", e.toString())); + 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()); + CMS.debug("EncryptionUnit.unwrap : Exception:"+e.toString()); return null; } } + /** + * External unwrapping. Unwraps the data using + * the transport private key. + */ + public byte[] decryptInternalPrivate(byte wrappedKeyData[]) throws EBaseException { try { @@ -506,6 +482,72 @@ public abstract class EncryptionUnit implements IEncryptionUnit { } /** + * External unwrapping of stored symmetric key. + */ + public SymmetricKey unwrap(byte wrappedKeyData[]) + throws EBaseException { + try { + DerValue val = new DerValue(wrappedKeyData); + // val.tag == DerValue.tag_Sequence + DerInputStream in = val.data; + DerValue dSession = in.getDerValue(); + byte session[] = dSession.getOctetString(); + DerValue dPri = in.getDerValue(); + byte pri[] = dPri.getOctetString(); + + CryptoToken token = getToken(); + // (1) unwrap the session key + KeyWrapper rsaWrap = token.getKeyWrapper( + KeyWrapAlgorithm.RSA); + + rsaWrap.initUnwrap(getPrivateKey(), null); + SymmetricKey sk = rsaWrap.unwrapSymmetric(session, + SymmetricKey.DES3, SymmetricKey.Usage.UNWRAP, 0); + + // (2) unwrap the symmetric key + KeyWrapper wrapper = token.getKeyWrapper( + KeyWrapAlgorithm.DES3_CBC_PAD); + + wrapper.initUnwrap(sk, IV); + + SymmetricKey sk_ret = wrapper.unwrapSymmetric(pri, + SymmetricKey.DES3, SymmetricKey.Usage.UNWRAP, + 0); + + return sk_ret; + } catch (TokenException e) { + 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()); + CMS.debug(e); + return null; + } catch (NoSuchAlgorithmException e) { + 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 (InvalidAlgorithmParameterException e) { + 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 (InvalidKeyException e) { + CMS.getLogger().log(ILogger.EV_SYSTEM, null, ILogger.S_KRA, ILogger.LL_FAILURE, + CMS.getLogMessage("CMSCORE_KRA_ENCRYPTION_UNWRAP", e.toString())); + Debug.printStackTrace(e); + return null; + } catch (IOException e) { + 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) { + Debug.printStackTrace(e); + return null; + } + } + + /** * Internal unwrapping. */ public PrivateKey unwrap_temp(byte wrappedKeyData[], PublicKey pubKey) @@ -592,6 +634,105 @@ public abstract class EncryptionUnit implements IEncryptionUnit { } } + /*** + * Internal wrap, accounts for either private or symmetric key + */ + private byte[] _wrap(PrivateKey priKey, SymmetricKey symmKey) throws EBaseException { + try { + if ((priKey == null && symmKey == null) || (priKey != null && symmKey != null)) { + return null; + } + CMS.debug("EncryptionUnit.wrap interal."); + CryptoToken token = getToken(); + + // (1) generate session key + org.mozilla.jss.crypto.KeyGenerator kg = + token.getKeyGenerator(KeyGenAlgorithm.DES3); + // internalToken.getKeyGenerator(KeyGenAlgorithm.DES3); + 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()); + + // (2) wrap private key with session key + // KeyWrapper wrapper = internalToken.getKeyWrapper( + KeyWrapper wrapper = token.getKeyWrapper( + KeyWrapAlgorithm.DES3_CBC_PAD); + + wrapper.initWrap(sk, IV); + + byte pri[] = null; + + if ( priKey != null) { + pri = wrapper.wrap(priKey); + } else if ( symmKey != null) { + pri = wrapper.wrap(symmKey); + } + CMS.debug("EncryptionUnit:wrap() privKey wrapped"); + + // (3) wrap session with transport public + KeyWrapper rsaWrap = token.getKeyWrapper( + KeyWrapAlgorithm.RSA); + + rsaWrap.initWrap(getPublicKey(), null); + byte session[] = rsaWrap.wrap(sk); + CMS.debug("EncryptionUnit:wrap() sessin key wrapped"); + + // use MY own structure for now: + // SEQUENCE { + // encryptedSession OCTET STRING, + // encryptedPrivate OCTET STRING + // } + + DerOutputStream tmp = new DerOutputStream(); + DerOutputStream out = new DerOutputStream(); + + tmp.putOctetString(session); + tmp.putOctetString(pri); + out.write(DerValue.tag_Sequence, tmp); + + return out.toByteArray(); + } catch (TokenException 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; + } catch (NoSuchAlgorithmException 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; + } catch (CharConversionException 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; + } catch (InvalidAlgorithmParameterException 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; + } catch (InvalidKeyException 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; + } catch (IOException 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; + } 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; + } + } + /** * Verify the given key pair. */ diff --git a/pki/base/kra/src/com/netscape/kra/EnrollmentService.java b/pki/base/kra/src/com/netscape/kra/EnrollmentService.java index b9df360b0..c2705e1e4 100644 --- a/pki/base/kra/src/com/netscape/kra/EnrollmentService.java +++ b/pki/base/kra/src/com/netscape/kra/EnrollmentService.java @@ -35,25 +35,15 @@ import netscape.security.x509.CertificateX509Key; import netscape.security.x509.X509CertInfo; import netscape.security.x509.X509Key; -import org.mozilla.jss.asn1.ANY; import org.mozilla.jss.asn1.ASN1Util; import org.mozilla.jss.asn1.ASN1Value; -import org.mozilla.jss.asn1.BIT_STRING; import org.mozilla.jss.asn1.InvalidBERException; import org.mozilla.jss.asn1.OBJECT_IDENTIFIER; -import org.mozilla.jss.asn1.OCTET_STRING; import org.mozilla.jss.asn1.SEQUENCE; -import org.mozilla.jss.asn1.SET; -import org.mozilla.jss.pkix.cms.EncryptedContentInfo; -import org.mozilla.jss.pkix.cms.EnvelopedData; -import org.mozilla.jss.pkix.cms.RecipientInfo; import org.mozilla.jss.pkix.crmf.CertReqMsg; import org.mozilla.jss.pkix.crmf.CertRequest; -import org.mozilla.jss.pkix.crmf.EncryptedKey; -import org.mozilla.jss.pkix.crmf.EncryptedValue; import org.mozilla.jss.pkix.crmf.PKIArchiveOptions; import org.mozilla.jss.pkix.primitive.AVA; -import org.mozilla.jss.pkix.primitive.AlgorithmIdentifier; import com.netscape.certsrv.apps.CMS; import com.netscape.certsrv.authentication.AuthToken; @@ -73,6 +63,7 @@ import com.netscape.certsrv.security.ITransportKeyUnit; import com.netscape.certsrv.util.IStatsSubsystem; import com.netscape.cmscore.crmf.CRMFParser; import com.netscape.cmscore.crmf.PKIArchiveOptionsContainer; +import com.netscape.kra.ArchiveOptions; import com.netscape.cmscore.dbs.KeyRecord; /** @@ -553,7 +544,7 @@ public class EnrollmentService implements IService { */ public static PKIArchiveOptionsContainer[] getPKIArchiveOptions(String crmfBlob) throws EBaseException { - Vector options = new Vector(); + Vector<Object> options = new Vector<Object>(); if (CMS.debugOn()) CMS.debug("EnrollmentService::getPKIArchiveOptions> crmfBlob=" + crmfBlob); @@ -876,107 +867,3 @@ public class EnrollmentService implements IService { msg); } } - -/** - * Parsed and Flattened structure of PKIArchiveOptions. - */ -class ArchiveOptions { - private String mSymmAlgOID = null; - private byte mSymmAlgParams[] = null; - private byte mEncSymmKey[] = null; - private byte mEncValue[] = null; - - public ArchiveOptions(PKIArchiveOptions opts) throws EBaseException { - try { - EncryptedKey key = opts.getEncryptedKey(); - ANY enveloped_val = null; - EncryptedValue val = null; - AlgorithmIdentifier symmAlg = null; - - if (key.getType() == org.mozilla.jss.pkix.crmf.EncryptedKey.ENVELOPED_DATA) { - CMS.debug("EnrollService: ArchiveOptions() EncryptedKey type= ENVELOPED_DATA"); - // this is the new RFC4211 EncryptedKey that should - // have EnvelopedData to replace the deprecated EncryptedValue - enveloped_val = key.getEnvelopedData(); - byte[] env_b = enveloped_val.getEncoded(); - EnvelopedData.Template env_template = new EnvelopedData.Template(); - EnvelopedData env_data = - (EnvelopedData) env_template.decode(new ByteArrayInputStream(env_b)); - EncryptedContentInfo eCI = env_data.getEncryptedContentInfo(); - symmAlg = eCI.getContentEncryptionAlgorithm(); - mSymmAlgOID = symmAlg.getOID().toString(); - mSymmAlgParams = - ((OCTET_STRING) ((ANY) symmAlg.getParameters()).decodeWith(OCTET_STRING.getTemplate())) - .toByteArray(); - - SET recipients = env_data.getRecipientInfos(); - if (recipients.size() <= 0) { - CMS.debug("EnrollService: ArchiveOptions() - missing recipient information "); - throw new EBaseException(CMS.getUserMessage("CMS_BASE_INVALID_ATTRIBUTE", - "[PKIArchiveOptions] missing recipient information ")); - } - //check recpient - later - //we only handle one recipient here anyways. so, either the key - //can be decrypted or it can't. No risk here. - RecipientInfo ri = (RecipientInfo) recipients.elementAt(0); - OCTET_STRING key_o = ri.getEncryptedKey(); - mEncSymmKey = key_o.toByteArray(); - - OCTET_STRING oString = eCI.getEncryptedContent(); - BIT_STRING encVal = new BIT_STRING(oString.toByteArray(), 0); - mEncValue = encVal.getBits(); - CMS.debug("EnrollService: ArchiveOptions() EncryptedKey type= ENVELOPED_DATA done"); - } else if (key.getType() == org.mozilla.jss.pkix.crmf.EncryptedKey.ENCRYPTED_VALUE) { - CMS.debug("EnrollService: ArchiveOptions() EncryptedKey type= ENCRYPTED_VALUE"); - // this is deprecated: EncryptedValue - val = key.getEncryptedValue(); - symmAlg = val.getSymmAlg(); - mSymmAlgOID = symmAlg.getOID().toString(); - mSymmAlgParams = - ((OCTET_STRING) ((ANY) symmAlg.getParameters()).decodeWith(OCTET_STRING.getTemplate())) - .toByteArray(); - BIT_STRING encSymmKey = val.getEncSymmKey(); - - mEncSymmKey = encSymmKey.getBits(); - BIT_STRING encVal = val.getEncValue(); - - mEncValue = encVal.getBits(); - CMS.debug("EnrollService: ArchiveOptions() EncryptedKey type= ENCRYPTED_VALUE done"); - } else { - CMS.debug("EnrollService: ArchiveOptions() invalid EncryptedKey type"); - throw new EBaseException(CMS.getUserMessage("CMS_BASE_INVALID_ATTRIBUTE", "[PKIArchiveOptions] type " - + key.getType())); - } - - } catch (InvalidBERException e) { - CMS.debug("EnrollService: ArchiveOptions(): " + e.toString()); - throw new EBaseException(CMS.getUserMessage("CMS_BASE_INVALID_ATTRIBUTE", - "[PKIArchiveOptions]" + e.toString())); - } catch (IOException e) { - CMS.debug("EnrollService: ArchiveOptions(): " + e.toString()); - throw new EBaseException("ArchiveOptions() exception caught: " + - e.toString()); - } catch (Exception e) { - CMS.debug("EnrollService: ArchiveOptions(): " + e.toString()); - throw new EBaseException("ArchiveOptions() exception caught: " + - e.toString()); - } - - } - - public String getSymmAlgOID() { - return mSymmAlgOID; - } - - public byte[] getSymmAlgParams() { - return mSymmAlgParams; - } - - public byte[] getEncSymmKey() { - return mEncSymmKey; - } - - public byte[] getEncValue() { - return mEncValue; - } -} diff --git a/pki/base/kra/src/com/netscape/kra/KRAService.java b/pki/base/kra/src/com/netscape/kra/KRAService.java index 916ebe3bb..1a351e061 100644 --- a/pki/base/kra/src/com/netscape/kra/KRAService.java +++ b/pki/base/kra/src/com/netscape/kra/KRAService.java @@ -46,10 +46,13 @@ public class KRAService implements IService { public final static String RECOVERY = IRequest.KEYRECOVERY_REQUEST; public final static String NETKEY_KEYGEN = IRequest.NETKEY_KEYGEN_REQUEST; public final static String NETKEY_KEYRECOVERY = IRequest.NETKEY_KEYRECOVERY_REQUEST; + public final static String SECURITY_DATA_ENROLLMENT = IRequest.SECURITY_DATA_ENROLLMENT_REQUEST; + public final static String SECURITY_DATA_RECOVERY = IRequest.SECURITY_DATA_RECOVERY_REQUEST; + // private variables private IKeyRecoveryAuthority mKRA = null; - private Hashtable mServices = new Hashtable(); + private Hashtable<String,IService> mServices = new Hashtable<String,IService>(); /** * Constructs KRA service. @@ -60,6 +63,8 @@ public class KRAService implements IService { mServices.put(RECOVERY, new RecoveryService(kra)); mServices.put(NETKEY_KEYGEN, new NetkeyKeygenService(kra)); mServices.put(NETKEY_KEYRECOVERY, new TokenKeyRecoveryService(kra)); + mServices.put(SECURITY_DATA_ENROLLMENT, new SecurityDataService(kra)); + mServices.put(SECURITY_DATA_RECOVERY, new SecurityDataRecoveryService(kra)); } /** diff --git a/pki/base/kra/src/com/netscape/kra/SecurityDataRecoveryService.java b/pki/base/kra/src/com/netscape/kra/SecurityDataRecoveryService.java new file mode 100644 index 000000000..b38730949 --- /dev/null +++ b/pki/base/kra/src/com/netscape/kra/SecurityDataRecoveryService.java @@ -0,0 +1,389 @@ +// --- BEGIN COPYRIGHT BLOCK --- +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; version 2 of the License. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// (C) 2007 Red Hat, Inc. +// All rights reserved. +// --- END COPYRIGHT BLOCK --- +package com.netscape.kra; + +import java.io.ByteArrayOutputStream; +import java.io.CharConversionException; +import java.io.IOException; +import java.math.BigInteger; +import java.security.InvalidAlgorithmParameterException; +import java.security.InvalidKeyException; +import java.security.NoSuchAlgorithmException; +import java.security.spec.AlgorithmParameterSpec; +import java.util.Hashtable; +import java.util.Random; + +import javax.crypto.spec.RC2ParameterSpec; + +import org.mozilla.jss.CryptoManager; +import org.mozilla.jss.asn1.OCTET_STRING; +import org.mozilla.jss.crypto.Cipher; +import org.mozilla.jss.crypto.CryptoToken; +import org.mozilla.jss.crypto.EncryptionAlgorithm; +import org.mozilla.jss.crypto.IVParameterSpec; +import org.mozilla.jss.crypto.KeyGenerator; +import org.mozilla.jss.crypto.KeyWrapAlgorithm; +import org.mozilla.jss.crypto.KeyWrapper; +import org.mozilla.jss.crypto.PBEAlgorithm; +import org.mozilla.jss.crypto.PBEKeyGenParams; +import org.mozilla.jss.crypto.SymmetricKey; +import org.mozilla.jss.crypto.TokenException; +import org.mozilla.jss.pkcs12.PasswordConverter; +import org.mozilla.jss.pkcs7.ContentInfo; +import org.mozilla.jss.pkcs7.EncryptedContentInfo; +import org.mozilla.jss.pkix.primitive.AlgorithmIdentifier; +import org.mozilla.jss.pkix.primitive.PBEParameter; +import org.mozilla.jss.util.Password; + +import com.netscape.certsrv.kra.EKRAException; +import com.netscape.certsrv.kra.IKeyRecoveryAuthority; +import com.netscape.certsrv.request.IService; +import com.netscape.certsrv.request.IRequest; +import com.netscape.certsrv.security.IStorageKeyUnit; +import com.netscape.certsrv.security.ITransportKeyUnit; +import com.netscape.certsrv.apps.CMS; +import com.netscape.certsrv.base.EBaseException; +import com.netscape.certsrv.dbs.keydb.IKeyRecord; +import com.netscape.certsrv.dbs.keydb.IKeyRepository; +import com.netscape.cms.servlet.request.KeyRequestResource; +import com.netscape.cmscore.dbs.KeyRecord; + +/** + * This implementation services SecurityData Recovery requests. + * <p> + * + * @version $Revision$, $Date$ + */ +@SuppressWarnings("deprecation") +public class SecurityDataRecoveryService implements IService { + + private IKeyRecoveryAuthority mKRA = null; + + private IKeyRepository mStorage = null; + private IStorageKeyUnit mStorageUnit = null; + private ITransportKeyUnit mTransportUnit = null; + + public static final String ATTR_SERIALNO = "serialNumber"; + public static final String ATTR_SESS_WRAPPED_DATA = "sessWrappedSecData"; + public static final String ATTR_PASS_WRAPPED_DATA = "passPhraseWrappedData"; + public static final String ATTR_KEY_RECORD = "keyRecord"; + + public SecurityDataRecoveryService(IKeyRecoveryAuthority kra) { + mKRA = kra; + mStorage = mKRA.getKeyRepository(); + mStorageUnit = mKRA.getStorageKeyUnit(); + mTransportUnit = mKRA.getTransportKeyUnit(); + + } + + /** + * Performs the service (such as certificate generation) + * represented by this request. + * <p> + * + * @param request + * The SecurityData recovery request that needs service. The service may use + * attributes stored in the request, and may update the + * values, or store new ones. + * @return + * an indication of whether this request is still pending. + * 'false' means the request will wait for further notification. + * @exception EBaseException indicates major processing failure. + */ + public boolean serviceRequest(IRequest request) + throws EBaseException { + + //Pave the way for allowing generated IV vector + byte iv[]= null; + byte iv_default[] = { 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1 }; + byte iv_in[] = null; + + Hashtable<String, Object> params = mKRA.getVolatileRequest( + request.getRequestId()); + + if (params == null) { + CMS.debug("Can't get volatile params."); + throw new EBaseException("Can't obtain volatile params!"); + } + + BigInteger serialno = request.getExtDataInBigInteger(ATTR_SERIALNO); + + request.setExtData(ATTR_KEY_RECORD, serialno); + + byte[] wrappedPassPhrase = null; + byte[] wrappedSessKey = null; + + String transWrappedSessKeyStr = (String) params.get(IRequest.SECURITY_DATA_TRANS_SESS_KEY); + if (transWrappedSessKeyStr != null) { + wrappedSessKey = com.netscape.osutil.OSUtil.AtoB(transWrappedSessKeyStr); + } + + String sessWrappedPassPhraseStr = (String) params.get(IRequest.SECURITY_DATA_SESS_PASS_PHRASE); + if (sessWrappedPassPhraseStr != null) { + wrappedPassPhrase = com.netscape.osutil.OSUtil.AtoB(sessWrappedPassPhraseStr); + } + + String ivInStr = (String) params.get(IRequest.SECURITY_DATA_IV_STRING_IN); + if (ivInStr != null) { + iv_in = com.netscape.osutil.OSUtil.AtoB(ivInStr); + } + + if (transWrappedSessKeyStr == null && sessWrappedPassPhraseStr == null) { + //We may be in recovery case where no params were initially submitted. + return false; + } + + //Create the return IV if needed. + iv = new byte[8]; + + try { + Random rnd = new Random(); + rnd.nextBytes(iv); + } catch (Exception e) { + iv = iv_default; + } + + String ivStr = com.netscape.osutil.OSUtil.BtoA(iv); + + KeyRecord keyRecord = (KeyRecord) mStorage.readKeyRecord(serialno); + + SymmetricKey unwrappedSess = null; + + String dataType = (String) keyRecord.get(IKeyRecord.ATTR_DATA_TYPE); + SymmetricKey symKey = null; + byte[] unwrappedSecData = null; + if (dataType.equals(KeyRequestResource.SYMMETRIC_KEY_TYPE)) { + symKey = recoverSymKey(keyRecord); + } else if (dataType.equals(KeyRequestResource.PASS_PHRASE_TYPE)) { + unwrappedSecData = recoverSecurityData(keyRecord); + } + + CryptoToken ct = mTransportUnit.getToken(); + + byte[] key_data = null; + String pbeWrappedData = null; + + if (sessWrappedPassPhraseStr != null) { //We have a trans wrapped pass phrase, we will be doing PBE packaging + byte[] unwrappedPass = null; + Password pass = null; + + try { + unwrappedSess = mTransportUnit.unwrap_sym(wrappedSessKey, SymmetricKey.Usage.DECRYPT); + Cipher decryptor = ct.getCipherContext(EncryptionAlgorithm.DES3_CBC_PAD); + decryptor.initDecrypt(unwrappedSess, new IVParameterSpec(iv_in)); + unwrappedPass = decryptor.doFinal(wrappedPassPhrase); + String passStr = new String(unwrappedPass, "UTF-8"); + + pass = new Password(passStr.toCharArray()); + passStr = null; + + if (dataType.equals(KeyRequestResource.SYMMETRIC_KEY_TYPE)) { + pbeWrappedData = createEncryptedContentInfo(ct, symKey, null, + pass); + } else if (dataType.equals(KeyRequestResource.PASS_PHRASE_TYPE)) { + pbeWrappedData = createEncryptedContentInfo(ct, null, unwrappedSecData, + pass); + } + + params.put(ATTR_PASS_WRAPPED_DATA, pbeWrappedData); + + } catch (Exception e) { + throw new EBaseException("Can't unwrap pass phase! " + e.toString()); + } finally { + if ( pass != null) { + pass.clear(); + } + + if ( unwrappedPass != null) { + java.util.Arrays.fill(unwrappedPass, (byte) 0); + } + } + + } else { // No trans wrapped pass phrase, return session wrapped data. + if (dataType.equals(KeyRequestResource.SYMMETRIC_KEY_TYPE)) { + //wrap the key with session key + try { + unwrappedSess = mTransportUnit.unwrap_sym(wrappedSessKey, SymmetricKey.Usage.WRAP); + KeyWrapper wrapper = ct.getKeyWrapper(KeyWrapAlgorithm.DES3_CBC_PAD); + wrapper.initWrap(unwrappedSess, new IVParameterSpec(iv)); + key_data = wrapper.wrap(symKey); + } catch (Exception e) { + throw new EBaseException("Can't wrap symmetric key! " + e.toString()); + } + + } else if (dataType.equals(KeyRequestResource.PASS_PHRASE_TYPE)) { + try { + unwrappedSess = mTransportUnit.unwrap_sym(wrappedSessKey, SymmetricKey.Usage.ENCRYPT); + Cipher encryptor = ct.getCipherContext(EncryptionAlgorithm.DES3_CBC_PAD); + if (encryptor != null) { + encryptor.initEncrypt(unwrappedSess, new IVParameterSpec(iv)); + key_data = encryptor.doFinal(unwrappedSecData); + } else { + throw new IOException("Failed to create cipher"); + } + } catch (Exception e) { + throw new EBaseException("Can't wrap pass phrase!"); + } + } + + String wrappedKeyData = com.netscape.osutil.OSUtil.BtoA(key_data); + params.put(ATTR_SESS_WRAPPED_DATA, wrappedKeyData); + params.put(IRequest.SECURITY_DATA_IV_STRING_OUT, ivStr); + + } + return false; + } + + public SymmetricKey recoverSymKey(KeyRecord keyRecord) + throws EBaseException { + + try { + SymmetricKey symKey = + mStorageUnit.unwrap( + keyRecord.getPrivateKeyData()); + + if (symKey == null) { + throw new EKRAException(CMS.getUserMessage("CMS_KRA_RECOVERY_FAILED_1", + "symmetric key unwrapping failure")); + } + + return symKey; + } catch (Exception e) { + + throw new EKRAException(CMS.getUserMessage("CMS_KRA_RECOVERY_FAILED_1", + "recoverSymKey() " + e.toString())); + } + } + + public byte[] recoverSecurityData(KeyRecord keyRecord) + throws EBaseException { + + byte[] decodedData = null; + + try { + decodedData = mStorageUnit.decryptInternalPrivate( + keyRecord.getPrivateKeyData()); + + if (decodedData == null) { + throw new EKRAException(CMS.getUserMessage("CMS_KRA_RECOVERY_FAILED_1", + "security data unwrapping failure")); + } + + return decodedData; + } catch (Exception e) { + + throw new EKRAException(CMS.getUserMessage("CMS_KRA_RECOVERY_FAILED_1", + "recoverSecurityData() " + e.toString())); + } + } + + //ToDo: This might fit in JSS. + private static EncryptedContentInfo + createEncryptedContentInfoPBEOfSymmKey(PBEAlgorithm keyGenAlg, Password password, byte[] salt, + int iterationCount, + KeyGenerator.CharToByteConverter charToByteConverter, + SymmetricKey symKey, CryptoToken token) + throws CryptoManager.NotInitializedException, NoSuchAlgorithmException, + InvalidKeyException, InvalidAlgorithmParameterException, TokenException, + CharConversionException { + + if (!(keyGenAlg instanceof PBEAlgorithm)) { + throw new NoSuchAlgorithmException("Key generation algorithm" + + " is not a PBE algorithm"); + } + PBEAlgorithm pbeAlg = (PBEAlgorithm) keyGenAlg; + + KeyGenerator kg = token.getKeyGenerator(keyGenAlg); + PBEKeyGenParams pbekgParams = new PBEKeyGenParams( + password, salt, iterationCount); + if (charToByteConverter != null) { + kg.setCharToByteConverter(charToByteConverter); + } + kg.initialize(pbekgParams); + SymmetricKey key = kg.generate(); + + EncryptionAlgorithm encAlg = pbeAlg.getEncryptionAlg(); + AlgorithmParameterSpec params = null; + if (encAlg.getParameterClass().equals(IVParameterSpec.class)) { + params = new IVParameterSpec(kg.generatePBE_IV()); + } else if (encAlg.getParameterClass().equals( + RC2ParameterSpec.class)) { + params = new RC2ParameterSpec(key.getStrength(), + kg.generatePBE_IV()); + } + + KeyWrapper wrapper = token.getKeyWrapper( + KeyWrapAlgorithm.DES3_CBC_PAD); + wrapper.initWrap(key, params); + byte encrypted[] = wrapper.wrap(symKey); + + PBEParameter pbeParam = new PBEParameter(salt, iterationCount); + AlgorithmIdentifier encAlgID = new AlgorithmIdentifier( + keyGenAlg.toOID(), pbeParam); + + EncryptedContentInfo encCI = new EncryptedContentInfo( + ContentInfo.DATA, + encAlgID, + new OCTET_STRING(encrypted)); + + return encCI; + + } + + private static String createEncryptedContentInfo(CryptoToken ct, SymmetricKey symKey, byte[] securityData, + Password password) + throws EBaseException { + + EncryptedContentInfo cInfo = null; + String retData = null; + PBEAlgorithm keyGenAlg = PBEAlgorithm.PBE_SHA1_DES3_CBC; + + byte[] encoded = null; + try { + PasswordConverter passConverter = new + PasswordConverter(); + byte salt[] = { 0x01, 0x01, 0x01, 0x01 }; + if (symKey != null) { + + cInfo = createEncryptedContentInfoPBEOfSymmKey(keyGenAlg, password, salt, + 1, + passConverter, + symKey, ct); + + } else if (securityData != null) { + + cInfo = EncryptedContentInfo.createPBE(keyGenAlg, password, salt, 1, passConverter, securityData); + } + + if(cInfo == null) { + throw new EBaseException("Can't create a PBE wrapped EncryptedContentInfo!"); + } + + ByteArrayOutputStream oStream = new ByteArrayOutputStream(); + cInfo.encode(oStream); + encoded = oStream.toByteArray(); + retData = com.netscape.osutil.OSUtil.BtoA(encoded); + + } catch (Exception e) { + throw new EBaseException("Can't create a PBE wrapped EncryptedContentInfo! " + e.toString()); + } + + return retData; + } + +} diff --git a/pki/base/kra/src/com/netscape/kra/SecurityDataService.java b/pki/base/kra/src/com/netscape/kra/SecurityDataService.java new file mode 100644 index 000000000..7f9902eda --- /dev/null +++ b/pki/base/kra/src/com/netscape/kra/SecurityDataService.java @@ -0,0 +1,170 @@ +// --- BEGIN COPYRIGHT BLOCK --- +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; version 2 of the License. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// (C) 2007 Red Hat, Inc. +// All rights reserved. +// --- END COPYRIGHT BLOCK --- +package com.netscape.kra; + +import java.math.BigInteger; +import org.mozilla.jss.crypto.SymmetricKey; +import com.netscape.certsrv.kra.IKeyRecoveryAuthority; +import com.netscape.certsrv.logging.ILogger; +import com.netscape.certsrv.profile.IEnrollProfile; +import com.netscape.certsrv.request.IService; +import com.netscape.certsrv.request.IRequest; +import com.netscape.certsrv.security.IStorageKeyUnit; +import com.netscape.certsrv.security.ITransportKeyUnit; +import com.netscape.certsrv.base.EBaseException; +import com.netscape.certsrv.dbs.keydb.IKeyRecord; +import com.netscape.certsrv.dbs.keydb.IKeyRepository; +import com.netscape.certsrv.apps.CMS; +import com.netscape.cms.servlet.request.KeyRequestResource; +import com.netscape.cmscore.dbs.KeyRecord; + +/** + * This implementation implements SecurityData archival operations. + * <p> + * + * @version $Revision$, $Date$ + */ +public class SecurityDataService implements IService { + + private final static String DEFAULT_OWNER = "IPA Agent"; + public final static String ATTR_KEY_RECORD = "keyRecord"; + private final static String STATUS_ACTIVE = "active"; + + private IKeyRecoveryAuthority mKRA = null; + private ITransportKeyUnit mTransportUnit = null; + private IStorageKeyUnit mStorageUnit = null; + + public SecurityDataService(IKeyRecoveryAuthority kra) { + mKRA = kra; + mTransportUnit = kra.getTransportKeyUnit(); + mStorageUnit = kra.getStorageKeyUnit(); + } + + /** + * Performs the service of archiving Security Data. + * represented by this request. + * <p> + * + * @param request + * The request that needs service. The service may use + * attributes stored in the request, and may update the + * values, or store new ones. + * @return + * an indication of whether this request is still pending. + * 'false' means the request will wait for further notification. + * @exception EBaseException indicates major processing failure. + */ + public boolean serviceRequest(IRequest request) + throws EBaseException { + String id = request.getRequestId().toString(); + String clientId = request.getExtDataInString(IRequest.SECURITY_DATA_CLIENT_ID); + String wrappedSecurityData = request.getExtDataInString(IEnrollProfile.REQUEST_ARCHIVE_OPTIONS); + String dataType = request.getExtDataInString(IRequest.SECURITY_DATA_TYPE); + + CMS.debug("SecurityDataService.serviceRequest. Request id: " + id); + CMS.debug("SecurityDataService.serviceRequest wrappedSecurityData: " + wrappedSecurityData); + + String owner = getOwnerName(request); + + //Check here even though restful layer checks for this. + if(wrappedSecurityData == null || clientId == null || dataType == null) { + throw new EBaseException("Bad data in SecurityDataService.serviceRequest"); + } + //We need some info from the PKIArchiveOptions wrapped security data + + byte[] encoded = com.netscape.osutil.OSUtil.AtoB(wrappedSecurityData); + + ArchiveOptions options = ArchiveOptions.toArchiveOptions(encoded); + + //Check here just in case a null ArchiveOptions makes it this far + if(options == null) { + throw new EBaseException("Problem decofing PKIArchiveOptions."); + } + + String algStr = options.getSymmAlgOID(); + + SymmetricKey securitySymKey = null; + byte[] securityData = null; + + String keyType = null; + if (dataType.equals(KeyRequestResource.SYMMETRIC_KEY_TYPE)) { + // Symmetric Key + keyType = KeyRequestResource.SYMMETRIC_KEY_TYPE; + securitySymKey = mTransportUnit.unwrap_symmetric(options.getEncSymmKey(), + options.getSymmAlgOID(), + options.getSymmAlgParams(), + options.getEncValue()); + + } else if (dataType.equals(KeyRequestResource.PASS_PHRASE_TYPE)) { + keyType = KeyRequestResource.PASS_PHRASE_TYPE; + securityData = mTransportUnit.decryptExternalPrivate(options.getEncSymmKey(), + options.getSymmAlgOID(), + options.getSymmAlgParams(), + options.getEncValue()); + + } + + byte[] publicKey = null; + byte privateSecurityData[] = null; + + if (securitySymKey != null) { + privateSecurityData = mStorageUnit.wrap(securitySymKey); + } else if (securityData != null) { + privateSecurityData = mStorageUnit.encryptInternalPrivate(securityData); + } else { // We have no data. + throw new EBaseException("Failed to create security data to archive!"); + } + // create key record + KeyRecord rec = new KeyRecord(null, publicKey, + privateSecurityData, owner, + algStr, owner); + + rec.set(IKeyRecord.ATTR_CLIENT_ID, clientId); + + //Now we need a serial number for our new key. + + if (rec.getSerialNumber() != null) { + throw new EBaseException(CMS.getUserMessage("CMS_KRA_INVALID_STATE")); + } + + IKeyRepository storage = mKRA.getKeyRepository(); + BigInteger serialNo = storage.getNextSerialNumber(); + + if (serialNo == null) { + mKRA.log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSCORE_KRA_GET_NEXT_SERIAL")); + throw new EBaseException(CMS.getUserMessage("CMS_KRA_INVALID_STATE")); + } + + rec.set(KeyRecord.ATTR_ID, serialNo); + rec.set(KeyRecord.ATTR_DATA_TYPE, keyType); + rec.set(KeyRecord.ATTR_STATUS, STATUS_ACTIVE); + request.setExtData(ATTR_KEY_RECORD, serialNo); + + CMS.debug("KRA adding Security Data key record " + serialNo); + + storage.addKeyRecord(rec); + + return true; + + } + //ToDo: return real owner with auth + private String getOwnerName(IRequest request) { + return DEFAULT_OWNER; + } +}
\ No newline at end of file |