>From 0de329c17a0bc24176f196a96dc7939fe2f368ea Mon Sep 17 00:00:00 2001
From: Ade Lee <alee@redhat.com>
Date: Tue, 4 Feb 2014 13:17:18 -0500
Subject: [PATCH] Fix DRM archival, recovery and generation for non-DES3 keys.

In the archival, recovery and generation code for symmetric keys,
we use functions that require knowledge of the symmetric keys algorithm
and key size.  These were hardcoded to DES3, and so only DES3 worked.

We added those parameters to the archival request, save them in the
KeyRecord and retrive them when recovering the key.

Tests have been added to DRMTest for the relevant usages.
---
 .../netscape/certsrv/key/KeyArchivalRequest.java   | 34 ++++++++
 .../netscape/certsrv/key/KeyRequestResource.java   |  8 ++
 .../certsrv/key/SymKeyGenerationRequest.java       | 10 +--
 .../src/com/netscape/certsrv/kra/KRAClient.java    |  4 +-
 .../src/com/netscape/certsrv/request/IRequest.java |  2 +
 .../netscape/certsrv/security/IEncryptionUnit.java |  7 +-
 .../src/com/netscape/cms/servlet/test/DRMTest.java | 94 ++++++++++++++++++++--
 base/kra/src/com/netscape/kra/EncryptionUnit.java  | 11 +--
 .../netscape/kra/SecurityDataRecoveryService.java  |  5 +-
 .../src/com/netscape/kra/SecurityDataService.java  | 13 ++-
 .../kra/src/com/netscape/kra/SymKeyGenService.java |  2 +
 .../netscape/cms/servlet/key/KeyRequestDAO.java    | 11 +++
 .../cms/servlet/request/KeyRequestService.java     | 31 +++++--
 13 files changed, 200 insertions(+), 32 deletions(-)

