>From d87aadd66d67667884599d482be9e06deaeb2393 Mon Sep 17 00:00:00 2001
From: Ade Lee <alee@redhat.com>
Date: Fri, 21 Feb 2014 21:24:39 -0500
Subject: [PATCH 203/203] Added error checking in python client calls

1) Added error checking in python client calls.
2) Allow symmetric key generation with default params.  Fix bug for
   when usages is not defined.
3) Fix bug when requesting key recovery - must check if key exists.
4) Extend key gen to allow for providing trans_wrapped_session_key
5) added constants to python client for key status
---
 base/common/python/pki/key.py                      | 102 +++++++++++++++++----
 .../certsrv/key/SymKeyGenerationRequest.java       |  22 ++++-
 .../src/com/netscape/certsrv/request/IRequest.java |   1 +
 base/kra/functional/drmtest.py                     |  26 ++++--
 base/kra/src/CMakeLists.txt                        |   9 +-
 .../kra/src/com/netscape/kra/SymKeyGenService.java |   4 +-
 .../netscape/cms/servlet/key/KeyRequestDAO.java    |  29 ++++--
 7 files changed, 159 insertions(+), 34 deletions(-)

diff --git a/base/common/python/pki/key.py b/base/common/python/pki/key.py
index 7d93e783ab68f2fc351dbaf4b784b9933673367d..3fa5952dbf37acaf898c16914f5b16030c2d741a 100644
--- a/base/common/python/pki/key.py
+++ b/base/common/python/pki/key.py
@@ -94,7 +94,7 @@ class KeyInfo(object):
 
     def get_key_id(self):
         ''' Return the key ID as parsed from key URL '''
-        if self.keyURL != None:
+        if self.keyURL is not None:
             indx = str(self.keyURL).rfind("/") + 1
             return str(self.keyURL)[indx:]
         return None
@@ -146,14 +146,14 @@ class KeyRequestInfo(object):
 
     def get_request_id(self):
         ''' Return the request ID by parsing the request URL. '''
-        if self.requestURL != None:
+        if self.requestURL is not None:
             indx = str(self.requestURL).rfind("/") + 1
             return str(self.requestURL)[indx:]
         return None
 
     def get_key_id(self):
         ''' Return the ID of the secret referred to by this request. '''
-        if self.keyURL != None:
+        if self.keyURL is not None:
             indx = str(self.keyURL).rfind("/") + 1
             return str(self.keyURL)[indx:]
         return None
@@ -268,7 +268,7 @@ class SymKeyGenerationRequest(pki.ResourceMessage):
     ENCRYPT_USAGE = "encrypt"
 
     def __init__(self, client_key_id=None, key_size=None, key_algorithm=None,
-                 key_usages=None):
+                 key_usages=None, trans_wrapped_session_key=None):
         ''' Constructor '''
         pki.ResourceMessage.__init__(self,
                                  "com.netscape.certsrv.key.SymKeyGenerationRequest")
@@ -277,6 +277,7 @@ class SymKeyGenerationRequest(pki.ResourceMessage):
         self.add_attribute("keySize", key_size)
         self.add_attribute("keyAlgorithm", key_algorithm)
         self.add_attribute("keyUsage", ','.join(key_usages))
