summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--pki/base/ca/shared/conf/index.ldif21
-rw-r--r--pki/base/ca/shared/conf/schema.ldif17
-rw-r--r--pki/base/common/src/com/netscape/certsrv/dbs/keydb/IKeyRecord.java29
-rw-r--r--pki/base/common/src/com/netscape/certsrv/request/IRequest.java14
-rw-r--r--pki/base/common/src/com/netscape/certsrv/security/IEncryptionUnit.java51
-rw-r--r--pki/base/common/src/com/netscape/certsrv/security/ITransportKeyUnit.java55
-rw-r--r--pki/base/common/src/com/netscape/cms/servlet/key/KeyResourceService.java16
-rw-r--r--pki/base/common/src/com/netscape/cms/servlet/key/KeysResourceService.java2
-rw-r--r--pki/base/common/src/com/netscape/cms/servlet/key/model/KeyDAO.java109
-rw-r--r--pki/base/common/src/com/netscape/cms/servlet/key/model/KeyData.java19
-rw-r--r--pki/base/common/src/com/netscape/cms/servlet/request/KeyRequestResource.java3
-rw-r--r--pki/base/common/src/com/netscape/cms/servlet/request/KeyRequestResourceService.java26
-rw-r--r--pki/base/common/src/com/netscape/cms/servlet/request/model/KeyRequestDAO.java97
-rw-r--r--pki/base/common/src/com/netscape/cms/servlet/request/model/RecoveryRequestData.java21
-rw-r--r--pki/base/common/src/com/netscape/cmscore/dbs/KeyDBSchema.java3
-rw-r--r--pki/base/common/src/com/netscape/cmscore/dbs/KeyRecord.java41
-rw-r--r--pki/base/common/src/com/netscape/cmscore/dbs/KeyRepository.java13
-rw-r--r--pki/base/kra/functional/src/com/netscape/cms/servlet/test/DRMRestClient.java16
-rw-r--r--pki/base/kra/functional/src/com/netscape/cms/servlet/test/DRMTest.java218
-rw-r--r--pki/base/kra/shared/conf/index.ldif21
-rw-r--r--pki/base/kra/shared/conf/schema.ldif17
-rw-r--r--pki/base/kra/src/com/netscape/kra/ArchiveOptions.java154
-rw-r--r--pki/base/kra/src/com/netscape/kra/EncryptionUnit.java347
-rw-r--r--pki/base/kra/src/com/netscape/kra/EnrollmentService.java117
-rw-r--r--pki/base/kra/src/com/netscape/kra/KRAService.java7
-rw-r--r--pki/base/kra/src/com/netscape/kra/SecurityDataRecoveryService.java389
-rw-r--r--pki/base/kra/src/com/netscape/kra/SecurityDataService.java170
-rw-r--r--pki/base/ocsp/shared/conf/index.ldif21
-rw-r--r--pki/base/ocsp/shared/conf/schema.ldif17
-rw-r--r--pki/base/tks/shared/conf/index.ldif21
-rw-r--r--pki/base/tks/shared/conf/schema.ldif17
31 files changed, 1764 insertions, 305 deletions
diff --git a/pki/base/ca/shared/conf/index.ldif b/pki/base/ca/shared/conf/index.ldif
index c1eecc19d..4bc8aebf9 100644
--- a/pki/base/ca/shared/conf/index.ldif
+++ b/pki/base/ca/shared/conf/index.ldif
@@ -19,6 +19,27 @@ nsIndexType: eq
nsSystemIndex: false
cn: publicKeyData
+dn: cn=clientId,cn=index,cn={database},cn=ldbm database, cn=plugins, cn=config
+objectClass: top
+objectClass: nsIndex
+nsIndexType: eq
+nsSystemIndex: false
+cn: clientId
+
+dn: cn=dataType,cn=index,cn={database},cn=ldbm database, cn=plugins, cn=config
+objectClass: top
+objectClass: nsIndex
+nsIndexType: eq
+nsSystemIndex: false
+cn: dataType
+
+dn: cn=status,cn=index,cn={database},cn=ldbm database, cn=plugins, cn=config
+objectClass: top
+objectClass: nsIndex
+nsIndexType: eq
+nsSystemIndex: false
+cn: status
+
dn: cn=description,cn=index,cn={database},cn=ldbm database, cn=plugins, cn=config
objectClass: top
objectClass: nsIndex
diff --git a/pki/base/ca/shared/conf/schema.ldif b/pki/base/ca/shared/conf/schema.ldif
index caf71e965..70578e21c 100644
--- a/pki/base/ca/shared/conf/schema.ldif
+++ b/pki/base/ca/shared/conf/schema.ldif
@@ -161,6 +161,21 @@ attributeTypes: ( keySize-oid NAME 'keySize' DESC 'CMS defined attribute' SYNTAX
dn: cn=schema
changetype: modify
add: attributeTypes
+attributeTypes: ( clientId-oid NAME 'clientId' DESC 'CMS defined attribute' SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 X-ORIGIN 'user defined' )
+
+dn: cn=schema
+changetype: modify
+add: attributeTypes
+attributeTypes: ( dataType-oid NAME 'dataType' DESC 'CMS defined attribute' SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 X-ORIGIN 'user defined' )
+
+dn: cn=schema
+changetype: modify
+add: attributeTypes
+attributeTypes: ( status-oid NAME 'status' DESC 'CMS defined attribute' SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 X-ORIGIN 'user defined' )
+
+dn: cn=schema
+changetype: modify
+add: attributeTypes
attributeTypes: ( keyState-oid NAME 'keyState' DESC 'CMS defined attribute' SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 X-ORIGIN 'user defined' )
dn: cn=schema
@@ -446,7 +461,7 @@ objectClasses: ( userDetails-oid NAME 'userDetails' DESC 'CMS defined class' SUP
dn: cn=schema
changetype: modify
add: objectClasses
-objectClasses: ( keyRecord-oid NAME 'keyRecord' DESC 'CMS defined class' SUP top STRUCTURAL MUST cn MAY ( serialno $ dateOfCreate $ dateOfModify $ keyState $ privateKeyData $ ownerName $ keySize $ metaInfo $ dateOfArchival $ dateOfRecovery $ algorithm $ publicKeyFormat $ publicKeyData $ archivedBy ) X-ORIGIN 'user defined' )
+objectClasses: ( keyRecord-oid NAME 'keyRecord' DESC 'CMS defined class' SUP top STRUCTURAL MUST cn MAY ( serialno $ dateOfCreate $ dateOfModify $ keyState $ privateKeyData $ ownerName $ keySize $ metaInfo $ dateOfArchival $ dateOfRecovery $ algorithm $ publicKeyFormat $ publicKeyData $ archivedBy $ clientId $ dataType $ status ) X-ORIGIN 'user defined' )
dn: cn=schema
changetype: modify
diff --git a/pki/base/common/src/com/netscape/certsrv/dbs/keydb/IKeyRecord.java b/pki/base/common/src/com/netscape/certsrv/dbs/keydb/IKeyRecord.java
index 010661d8b..7da212469 100644
--- a/pki/base/common/src/com/netscape/certsrv/dbs/keydb/IKeyRecord.java
+++ b/pki/base/common/src/com/netscape/certsrv/dbs/keydb/IKeyRecord.java
@@ -40,6 +40,10 @@ public interface IKeyRecord {
public static final String ATTR_MODIFY_TIME = "keyModifyTime";
public static final String ATTR_META_INFO = "keyMetaInfo";
public static final String ATTR_ARCHIVED_BY = "keyArchivedBy";
+ public static final String ATTR_CLIENT_ID = "clientId";
+ public static final String ATTR_DATA_TYPE = "dataType";
+ public static final String ATTR_STATUS = "status";
+
// key state
public static final String STATUS_ANY = "ANY";
@@ -86,10 +90,35 @@ public interface IKeyRecord {
public Integer getKeySize() throws EBaseException;
/**
+ * Retrieves client ID.
+ *
+ * @return client id
+ * @exception EBaseException failed to retrieve client id
+ */
+ public String getClientId() throws EBaseException;
+
+ /**
+ * Retrieves key data type.
+ *
+ * @return data type
+ * @exception EBaseException failed to retrieve data type
+ */
+ public String getDataType() throws EBaseException;
+
+ /**
+ * Retrieves key status.
+ *
+ * @return key status
+ * @exception EBaseException failed to retrieve key status
+ */
+ public String getKeyStatus() throws EBaseException;
+
+ /**
* Retrieves archiver identifier.
*
* @return archiver uid
*/
+
public String getArchivedBy();
/**
diff --git a/pki/base/common/src/com/netscape/certsrv/request/IRequest.java b/pki/base/common/src/com/netscape/certsrv/request/IRequest.java
index 19b830898..ec1f43fb3 100644
--- a/pki/base/common/src/com/netscape/certsrv/request/IRequest.java
+++ b/pki/base/common/src/com/netscape/certsrv/request/IRequest.java
@@ -69,8 +69,6 @@ public interface IRequest {
public static final String CLA_UNCERT4CRL_REQUEST = "uncert4crl";
public static final String NETKEY_KEYGEN_REQUEST = "netkeyKeygen";
public static final String NETKEY_KEYRECOVERY_REQUEST = "netkeyKeyRecovery";
- public static final String SECURITY_DATA_ENROLLMENT_REQUEST = "securityDataEnrollment";
- public static final String SECURITY_DATA_RECOVERY_REQUEST = "securityDataRecovery";
public static final String REQUESTOR_NAME = "csrRequestorName";
public static final String REQUESTOR_PHONE = "csrRequestorPhone";
@@ -152,6 +150,18 @@ public interface IRequest {
public final static String NETKEY_ATTR_USER_CERT = "cert";
public final static String NETKEY_ATTR_KEY_SIZE = "keysize";
+ //Security Data request attributes
+ public static final String SECURITY_DATA_ENROLLMENT_REQUEST = "securityDataEnrollment";
+ public static final String SECURITY_DATA_RECOVERY_REQUEST = "securityDataRecovery";
+ public static final String SECURITY_DATA_CLIENT_ID = "clientID";
+ public static final String SECURITY_DATA_TYPE = "dataType";
+ public static final String SECURITY_DATA_STATUS = "status";
+ public static final String SECURITY_DATA_TRANS_SESS_KEY = "transWrappedSessionKey";
+ public static final String SECURITY_DATA_SESS_PASS_PHRASE = "sessionWrappedPassphrase";
+ public static final String SECURITY_DATA_IV_STRING_IN = "iv_in";
+ public static final String SECURITY_DATA_IV_STRING_OUT = "iv_out";
+
+
// requestor type values.
public static final String REQUESTOR_EE = "EE";
public static final String REQUESTOR_RA = "RA";
diff --git a/pki/base/common/src/com/netscape/certsrv/security/IEncryptionUnit.java b/pki/base/common/src/com/netscape/certsrv/security/IEncryptionUnit.java
index e318188a6..0a526e582 100644
--- a/pki/base/common/src/com/netscape/certsrv/security/IEncryptionUnit.java
+++ b/pki/base/common/src/com/netscape/certsrv/security/IEncryptionUnit.java
@@ -20,6 +20,7 @@ package com.netscape.certsrv.security;
import java.security.PublicKey;
import org.mozilla.jss.crypto.PrivateKey;
+import org.mozilla.jss.crypto.SymmetricKey;
import com.netscape.certsrv.base.EBaseException;
@@ -48,6 +49,16 @@ public interface IEncryptionUnit extends IToken {
public byte[] wrap(PrivateKey priKey) throws EBaseException;
/**
+ * Wraps data. The given key will be wrapped by the
+ * private key in this unit.
+ *
+ * @param symKey symmetric key to be wrapped
+ * @return wrapped data
+ * @exception EBaseException failed to wrap
+ */
+ public byte[] wrap(SymmetricKey symKey) throws EBaseException;
+
+ /**
* Verifies the given key pair.
*
* @param publicKey public key
@@ -74,6 +85,46 @@ public interface IEncryptionUnit extends IToken {
throws EBaseException;
/**
+ * Unwraps symmetric key data. This method rebuilds the symmetric key by
+ * unwrapping the private data blob.
+ *
+ * @param wrappedKeyData symmetric key data wrapped up with session key
+ * @return Symmetric key object
+ * @exception EBaseException failed to unwrap
+ */
+
+ public SymmetricKey unwrap(byte wrappedKeyData[])
+ throws EBaseException;
+
+ /**
+ * Unwraps symmetric key . This method
+ * unwraps the symmetric key.
+ *
+ * @param sessionKey session key that unwrap the symmetric key
+ * @param symmAlgOID symmetric algorithm
+ * @param symmAlgParams symmetric algorithm parameters
+ * @param symmetricKey symmetric key data
+ * @return Symmetric key object
+ * @exception EBaseException failed to unwrap
+ */
+
+ public SymmetricKey unwrap_symmetric(byte sessionKey[], String symmAlgOID,
+ byte symmAlgParams[], byte symmetricKey[])
+ throws EBaseException;
+
+ /**
+ * Unwraps symmetric key . This method
+ * unwraps the symmetric key.
+ *
+ * @param encSymmKey wrapped symmetric key to be unwrapped
+ * @return Symmetric key object
+ * @exception EBaseException failed to unwrap
+ */
+
+ public SymmetricKey unwrap_sym(byte encSymmKey[],
+ SymmetricKey.Usage usage);
+
+ /**
* Unwraps data. This method rebuilds the private key by
* unwrapping the private key data.
*
diff --git a/pki/base/common/src/com/netscape/certsrv/security/ITransportKeyUnit.java b/pki/base/common/src/com/netscape/certsrv/security/ITransportKeyUnit.java
index 0a012e8a6..6e1c7ab4a 100644
--- a/pki/base/common/src/com/netscape/certsrv/security/ITransportKeyUnit.java
+++ b/pki/base/common/src/com/netscape/certsrv/security/ITransportKeyUnit.java
@@ -41,16 +41,71 @@ public interface ITransportKeyUnit extends IEncryptionUnit {
*/
public org.mozilla.jss.crypto.X509Certificate getCertificate();
+ /**
+ * Unwraps symmetric key . This method
+ * unwraps the symmetric key.
+ *
+ * @param encSymmKey wrapped symmetric key to be unwrapped
+ * @param usage Key usage for unwrapped key.
+ * @return Symmetric key object
+ * @exception EBaseException failed to unwrap
+ */
+
+ public SymmetricKey unwrap_sym(byte encSymmKey[], SymmetricKey.Usage usage);
+
+ /**
+ * Unwraps symmetric key . This method
+ * unwraps the symmetric key.
+ *
+ * @param encSymmKey wrapped symmetric key to be unwrapped
+ * @return Symmetric key object
+ * @exception EBaseException failed to unwrap
+ */
+
public SymmetricKey unwrap_sym(byte encSymmKey[]);
+ /**
+ * Unwraps symmetric key for encrypton . This method
+ * unwraps the symmetric key.
+ *
+ * @param encSymmKey wrapped symmetric key to be unwrapped
+ * @return Symmetric key object
+ * @exception EBaseException failed to unwrap
+ */
+
public SymmetricKey unwrap_encrypt_sym(byte encSymmKey[]);
+ /**
+ * Unwraps temporary private key . This method
+ * unwraps the temporary private key.
+ *
+ * @param wrappedKeyData wrapped private key to be unwrapped
+ * @param pubKey public key
+ * @return Private key object
+ * @exception EBaseException failed to unwrap
+ */
+
public PrivateKey unwrap_temp(byte wrappedKeyData[], PublicKey
pubKey) throws EBaseException;
+ /**
+ * Returns this Unit's crypto token object.
+ * @return CryptoToken object.
+ */
public CryptoToken getToken();
+ /**
+ * Returns this Unit's signing algorithm in String format.
+ * @return String of signing algorithm
+ * @throws EBaseException
+ */
+
public String getSigningAlgorithm() throws EBaseException;
+ /**
+ * Sets this Unit's signing algorithm.
+ * @param str String of signing algorithm to set.
+ * @throws EBaseException
+ */
public void setSigningAlgorithm(String str) throws EBaseException;
}
diff --git a/pki/base/common/src/com/netscape/cms/servlet/key/KeyResourceService.java b/pki/base/common/src/com/netscape/cms/servlet/key/KeyResourceService.java
index 887820c3f..4888d609f 100644
--- a/pki/base/common/src/com/netscape/cms/servlet/key/KeyResourceService.java
+++ b/pki/base/common/src/com/netscape/cms/servlet/key/KeyResourceService.java
@@ -18,6 +18,7 @@
package com.netscape.cms.servlet.key;
+
import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MultivaluedMap;
@@ -73,11 +74,6 @@ public class KeyResourceService extends CMSResourceService implements KeyResourc
}
private String validateRequest(RecoveryRequestData data) {
- // confirm that at least one wrapping method exists
- if ((data.getTransWrappedSessionKey() == null) && (data.getTransWrappedSessionKey() == null)) {
- // log error
- throw new WebApplicationException(Response.Status.BAD_REQUEST);
- }
// confirm request exists
String reqId = data.getRequestId();
@@ -85,6 +81,14 @@ public class KeyResourceService extends CMSResourceService implements KeyResourc
// log error
throw new WebApplicationException(Response.Status.BAD_REQUEST);
}
+
+ // confirm that at least one wrapping method exists
+ // There must be at least the wrapped session key method.
+ if ((data.getTransWrappedSessionKey() == null)) {
+ // log error
+ throw new WebApplicationException(Response.Status.BAD_REQUEST);
+ }
+
KeyRequestDAO reqDAO = new KeyRequestDAO();
KeyRequestInfo reqInfo;
try {
@@ -117,7 +121,7 @@ public class KeyResourceService extends CMSResourceService implements KeyResourc
}
String keyURL = reqInfo.getKeyURL();
- return keyURL.substring(keyURL.lastIndexOf("/"));
+ return keyURL.substring(keyURL.lastIndexOf("/") + 1);
}
}
diff --git a/pki/base/common/src/com/netscape/cms/servlet/key/KeysResourceService.java b/pki/base/common/src/com/netscape/cms/servlet/key/KeysResourceService.java
index 471abc161..b5032fa86 100644
--- a/pki/base/common/src/com/netscape/cms/servlet/key/KeysResourceService.java
+++ b/pki/base/common/src/com/netscape/cms/servlet/key/KeysResourceService.java
@@ -76,7 +76,7 @@ public class KeysResourceService extends CMSResourceService implements KeysResou
}
if (clientID != null) {
- filter += "(clientID=\'" + clientID + "\')";
+ filter += "(clientID=" + clientID + ")";
matches ++;
}
diff --git a/pki/base/common/src/com/netscape/cms/servlet/key/model/KeyDAO.java b/pki/base/common/src/com/netscape/cms/servlet/key/model/KeyDAO.java
index 5fd17a333..fd9d2d2c0 100644
--- a/pki/base/common/src/com/netscape/cms/servlet/key/model/KeyDAO.java
+++ b/pki/base/common/src/com/netscape/cms/servlet/key/model/KeyDAO.java
@@ -20,8 +20,11 @@ package com.netscape.cms.servlet.key.model;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.Enumeration;
+import java.util.Hashtable;
import java.util.List;
+import javax.ws.rs.WebApplicationException;
+import javax.ws.rs.core.Response;
import javax.ws.rs.core.UriBuilder;
import javax.ws.rs.core.UriInfo;
import com.netscape.certsrv.apps.CMS;
@@ -29,7 +32,12 @@ import com.netscape.certsrv.base.EBaseException;
import com.netscape.certsrv.dbs.keydb.IKeyRecord;
import com.netscape.certsrv.dbs.keydb.IKeyRepository;
import com.netscape.certsrv.kra.IKeyRecoveryAuthority;
+import com.netscape.certsrv.request.IRequest;
+import com.netscape.certsrv.request.IRequestQueue;
+import com.netscape.certsrv.request.RequestId;
+import com.netscape.certsrv.request.RequestStatus;
import com.netscape.cms.servlet.request.model.RecoveryRequestData;
+import com.netscape.kra.SecurityDataRecoveryService;
/**
* @author alee
@@ -38,11 +46,13 @@ import com.netscape.cms.servlet.request.model.RecoveryRequestData;
public class KeyDAO {
private IKeyRepository repo;
+ private IKeyRecoveryAuthority kra;
+ private IRequestQueue queue;
public KeyDAO() {
- IKeyRecoveryAuthority kra = null;
kra = ( IKeyRecoveryAuthority ) CMS.getSubsystem( "kra" );
repo = kra.getKeyRepository();
+ queue = kra.getRequestQueue();
}
/**
* Returns list of keys meeting specified search filter.
@@ -79,18 +89,100 @@ public class KeyDAO {
}
public KeyData getKey(String keyId, RecoveryRequestData data) throws EBaseException {
- KeyData keyData = null;
+ KeyData keyData;
BigInteger serial = new BigInteger(keyId);
- // get wrapped key
+ String rId = data.getRequestId();
+
+ String transWrappedSessionKey;
+ String sessionWrappedPassphrase;
+
+ IRequest request = queue.findRequest(new RequestId(rId));
+
+ if (request == null) {
+ return null;
+ }
+
+ // get wrapped key
IKeyRecord rec = repo.readKeyRecord(serial);
if (rec == null) {
- // key does not exist
- // log the error
return null;
}
- // TODO unwrap the key and wrap with the credential in RecoveryRequestData
- // need to figure out how to do this with jmagne
+
+ Hashtable<String, Object> requestParams = kra.getVolatileRequest(
+ request.getRequestId());
+
+ if(requestParams == null) {
+ throw new EBaseException("Can't obtain Volatile requestParams in KeyDAO.getKey!");
+ }
+
+ String sessWrappedKeyData = (String) requestParams.get(SecurityDataRecoveryService.ATTR_SESS_WRAPPED_DATA);
+ String passWrappedKeyData = (String) requestParams.get(SecurityDataRecoveryService.ATTR_PASS_WRAPPED_DATA);
+ String nonceData = (String) requestParams.get(IRequest.SECURITY_DATA_IV_STRING_OUT);
+
+ if (sessWrappedKeyData != null || passWrappedKeyData != null) {
+ //The recovery process has already placed a valid recovery
+ //package, either session key wrapped or pass wrapped, into the request.
+ //Request already has been processed.
+ keyData = new KeyData();
+
+ } else {
+ // The request has not yet been processed, let's see if the RecoveryRequestData contains
+ // the info now needed to process the recovery request.
+
+ transWrappedSessionKey = data.getTransWrappedSessionKey();
+ sessionWrappedPassphrase = data.getSessionWrappedPassphrase();
+ nonceData = data.getNonceData();
+
+ if(transWrappedSessionKey == null) {
+ //There must be at least a transWrappedSessionKey input provided.
+ //The command AND the request have provided insufficient data, end of the line.
+ throw new EBaseException("Can't retrieve key, insufficient input data!");
+ }
+
+ if (sessionWrappedPassphrase != null) {
+ requestParams.put(IRequest.SECURITY_DATA_SESS_PASS_PHRASE, sessionWrappedPassphrase);
+ }
+
+ if (transWrappedSessionKey != null) {
+ requestParams.put(IRequest.SECURITY_DATA_TRANS_SESS_KEY, transWrappedSessionKey);
+ }
+
+ if (nonceData != null) {
+ requestParams.put(IRequest.SECURITY_DATA_IV_STRING_IN, nonceData);
+ }
+
+ try {
+ // Has to be in this state or it won't go anywhere.
+ request.setRequestStatus(RequestStatus.BEGIN);
+ queue.processRequest(request);
+ } catch (EBaseException e) {
+ kra.destroyVolatileRequest(request.getRequestId());
+ throw new EBaseException(e.toString());
+ }
+
+ nonceData = null;
+ keyData = new KeyData();
+
+ sessWrappedKeyData = (String) requestParams.get(SecurityDataRecoveryService.ATTR_SESS_WRAPPED_DATA);
+ passWrappedKeyData = (String) requestParams.get(SecurityDataRecoveryService.ATTR_PASS_WRAPPED_DATA);
+ nonceData = (String) requestParams.get(IRequest.SECURITY_DATA_IV_STRING_OUT);
+
+ }
+
+ if (sessWrappedKeyData != null) {
+ keyData.setWrappedPrivateData(sessWrappedKeyData);
+ }
+ if (passWrappedKeyData != null) {
+ keyData.setWrappedPrivateData(passWrappedKeyData);
+ }
+ if (nonceData != null) {
+ keyData.setNonceData(nonceData);
+ }
+
+ kra.destroyVolatileRequest(request.getRequestId());
+
+ queue.markAsServiced(request);
return keyData;
}
@@ -103,9 +195,6 @@ public class KeyDAO {
UriBuilder keyBuilder = uriInfo.getBaseUriBuilder();
keyBuilder.path("/key/" + serial);
ret.setKeyURL(keyBuilder.build().toString());
-
- // clientID = rec.getClientID();
- // TODO add other fields as needed
return ret;
}
diff --git a/pki/base/common/src/com/netscape/cms/servlet/key/model/KeyData.java b/pki/base/common/src/com/netscape/cms/servlet/key/model/KeyData.java
index 0e6e80dec..4f303e27d 100644
--- a/pki/base/common/src/com/netscape/cms/servlet/key/model/KeyData.java
+++ b/pki/base/common/src/com/netscape/cms/servlet/key/model/KeyData.java
@@ -36,6 +36,9 @@ public class KeyData {
@XmlElement
String wrappedPrivateData;
+ @XmlElement
+ String nonceData;
+
public KeyData() {
// required for JAXB (defaults)
}
@@ -54,4 +57,20 @@ public class KeyData {
this.wrappedPrivateData = wrappedPrivateData;
}
+ /**
+ * @return the nonceData
+ */
+
+ public String getNonceData() {
+ return nonceData;
+ }
+
+ /**
+ * @param nonceData the nonceData to set
+ */
+
+ public void setNonceData(String nonceData) {
+ this.nonceData = nonceData;
+ }
+
}
diff --git a/pki/base/common/src/com/netscape/cms/servlet/request/KeyRequestResource.java b/pki/base/common/src/com/netscape/cms/servlet/request/KeyRequestResource.java
index 146b03d89..656768f02 100644
--- a/pki/base/common/src/com/netscape/cms/servlet/request/KeyRequestResource.java
+++ b/pki/base/common/src/com/netscape/cms/servlet/request/KeyRequestResource.java
@@ -14,6 +14,9 @@ import com.netscape.cms.servlet.request.model.RecoveryRequestData;
@Path("/keyrequest")
public interface KeyRequestResource {
+ public final String SYMMETRIC_KEY_TYPE = "symmetricKey";
+ public final String PASS_PHRASE_TYPE = "passPhrase";
+ public final String ASYMMETRIC_KEY_TYPE = "asymmetricKey";
/**
* Used to retrieve key request info for a specific request
diff --git a/pki/base/common/src/com/netscape/cms/servlet/request/KeyRequestResourceService.java b/pki/base/common/src/com/netscape/cms/servlet/request/KeyRequestResourceService.java
index da08c4d69..e18407727 100644
--- a/pki/base/common/src/com/netscape/cms/servlet/request/KeyRequestResourceService.java
+++ b/pki/base/common/src/com/netscape/cms/servlet/request/KeyRequestResourceService.java
@@ -69,6 +69,14 @@ public class KeyRequestResourceService extends CMSResourceService implements Key
public KeyRequestInfo archiveKey(ArchivalRequestData data) {
// auth and authz
+ // Catch this before internal server processing has to deal with it
+
+ if (data == null || data.getClientId() == null
+ || data.getWrappedPrivateData() == null
+ || data.getDataType() == null) {
+ throw new WebApplicationException(Response.Status.BAD_REQUEST);
+ }
+
KeyRequestDAO dao = new KeyRequestDAO();
KeyRequestInfo info;
try {
@@ -89,6 +97,15 @@ public class KeyRequestResourceService extends CMSResourceService implements Key
public KeyRequestInfo recoverKey(RecoveryRequestData data) {
// auth and authz
+
+ //Check for entirely illegal data combination here
+ //Catch this before the internal server processing has to deal with it
+ //If data has been provided, we need at least the wrapped session key,
+ //or the command is invalid.
+ if (data == null || (data.getTransWrappedSessionKey() == null
+ && data.getSessionWrappedPassphrase() != null)) {
+ throw new WebApplicationException(Response.Status.BAD_REQUEST);
+ }
KeyRequestDAO dao = new KeyRequestDAO();
KeyRequestInfo info;
try {
@@ -102,6 +119,9 @@ public class KeyRequestResourceService extends CMSResourceService implements Key
}
public void approveRequest(@PathParam("id") String id) {
+ if ( id == null) {
+ throw new WebApplicationException(Response.Status.BAD_REQUEST);
+ }
// auth and authz
KeyRequestDAO dao = new KeyRequestDAO();
try {
@@ -114,6 +134,9 @@ public class KeyRequestResourceService extends CMSResourceService implements Key
}
public void rejectRequest(@PathParam("id") String id) {
+ if ( id == null) {
+ throw new WebApplicationException(Response.Status.BAD_REQUEST);
+ }
// auth and authz
KeyRequestDAO dao = new KeyRequestDAO();
try {
@@ -126,6 +149,9 @@ public class KeyRequestResourceService extends CMSResourceService implements Key
}
public void cancelRequest(@PathParam("id") String id) {
+ if ( id == null) {
+ throw new WebApplicationException(Response.Status.BAD_REQUEST);
+ }
// auth and authz
KeyRequestDAO dao = new KeyRequestDAO();
try {
diff --git a/pki/base/common/src/com/netscape/cms/servlet/request/model/KeyRequestDAO.java b/pki/base/common/src/com/netscape/cms/servlet/request/model/KeyRequestDAO.java
index 16da23d8b..623fa941f 100644
--- a/pki/base/common/src/com/netscape/cms/servlet/request/model/KeyRequestDAO.java
+++ b/pki/base/common/src/com/netscape/cms/servlet/request/model/KeyRequestDAO.java
@@ -19,9 +19,12 @@ package com.netscape.cms.servlet.request.model;
import java.net.URI;
import java.util.ArrayList;
+import java.util.Hashtable;
import java.util.List;
+import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.MultivaluedMap;
+import javax.ws.rs.core.Response;
import javax.ws.rs.core.UriBuilder;
import javax.ws.rs.core.UriInfo;
@@ -35,6 +38,9 @@ import com.netscape.certsrv.request.IRequestVirtualList;
import com.netscape.certsrv.request.RequestId;
import com.netscape.certsrv.request.RequestStatus;
import com.netscape.cms.servlet.base.model.Link;
+import com.netscape.cms.servlet.key.model.KeyDAO;
+import com.netscape.cms.servlet.key.model.KeyDataInfos;
+import com.netscape.certsrv.profile.IEnrollProfile;
/**
* @author alee
@@ -42,6 +48,9 @@ import com.netscape.cms.servlet.base.model.Link;
*/
public class KeyRequestDAO {
private IRequestQueue queue;
+ private IKeyRecoveryAuthority kra;
+
+ private static String REQUEST_ARCHIVE_OPTIONS = IEnrollProfile.REQUEST_ARCHIVE_OPTIONS;
private String[] vlvFilters = {
"(requeststate=*)", "(requesttype=enrollment)",
@@ -56,8 +65,9 @@ public class KeyRequestDAO {
"(&(requeststate=complete)(requesttype=recovery))"
};
+ public static final String ATTR_SERIALNO = "serialNumber";
+
public KeyRequestDAO() {
- IKeyRecoveryAuthority kra = null;
kra = ( IKeyRecoveryAuthority ) CMS.getSubsystem( "kra" );
queue = kra.getRequestQueue();
}
@@ -104,6 +114,10 @@ public class KeyRequestDAO {
// We should think about whether they should be, or if we need to
// limit the number of results returned.
IRequestList requests = queue.listRequestsByFilter(filter, maxResults, maxTime);
+
+ if (requests == null) {
+ return null;
+ }
while (requests.hasMoreElements()) {
RequestId rid = (RequestId) requests.nextElement();
IRequest request = queue.findRequest(rid);
@@ -168,10 +182,26 @@ public class KeyRequestDAO {
* @throws EBaseException
*/
public KeyRequestInfo submitRequest(ArchivalRequestData data, UriInfo uriInfo) throws EBaseException {
+ String clientId = data.getClientId();
+ String wrappedSecurityData = data.getWrappedPrivateData();
+ String dataType = data.getDataType();
+
+ boolean keyExists = doesKeyExist(clientId, "active", uriInfo);
+
+ if(keyExists == true) {
+ throw new EBaseException("Can not archive already active existing key!");
+ }
+
IRequest request = queue.newRequest(IRequest.SECURITY_DATA_ENROLLMENT_REQUEST);
- //TODO :
- //set data using request.setExtData(field, data)
+
+ request.setExtData(REQUEST_ARCHIVE_OPTIONS, wrappedSecurityData);
+ request.setExtData(IRequest.SECURITY_DATA_CLIENT_ID, clientId);
+ request.setExtData(IRequest.SECURITY_DATA_TYPE, dataType);
+
queue.processRequest(request);
+
+ queue.markAsServiced(request);
+
return createKeyRequestInfo(request, uriInfo);
}
/**
@@ -181,25 +211,61 @@ public class KeyRequestDAO {
* @throws EBaseException
*/
public KeyRequestInfo submitRequest(RecoveryRequestData data, UriInfo uriInfo) throws EBaseException {
- IRequest request = queue.newRequest(IRequest.SECURITY_DATA_RECOVERY_REQUEST);
+
// set data using request.setExtData(field, data)
+
+ String wrappedSessionKeyStr = data.getTransWrappedSessionKey();
+ String wrappedPassPhraseStr = data.getSessionWrappedPassphrase();
+ String nonceDataStr = data.getNonceData();
+
+ IRequest request = queue.newRequest(IRequest.SECURITY_DATA_RECOVERY_REQUEST);
+
+ String keyId = data.getKeyId();
+
+ Hashtable<String, Object> requestParams;
+ requestParams = kra.createVolatileRequest(request.getRequestId());
+
+ if(requestParams == null) {
+ throw new EBaseException("Can not create Volatile params in submitRequest!");
+ }
+
+ CMS.debug("Create volatile params for recovery request. " + requestParams);
+
+ if (wrappedPassPhraseStr != null) {
+ requestParams.put(IRequest.SECURITY_DATA_SESS_PASS_PHRASE, wrappedPassPhraseStr);
+ }
+
+ if (wrappedSessionKeyStr != null) {
+ requestParams.put(IRequest.SECURITY_DATA_TRANS_SESS_KEY, wrappedSessionKeyStr);
+ }
+
+ if (nonceDataStr != null) {
+ requestParams.put(IRequest.SECURITY_DATA_IV_STRING_IN, nonceDataStr);
+ }
+
+ request.setExtData(ATTR_SERIALNO,keyId);
+
queue.processRequest(request);
+
return createKeyRequestInfo(request, uriInfo);
}
public void approveRequest(String id) throws EBaseException {
IRequest request = queue.findRequest(new RequestId(id));
request.setRequestStatus(RequestStatus.APPROVED);
+ queue.updateRequest(request);
}
public void rejectRequest(String id) throws EBaseException {
IRequest request = queue.findRequest(new RequestId(id));
request.setRequestStatus(RequestStatus.CANCELED);
+ queue.updateRequest(request);
}
public void cancelRequest(String id) throws EBaseException {
IRequest request = queue.findRequest(new RequestId(id));
request.setRequestStatus(RequestStatus.REJECTED);
+ queue.updateRequest(request);
}
public KeyRequestInfo createKeyRequestInfo(IRequest request, UriInfo uriInfo) {
@@ -229,4 +295,27 @@ public class KeyRequestDAO {
}
return false;
}
+
+ //We only care if the key exists or not
+ private boolean doesKeyExist(String clientId, String keyStatus, UriInfo uriInfo) {
+ boolean ret = false;
+ String state = "active";
+
+ KeyDAO keys = new KeyDAO();
+
+ KeyDataInfos existingKeys;
+ String filter = "(&(" + IRequest.SECURITY_DATA_CLIENT_ID + "=" + clientId + ")"
+ + "(" + IRequest.SECURITY_DATA_STATUS + "=" + state + "))";
+ try {
+ existingKeys = keys.listKeys(filter, 1, 10, uriInfo);
+
+ if(existingKeys != null && existingKeys.getKeyInfos().size() > 0) {
+ ret = true;
+ }
+ } catch (EBaseException e) {
+ ret= false;
+ }
+
+ return ret;
+ }
}
diff --git a/pki/base/common/src/com/netscape/cms/servlet/request/model/RecoveryRequestData.java b/pki/base/common/src/com/netscape/cms/servlet/request/model/RecoveryRequestData.java
index c84d8f491..ae8417542 100644
--- a/pki/base/common/src/com/netscape/cms/servlet/request/model/RecoveryRequestData.java
+++ b/pki/base/common/src/com/netscape/cms/servlet/request/model/RecoveryRequestData.java
@@ -39,6 +39,7 @@ public class RecoveryRequestData {
private static final String REQUEST_ID = "requestId";
private static final String TRANS_WRAPPED_SESSION_KEY = "transWrappedSessionKey";
private static final String SESSION_WRAPPED_PASSPHRASE = "sessionWrappedPassphrase";
+ private static final String NONCE_DATA = "nonceData";
@XmlElement
protected String keyId;
@@ -52,6 +53,9 @@ public class RecoveryRequestData {
@XmlElement
protected String sessionWrappedPassphrase;
+ @XmlElement
+ protected String nonceData;
+
public RecoveryRequestData() {
// required for JAXB (defaults)
}
@@ -61,6 +65,7 @@ public class RecoveryRequestData {
requestId = form.getFirst(REQUEST_ID);
transWrappedSessionKey = form.getFirst(TRANS_WRAPPED_SESSION_KEY);
sessionWrappedPassphrase = form.getFirst(SESSION_WRAPPED_PASSPHRASE);
+ nonceData = form.getFirst(NONCE_DATA);
}
/**
@@ -119,4 +124,20 @@ public class RecoveryRequestData {
this.sessionWrappedPassphrase = sessionWrappedPassphrase;
}
+ /**
+ * @return nonceData
+ */
+
+ public String getNonceData() {
+ return nonceData;
+ }
+
+ /**
+ * @param nonceData the nonceData to set
+ */
+
+ public void setNonceData(String nonceData) {
+ this.nonceData = nonceData;
+ }
+
}
diff --git a/pki/base/common/src/com/netscape/cmscore/dbs/KeyDBSchema.java b/pki/base/common/src/com/netscape/cmscore/dbs/KeyDBSchema.java
index ca9db779b..50b3badc3 100644
--- a/pki/base/common/src/com/netscape/cmscore/dbs/KeyDBSchema.java
+++ b/pki/base/common/src/com/netscape/cmscore/dbs/KeyDBSchema.java
@@ -45,4 +45,7 @@ public class KeyDBSchema {
public static final String LDAP_ATTR_PUBLIC_KEY_FORMAT =
"publicKeyFormat";
public static final String LDAP_ATTR_ARCHIVED_BY = "archivedBy";
+ public static final String LDAP_ATTR_CLIENT_ID = "clientId";
+ public static final String LDAP_ATTR_STATUS = "status";
+ public static final String LDAP_ATTR_DATA_TYPE = "dataType";
}
diff --git a/pki/base/common/src/com/netscape/cmscore/dbs/KeyRecord.java b/pki/base/common/src/com/netscape/cmscore/dbs/KeyRecord.java
index 8f2888715..f7773e3fa 100644
--- a/pki/base/common/src/com/netscape/cmscore/dbs/KeyRecord.java
+++ b/pki/base/common/src/com/netscape/cmscore/dbs/KeyRecord.java
@@ -56,6 +56,10 @@ public class KeyRecord implements IDBObj, IKeyRecord {
private Date mCreateTime = null;
private Date mModifyTime = null;
private String mArchivedBy = null;
+ private String mClientId = null;
+ private String mStatus = null;
+ private String mDataType = null;
+
protected static Vector<String> mNames = new Vector<String>();
static {
@@ -71,6 +75,9 @@ public class KeyRecord implements IDBObj, IKeyRecord {
mNames.addElement(ATTR_CREATE_TIME);
mNames.addElement(ATTR_MODIFY_TIME);
mNames.addElement(ATTR_ARCHIVED_BY);
+ mNames.addElement(ATTR_CLIENT_ID);
+ mNames.addElement(ATTR_STATUS);
+ mNames.addElement(ATTR_DATA_TYPE);
}
/**
@@ -128,6 +135,12 @@ public class KeyRecord implements IDBObj, IKeyRecord {
mModifyTime = (Date) object;
} else if (name.equalsIgnoreCase(ATTR_ARCHIVED_BY)) {
mArchivedBy = (String) object;
+ } else if (name.equalsIgnoreCase(ATTR_CLIENT_ID)) {
+ mClientId = (String) object;
+ } else if (name.equalsIgnoreCase(ATTR_DATA_TYPE)) {
+ mDataType = (String) object;
+ } else if (name.equalsIgnoreCase(ATTR_STATUS)) {
+ mStatus = (String) object;
} else {
throw new EBaseException(com.netscape.certsrv.apps.CMS.getUserMessage("CMS_BASE_INVALID_ATTRIBUTE", name));
}
@@ -162,6 +175,12 @@ public class KeyRecord implements IDBObj, IKeyRecord {
return mMetaInfo;
} else if (name.equalsIgnoreCase(ATTR_ARCHIVED_BY)) {
return mArchivedBy;
+ } else if (name.equalsIgnoreCase(ATTR_CLIENT_ID)) {
+ return mClientId;
+ } else if (name.equalsIgnoreCase(ATTR_DATA_TYPE)) {
+ return mDataType;
+ } else if (name.equalsIgnoreCase(ATTR_STATUS)) {
+ return mStatus;
} else {
throw new EBaseException(com.netscape.certsrv.apps.CMS.getUserMessage("CMS_BASE_INVALID_ATTRIBUTE", name));
}
@@ -342,4 +361,26 @@ public class KeyRecord implements IDBObj, IKeyRecord {
public Date getModifyTime() {
return mModifyTime;
}
+
+ /**
+ * Retrieves the client ID of this record.
+ */
+ public String getClientId() throws EBaseException {
+ return mClientId ;
+ }
+
+ /**
+ * Retrieves the key status of this record.
+ */
+ public String getKeyStatus() throws EBaseException {
+ return mStatus;
+
+ }
+
+ /**
+ * Retrieves the key data type of this record.
+ */
+ public String getDataType() throws EBaseException {
+ return mDataType;
+ }
}
diff --git a/pki/base/common/src/com/netscape/cmscore/dbs/KeyRepository.java b/pki/base/common/src/com/netscape/cmscore/dbs/KeyRepository.java
index 269a94c9d..6219bab0c 100644
--- a/pki/base/common/src/com/netscape/cmscore/dbs/KeyRepository.java
+++ b/pki/base/common/src/com/netscape/cmscore/dbs/KeyRepository.java
@@ -129,6 +129,19 @@ public class KeyRepository extends Repository implements IKeyRepository {
reg.registerAttribute(KeyRecord.ATTR_ARCHIVED_BY, new
StringMapper(KeyDBSchema.LDAP_ATTR_ARCHIVED_BY));
}
+ if (!reg.isAttributeRegistered(KeyRecord.ATTR_CLIENT_ID)) {
+ reg.registerAttribute(KeyRecord.ATTR_CLIENT_ID, new
+ StringMapper(KeyDBSchema.LDAP_ATTR_CLIENT_ID));
+ }
+ if (!reg.isAttributeRegistered(KeyRecord.ATTR_STATUS)) {
+ reg.registerAttribute(KeyRecord.ATTR_STATUS, new
+ StringMapper(KeyDBSchema.LDAP_ATTR_STATUS));
+ }
+ if (!reg.isAttributeRegistered(KeyRecord.ATTR_DATA_TYPE)) {
+ reg.registerAttribute(KeyRecord.ATTR_DATA_TYPE, new
+ StringMapper(KeyDBSchema.LDAP_ATTR_DATA_TYPE));
+ }
+
}
public void setKeyStatusUpdateInterval(IRepository requestRepo, int interval) {
diff --git a/pki/base/kra/functional/src/com/netscape/cms/servlet/test/DRMRestClient.java b/pki/base/kra/functional/src/com/netscape/cms/servlet/test/DRMRestClient.java
index 06d5d961f..4f7de8f84 100644
--- a/pki/base/kra/functional/src/com/netscape/cms/servlet/test/DRMRestClient.java
+++ b/pki/base/kra/functional/src/com/netscape/cms/servlet/test/DRMRestClient.java
@@ -49,12 +49,13 @@ public class DRMRestClient {
return list;
}
- public KeyRequestInfo archiveSecurityData(byte[] encoded, String clientId) {
+ public KeyRequestInfo archiveSecurityData(byte[] encoded, String clientId, String dataType) {
// create archival request
ArchivalRequestData data = new ArchivalRequestData();
String req1 = com.netscape.osutil.OSUtil.BtoA(encoded);
data.setWrappedPrivateData(req1);
data.setClientId(clientId);
+ data.setDataType(dataType);
KeyRequestInfo info = keyRequestClient.archiveKey(data);
return info;
@@ -75,7 +76,7 @@ public class DRMRestClient {
return null;
}
- public KeyRequestInfo requestRecovery(String keyId, byte[] rpwd, byte[] rkey) {
+ public KeyRequestInfo requestRecovery(String keyId, byte[] rpwd, byte[] rkey, byte[] nonceData) {
// create recovery request
RecoveryRequestData data = new RecoveryRequestData();
data.setKeyId(keyId);
@@ -86,6 +87,10 @@ public class DRMRestClient {
data.setTransWrappedSessionKey(com.netscape.osutil.OSUtil.BtoA(rkey));
}
+ if (nonceData != null) {
+ data.setNonceData(com.netscape.osutil.OSUtil.BtoA(nonceData));
+ }
+
KeyRequestInfo info = keyRequestClient.recoverKey(data);
return info;
}
@@ -94,7 +99,7 @@ public class DRMRestClient {
keyRequestClient.approveRequest(recoveryId);
}
- public KeyData retrieveKey(String keyId, String requestId, byte[] rpwd, byte[] rkey) {
+ public KeyData retrieveKey(String keyId, String requestId, byte[] rpwd, byte[] rkey, byte[] nonceData) {
// create recovery request
RecoveryRequestData data = new RecoveryRequestData();
data.setKeyId(keyId);
@@ -105,6 +110,11 @@ public class DRMRestClient {
if (rpwd != null) {
data.setSessionWrappedPassphrase(com.netscape.osutil.OSUtil.BtoA(rpwd));
}
+
+ if (nonceData != null) {
+ data.setNonceData(com.netscape.osutil.OSUtil.BtoA(nonceData));
+ }
+
KeyData key = keyClient.retrieveKey(data);
return key;
}
diff --git a/pki/base/kra/functional/src/com/netscape/cms/servlet/test/DRMTest.java b/pki/base/kra/functional/src/com/netscape/cms/servlet/test/DRMTest.java
index a8560dc2e..7890b96c8 100644
--- a/pki/base/kra/functional/src/com/netscape/cms/servlet/test/DRMTest.java
+++ b/pki/base/kra/functional/src/com/netscape/cms/servlet/test/DRMTest.java
@@ -17,6 +17,7 @@
// --- END COPYRIGHT BLOCK ---
package com.netscape.cms.servlet.test;
+import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.CharConversionException;
import java.io.IOException;
@@ -27,11 +28,13 @@ import java.security.cert.CertificateEncodingException;
import java.util.Calendar;
import java.util.Collection;
import java.util.Iterator;
+import java.util.Random;
+
import org.mozilla.jss.CryptoManager;
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.crypto.AlreadyInitializedException;
import org.mozilla.jss.crypto.BadPaddingException;
import org.mozilla.jss.crypto.Cipher;
@@ -43,13 +46,15 @@ import org.mozilla.jss.crypto.KeyGenAlgorithm;
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.SymmetricKey;
import org.mozilla.jss.crypto.TokenException;
import org.mozilla.jss.crypto.X509Certificate;
+import org.mozilla.jss.pkcs12.PasswordConverter;
+import org.mozilla.jss.pkcs7.EncryptedContentInfo;
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 org.mozilla.jss.util.Password;
@@ -63,6 +68,7 @@ import org.apache.commons.cli.PosixParser;
import com.netscape.cms.servlet.base.CMSResourceService;
import com.netscape.cms.servlet.key.model.KeyData;
import com.netscape.cms.servlet.key.model.KeyDataInfo;
+import com.netscape.cms.servlet.request.KeyRequestResource;
import com.netscape.cms.servlet.request.model.KeyRequestInfo;
@SuppressWarnings("deprecation")
@@ -123,8 +129,16 @@ public class DRMTest {
// used for crypto operations
byte iv[] = { 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1 };
- IVParameterSpec IV = null;
- IV = new IVParameterSpec(iv);
+ IVParameterSpec ivSpec;
+ IVParameterSpec ivSpecServer;
+
+ try {
+ ivSpec = genIV(8);
+ } catch (Exception e) {
+ log("Can't generate initialization vector use default: " + e);
+ ivSpec = new IVParameterSpec(iv);
+ }
+
CryptoManager manager = null;
CryptoToken token = null;
KeyGenerator kg1 = null;
@@ -196,7 +210,7 @@ public class DRMTest {
// Test 2: Get list of completed key archival requests
log("\n\nList of completed archival requests");
- Collection<KeyRequestInfo> list = client.listRequests("complete", "enrollment");
+ Collection<KeyRequestInfo> list = client.listRequests("complete", "securityDataEnrollment");
if (list == null) {
log("No requests found");
} else {
@@ -209,7 +223,7 @@ public class DRMTest {
// Test 3: Get list of key recovery requests
log("\n\nList of completed recovery requests");
- Collection<KeyRequestInfo> list2 = client.listRequests("complete", "recovery");
+ Collection<KeyRequestInfo> list2 = client.listRequests("complete", "securityDataRecovery");
if (list2 == null) {
log("No requests found");
} else {
@@ -226,9 +240,10 @@ public class DRMTest {
try {
kg1 = token.getKeyGenerator(KeyGenAlgorithm.DES3);
vek = kg1.generate();
- byte[] encoded = createPKIArchiveOptions(manager, token, transportCert, vek, null, kg1);
- KeyRequestInfo info = client.archiveSecurityData(encoded, clientId);
+ byte[] encoded = createPKIArchiveOptions(manager, token, transportCert, vek, null, kg1, ivSpec);
+
+ KeyRequestInfo info = client.archiveSecurityData(encoded, clientId, KeyRequestResource.SYMMETRIC_KEY_TYPE);
log("Archival Results:");
printRequestInfo(info);
keyId = getId(info.getKeyURL());
@@ -238,6 +253,7 @@ public class DRMTest {
}
//Test 5: Get keyId for active key with client ID
+
log("Getting key ID for symmetric key");
keyInfo = client.getKeyData(clientId, "active");
String keyId2 = getId(keyInfo.getKeyURL());
@@ -249,6 +265,8 @@ public class DRMTest {
if (!keyId.equals(keyId2)) {
log("Error: key ids from search and archival do not match");
+ } else {
+ log("Success: keyids from search and archival match.");
}
// Test 6: Submit a recovery request for the symmetric key using a session key
@@ -256,7 +274,7 @@ public class DRMTest {
try {
recoveryKey = kg1.generate();
wrappedRecoveryKey = wrapSymmetricKey(manager, token, transportCert, recoveryKey);
- KeyRequestInfo info = client.requestRecovery(keyId, null, wrappedRecoveryKey);
+ KeyRequestInfo info = client.requestRecovery(keyId, null, wrappedRecoveryKey, ivSpec.getIV());
recoveryRequestId = getId(info.getRequestURL());
} catch (Exception e) {
log("Exception in recovering symmetric key using session key: " + e.getMessage());
@@ -269,10 +287,12 @@ public class DRMTest {
// Test 8: Get key
log("Getting key: " + keyId);
- keyData = client.retrieveKey(keyId, recoveryRequestId, null, wrappedRecoveryKey);
+ keyData = client.retrieveKey(keyId, recoveryRequestId, null, wrappedRecoveryKey, ivSpec.getIV());
wrappedRecoveredKey = keyData.getWrappedPrivateData();
+
+ ivSpecServer = new IVParameterSpec( com.netscape.osutil.OSUtil.AtoB(keyData.getNonceData()));
try {
- recoveredKey = unwrap(token, IV, wrappedRecoveredKey.getBytes("ISO-8859-1"), recoveryKey);
+ recoveredKey = unwrap(token, ivSpecServer,com.netscape.osutil.OSUtil.AtoB(wrappedRecoveredKey), recoveryKey);
} catch (Exception e) {
log("Exception in unwrapping key: " + e.toString());
e.printStackTrace();
@@ -280,6 +300,8 @@ public class DRMTest {
if (!recoveredKey.equals(com.netscape.osutil.OSUtil.BtoA(vek.getEncoded()))) {
log("Error: recovered and archived keys do not match!");
+ } else {
+ log("Success: recoverd and archived keys match!");
}
// Test 9: Submit a recovery request for the symmetric key using a passphrase
@@ -288,9 +310,10 @@ public class DRMTest {
try {
recoveryKey = kg1.generate();
- wrappedRecoveryPassphrase = wrapPassphrase(token, recoveryPassphrase, IV, recoveryKey);
+ wrappedRecoveryPassphrase = wrapPassphrase(token, recoveryPassphrase, ivSpec, recoveryKey);
wrappedRecoveryKey = wrapSymmetricKey(manager, token, transportCert, recoveryKey);
- requestInfo = client.requestRecovery(keyId, wrappedRecoveryPassphrase, wrappedRecoveryKey);
+
+ requestInfo = client.requestRecovery(keyId, wrappedRecoveryPassphrase, wrappedRecoveryKey, ivSpec.getIV());
recoveryRequestId = getId(requestInfo.getRequestURL());
} catch (Exception e) {
log("Exception in recovering symmetric key using passphrase" + e.toString());
@@ -303,19 +326,25 @@ public class DRMTest {
// Test 11: Get key
log("Getting key: " + keyId);
- keyData = client.retrieveKey(keyId, recoveryRequestId, wrappedRecoveryPassphrase, wrappedRecoveryKey);
+ keyData = client.retrieveKey(keyId, recoveryRequestId, wrappedRecoveryPassphrase, wrappedRecoveryKey, ivSpec.getIV());
wrappedRecoveredKey = keyData.getWrappedPrivateData();
+
recoveredKey = unwrap(wrappedRecoveredKey, recoveryPassphrase);
- if (!recoveredKey.equals(com.netscape.osutil.OSUtil.BtoA(vek.getEncoded()))) {
+
+ if (recoveredKey == null || !recoveredKey.equals(com.netscape.osutil.OSUtil.BtoA(vek.getEncoded()))) {
log("Error: recovered and archived keys do not match!");
+ } else {
+ log("Success: recovered and archived keys do match!");
}
+
+ passphrase = "secret12345";
// Test 12: Generate and archive a passphrase
clientId = "UUID: 123-45-6789 RKEK " + Calendar.getInstance().getTime().toString();
try {
- byte[] encoded = createPKIArchiveOptions(manager, token, transportCert, null, passphrase, kg1);
- requestInfo = client.archiveSecurityData(encoded, clientId);
+ byte[] encoded = createPKIArchiveOptions(manager, token, transportCert, null, passphrase, kg1, ivSpec);
+ requestInfo = client.archiveSecurityData(encoded, clientId, KeyRequestResource.PASS_PHRASE_TYPE);
log("Archival Results:");
printRequestInfo(requestInfo);
keyId = getId(requestInfo.getKeyURL());
@@ -336,6 +365,8 @@ public class DRMTest {
if (!keyId.equals(keyId2)) {
log("Error: key ids from search and archival do not match");
+ } else {
+ log("Success: key ids from search and archival do match!");
}
// Test 14: Submit a recovery request for the passphrase using a session key
@@ -346,7 +377,8 @@ public class DRMTest {
try {
recoveryKey = kg1.generate();
wrappedRecoveryKey = wrapSymmetricKey(manager, token, transportCert, recoveryKey);
- requestInfo = client.requestRecovery(keyId, null, wrappedRecoveryKey);
+ wrappedRecoveryPassphrase = wrapPassphrase(token, recoveryPassphrase, ivSpec, recoveryKey);
+ requestInfo = client.requestRecovery(keyId, null, wrappedRecoveryKey, ivSpec.getIV());
recoveryRequestId = getId(requestInfo.getRequestURL());
} catch (Exception e) {
log("Exception in recovering passphrase using session key: " + e.getMessage());
@@ -359,22 +391,26 @@ public class DRMTest {
// Test 16: Get key
log("Getting passphrase: " + keyId);
- keyData = client.retrieveKey(keyId, recoveryRequestId, null, wrappedRecoveryKey);
+ keyData = client.retrieveKey(keyId, recoveryRequestId, null, wrappedRecoveryKey, ivSpec.getIV());
wrappedRecoveredKey = keyData.getWrappedPrivateData();
+ ivSpecServer = new IVParameterSpec( com.netscape.osutil.OSUtil.AtoB(keyData.getNonceData()));
try {
- recoveredKey = unwrap(token, IV, wrappedRecoveredKey.getBytes("ISO-8859-1"), recoveryKey);
+ recoveredKey = unwrap(token, ivSpecServer, com.netscape.osutil.OSUtil.AtoB(wrappedRecoveredKey), recoveryKey);
+ recoveredKey = new String(com.netscape.osutil.OSUtil.AtoB(recoveredKey), "UTF-8");
} catch (Exception e) {
log("Exception in unwrapping key: " + e.toString());
e.printStackTrace();
}
- if (!recoveredKey.equals(passphrase)) {
+ if (recoveredKey == null || !recoveredKey.equals(passphrase)) {
log("Error: recovered and archived passphrases do not match!");
+ } else {
+ log("Success: recovered and archived passphrases do match!");
}
// Test 17: Submit a recovery request for the passphrase using a passphrase
log("Submitting a recovery request for the passphrase using a passphrase");
- requestInfo = client.requestRecovery(keyId, wrappedRecoveryPassphrase, wrappedRecoveryKey);
+ requestInfo = client.requestRecovery(keyId, wrappedRecoveryPassphrase, wrappedRecoveryKey, ivSpec.getIV());
recoveryRequestId = getId(requestInfo.getRequestURL());
//Test 18: Approve recovery
@@ -383,19 +419,80 @@ public class DRMTest {
// Test 19: Get key
log("Getting passphrase: " + keyId);
- keyData = client.retrieveKey(keyId, recoveryRequestId, wrappedRecoveryPassphrase, wrappedRecoveryKey);
+ keyData = client.retrieveKey(keyId, recoveryRequestId, wrappedRecoveryPassphrase, wrappedRecoveryKey, ivSpec.getIV());
wrappedRecoveredKey = keyData.getWrappedPrivateData();
recoveredKey = unwrap(wrappedRecoveredKey, recoveryPassphrase);
+ try {
+ recoveredKey = new String(com.netscape.osutil.OSUtil.AtoB(recoveredKey), "UTF-8");
+ } catch (Exception e) {
+ log("Error: Can't convert recovered passphrase from binary to ascii!");
+ }
- if (!recoveredKey.equals(passphrase)) {
+ if (recoveredKey == null || !recoveredKey.equals(passphrase)) {
log("Error: recovered and archived passphrases do not match!");
+ } else {
+ log("Success: recovered and archived passphrases do match!");
+ }
+
+ // Test 20: Submit a recovery request for the passphrase using a passphrase
+ //Wait until retrieving key before sending input data.
+
+ log("Submitting a recovery request for the passphrase using a passphrase, wait till end to provide recovery data.");
+ requestInfo = client.requestRecovery(keyId, null, null, null);
+ recoveryRequestId = getId(requestInfo.getRequestURL());
+
+ //Test 21: Approve recovery
+ log("Approving recovery request: " + recoveryRequestId);
+ client.approveRecovery(recoveryRequestId);
+
+ // Test 22: Get key
+ log("Getting passphrase: " + keyId);
+ keyData = client.retrieveKey(keyId, recoveryRequestId, wrappedRecoveryPassphrase, wrappedRecoveryKey, ivSpec.getIV());
+ wrappedRecoveredKey = keyData.getWrappedPrivateData();
+ recoveredKey = unwrap(wrappedRecoveredKey, recoveryPassphrase);
+ try {
+ recoveredKey = new String(com.netscape.osutil.OSUtil.AtoB(recoveredKey), "UTF-8");
+ } catch (Exception e) {
+ log("Error: Can't convert recovered passphrase from binary to ascii!");
}
+ if (recoveredKey == null || !recoveredKey.equals(passphrase)) {
+ log("Error: recovered and archived passphrases do not match!");
+ } else {
+ log("Success: recovered and archived passphrases do match!");
+ }
}
private static String unwrap(String wrappedRecoveredKey, String recoveryPassphrase) {
- // TODO Auto-generated method stub
- return null;
+
+ EncryptedContentInfo cInfo = null;
+ String unwrappedData = null;
+
+ //We have to do this to get the decoding to work.
+ PBEAlgorithm pbeAlg = PBEAlgorithm.PBE_SHA1_DES3_CBC;
+
+ log("pbeAlg: " + pbeAlg);
+ try {
+ Password pass = new Password(recoveryPassphrase.toCharArray());
+ PasswordConverter passConverter = new
+ PasswordConverter();
+
+ byte[] encoded = com.netscape.osutil.OSUtil.AtoB(wrappedRecoveredKey);
+
+ ByteArrayInputStream inStream = new ByteArrayInputStream(encoded);
+ cInfo = (EncryptedContentInfo)
+ new EncryptedContentInfo.Template().decode(inStream);
+
+ byte[] decodedData = cInfo.decrypt(pass, passConverter);
+
+ unwrappedData = com.netscape.osutil.OSUtil.BtoA(decodedData);
+
+ } catch (Exception e) {
+ log("Problem unwraping PBE wrapped datat! " + e.toString());
+
+ }
+
+ return unwrappedData;
}
private static void log(String string) {
@@ -407,31 +504,24 @@ public class DRMTest {
SymmetricKey recoveryKey) throws NoSuchAlgorithmException, TokenException, BadPaddingException,
IllegalBlockSizeException, InvalidKeyException, InvalidAlgorithmParameterException {
- if (wrappedRecoveredKey == null || recoveryKey == null || token == null) {
- return null;
- }
-
Cipher decryptor = token.getCipherContext(EncryptionAlgorithm.DES3_CBC_PAD);
decryptor.initDecrypt(recoveryKey, IV);
byte[] unwrappedData = decryptor.doFinal(wrappedRecoveredKey);
- String unwrappedS = new String(unwrappedData);
+ String unwrappedS = com.netscape.osutil.OSUtil.BtoA( unwrappedData);
return unwrappedS;
}
private static String getId(String link) {
- return link.substring(link.lastIndexOf("/"));
+ return link.substring(link.lastIndexOf("/") + 1);
}
private static byte[] createPKIArchiveOptions(CryptoManager manager, CryptoToken token, String transportCert,
- SymmetricKey vek, String passphrase, KeyGenerator kg1) throws TokenException, CharConversionException,
+ SymmetricKey vek, String passphrase, KeyGenerator kg1, IVParameterSpec IV) throws TokenException, CharConversionException,
NoSuchAlgorithmException, InvalidKeyException, InvalidAlgorithmParameterException,
CertificateEncodingException, IOException, IllegalStateException, IllegalBlockSizeException,
BadPaddingException {
byte[] key_data = null;
- byte iv[] = { 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1 };
- IVParameterSpec IV = null;
- IV = new IVParameterSpec(iv);
//generate session key
SymmetricKey sk = kg1.generate();
@@ -450,17 +540,35 @@ public class DRMTest {
// create PKIArchiveOptions structure
AlgorithmIdentifier algS = new AlgorithmIdentifier(new OBJECT_IDENTIFIER("1.2.840.113549.3.7"),
- new OCTET_STRING(iv));
+ new OCTET_STRING(IV.getIV()));
EncryptedValue encValue = new EncryptedValue(null, algS, new BIT_STRING(session_data, 0), null, null,
new BIT_STRING(key_data, 0));
EncryptedKey key = new EncryptedKey(encValue);
PKIArchiveOptions opt = new PKIArchiveOptions(key);
- SEQUENCE seq = new SEQUENCE();
- seq.addElement(new AVA(new OBJECT_IDENTIFIER("1.3.6.1.5.5.7.5.1.4"), opt));
- ByteArrayOutputStream bo = new ByteArrayOutputStream();
- seq.encode(bo);
- byte[] encoded = bo.toByteArray();
+ byte[] encoded = null;
+
+ try {
+
+ //Let's make sure we can decode the encoded PKIArchiveOptions..
+ ByteArrayOutputStream oStream = new ByteArrayOutputStream();
+
+ opt.encode(oStream);
+
+ encoded = oStream.toByteArray();
+ ByteArrayInputStream inStream = new ByteArrayInputStream( encoded);
+ PKIArchiveOptions options = (PKIArchiveOptions)
+ new PKIArchiveOptions.Template().decode(inStream);
+ log("Decoded PKIArchiveOptions: " + options);
+ } catch (IOException e) {
+ log("Problem with PKIArchiveOptions: " + e.toString());
+ return null;
+
+ } catch (InvalidBERException e) {
+ log("Problem with PKIArchiveOptions: " + e.toString());
+ return null;
+ }
+
return encoded;
}
@@ -470,28 +578,16 @@ public class DRMTest {
byte[] wrappedPassphrase = null;
Cipher encryptor = null;
- if (passphrase == null || sk == null || token == null || IV == null) {
- return null;
- }
-
encryptor = token.getCipherContext(EncryptionAlgorithm.DES3_CBC_PAD);
log("cipher " + encryptor);
if (encryptor != null) {
encryptor.initEncrypt(sk, IV);
- wrappedPassphrase = encryptor.doFinal(passphrase.getBytes());
- log("Pass phrase mode key_data: " + wrappedPassphrase);
-
- // Try to decrypt
- String wrappedS = new String(wrappedPassphrase, "ISO-8859-1");
- byte[] pPhrase = wrappedS.getBytes("ISO-8859-1");
- encryptor.initDecrypt(sk, IV);
- byte[] decrypted = encryptor.doFinal(pPhrase);
- String s = new String(decrypted, "ISO-8859-1");
- log("Re decrypted pass phrase " + s + " decrypted.size " + decrypted.length);
+ wrappedPassphrase = encryptor.doFinal(passphrase.getBytes("UTF-8"));
} else {
throw new IOException("Failed to create cipher");
}
+
return wrappedPassphrase;
}
@@ -513,4 +609,14 @@ public class DRMTest {
log("Type: " + info.getRequestType());
}
+ //Use this when we actually create random initialization vectors
+ private static IVParameterSpec genIV(int blockSize) throws Exception {
+ // generate an IV
+ byte[] iv = new byte[blockSize];
+
+ Random rnd = new Random();
+ rnd.nextBytes(iv);
+
+ return new IVParameterSpec(iv);
+ }
}
diff --git a/pki/base/kra/shared/conf/index.ldif b/pki/base/kra/shared/conf/index.ldif
index c1eecc19d..4bc8aebf9 100644
--- a/pki/base/kra/shared/conf/index.ldif
+++ b/pki/base/kra/shared/conf/index.ldif
@@ -19,6 +19,27 @@ nsIndexType: eq
nsSystemIndex: false
cn: publicKeyData
+dn: cn=clientId,cn=index,cn={database},cn=ldbm database, cn=plugins, cn=config
+objectClass: top
+objectClass: nsIndex
+nsIndexType: eq
+nsSystemIndex: false
+cn: clientId
+
+dn: cn=dataType,cn=index,cn={database},cn=ldbm database, cn=plugins, cn=config
+objectClass: top
+objectClass: nsIndex
+nsIndexType: eq
+nsSystemIndex: false
+cn: dataType
+
+dn: cn=status,cn=index,cn={database},cn=ldbm database, cn=plugins, cn=config
+objectClass: top
+objectClass: nsIndex
+nsIndexType: eq
+nsSystemIndex: false
+cn: status
+
dn: cn=description,cn=index,cn={database},cn=ldbm database, cn=plugins, cn=config
objectClass: top
objectClass: nsIndex
diff --git a/pki/base/kra/shared/conf/schema.ldif b/pki/base/kra/shared/conf/schema.ldif
index caf71e965..70578e21c 100644
--- a/pki/base/kra/shared/conf/schema.ldif
+++ b/pki/base/kra/shared/conf/schema.ldif
@@ -161,6 +161,21 @@ attributeTypes: ( keySize-oid NAME 'keySize' DESC 'CMS defined attribute' SYNTAX
dn: cn=schema
changetype: modify
add: attributeTypes
+attributeTypes: ( clientId-oid NAME 'clientId' DESC 'CMS defined attribute' SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 X-ORIGIN 'user defined' )
+
+dn: cn=schema
+changetype: modify
+add: attributeTypes
+attributeTypes: ( dataType-oid NAME 'dataType' DESC 'CMS defined attribute' SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 X-ORIGIN 'user defined' )
+
+dn: cn=schema
+changetype: modify
+add: attributeTypes
+attributeTypes: ( status-oid NAME 'status' DESC 'CMS defined attribute' SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 X-ORIGIN 'user defined' )
+
+dn: cn=schema
+changetype: modify
+add: attributeTypes
attributeTypes: ( keyState-oid NAME 'keyState' DESC 'CMS defined attribute' SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 X-ORIGIN 'user defined' )
dn: cn=schema
@@ -446,7 +461,7 @@ objectClasses: ( userDetails-oid NAME 'userDetails' DESC 'CMS defined class' SUP
dn: cn=schema
changetype: modify
add: objectClasses
-objectClasses: ( keyRecord-oid NAME 'keyRecord' DESC 'CMS defined class' SUP top STRUCTURAL MUST cn MAY ( serialno $ dateOfCreate $ dateOfModify $ keyState $ privateKeyData $ ownerName $ keySize $ metaInfo $ dateOfArchival $ dateOfRecovery $ algorithm $ publicKeyFormat $ publicKeyData $ archivedBy ) X-ORIGIN 'user defined' )
+objectClasses: ( keyRecord-oid NAME 'keyRecord' DESC 'CMS defined class' SUP top STRUCTURAL MUST cn MAY ( serialno $ dateOfCreate $ dateOfModify $ keyState $ privateKeyData $ ownerName $ keySize $ metaInfo $ dateOfArchival $ dateOfRecovery $ algorithm $ publicKeyFormat $ publicKeyData $ archivedBy $ clientId $ dataType $ status ) X-ORIGIN 'user defined' )
dn: cn=schema
changetype: modify
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
diff --git a/pki/base/ocsp/shared/conf/index.ldif b/pki/base/ocsp/shared/conf/index.ldif
index 567b707c8..184187045 100644
--- a/pki/base/ocsp/shared/conf/index.ldif
+++ b/pki/base/ocsp/shared/conf/index.ldif
@@ -24,6 +24,27 @@ nsIndexType: eq
nsSystemIndex: false
cn: publicKeyData
+dn: cn=clientId,cn=index,cn={database},cn=ldbm database, cn=plugins, cn=config
+objectClass: top
+objectClass: nsIndex
+nsIndexType: eq
+nsSystemIndex: false
+cn: clientId
+
+dn: cn=dataType,cn=index,cn={database},cn=ldbm database, cn=plugins, cn=config
+objectClass: top
+objectClass: nsIndex
+nsIndexType: eq
+nsSystemIndex: false
+cn: dataType
+
+dn: cn=status,cn=index,cn={database},cn=ldbm database, cn=plugins, cn=config
+objectClass: top
+objectClass: nsIndex
+nsIndexType: eq
+nsSystemIndex: false
+cn: status
+
dn: cn=description,cn=index,cn={database},cn=ldbm database, cn=plugins, cn=config
objectClass: top
objectClass: nsIndex
diff --git a/pki/base/ocsp/shared/conf/schema.ldif b/pki/base/ocsp/shared/conf/schema.ldif
index caf71e965..70578e21c 100644
--- a/pki/base/ocsp/shared/conf/schema.ldif
+++ b/pki/base/ocsp/shared/conf/schema.ldif
@@ -161,6 +161,21 @@ attributeTypes: ( keySize-oid NAME 'keySize' DESC 'CMS defined attribute' SYNTAX
dn: cn=schema
changetype: modify
add: attributeTypes
+attributeTypes: ( clientId-oid NAME 'clientId' DESC 'CMS defined attribute' SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 X-ORIGIN 'user defined' )
+
+dn: cn=schema
+changetype: modify
+add: attributeTypes
+attributeTypes: ( dataType-oid NAME 'dataType' DESC 'CMS defined attribute' SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 X-ORIGIN 'user defined' )
+
+dn: cn=schema
+changetype: modify
+add: attributeTypes
+attributeTypes: ( status-oid NAME 'status' DESC 'CMS defined attribute' SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 X-ORIGIN 'user defined' )
+
+dn: cn=schema
+changetype: modify
+add: attributeTypes
attributeTypes: ( keyState-oid NAME 'keyState' DESC 'CMS defined attribute' SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 X-ORIGIN 'user defined' )
dn: cn=schema
@@ -446,7 +461,7 @@ objectClasses: ( userDetails-oid NAME 'userDetails' DESC 'CMS defined class' SUP
dn: cn=schema
changetype: modify
add: objectClasses
-objectClasses: ( keyRecord-oid NAME 'keyRecord' DESC 'CMS defined class' SUP top STRUCTURAL MUST cn MAY ( serialno $ dateOfCreate $ dateOfModify $ keyState $ privateKeyData $ ownerName $ keySize $ metaInfo $ dateOfArchival $ dateOfRecovery $ algorithm $ publicKeyFormat $ publicKeyData $ archivedBy ) X-ORIGIN 'user defined' )
+objectClasses: ( keyRecord-oid NAME 'keyRecord' DESC 'CMS defined class' SUP top STRUCTURAL MUST cn MAY ( serialno $ dateOfCreate $ dateOfModify $ keyState $ privateKeyData $ ownerName $ keySize $ metaInfo $ dateOfArchival $ dateOfRecovery $ algorithm $ publicKeyFormat $ publicKeyData $ archivedBy $ clientId $ dataType $ status ) X-ORIGIN 'user defined' )
dn: cn=schema
changetype: modify
diff --git a/pki/base/tks/shared/conf/index.ldif b/pki/base/tks/shared/conf/index.ldif
index 567b707c8..184187045 100644
--- a/pki/base/tks/shared/conf/index.ldif
+++ b/pki/base/tks/shared/conf/index.ldif
@@ -24,6 +24,27 @@ nsIndexType: eq
nsSystemIndex: false
cn: publicKeyData
+dn: cn=clientId,cn=index,cn={database},cn=ldbm database, cn=plugins, cn=config
+objectClass: top
+objectClass: nsIndex
+nsIndexType: eq
+nsSystemIndex: false
+cn: clientId
+
+dn: cn=dataType,cn=index,cn={database},cn=ldbm database, cn=plugins, cn=config
+objectClass: top
+objectClass: nsIndex
+nsIndexType: eq
+nsSystemIndex: false
+cn: dataType
+
+dn: cn=status,cn=index,cn={database},cn=ldbm database, cn=plugins, cn=config
+objectClass: top
+objectClass: nsIndex
+nsIndexType: eq
+nsSystemIndex: false
+cn: status
+
dn: cn=description,cn=index,cn={database},cn=ldbm database, cn=plugins, cn=config
objectClass: top
objectClass: nsIndex
diff --git a/pki/base/tks/shared/conf/schema.ldif b/pki/base/tks/shared/conf/schema.ldif
index caf71e965..70578e21c 100644
--- a/pki/base/tks/shared/conf/schema.ldif
+++ b/pki/base/tks/shared/conf/schema.ldif
@@ -161,6 +161,21 @@ attributeTypes: ( keySize-oid NAME 'keySize' DESC 'CMS defined attribute' SYNTAX
dn: cn=schema
changetype: modify
add: attributeTypes
+attributeTypes: ( clientId-oid NAME 'clientId' DESC 'CMS defined attribute' SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 X-ORIGIN 'user defined' )
+
+dn: cn=schema
+changetype: modify
+add: attributeTypes
+attributeTypes: ( dataType-oid NAME 'dataType' DESC 'CMS defined attribute' SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 X-ORIGIN 'user defined' )
+
+dn: cn=schema
+changetype: modify
+add: attributeTypes
+attributeTypes: ( status-oid NAME 'status' DESC 'CMS defined attribute' SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 X-ORIGIN 'user defined' )
+
+dn: cn=schema
+changetype: modify
+add: attributeTypes
attributeTypes: ( keyState-oid NAME 'keyState' DESC 'CMS defined attribute' SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 X-ORIGIN 'user defined' )
dn: cn=schema
@@ -446,7 +461,7 @@ objectClasses: ( userDetails-oid NAME 'userDetails' DESC 'CMS defined class' SUP
dn: cn=schema
changetype: modify
add: objectClasses
-objectClasses: ( keyRecord-oid NAME 'keyRecord' DESC 'CMS defined class' SUP top STRUCTURAL MUST cn MAY ( serialno $ dateOfCreate $ dateOfModify $ keyState $ privateKeyData $ ownerName $ keySize $ metaInfo $ dateOfArchival $ dateOfRecovery $ algorithm $ publicKeyFormat $ publicKeyData $ archivedBy ) X-ORIGIN 'user defined' )
+objectClasses: ( keyRecord-oid NAME 'keyRecord' DESC 'CMS defined class' SUP top STRUCTURAL MUST cn MAY ( serialno $ dateOfCreate $ dateOfModify $ keyState $ privateKeyData $ ownerName $ keySize $ metaInfo $ dateOfArchival $ dateOfRecovery $ algorithm $ publicKeyFormat $ publicKeyData $ archivedBy $ clientId $ dataType $ status ) X-ORIGIN 'user defined' )
dn: cn=schema
changetype: modify