diff --git a/base/common/src/com/netscape/certsrv/key/KeyArchivalRequest.java b/base/common/src/com/netscape/certsrv/key/KeyArchivalRequest.java
index 1655fdb283fa0d7af0a12e29acc04e05e459e4d0..bb25974e90b4aed0cf49a0c59b63386d682455d6 100644
--- a/base/common/src/com/netscape/certsrv/key/KeyArchivalRequest.java
+++ b/base/common/src/com/netscape/certsrv/key/KeyArchivalRequest.java
@@ -39,6 +39,8 @@ public class KeyArchivalRequest extends ResourceMessage {
     private static final String CLIENT_ID = "clientID";
     private static final String DATA_TYPE = "dataType";
     private static final String WRAPPED_PRIVATE_DATA = "wrappedPrivateData";
+    private static final String KEY_ALGORITHM = "keyAlgorithm";
+    private static final String KEY_STRENGTH = "keyStrength";
 
     public KeyArchivalRequest() {
         // required for JAXB (defaults)
@@ -49,6 +51,8 @@ public class KeyArchivalRequest extends ResourceMessage {
         attributes.put(CLIENT_ID, form.getFirst(CLIENT_ID));
         attributes.put(DATA_TYPE, form.getFirst(DATA_TYPE));
         attributes.put(WRAPPED_PRIVATE_DATA, form.getFirst(WRAPPED_PRIVATE_DATA));
+        attributes.put(KEY_ALGORITHM, form.getFirst(KEY_ALGORITHM));
+        attributes.put(KEY_STRENGTH, form.getFirst(KEY_STRENGTH));
         setClassName(getClass().getName());
     }
 
@@ -99,6 +103,34 @@ public class KeyArchivalRequest extends ResourceMessage {
         attributes.put(WRAPPED_PRIVATE_DATA, wrappedPrivateData);
     }
 
+    /**
+     * @return the keyAlgorithm (valid for symmetric keys)
+     */
+    public String getKeyAlgorithm() {
+        return attributes.get(KEY_ALGORITHM);
+    }
+
+    /**
+     * @param algorithm the key algorithm to set (valid for symmetric keys)
+     */
+    public void setKeyAlgorithm(String algorithm) {
+        attributes.put(KEY_ALGORITHM, algorithm);
+    }
+
+    /**
+     * @return the key strength (valid for symmetric keys)
+     */
+    public int getKeyStrength() {
+        return Integer.parseInt(attributes.get(KEY_STRENGTH));
+    }
+
+    /**
+     * @param strength the key strength to set (valid for symmetric keys)
+     */
+    public void setKeyStrength(int strength) {
+        attributes.put(KEY_STRENGTH, Integer.toString(strength));
+    }
+
     public String toString() {
         try {
             return ResourceMessage.marshal(this, KeyArchivalRequest.class);
@@ -121,6 +153,8 @@ public class KeyArchivalRequest extends ResourceMessage {
         before.setClientId("vek 12345");
         before.setDataType(KeyRequestResource.SYMMETRIC_KEY_TYPE);
         before.setWrappedPrivateData("XXXXABCDEFXXX");
+        before.setKeyAlgorithm(KeyRequestResource.AES_ALGORITHM);
+        before.setKeyStrength(128);
 
         String string = before.toString();
         System.out.println(string);
diff --git a/base/common/src/com/netscape/certsrv/key/KeyRequestResource.java b/base/common/src/com/netscape/certsrv/key/KeyRequestResource.java
index 27f0362a1cca17224d7e441eac00ae646ee60d6a..81cca7b41622b788c1998df9eef458fc8aca8051 100644
--- a/base/common/src/com/netscape/certsrv/key/KeyRequestResource.java
+++ b/base/common/src/com/netscape/certsrv/key/KeyRequestResource.java
@@ -28,6 +28,14 @@ public interface KeyRequestResource {
     public static final String PASS_PHRASE_TYPE = "passPhrase";
     public static final String ASYMMETRIC_KEY_TYPE = "asymmetricKey";
 
+    /* Symmetric Key Algorithms */
+    public static final String DES_ALGORITHM = "DES";
+    public static final String DESEDE_ALGORITHM = "DESede";
+    public static final String DES3_ALGORITHM = "DES3";
+    public static final String RC2_ALGORITHM = "RC2";
+    public static final String RC4_ALGORITHM = "RC4";
+    public static final String AES_ALGORITHM = "AES";
+
     /**
      * Used to generate list of key requests based on the search parameters
      */
diff --git a/base/common/src/com/netscape/certsrv/key/SymKeyGenerationRequest.java b/base/common/src/com/netscape/certsrv/key/SymKeyGenerationRequest.java
index f9feb6410c2b0b47084ceeebc0355c6d7940b95a..c0445e455e14011c53ab3e1ff3f5c81b3749cfeb 100644
--- a/base/common/src/com/netscape/certsrv/key/SymKeyGenerationRequest.java
+++ b/base/common/src/com/netscape/certsrv/key/SymKeyGenerationRequest.java
@@ -26,14 +26,6 @@ public class SymKeyGenerationRequest extends ResourceMessage {
     private static final String KEY_ALGORITHM = "keyAlgorithm";
     private static final String KEY_USAGE = "keyUsage";
 
-    /* Symmetric Key Algorithms */
-    public static final String DES_ALGORITHM = "DES";
-    public static final String DESEDE_ALGORITHM = "DESede";
-    public static final String DES3_ALGORITHM = "DES3";
-    public static final String RC2_ALGORITHM = "RC2";
-    public static final String RC4_ALGORITHM = "RC4";
-    public static final String AES_ALGORITHM = "AES";
-
     /* Symmetric Key usages */
     public static final String UWRAP_USAGE = "unwrap";
     public static final String WRAP_USAGE = "wrap";
@@ -148,7 +140,7 @@ public class SymKeyGenerationRequest extends ResourceMessage {
 
         SymKeyGenerationRequest before = new SymKeyGenerationRequest();
         before.setClientId("vek 12345");
-        before.setKeyAlgorithm(SymKeyGenerationRequest.AES_ALGORITHM);
+        before.setKeyAlgorithm(KeyRequestResource.AES_ALGORITHM);
         before.setKeySize(128);
         before.addUsage(SymKeyGenerationRequest.DECRYPT_USAGE);
         before.addUsage(SymKeyGenerationRequest.ENCRYPT_USAGE);
diff --git a/base/common/src/com/netscape/certsrv/kra/KRAClient.java b/base/common/src/com/netscape/certsrv/kra/KRAClient.java
index 943a6f21f0b3f675cb0c5e6fe40569277c6593ef..76e321ac87c9ac53b784e0c303c78de33587eb5c 100644
--- a/base/common/src/com/netscape/certsrv/kra/KRAClient.java
+++ b/base/common/src/com/netscape/certsrv/kra/KRAClient.java
@@ -69,13 +69,15 @@ public class KRAClient extends SubsystemClient {
         return list;
     }
 
-    public KeyRequestInfo archiveSecurityData(byte[] encoded, String clientId, String dataType) {
+    public KeyRequestInfo archiveSecurityData(byte[] encoded, String clientId, String dataType, String algorithm, int strength) {
         // create archival request
         KeyArchivalRequest data = new KeyArchivalRequest();
         String req1 = Utils.base64encode(encoded);
         data.setWrappedPrivateData(req1);
         data.setClientId(clientId);
         data.setDataType(dataType);
+        data.setKeyAlgorithm(algorithm);
+        data.setKeyStrength(strength);
 
         @SuppressWarnings("unchecked")
         ClientResponse<KeyRequestInfo> response = (ClientResponse<KeyRequestInfo>)
diff --git a/base/common/src/com/netscape/certsrv/request/IRequest.java b/base/common/src/com/netscape/certsrv/request/IRequest.java
index 3b3886298b33322951757ee59393d98752a2d865..3dba97a5ee728ba4f510607bd1419aad4a457f87 100644
--- a/base/common/src/com/netscape/certsrv/request/IRequest.java
+++ b/base/common/src/com/netscape/certsrv/request/IRequest.java
@@ -157,6 +157,8 @@ public interface IRequest extends Serializable {
     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_STRENGTH = "strength";
+    public static final String SECURITY_DATA_ALGORITHM = "algorithm";
     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";
diff --git a/base/common/src/com/netscape/certsrv/security/IEncryptionUnit.java b/base/common/src/com/netscape/certsrv/security/IEncryptionUnit.java
index 55bd563186fb182697009405a76f0ab35a7ac534..6e4b9252c43ffad23a38ad47809f2290a537e852 100644
--- a/base/common/src/com/netscape/certsrv/security/IEncryptionUnit.java
+++ b/base/common/src/com/netscape/certsrv/security/IEncryptionUnit.java
@@ -21,6 +21,7 @@ import java.security.PublicKey;
 
 import org.mozilla.jss.crypto.PrivateKey;
 import org.mozilla.jss.crypto.SymmetricKey;
+import org.mozilla.jss.crypto.SymmetricKey.Type;
 
 import com.netscape.certsrv.base.EBaseException;
 
@@ -111,7 +112,7 @@ public interface IEncryptionUnit extends IToken {
      * @exception EBaseException failed to unwrap
      */
 
-    public SymmetricKey unwrap(byte wrappedKeyData[])
+    public SymmetricKey unwrap(byte wrappedKeyData[], SymmetricKey.Type algorithm, int keySize)
             throws EBaseException;
 
     /**
@@ -122,12 +123,14 @@ public interface IEncryptionUnit extends IToken {
      * @param symmAlgOID symmetric algorithm
      * @param symmAlgParams symmetric algorithm parameters
      * @param symmetricKey  symmetric key data
+     * @param type symmetric key algorithm
+     * @param strength symmetric key strength in bytes
      * @return Symmetric key object
      * @exception EBaseException failed to unwrap
      */
 
     public SymmetricKey unwrap_symmetric(byte sessionKey[], String symmAlgOID,
-            byte symmAlgParams[], byte symmetricKey[])
+            byte symmAlgParams[], byte symmetricKey[], Type type, int strength)
             throws EBaseException;
 
     /**
diff --git a/base/kra/functional/src/com/netscape/cms/servlet/test/DRMTest.java b/base/kra/functional/src/com/netscape/cms/servlet/test/DRMTest.java
index e1e730d82219799fdec465a321aef70489a5d86c..05995f614c160875985b781571d42c4e1e02cf49 100644
--- a/base/kra/functional/src/com/netscape/cms/servlet/test/DRMTest.java
+++ b/base/kra/functional/src/com/netscape/cms/servlet/test/DRMTest.java
@@ -36,6 +36,7 @@ import org.mozilla.jss.crypto.CryptoToken;
 import org.mozilla.jss.crypto.EncryptionAlgorithm;
 import org.mozilla.jss.crypto.IVParameterSpec;
 import org.mozilla.jss.crypto.KeyGenAlgorithm;
+import org.mozilla.jss.crypto.KeyGenerator;
 import org.mozilla.jss.crypto.SymmetricKey;
 import org.mozilla.jss.util.Password;
 
@@ -254,7 +255,8 @@ public class DRMTest {
             byte[] encoded = CryptoUtil.createPKIArchiveOptions(manager, token, transportCert, vek, null,
                     KeyGenAlgorithm.DES3, ivps);
 
-            KeyRequestInfo info = client.archiveSecurityData(encoded, clientId, KeyRequestResource.SYMMETRIC_KEY_TYPE);
+            KeyRequestInfo info = client.archiveSecurityData(encoded, clientId,
+                    KeyRequestResource.SYMMETRIC_KEY_TYPE, KeyRequestResource.DES3_ALGORITHM, 0);
             log("Archival Results:");
             printRequestInfo(info);
             keyId = info.getKeyId();
@@ -363,7 +365,8 @@ public class DRMTest {
         try {
             byte[] encoded = CryptoUtil.createPKIArchiveOptions(manager, token, transportCert, null, passphrase,
                     KeyGenAlgorithm.DES3, ivps);
-            requestInfo = client.archiveSecurityData(encoded, clientId, KeyRequestResource.PASS_PHRASE_TYPE);
+            requestInfo = client.archiveSecurityData(encoded, clientId,
+                    KeyRequestResource.PASS_PHRASE_TYPE, null, 0);
             log("Archival Results:");
             printRequestInfo(requestInfo);
             keyId = requestInfo.getKeyId();
@@ -529,7 +532,7 @@ public class DRMTest {
         log("Recovering X509 key based on request: " + recoveryRequestId);
         try {
             // KeyData recoveredX509Key = client.recoverKey(recoveryRequestId, "netscape");
-            //log("Success: X509Key recovered: "+ recoveredX509Key.getP12Data());
+            // log("Success: X509Key recovered: "+ recoveredX509Key.getP12Data());
         } catch (RequestNotFoundException e) {
             log("Error: recovering X509Key");
         }
@@ -560,7 +563,9 @@ public class DRMTest {
         List<String> usages = new ArrayList<String>();
         usages.add(SymKeyGenerationRequest.DECRYPT_USAGE);
         usages.add(SymKeyGenerationRequest.ENCRYPT_USAGE);
-        KeyRequestInfo genKeyInfo = client.generateKey(clientId, SymKeyGenerationRequest.AES_ALGORITHM, 128, usages);
+        KeyRequestInfo genKeyInfo = client.generateKey(clientId,
+                KeyRequestResource.AES_ALGORITHM,
+                128, usages);
         printRequestInfo(genKeyInfo);
         keyId = genKeyInfo.getKeyId();
 
@@ -603,9 +608,9 @@ public class DRMTest {
 
         ivps_server = new IVParameterSpec(Utils.base64decode(keyData.getNonceData()));
         try {
-        //    recoveredKey = CryptoUtil.unwrapUsingSymmetricKey(token, ivps_server,
-        //            Utils.base64decode(wrappedRecoveredKey),
-        //            recoveryKey, EncryptionAlgorithm.DES3_CBC_PAD);
+            recoveredKey = CryptoUtil.unwrapUsingSymmetricKey(token, ivps_server,
+                    Utils.base64decode(wrappedRecoveredKey),
+                    recoveryKey, EncryptionAlgorithm.DES3_CBC_PAD);
         } catch (Exception e) {
             log("Exception in unwrapping key: " + e.toString());
             e.printStackTrace();
@@ -631,6 +636,81 @@ public class DRMTest {
         } catch (Exception e) {
             log("Exception: " + e);
         }
+
+        // Test 36: Generate and archive a symmetric key of type AES
+        log("Archiving symmetric key");
+        clientId = "UUID: 123-45-6789 VEK " + Calendar.getInstance().getTime().toString();
+        try {
+            KeyGenerator kg = token.getKeyGenerator(KeyGenAlgorithm.AES);
+            kg.initialize(128);
+            vek = kg.generate();
+
+            byte[] encoded = CryptoUtil.createPKIArchiveOptions(manager, token, transportCert, vek, null,
+                    KeyGenAlgorithm.DES3, ivps);
+
+            KeyRequestInfo info = client.archiveSecurityData(encoded, clientId,
+                    KeyRequestResource.SYMMETRIC_KEY_TYPE, KeyRequestResource.AES_ALGORITHM, 128);
+            log("Archival Results:");
+            printRequestInfo(info);
+            keyId = info.getKeyId();
+        } catch (Exception e) {
+            log("Exception in archiving symmetric key:" + e.getMessage());
+            e.printStackTrace();
+        }
+
+        //Test 37: Get keyId for active key with client ID
+        log("Getting key ID for symmetric key");
+        keyInfo = client.getKeyData(clientId, "active");
+        keyId2 = keyInfo.getKeyId();
+        if (keyId2 == null) {
+            log("No archived key found");
+        } else {
+            log("Archived Key found: " + keyId);
+        }
+
+        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 38: Submit a recovery request for the symmetric key using a session key
+        log("Submitting a recovery request for the  symmetric key using session key");
+        try {
+            recoveryKey = CryptoUtil.generateKey(token, KeyGenAlgorithm.DES3);
+            wrappedRecoveryKey = CryptoUtil.wrapSymmetricKey(manager, token, transportCert, recoveryKey);
+            KeyRequestInfo info = client.requestRecovery(keyId, null, wrappedRecoveryKey, ivps.getIV());
+            recoveryRequestId = info.getRequestId();
+        } catch (Exception e) {
+            log("Exception in recovering symmetric key using session key: " + e.getMessage());
+        }
+
+        // Test 39: Approve recovery
+        log("Approving recovery request: " + recoveryRequestId);
+        client.approveRecovery(recoveryRequestId);
+
+        // Test 40: Get key
+        log("Getting key: " + keyId);
+
+        keyData = client.retrieveKey(keyId, recoveryRequestId, null, wrappedRecoveryKey, ivps.getIV());
+        wrappedRecoveredKey = keyData.getWrappedPrivateData();
+
+        ivps_server = new IVParameterSpec(Utils.base64decode(keyData.getNonceData()));
+        try {
+            recoveredKey = CryptoUtil.unwrapUsingSymmetricKey(token, ivps_server,
+                    Utils.base64decode(wrappedRecoveredKey),
+                    recoveryKey, EncryptionAlgorithm.DES3_CBC_PAD);
+        } catch (Exception e) {
+            log("Exception in unwrapping key: " + e.toString());
+            e.printStackTrace();
+        }
+
+        if (!recoveredKey.equals(Utils.base64encode(vek.getEncoded()))) {
+            log("Error: recovered and archived keys do not match!");
+        } else {
+            log("Success: recoverd and archived keys match!");
+        }
+
     }
 
     private static void log(String string) {
diff --git a/base/kra/src/com/netscape/kra/EncryptionUnit.java b/base/kra/src/com/netscape/kra/EncryptionUnit.java
index c082a784f78a973eb6d4039b94693fcf60b33fdb..71bd1d7816a9842753a9154c0285109ada85b314 100644
--- a/base/kra/src/com/netscape/kra/EncryptionUnit.java
+++ b/base/kra/src/com/netscape/kra/EncryptionUnit.java
@@ -301,7 +301,7 @@ public abstract class EncryptionUnit implements IEncryptionUnit {
      */
     public SymmetricKey unwrap_symmetric(byte encSymmKey[],
         String symmAlgOID, byte symmAlgParams[],
-        byte encValue[])
+        byte encValue[], SymmetricKey.Type algorithm, int strength)
         throws EBaseException {
         try {
             CryptoToken token = getToken();
@@ -323,7 +323,8 @@ public abstract class EncryptionUnit implements IEncryptionUnit {
             wrapper.initUnwrap(sk, new IVParameterSpec(
                     symmAlgParams));
 
-            SymmetricKey symKey = wrapper.unwrapSymmetric(encValue, SymmetricKey.DES3, SymmetricKey.Usage.DECRYPT, 0);
+            SymmetricKey symKey = wrapper.unwrapSymmetric(encValue, algorithm,
+                    SymmetricKey.Usage.DECRYPT, strength);
 
             return symKey;
         } catch (TokenException e) {
@@ -513,7 +514,7 @@ public abstract class EncryptionUnit implements IEncryptionUnit {
     /**
      * External unwrapping of stored symmetric key.
      */
-    public SymmetricKey unwrap(byte wrappedKeyData[])
+    public SymmetricKey unwrap(byte wrappedKeyData[], SymmetricKey.Type algorithm, int keySize)
             throws EBaseException {
         try {
             DerValue val = new DerValue(wrappedKeyData);
@@ -540,8 +541,8 @@ public abstract class EncryptionUnit implements IEncryptionUnit {
             wrapper.initUnwrap(sk, IV);
 
             SymmetricKey sk_ret = wrapper.unwrapSymmetric(pri,
-                    SymmetricKey.DES3, SymmetricKey.Usage.UNWRAP,
-                    0);
+                    algorithm, SymmetricKey.Usage.UNWRAP,
+                    keySize);
 
             return sk_ret;
         } catch (TokenException e) {
diff --git a/base/kra/src/com/netscape/kra/SecurityDataRecoveryService.java b/base/kra/src/com/netscape/kra/SecurityDataRecoveryService.java
index 50f163dfa274db51e8fa5ca4fd231257a9d39db9..f3b7709e74c46423a0baff616a2e552477ae1c2d 100644
--- a/base/kra/src/com/netscape/kra/SecurityDataRecoveryService.java
+++ b/base/kra/src/com/netscape/kra/SecurityDataRecoveryService.java
@@ -64,6 +64,7 @@ import com.netscape.certsrv.request.IService;
 import com.netscape.certsrv.request.RequestId;
 import com.netscape.certsrv.security.IStorageKeyUnit;
 import com.netscape.certsrv.security.ITransportKeyUnit;
+import com.netscape.cms.servlet.request.KeyRequestService;
 import com.netscape.cmscore.dbs.KeyRecord;
 import com.netscape.cmsutil.util.Utils;
 
@@ -277,7 +278,9 @@ public class SecurityDataRecoveryService implements IService {
         try {
             SymmetricKey symKey =
                     mStorageUnit.unwrap(
-                            keyRecord.getPrivateKeyData());
+                            keyRecord.getPrivateKeyData(),
+                            KeyRequestService.SYMKEY_TYPES.get(keyRecord.getAlgorithm()),
+                            keyRecord.getKeySize());
 
             if (symKey == null) {
                 throw new EKRAException(CMS.getUserMessage("CMS_KRA_RECOVERY_FAILED_1",
diff --git a/base/kra/src/com/netscape/kra/SecurityDataService.java b/base/kra/src/com/netscape/kra/SecurityDataService.java
index 428dd660bfe41d42e24ac6d44890003c5e465080..bbea11c32a0d53905cbdffd1377755c0d68c279e 100644
--- a/base/kra/src/com/netscape/kra/SecurityDataService.java
+++ b/base/kra/src/com/netscape/kra/SecurityDataService.java
@@ -35,6 +35,7 @@ import com.netscape.certsrv.request.IService;
 import com.netscape.certsrv.request.RequestId;
 import com.netscape.certsrv.security.IStorageKeyUnit;
 import com.netscape.certsrv.security.ITransportKeyUnit;
+import com.netscape.cms.servlet.request.KeyRequestService;
 import com.netscape.cmscore.dbs.KeyRecord;
 import com.netscape.cmsutil.util.Utils;
 
@@ -85,6 +86,8 @@ public class SecurityDataService implements IService {
         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);
+        String algorithm = request.getExtDataInString(IRequest.SECURITY_DATA_ALGORITHM);
+        int strength = request.getExtDataInInteger(IRequest.SECURITY_DATA_STRENGTH);
 
         CMS.debug("SecurityDataService.serviceRequest. Request id: " + id);
         CMS.debug("SecurityDataService.serviceRequest wrappedSecurityData: " + wrappedSecurityData);
@@ -123,7 +126,9 @@ public class SecurityDataService implements IService {
             securitySymKey = mTransportUnit.unwrap_symmetric(options.getEncSymmKey(),
                       options.getSymmAlgOID(),
                       options.getSymmAlgParams(),
-                      options.getEncValue());
+                      options.getEncValue(),
+                      KeyRequestService.SYMKEY_TYPES.get(algorithm),
+                      strength);
 
         } else if (dataType.equals(KeyRequestResource.PASS_PHRASE_TYPE)) {
             keyType = KeyRequestResource.PASS_PHRASE_TYPE;
@@ -175,6 +180,12 @@ public class SecurityDataService implements IService {
         rec.set(KeyRecord.ATTR_ID, serialNo);
         rec.set(KeyRecord.ATTR_DATA_TYPE, keyType);
         rec.set(KeyRecord.ATTR_STATUS, STATUS_ACTIVE);
+
+        if (dataType.equals(KeyRequestResource.SYMMETRIC_KEY_TYPE)) {
+            rec.set(KeyRecord.ATTR_ALGORITHM, algorithm);
+            rec.set(KeyRecord.ATTR_KEY_SIZE, strength);
+        }
+
         request.setExtData(ATTR_KEY_RECORD, serialNo);
 
         CMS.debug("KRA adding Security Data key record " + serialNo);
diff --git a/base/kra/src/com/netscape/kra/SymKeyGenService.java b/base/kra/src/com/netscape/kra/SymKeyGenService.java
index 3ebf1bed02080d9a3bb1115862b6382536785671..32dc1ceb9f1c600b6c14533d190086475cfd345e 100644
--- a/base/kra/src/com/netscape/kra/SymKeyGenService.java
+++ b/base/kra/src/com/netscape/kra/SymKeyGenService.java
@@ -209,6 +209,8 @@ public class SymKeyGenService implements IService {
         rec.set(KeyRecord.ATTR_ID, serialNo);
         rec.set(KeyRecord.ATTR_DATA_TYPE, KeyRequestResource.SYMMETRIC_KEY_TYPE);
         rec.set(KeyRecord.ATTR_STATUS, STATUS_ACTIVE);
+        rec.set(KeyRecord.ATTR_ALGORITHM, algorithm);
+        rec.set(KeyRecord.ATTR_KEY_SIZE, keySize);
         request.setExtData(ATTR_KEY_RECORD, serialNo);
 
         CMS.debug("KRA adding Security Data key record " + serialNo);
diff --git a/base/server/cms/src/com/netscape/cms/servlet/key/KeyRequestDAO.java b/base/server/cms/src/com/netscape/cms/servlet/key/KeyRequestDAO.java
index 536e43fc0c6e958b29ca4e67876651b0f94ecec5..7d45420a4eba6624799e09801da4e4916b934d23 100644
--- a/base/server/cms/src/com/netscape/cms/servlet/key/KeyRequestDAO.java
+++ b/base/server/cms/src/com/netscape/cms/servlet/key/KeyRequestDAO.java
@@ -137,6 +137,8 @@ public class KeyRequestDAO extends CMSRequestDAO {
         String clientId = data.getClientId();
         String wrappedSecurityData = data.getWrappedPrivateData();
         String dataType = data.getDataType();
+        String keyAlgorithm = data.getKeyAlgorithm();
+        int keyStrength = data.getKeyStrength();
 
         boolean keyExists = doesKeyExist(clientId, "active", uriInfo);
 
@@ -149,6 +151,12 @@ public class KeyRequestDAO extends CMSRequestDAO {
         request.setExtData(REQUEST_ARCHIVE_OPTIONS, wrappedSecurityData);
         request.setExtData(IRequest.SECURITY_DATA_CLIENT_ID, clientId);
         request.setExtData(IRequest.SECURITY_DATA_TYPE, dataType);
+        request.setExtData(IRequest.SECURITY_DATA_STRENGTH,
+                (keyStrength > 0) ? Integer.toString(keyStrength) : Integer.toString(0));
+
+        if (keyAlgorithm != null) {
+            request.setExtData(IRequest.SECURITY_DATA_ALGORITHM, keyAlgorithm);
+        }
 
         queue.processRequest(request);
 
@@ -232,6 +240,9 @@ public class KeyRequestDAO extends CMSRequestDAO {
 
         request.setExtData(IRequest.SYMKEY_GEN_ALGORITHM, algName);
         request.setExtData(IRequest.SYMKEY_GEN_SIZE, size);
+        request.setExtData(IRequest.SECURITY_DATA_STRENGTH, size);
+        request.setExtData(IRequest.SECURITY_DATA_ALGORITHM, algName);
+
         request.setExtData(IRequest.SYMKEY_GEN_USAGES, StringUtils.join(usages, ","));
         request.setExtData(IRequest.SECURITY_DATA_CLIENT_ID, clientId);
 
diff --git a/base/server/cms/src/com/netscape/cms/servlet/request/KeyRequestService.java b/base/server/cms/src/com/netscape/cms/servlet/request/KeyRequestService.java
index fccfaaab4690d8ddde6676d041403e80e47cafe7..19f053d0e394308b599dc0bd3191a1370f6d17d5 100644
--- a/base/server/cms/src/com/netscape/cms/servlet/request/KeyRequestService.java
+++ b/base/server/cms/src/com/netscape/cms/servlet/request/KeyRequestService.java
@@ -38,6 +38,7 @@ import javax.ws.rs.core.UriInfo;
 import netscape.security.x509.X509CertImpl;
 
 import org.mozilla.jss.crypto.KeyGenAlgorithm;
+import org.mozilla.jss.crypto.SymmetricKey;
 
 import com.netscape.certsrv.apps.CMS;
 import com.netscape.certsrv.base.BadRequestException;
@@ -106,12 +107,23 @@ public class KeyRequestService extends PKIService implements KeyRequestResource
 
     static {
         KEYGEN_ALGORITHMS = new HashMap<String, KeyGenAlgorithm>();
-        KEYGEN_ALGORITHMS.put(SymKeyGenerationRequest.DES_ALGORITHM, KeyGenAlgorithm.DES);
-        KEYGEN_ALGORITHMS.put(SymKeyGenerationRequest.DESEDE_ALGORITHM, KeyGenAlgorithm.DESede);
-        KEYGEN_ALGORITHMS.put(SymKeyGenerationRequest.DES3_ALGORITHM, KeyGenAlgorithm.DES3);
-        KEYGEN_ALGORITHMS.put(SymKeyGenerationRequest.RC2_ALGORITHM, KeyGenAlgorithm.RC2);
-        KEYGEN_ALGORITHMS.put(SymKeyGenerationRequest.RC4_ALGORITHM, KeyGenAlgorithm.RC4);
-        KEYGEN_ALGORITHMS.put(SymKeyGenerationRequest.AES_ALGORITHM, KeyGenAlgorithm.AES);
+        KEYGEN_ALGORITHMS.put(KeyRequestResource.DES_ALGORITHM, KeyGenAlgorithm.DES);
+        KEYGEN_ALGORITHMS.put(KeyRequestResource.DESEDE_ALGORITHM, KeyGenAlgorithm.DESede);
+        KEYGEN_ALGORITHMS.put(KeyRequestResource.DES3_ALGORITHM, KeyGenAlgorithm.DES3);
+        KEYGEN_ALGORITHMS.put(KeyRequestResource.RC2_ALGORITHM, KeyGenAlgorithm.RC2);
+        KEYGEN_ALGORITHMS.put(KeyRequestResource.RC4_ALGORITHM, KeyGenAlgorithm.RC4);
+        KEYGEN_ALGORITHMS.put(KeyRequestResource.AES_ALGORITHM, KeyGenAlgorithm.AES);
+    }
+
+    public static final Map<String, SymmetricKey.Type> SYMKEY_TYPES;
+    static {
+        SYMKEY_TYPES = new HashMap<String, SymmetricKey.Type>();
+        SYMKEY_TYPES.put(KeyRequestResource.DES_ALGORITHM, SymmetricKey.DES);
+        SYMKEY_TYPES.put(KeyRequestResource.DESEDE_ALGORITHM, SymmetricKey.DES3);
+        SYMKEY_TYPES.put(KeyRequestResource.DES3_ALGORITHM, SymmetricKey.DES3);
+        SYMKEY_TYPES.put(KeyRequestResource.RC2_ALGORITHM, SymmetricKey.RC2);
+        SYMKEY_TYPES.put(KeyRequestResource.RC4_ALGORITHM, SymmetricKey.RC4);
+        SYMKEY_TYPES.put(KeyRequestResource.AES_ALGORITHM, SymmetricKey.AES);
     }
 
     public KeyRequestService() {
@@ -156,6 +168,13 @@ public class KeyRequestService extends PKIService implements KeyRequestResource
             throw new BadRequestException("Invalid key archival request.");
         }
 
+        if (data.getDataType().equals(KeyRequestResource.SYMMETRIC_KEY_TYPE)) {
+            if ((data.getKeyAlgorithm() == null) ||
+                (! SYMKEY_TYPES.containsKey(data.getKeyAlgorithm()))) {
+                throw new BadRequestException("Invalid key archival request.  Bad algorithm.");
+            }
+        }
+
         KeyRequestDAO dao = new KeyRequestDAO();
         KeyRequestInfo info;
         try {
-- 
1.8.4.2