+        self.add_attribute("transWrappedSessionKey", trans_wrapped_session_key)
 
 class KeyClient(object):
     '''
@@ -288,6 +289,9 @@ class KeyClient(object):
     PASS_PHRASE_TYPE = "passPhrase"
     ASYMMETRIC_KEY_TYPE = "asymmetricKey"
 
+    KEY_STATUS_ACTIVE = "active"
+    KEY_STATUS_INACTIVE = "inactive"
+
     def __init__(self, connection, crypto, transport_cert_nick=None):
         ''' Constructor '''
         self.connection = connection
@@ -297,7 +301,7 @@ class KeyClient(object):
         self.keyRequestsURL = '/rest/agent/keyrequests'
         self.crypto = crypto
 
-        if transport_cert_nick != None:
+        if transport_cert_nick is not None:
             self.crypto.initialize()
             self.transport_cert = crypto.get_cert(transport_cert_nick)
         else:
@@ -305,6 +309,8 @@ class KeyClient(object):
 
     def set_transport_cert(self, transport_cert_nick):
         ''' Set the transport certificate for crypto operations '''
+        if transport_cert_nick is None:
+            raise ValueError("Transport cert nickname must be specified.")
         self.transport_cert = self.crypto.get_cert(transport_cert_nick)
 
     @pki.handle_exceptions()
@@ -339,6 +345,9 @@ class KeyClient(object):
     @pki.handle_exceptions()
     def get_request_info(self, request_id):
         ''' Return a KeyRequestInfo object for a specific request. '''
+        if request_id is None:
+            raise ValueError("request_id must be specified")
+
         url = self.keyRequestsURL + '/' + request_id
         response = self.connection.get(url, self.headers)
         return KeyRequestInfo.from_json(response.json())
@@ -346,6 +355,9 @@ class KeyClient(object):
     @pki.handle_exceptions()
     def get_key_info(self, key_id):
         ''' Get the info in the KeyRecord for a specific secret in the DRM. '''
+        if key_id is None:
+            raise ValueError("key_id must be specified")
+
         url = self.keyURL + '/' + key_id
         response = self.connection.get(url, headers=self.headers)
         return KeyInfo.from_json(response.json())
@@ -353,6 +365,9 @@ class KeyClient(object):
     @pki.handle_exceptions()
     def get_active_key_info(self, client_key_id):
         ''' Get the info in the KeyRecord for the active secret in the DRM. '''
+        if client_key_id is None:
+            raise ValueError("client_key_id must be specified")
+
         url = self.keyURL + '/active/' + urllib.quote_plus(client_key_id)
         response = self.connection.get(url, headers=self.headers)
         return KeyInfo.from_json(response.json())
@@ -360,6 +375,9 @@ class KeyClient(object):
     @pki.handle_exceptions()
     def modify_key_status(self, key_id, status):
         ''' Modify the status of a key '''
+        if (key_id is None) or (status is None):
+            raise ValueError("key_id and status must be specified")
+
         url = self.keyURL + '/' + key_id
         params = {'status':status}
         self.connection.post(url, None, headers=self.headers, params=params)
@@ -367,18 +385,27 @@ class KeyClient(object):
     @pki.handle_exceptions()
     def approve_request(self, request_id):
         ''' Approve a secret recovery request '''
+        if request_id is None:
+            raise ValueError("request_id must be specified")
+
         url = self.keyRequestsURL + '/' + request_id + '/approve'
         self.connection.post(url, self.headers)
 
     @pki.handle_exceptions()
     def reject_request(self, request_id):
         ''' Reject a secret recovery request. '''
+        if request_id is None:
+            raise ValueError("request_id must be specified")
+
         url = self.keyRequestsURL + '/' + request_id + '/reject'
         self.connection.post(url, self.headers)
 
     @pki.handle_exceptions()
     def cancel_request(self, request_id):
         ''' Cancel a secret recovery request '''
+        if request_id is None:
+            raise ValueError("request_id must be specified")
+
         url = self.keyRequestsURL + '/' + request_id + '/cancel'
         self.connection.post(url, self.headers)
 
@@ -403,6 +430,9 @@ class KeyClient(object):
 
             This method expects initialize_nss() to have been called previously.
         '''
+        if secret is None:
+            raise ValueError("secret must be specified")
+
         session_key = self.crypto.generate_symmetric_key()
         trans_wrapped_session_key = self.crypto.asymmetric_wrap(session_key, self.transport_cert)
         wrapped_secret = self.crypto.symmetric_wrap(secret, session_key)
@@ -419,22 +449,42 @@ class KeyClient(object):
 
             returns a KeyRequestResponse object.
         '''
+        if request is None:
+            raise ValueError("request must be specified")
+
         url = self.keyRequestsURL
         key_request = json.dumps(request, cls=encoder.CustomTypeEncoder, sort_keys=True)
         response = self.connection.post(url, key_request, self.headers)
         return KeyRequestResponse.from_json(response.json())
 
     @pki.handle_exceptions()
-    def generate_symmetric_key(self, client_key_id, algorithm, size, usages):
+    def generate_symmetric_key(self, client_key_id, algorithm=None, size=None, usages=None,
+                               trans_wrapped_session_key=None):
         ''' Generate and archive a symmetric key on the DRM.
 
             Return a KeyRequestResponse which contains a KeyRequestInfo
             object that describes the URL for the request and generated key.
+
         '''
-        request = SymKeyGenerationRequest(client_key_id=client_key_id,
-                                          key_size=size,
-                                          key_algorithm=algorithm,
-                                          key_usages=usages)
+        if client_key_id is None:
+            raise ValueError("Must specify client_key_id")
+
+        if trans_wrapped_session_key is not None:
+            twsk = base64.encodestring(trans_wrapped_session_key)
+            request = SymKeyGenerationRequest(
+                            client_key_id=client_key_id,
+                            key_size=size,
+                            key_algorithm=algorithm,
+                            key_usages=usages,
+                            trans_wrapped_session_key=twsk)
+            raise NotImplementedError(
+                    "Returning the symmetric key in the same call is not yet implemented.")
+        else:
+            request = SymKeyGenerationRequest(
+                            client_key_id=client_key_id,
+                            key_size=size,
+                            key_algorithm=algorithm,
+                            key_usages=usages)
         return self.create_request(request)
 
     @pki.handle_exceptions()
@@ -448,9 +498,9 @@ class KeyClient(object):
             key exists, a BadRequestException is thrown.
 
             data_type can be one of the following:
-                KeyRequestResource.SYMMETRIC_KEY_TYPE,
-                KeyRequestResource.ASYMMETRIC_KEY_TYPE,
-                KeyRequestResource.PASS_PHRASE_TYPE
+                KeyClient.SYMMETRIC_KEY_TYPE,
+                KeyClient.ASYMMETRIC_KEY_TYPE,
+                KeyClient.PASS_PHRASE_TYPE
 
             key_algorithm and key_size are applicable to symmetric keys only.
             If a symmetric key is being archived, these parameters are required.
@@ -469,8 +519,16 @@ class KeyClient(object):
             The function returns a KeyRequestResponse object containing a KeyRequestInfo
             object with details about the archival request and key archived.
         '''
-        if wrapped_private_data == None:
-            if private_data == None:
+        if (client_key_id is None) or (data_type is None):
+            raise ValueError("client_key_id and data_type must be specified")
+
+        if data_type == KeyClient.SYMMETRIC_KEY_TYPE:
+            if (key_algorithm is None) or (key_size is None):
+                raise ValueError(
+                        "For symmetric keys, key algorithm and key_size must be specified")
+
+        if wrapped_private_data is None:
+            if private_data is None:
                 raise ValueError("No data provided to be archived")
             wrapped_private_data = self.generate_archive_options(private_data)
 
@@ -494,6 +552,9 @@ class KeyClient(object):
             To retrieve an asymmetric key, the keyId and the the base-64 encoded certificate
             is required.
         '''
+        if key_id is None:
+            raise ValueError("key_id must be defined")
+
         request = KeyRecoveryRequest(key_id=key_id,
                                      request_id=request_id,
                                      trans_wrapped_session_key=trans_wrapped_session_key,
@@ -513,6 +574,9 @@ class KeyClient(object):
 
             Returns a KeyData object containing the wrapped secret.
         '''
+        if data is None:
+            raise ValueError("KeyRecoveryRequest must be specified")
+
         url = self.keyURL + '/retrieve'
         keyRequest = json.dumps(data, cls=encoder.CustomTypeEncoder, sort_keys=True)
         response = self.connection.post(url, keyRequest, self.headers)
@@ -546,8 +610,11 @@ class KeyClient(object):
         The function will return the tuple (KeyData, None), where the KeyData structure includes the
         wrapped secret and some nonce data to be used as a salt when unwrapping.
         '''
+        if key_id is None:
+            raise ValueError("key_id must be specified")
+
         key_provided = True
-        if (trans_wrapped_session_key == None):
+        if trans_wrapped_session_key is None:
             key_provided = False
             session_key = self.crypto.generate_symmetric_key()
             trans_wrapped_session_key = self.crypto.asymmetric_wrap(session_key,
@@ -629,6 +696,9 @@ class KeyClient(object):
 
         The function returns a KeyData object.
         '''
+        if (key_id is None) or (certificate is None) or (passphrase is None):
+            raise ValueError("key_id, certificate and passphrase must all be specified")
+
         response = self.recover_key(key_id, b64certificate=certificate)
         request_id = response.get_request_id()
         self.approve_request(request_id)
diff --git a/base/common/src/com/netscape/certsrv/key/SymKeyGenerationRequest.java b/base/common/src/com/netscape/certsrv/key/SymKeyGenerationRequest.java
index 01326442f043e02a70221106b9a2d42cc08f3a1d..27dc69fd553e128ecf035c3b38ce1eedb9aab7e6 100644
--- a/base/common/src/com/netscape/certsrv/key/SymKeyGenerationRequest.java
+++ b/base/common/src/com/netscape/certsrv/key/SymKeyGenerationRequest.java
@@ -25,6 +25,7 @@ public class SymKeyGenerationRequest extends ResourceMessage {
     private static final String KEY_SIZE = "keySize";
     private static final String KEY_ALGORITHM = "keyAlgorithm";
     private static final String KEY_USAGE = "keyUsage";
+    private static final String TRANS_WRAPPED_SESSION_KEY = "transWrappedSessionKey";
 
     /* Symmetric Key usages */
     public static final String UWRAP_USAGE = "unwrap";
@@ -65,6 +66,7 @@ public class SymKeyGenerationRequest extends ResourceMessage {
         attributes.put(KEY_SIZE, form.getFirst(KEY_SIZE));
         attributes.put(KEY_ALGORITHM, form.getFirst(KEY_ALGORITHM));
         attributes.put(KEY_USAGE, form.getFirst(KEY_USAGE));
+        attributes.put(TRANS_WRAPPED_SESSION_KEY, form.getFirst(TRANS_WRAPPED_SESSION_KEY));
 
         String usageString = attributes.get(KEY_USAGE);
         if (! StringUtils.isBlank(usageString)) {
@@ -96,7 +98,11 @@ public class SymKeyGenerationRequest extends ResourceMessage {
      * @return the keySize
      */
     public Integer getKeySize() {
-        return new Integer(attributes.get(KEY_SIZE));
+        try {
+            return new Integer(attributes.get(KEY_SIZE));
+        } catch (NumberFormatException e) {
+            return null;
+        }
     }
 
     /**
@@ -120,6 +126,20 @@ public class SymKeyGenerationRequest extends ResourceMessage {
         attributes.put(KEY_ALGORITHM, keyAlgorithm);
     }
 
+    /**
+     * @return the transWrappedSessionKey
+     */
+    public String getTransWrappedSessionKey() {
+        return attributes.get(TRANS_WRAPPED_SESSION_KEY);
+    }
+
+    /**
+     * @param transWrappedSessionKey the wrapped seesion key to set
+     */
+    public void setTransWrappedSessionKey(String transWrappedSessionKey) {
+        attributes.put(TRANS_WRAPPED_SESSION_KEY, transWrappedSessionKey);
+    }
+
     public String toString() {
         try {
             return ResourceMessage.marshal(this, SymKeyGenerationRequest.class);
diff --git a/base/common/src/com/netscape/certsrv/request/IRequest.java b/base/common/src/com/netscape/certsrv/request/IRequest.java
index e77a2e2b87b981ce3f09a2d64c306420074f02d3..f9c4427544c3b53973f5e405b2b27499a436959f 100644
--- a/base/common/src/com/netscape/certsrv/request/IRequest.java
+++ b/base/common/src/com/netscape/certsrv/request/IRequest.java
@@ -174,6 +174,7 @@ public interface IRequest extends Serializable {
     public static final String SYMKEY_GEN_ALGORITHM = "symkeyGenAlgorithm";
     public static final String SYMKEY_GEN_SIZE = "symkeyGenSize";
     public static final String SYMKEY_GEN_USAGES = "symkeyGenUsages";
+    public static final String SYMKEY_TRANS_WRAPPED_SESSION_KEY = "transWrappedSessionKey";
 
     // requestor type values.
     public static final String REQUESTOR_EE = "EE";
diff --git a/base/kra/functional/drmtest.py b/base/kra/functional/drmtest.py
index a1db60c55ba0cfd6c4029b19affa5558ea3932bc..b53c5569a227bf72048a6cf754fef2357afa3d6a 100644
--- a/base/kra/functional/drmtest.py
+++ b/base/kra/functional/drmtest.py
@@ -106,18 +106,21 @@ def main():
     # Test 4: generate symkey -- same as barbican_encode()
     print "Now generating symkey on KRA"
     #client_key_id = "Vek #1" + time.strftime('%X %x %Z')
-    client_key_id = "vek1234567"
+    client_key_id = "veka6"
     algorithm = "AES"
     key_size = 128
     usages = [key.SymKeyGenerationRequest.DECRYPT_USAGE, key.SymKeyGenerationRequest.ENCRYPT_USAGE]
-    response = keyclient.generate_symmetric_key(client_key_id, algorithm, key_size, usages)
+    response = keyclient.generate_symmetric_key(client_key_id,
+                                                algorithm=algorithm,
+                                                size=key_size,
+                                                usages=usages)
     print_key_request(response.requestInfo)
     print "Request ID is " + response.requestInfo.get_request_id()
     key_id = response.get_key_id()
 
     # Test 5: Confirm the key_id matches
     print "Now getting key ID for clientKeyID=\"" + client_key_id + "\""
-    key_infos = keyclient.list_keys(client_key_id=client_key_id, status="active")
+    key_infos = keyclient.list_keys(client_key_id=client_key_id, status=keyclient.KEY_STATUS_ACTIVE)
     for key_info in key_infos.key_infos:
         print_key_info(key_info)
         key_id2 = key_info.get_key_id()
@@ -152,7 +155,10 @@ def main():
     # Test 10 = test BadRequestException on create()
     print "Trying to generate a new symkey with the same client ID"
     try:
-        response = keyclient.generate_symmetric_key(client_key_id, algorithm, key_size, usages)
+        response = keyclient.generate_symmetric_key(client_key_id,
+                                                    algorithm=algorithm,
+                                                    size=key_size,
+                                                    usages=usages)
     except pki.BadRequestException as exc:
         print "BadRequestException thrown - Code:" + exc.code + " Message: " + exc.message
 
@@ -169,10 +175,6 @@ def main():
         key_data, unwrapped_key = keyclient.retrieve_key('2000003434')
     except pki.KeyNotFoundException as exc:
         print "KeyNotFoundException thrown - Code:" + exc.code + " Message: " + exc.message
-    except pki.PKIException as exc:
-        # note: this is broken - we should be sending KeyNotFoundException here before the recovery
-        # request is created - to be fixed in next patch
-        print "PKIException thrown - Code:" + exc.code + " Message: " + exc.message
 
     #Test 13 = getKeyInfo
     print "Get key info for existing key"
@@ -186,7 +188,7 @@ def main():
 
     #Test 15: change the key status
     print "Change the key status"
-    keyclient.modify_key_status(key_id, "inactive")
+    keyclient.modify_key_status(key_id, keyclient.KEY_STATUS_INACTIVE)
     print_key_info(keyclient.get_key_info(key_id))
 
     # Test 16: Get key info for non-existent key
@@ -200,8 +202,14 @@ def main():
     print "Get non-existent active key"
     try:
         key_info = keyclient.get_active_key_info(client_key_id)
+        print_key_info(key_info)
     except pki.ResourceNotFoundException as exc:
         print "ResourceNotFoundException thrown - Code: " + exc.code + "Message: " + exc.message
 
+    #Test 18: Generate a symmetric key with default parameters
+    client_key_id = "Vek #3" + time.strftime('%X %x %Z')
+    response = keyclient.generate_symmetric_key(client_key_id)
+    print_key_request(response.requestInfo)
+
 if __name__ == "__main__":
     main()
diff --git a/base/kra/src/CMakeLists.txt b/base/kra/src/CMakeLists.txt
index 99088ce069cfd0f5b70f33b79f8bfb6dbfec83bf..ccbc6a6c3eeb79f8f06f76b24f95214f39dffe42 100644
--- a/base/kra/src/CMakeLists.txt
+++ b/base/kra/src/CMakeLists.txt
@@ -75,6 +75,13 @@ find_file(SYMKEY_JAR
         ${JAVA_LIB_INSTALL_DIR}
 )
 
+find_file(COMMONS_LANG_JAR
+    NAMES
+	commons-lang.jar
+    PATHS
+	/usr/share/java
+)
+
 
 # build pki-kra
 javac(pki-kra-classes
@@ -84,7 +91,7 @@ javac(pki-kra-classes
         ${PKI_CERTSRV_JAR} ${PKI_CMS_JAR} ${PKI_CMSCORE_JAR}
         ${PKI_CMSUTIL_JAR} ${PKI_NSUTIL_JAR}
         ${LDAPJDK_JAR} ${JAXRS_API_JAR}
-        ${JSS_JAR} ${COMMONS_CODEC_JAR} ${SYMKEY_JAR}
+        ${JSS_JAR} ${COMMONS_CODEC_JAR} ${COMMONS_LANG_JAR} ${SYMKEY_JAR}
     OUTPUT_DIR
         ${CMAKE_BINARY_DIR}/classes
     DEPENDS
diff --git a/base/kra/src/com/netscape/kra/SymKeyGenService.java b/base/kra/src/com/netscape/kra/SymKeyGenService.java
index 99c57b8d9fd4e6be1308d859df4e43bb5a069ba7..d1e60fa704db9458c5a4d0b8d042497d810f3140 100644
--- a/base/kra/src/com/netscape/kra/SymKeyGenService.java
+++ b/base/kra/src/com/netscape/kra/SymKeyGenService.java
@@ -25,6 +25,7 @@ import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.List;
 
+import org.apache.commons.lang.StringUtils;
 import org.mozilla.jss.crypto.CryptoToken;
 import org.mozilla.jss.crypto.KeyGenAlgorithm;
 import org.mozilla.jss.crypto.KeyGenerator;
@@ -92,7 +93,8 @@ public class SymKeyGenService implements IService {
         String algorithm = request.getExtDataInString(IRequest.SYMKEY_GEN_ALGORITHM);
 
         String usageStr = request.getExtDataInString(IRequest.SYMKEY_GEN_USAGES);
-        List<String> usages = new ArrayList<String>(Arrays.asList(usageStr.split(",")));
+        List<String> usages = new ArrayList<String>(
+                Arrays.asList(StringUtils.split(usageStr, ",")));
 
         String keySizeStr = request.getExtDataInString(IRequest.SYMKEY_GEN_SIZE);
         int keySize = Integer.parseInt(keySizeStr);
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 308d3daf892d15410d5437e29bbd99c5b82be7ea..d84bbd013d16fbea214ce28a9046eae2d8737410 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
@@ -32,11 +32,13 @@ import org.mozilla.jss.crypto.KeyGenAlgorithm;
 import com.netscape.certsrv.apps.CMS;
 import com.netscape.certsrv.base.BadRequestException;
 import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.dbs.EDBRecordNotFoundException;
 import com.netscape.certsrv.dbs.keydb.IKeyRecord;
 import com.netscape.certsrv.dbs.keydb.IKeyRepository;
 import com.netscape.certsrv.dbs.keydb.KeyId;
 import com.netscape.certsrv.key.KeyArchivalRequest;
 import com.netscape.certsrv.key.KeyData;
+import com.netscape.certsrv.key.KeyNotFoundException;
 import com.netscape.certsrv.key.KeyRecoveryRequest;
 import com.netscape.certsrv.key.KeyRequestInfo;
 import com.netscape.certsrv.key.KeyRequestInfoCollection;
@@ -142,7 +144,7 @@ public class KeyRequestDAO extends CMSRequestDAO {
         String keyAlgorithm = data.getKeyAlgorithm();
         int keyStrength = data.getKeySize();
 
-        boolean keyExists = doesKeyExist(clientKeyId, "active", uriInfo);
+        boolean keyExists = doesKeyExist(clientKeyId, "active");
 
         if (keyExists == true) {
             throw new EBaseException("Can not archive already active existing key!");
@@ -184,6 +186,11 @@ public class KeyRequestDAO extends CMSRequestDAO {
         IRequest request = queue.newRequest(IRequest.SECURITY_DATA_RECOVERY_REQUEST);
 
         KeyId keyId = data.getKeyId();
+        try {
+            repo.readKeyRecord(keyId.toBigInteger());
+        } catch (EDBRecordNotFoundException e) {
+            throw new KeyNotFoundException(keyId);
+        }
 
         Hashtable<String, Object> requestParams;
 
@@ -219,12 +226,13 @@ public class KeyRequestDAO extends CMSRequestDAO {
         String algName = data.getKeyAlgorithm();
         Integer keySize = data.getKeySize();
         List<String> usages = data.getUsages();
+        String transWrappedSessionKey = data.getTransWrappedSessionKey();
 
         if (StringUtils.isBlank(clientKeyId)) {
             throw new BadRequestException("Invalid key generation request. Missing client ID");
         }
 
-        boolean keyExists = doesKeyExist(clientKeyId, "active", uriInfo);
+        boolean keyExists = doesKeyExist(clientKeyId, "active");
         if (keyExists == true) {
             throw new BadRequestException("Can not archive already active existing key!");
         }
@@ -261,6 +269,11 @@ public class KeyRequestDAO extends CMSRequestDAO {
         request.setExtData(IRequest.SYMKEY_GEN_USAGES, StringUtils.join(usages, ","));
         request.setExtData(IRequest.SECURITY_DATA_CLIENT_KEY_ID, clientKeyId);
 
+        if (transWrappedSessionKey != null) {
+            request.setExtData(IRequest.SYMKEY_TRANS_WRAPPED_SESSION_KEY,
+                    transWrappedSessionKey);
+        }
+
         queue.processRequest(request);
         queue.markAsServiced(request);
 
@@ -331,10 +344,14 @@ public class KeyRequestDAO extends CMSRequestDAO {
     }
 
     //We only care if the key exists or not
-    private boolean doesKeyExist(String clientKeyId, String keyStatus, UriInfo uriInfo) {
-        String state = "active";
-        String filter = "(&(" + IRequest.SECURITY_DATA_CLIENT_KEY_ID + "=" + clientKeyId + ")"
-                + "(" + IRequest.SECURITY_DATA_STATUS + "=" + state + "))";
+    private boolean doesKeyExist(String clientKeyId, String keyStatus) {
+        String filter = null;
+        if (keyStatus == null) {
+            filter = "(" + IKeyRecord.ATTR_CLIENT_ID + "=" + clientKeyId + ")";
+        } else {
+            filter = "(&(" + IKeyRecord.ATTR_CLIENT_ID + "=" + clientKeyId + ")"
+                     + "(" + IKeyRecord.ATTR_STATUS + "=" + keyStatus + "))";
+        }
         try {
             Enumeration<IKeyRecord> existingKeys = null;
 
-- 
1.8.4.2

