diff options
author | Ade Lee <alee@redhat.com> | 2014-02-24 15:31:12 -0500 |
---|---|---|
committer | Ade Lee <alee@redhat.com> | 2014-02-26 01:18:56 -0500 |
commit | 62d4b2b3934507b1ddf699bcea4a6295565bb008 (patch) | |
tree | 624b07de5aa7dc1b824f4094f3b3a1fb4fab2320 | |
parent | 4488bb70e2b762d5282fcf88f1c4a349300dd6ea (diff) | |
download | pki-62d4b2b3934507b1ddf699bcea4a6295565bb008.tar.gz pki-62d4b2b3934507b1ddf699bcea4a6295565bb008.tar.xz pki-62d4b2b3934507b1ddf699bcea4a6295565bb008.zip |
Add ability to archive without sending pkiArchiveOptions object.
With this patch, you can now either send a pkiArchiveOptions object
or the exploded parameters. This reduces the processing required on
the client side.
10 files changed, 337 insertions, 107 deletions
diff --git a/base/common/python/pki/__init__.py b/base/common/python/pki/__init__.py index 7e4e2771c..a747ddb2d 100644 --- a/base/common/python/pki/__init__.py +++ b/base/common/python/pki/__init__.py @@ -94,6 +94,7 @@ def implementation_version(): raise Exception('Missing implementation version.') +#pylint: disable-msg=R0903 class Attribute(object): ''' Class representing a key/value pair. @@ -106,6 +107,7 @@ class Attribute(object): self.name = name self.value = value +#pylint: disable-msg=R0903 class AttributeList(object): ''' Class representing a list of attributes. @@ -113,6 +115,7 @@ class AttributeList(object): This class is needed because of a JavaMapper used in the REST API. ''' + # pylint: disable-msg=C0103 def __init__(self): ''' Constructor ''' self.Attribute = [] @@ -123,6 +126,7 @@ class ResourceMessage(object): It is essentially a list of attributes. ''' + # pylint: disable-msg=C0103 def __init__(self, class_name): ''' Constructor ''' self.Attributes = AttributeList() @@ -246,24 +250,24 @@ class PropertyFile(object): self.lines = [] def read(self): - ''' Read from propert file ''' + ''' Read from property file ''' self.lines = [] if not os.path.exists(self.filename): return # read all lines and preserve the original order - with open(self.filename, 'r') as f: - for line in f: + with open(self.filename, 'r') as f_in: + for line in f_in: line = line.strip('\n') self.lines.append(line) def write(self): ''' Write to property file ''' # write all lines in the original order - with open(self.filename, 'w') as f: + with open(self.filename, 'w') as f_out: for line in self.lines: - f.write(line + '\n') + f_out.write(line + '\n') def show(self): ''' Show contents of property file.''' diff --git a/base/common/python/pki/key.py b/base/common/python/pki/key.py index b4158fed6..de9fcc959 100644 --- a/base/common/python/pki/key.py +++ b/base/common/python/pki/key.py @@ -30,6 +30,7 @@ import pki import types import urllib +#pylint: disable-msg=R0903 class KeyId(object): ''' Class representing a key ID @@ -39,6 +40,7 @@ class KeyId(object): self.value = key_id #should be moved to request.py +#pylint: disable-msg=R0903 class RequestId(object): ''' Class representing a Request ID @@ -47,12 +49,14 @@ class RequestId(object): ''' Constructor''' self.value = req_id +#pylint: disable-msg=R0903 class KeyData(object): ''' This is the object that contains the wrapped secret when that secret is retrieved. ''' + # pylint: disable-msg=C0103 def __init__(self): ''' Constructor ''' self.algorithm = None @@ -75,6 +79,7 @@ class KeyInfo(object): contain the secret itself. ''' + # pylint: disable-msg=C0103 def __init__(self): ''' Constructor ''' self.clientKeyID = None @@ -99,7 +104,7 @@ class KeyInfo(object): return str(self.keyURL)[indx:] return None - +#pylint: disable-msg=R0903 class KeyInfoCollection(object): ''' This class represents data returned when searching the DRM archived @@ -129,6 +134,7 @@ class KeyRequestInfo(object): key generation etc.) in the DRM. ''' + # pylint: disable-msg=C0103 def __init__(self): ''' Constructor ''' self.requestURL = None @@ -158,6 +164,7 @@ class KeyRequestInfo(object): return str(self.keyURL)[indx:] return None +#pylint: disable-msg=R0903 class KeyRequestInfoCollection(object): ''' This class represents the data returned when searching the key @@ -190,6 +197,7 @@ class KeyRequestResponse(object): which contains the wrapped secret (if that operation is supported). ''' + # pylint: disable-msg=C0103 def __init__(self): ''' Constructor ''' self.requestInfo = None @@ -221,15 +229,32 @@ class KeyArchivalRequest(pki.ResourceMessage): ''' def __init__(self, client_key_id=None, data_type=None, wrapped_private_data=None, + trans_wrapped_session_key=None, pki_archive_options=None, + algorithm_oid = None, symkey_params = None, key_algorithm=None, key_size=None): ''' Constructor ''' pki.ResourceMessage.__init__(self, "com.netscape.certsrv.key.KeyArchivalRequest") self.add_attribute("clientKeyID", client_key_id) self.add_attribute("dataType", data_type) - self.add_attribute("wrappedPrivateData", wrapped_private_data) - self.add_attribute("keyAlgorithm", key_algorithm) - self.add_attribute("keySize", key_size) + + if wrapped_private_data is not None: + self.add_attribute("wrappedPrivateData", wrapped_private_data) + if trans_wrapped_session_key is not None: + self.add_attribute("transWrappedSessionKey", trans_wrapped_session_key) + if algorithm_oid is not None: + self.add_attribute("algorithmOID", algorithm_oid) + if symkey_params is not None: + self.add_attribute("symmetricAlgorithmParams", symkey_params) + + if pki_archive_options is not None: + self.add_attribute("pkiArchiveOptions", pki_archive_options) + + if key_algorithm is not None: + self.add_attribute("keyAlgorithm", key_algorithm) + + if key_size is not None: + self.add_attribute("keySize", key_size) class KeyRecoveryRequest(pki.ResourceMessage): ''' @@ -292,13 +317,20 @@ class KeyClient(object): KEY_STATUS_ACTIVE = "active" KEY_STATUS_INACTIVE = "inactive" + DES_ALGORITHM = "DES" + DESEDE_ALGORITHM = "DESede" + DES3_ALGORITHM = "DES3" + RC2_ALGORITHM = "RC2" + RC4_ALGORITHM = "RC4" + AES_ALGORITHM = "AES" + def __init__(self, connection, crypto, transport_cert_nick=None): ''' Constructor ''' self.connection = connection self.headers = {'Content-type': 'application/json', 'Accept': 'application/json'} - self.keyURL = '/rest/agent/keys' - self.keyRequestsURL = '/rest/agent/keyrequests' + self.key_url = '/rest/agent/keys' + self.key_requests_url = '/rest/agent/keyrequests' self.crypto = crypto if transport_cert_nick is not None: @@ -324,7 +356,7 @@ class KeyClient(object): query_params = {'clientKeyID':client_key_id, 'status':status, 'maxResults':max_results, 'maxTime':max_time, 'start':start, 'size':size} - response = self.connection.get(self.keyURL, self.headers, params=query_params) + response = self.connection.get(self.key_url, self.headers, params=query_params) return KeyInfoCollection.from_json(response.json()) @pki.handle_exceptions() @@ -338,7 +370,7 @@ class KeyClient(object): query_params = {'requestState':request_state, 'requestType':request_type, 'clientKeyID':client_key_id, 'start':start, 'pageSize':page_size, 'maxResults':max_results, 'maxTime':max_time} - response = self.connection.get(self.keyRequestsURL, self.headers, + response = self.connection.get(self.key_requests_url, self.headers, params=query_params) return KeyRequestInfoCollection.from_json(response.json()) @@ -348,7 +380,7 @@ class KeyClient(object): if request_id is None: raise ValueError("request_id must be specified") - url = self.keyRequestsURL + '/' + request_id + url = self.key_requests_url + '/' + request_id response = self.connection.get(url, self.headers) return KeyRequestInfo.from_json(response.json()) @@ -358,7 +390,7 @@ class KeyClient(object): if key_id is None: raise ValueError("key_id must be specified") - url = self.keyURL + '/' + key_id + url = self.key_url + '/' + key_id response = self.connection.get(url, headers=self.headers) return KeyInfo.from_json(response.json()) @@ -368,7 +400,7 @@ class KeyClient(object): if client_key_id is None: raise ValueError("client_key_id must be specified") - url = self.keyURL + '/active/' + urllib.quote_plus(client_key_id) + url = self.key_url + '/active/' + urllib.quote_plus(client_key_id) response = self.connection.get(url, headers=self.headers) return KeyInfo.from_json(response.json()) @@ -378,7 +410,7 @@ class KeyClient(object): if (key_id is None) or (status is None): raise ValueError("key_id and status must be specified") - url = self.keyURL + '/' + key_id + url = self.key_url + '/' + key_id params = {'status':status} self.connection.post(url, None, headers=self.headers, params=params) @@ -388,7 +420,7 @@ class KeyClient(object): if request_id is None: raise ValueError("request_id must be specified") - url = self.keyRequestsURL + '/' + request_id + '/approve' + url = self.key_requests_url + '/' + request_id + '/approve' self.connection.post(url, self.headers) @pki.handle_exceptions() @@ -397,7 +429,7 @@ class KeyClient(object): if request_id is None: raise ValueError("request_id must be specified") - url = self.keyRequestsURL + '/' + request_id + '/reject' + url = self.key_requests_url + '/' + request_id + '/reject' self.connection.post(url, self.headers) @pki.handle_exceptions() @@ -406,39 +438,9 @@ class KeyClient(object): if request_id is None: raise ValueError("request_id must be specified") - url = self.keyRequestsURL + '/' + request_id + '/cancel' + url = self.key_requests_url + '/' + request_id + '/cancel' self.connection.post(url, self.headers) - def generate_pki_archive_options(self, trans_wrapped_session_key, session_wrapped_secret): - ''' Return a PKIArchiveOptions structure for archiving a secret - - Takes in a session key wrapped by the DRM transport certificate, - and a secret wrapped with the session key and creates a PKIArchiveOptions - structure to be used when archiving a secret - ''' - pass - - def generate_archive_options(self, secret): - ''' Return a PKIArchiveOptions structure for archiving a secret. - - This method uses NSS calls to do the following: - 1) generate a session key - 2) wrap the session key with the transport key - 3) wrap the secret with the session key - 4) create the PKIArchiveOptions structure using the results of - (2) and (3) - - 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_session_key() - trans_wrapped_session_key = self.crypto.asymmetric_wrap(session_key, self.transport_cert) - wrapped_secret = self.crypto.symmetric_wrap(secret, session_key) - - return self.generate_pki_archive_options(trans_wrapped_session_key, wrapped_secret) - @pki.handle_exceptions() def create_request(self, request): ''' Submit an archival, recovery or key generation request @@ -452,7 +454,7 @@ class KeyClient(object): if request is None: raise ValueError("request must be specified") - url = self.keyRequestsURL + url = self.key_requests_url 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()) @@ -489,7 +491,9 @@ class KeyClient(object): @pki.handle_exceptions() def archive_key(self, client_key_id, data_type, private_data=None, - wrapped_private_data=None, + wrapped_private_data=None, trans_wrapped_session_key=None, + algorithm_oid=None, symkey_params=None, + pki_archive_options=None, key_algorithm=None, key_size=None): ''' Archive a secret (symmetric key or passphrase) on the DRM. @@ -505,16 +509,22 @@ class KeyClient(object): key_algorithm and key_size are applicable to symmetric keys only. If a symmetric key is being archived, these parameters are required. - wrapped_private_data consists of a PKIArchiveOptions structure, which - can be constructed using either generate_archive_options() or - generate_pki_archive_options() below. + Callers can invoke this method in one of three ways: - private_data is the secret that is to be archived. + 1. Provide the private_data. This is the secret to be archived. + It will be wrapped and sent to the DRM. + + 2. Provide the following pieces: + - wrapped_private_data - which is the secret wrapped by a session + key (168 bit 3DES symmetric key) + - trans_wrapped_session_key - the above session key wrapped by the + DRM transport certificate public key. + - the algorithm_oid string for the symmetric key wrap + - the symkey_params for the symmetric key wrap + + 3. wrapped_private_data which consists of a PKIArchiveOptions structure, - Callers must specify EITHER wrapped_private_data OR private_data. - If wrapped_private_data is specified, then this data is forwarded to the - DRM unchanged. Otherwise, the private_data is converted to a - PKIArchiveOptions structure using the functions below. + private_data is the secret that is to be archived. The function returns a KeyRequestResponse object containing a KeyRequestInfo object with details about the archival request and key archived. @@ -527,16 +537,50 @@ class KeyClient(object): 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) - - request = KeyArchivalRequest(client_key_id=client_key_id, + if private_data is None: + if wrapped_private_data is None: + if pki_archive_options is None: + raise ValueError("No data provided to be archived") + else: + data = base64.encodestring(pki_archive_options) + request = KeyArchivalRequest(client_key_id=client_key_id, data_type=data_type, - wrapped_private_data=wrapped_private_data, + pki_archive_options=data, key_algorithm=key_algorithm, key_size=key_size) + if trans_wrapped_session_key is None: + raise ValueError("Session Key not provided") + else: + twsk = base64.encodestring(trans_wrapped_session_key) + data = base64.encodestring(wrapped_private_data) + request = KeyArchivalRequest(client_key_id=client_key_id, + data_type=data_type, + wrapped_private_data=data, + trans_wrapped_session_key=twsk, + algorithm_oid=algorithm_oid, + symkey_params=symkey_params, + key_algorithm=key_algorithm, + key_size=key_size) + else: + session_key = self.crypto.generate_session_key() + trans_wrapped_session_key = \ + self.crypto.asymmetric_wrap(session_key, self.transport_cert) + wrapped_private_data = self.crypto.symmetric_wrap(private_data, session_key) + + twsk = base64.encodestring(trans_wrapped_session_key) + data = base64.encodestring(wrapped_private_data) + + # TODO - generate_algorithm_oid here + # generate symkey_params here + + request = KeyArchivalRequest(client_key_id=client_key_id, + data_type=data_type, + wrapped_private_data=data, + trans_wrapped_session_key=twsk, + algorithm_oid=algorithm_oid, + symkey_params=symkey_params, + key_algorithm=key_algorithm, + key_size=key_size) return self.create_request(request) @pki.handle_exceptions() @@ -577,9 +621,9 @@ class KeyClient(object): 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) + url = self.key_url + '/retrieve' + key_request = json.dumps(data, cls=encoder.CustomTypeEncoder, sort_keys=True) + response = self.connection.post(url, key_request, self.headers) return KeyData.from_json(response.json()) @pki.handle_exceptions() diff --git a/base/common/src/com/netscape/certsrv/key/KeyArchivalRequest.java b/base/common/src/com/netscape/certsrv/key/KeyArchivalRequest.java index 3c7628af9..03bbfb53a 100644 --- a/base/common/src/com/netscape/certsrv/key/KeyArchivalRequest.java +++ b/base/common/src/com/netscape/certsrv/key/KeyArchivalRequest.java @@ -38,7 +38,17 @@ public class KeyArchivalRequest extends ResourceMessage { private static final String CLIENT_KEY_ID = "clientKeyID"; private static final String DATA_TYPE = "dataType"; + + // exploded pkiArchiveOptions parameters private static final String WRAPPED_PRIVATE_DATA = "wrappedPrivateData"; + private static final String TRANS_WRAPPED_SESSION_KEY = "transWrappedSessionKey"; + private static final String ALGORITHM_OID = "algorithmOID"; + private static final String SYMMETRIC_ALGORITHM_PARAMS = "symmetricAlgorithmParams"; + + // parameter for un-exploded pkiArchiveOptions + private static final String PKI_ARCHIVE_OPTIONS = "pkiArchiveOptions"; + + // parameters for symmetric keys private static final String KEY_ALGORITHM = "keyAlgorithm"; private static final String KEY_SIZE = "keySize"; @@ -53,6 +63,8 @@ public class KeyArchivalRequest extends ResourceMessage { attributes.put(WRAPPED_PRIVATE_DATA, form.getFirst(WRAPPED_PRIVATE_DATA)); attributes.put(KEY_ALGORITHM, form.getFirst(KEY_ALGORITHM)); attributes.put(KEY_SIZE, form.getFirst(KEY_SIZE)); + attributes.put(PKI_ARCHIVE_OPTIONS, form.getFirst(PKI_ARCHIVE_OPTIONS)); + attributes.put(TRANS_WRAPPED_SESSION_KEY, form.getFirst(TRANS_WRAPPED_SESSION_KEY)); setClassName(getClass().getName()); } @@ -90,7 +102,63 @@ public class KeyArchivalRequest extends ResourceMessage { } /** - * @return the wrappedPrivateData + * @return the transWrappedSessionKey + */ + public String getTransWrappedSessionKey() { + return attributes.get(TRANS_WRAPPED_SESSION_KEY); + } + + /** + * @param transWrappedSessionKey the trans wrapped session key to set + */ + public void setTransWrappedSessionKey(String twsk) { + attributes.put(TRANS_WRAPPED_SESSION_KEY, twsk); + } + + /** + * @return the PKIArchiveOptions structure + */ + public String getPKIArchiveOptions() { + return attributes.get(PKI_ARCHIVE_OPTIONS); + } + + /** + * @param pkiArchiveIOptions the archive options structure to set + */ + public void setPKIArchiveOptions(String pkiArchiveOptions) { + attributes.put(PKI_ARCHIVE_OPTIONS, pkiArchiveOptions); + } + + /** + * @return the algorithm OID structure + */ + public String getAlgorithmOID() { + return attributes.get(ALGORITHM_OID); + } + + /** + * @param algorithmOID the symmetric algorithm OID to set + */ + public void setAlgorithmOID(String algOID) { + attributes.put(ALGORITHM_OID, algOID); + } + + /** + * @return the algorithm params structure + */ + public String getSymmetricAlgorithmParams() { + return attributes.get(SYMMETRIC_ALGORITHM_PARAMS); + } + + /** + * @param params the algorithm params to set + */ + public void setSymmetricAlgorithmParams(String params) { + attributes.put(SYMMETRIC_ALGORITHM_PARAMS, params); + } + + /** + * @return the pkiArchiveOptions structure */ public String getWrappedPrivateData() { return attributes.get(WRAPPED_PRIVATE_DATA); diff --git a/base/common/src/com/netscape/certsrv/key/KeyClient.java b/base/common/src/com/netscape/certsrv/key/KeyClient.java index 3c27dbb6c..0fa1f264e 100644 --- a/base/common/src/com/netscape/certsrv/key/KeyClient.java +++ b/base/common/src/com/netscape/certsrv/key/KeyClient.java @@ -118,11 +118,28 @@ public class KeyClient extends Client { return client.getEntity(response, KeyRequestInfo.class); } - public KeyRequestResponse archiveSecurityData(byte[] encoded, String clientKeyId, String dataType, String algorithm, int strength) { + public KeyRequestResponse archiveSecurityData(String clientKeyId, String dataType, + String algorithm, int strength, byte[] pkiArchiveOptions) { // create archival request KeyArchivalRequest data = new KeyArchivalRequest(); - String req1 = Utils.base64encode(encoded); - data.setWrappedPrivateData(req1); + data.setPKIArchiveOptions(Utils.base64encode(pkiArchiveOptions)); + data.setClientKeyId(clientKeyId); + data.setDataType(dataType); + data.setKeyAlgorithm(algorithm); + data.setKeySize(strength); + + return createRequest(data); + } + + public KeyRequestResponse archiveSecurityData(String clientKeyId, String dataType, + String algorithm, int strength, byte[] wrappedPrivateData, + byte[] wrappedSessionKey, String algorithmOID, byte[] algParams) { + // create archival request + KeyArchivalRequest data = new KeyArchivalRequest(); + data.setTransWrappedSessionKey(Utils.base64encode(wrappedSessionKey)); + data.setWrappedPrivateData(Utils.base64encode(wrappedPrivateData)); + data.setAlgorithmOID(algorithmOID); + data.setSymmetricAlgorithmParams(Utils.base64encode(algParams)); data.setClientKeyId(clientKeyId); data.setDataType(dataType); data.setKeyAlgorithm(algorithm); diff --git a/base/common/src/com/netscape/certsrv/profile/IEnrollProfile.java b/base/common/src/com/netscape/certsrv/profile/IEnrollProfile.java index a2767ee53..69a39d7e2 100644 --- a/base/common/src/com/netscape/certsrv/profile/IEnrollProfile.java +++ b/base/common/src/com/netscape/certsrv/profile/IEnrollProfile.java @@ -155,6 +155,26 @@ public interface IEnrollProfile extends IProfile { public static final String REQUEST_TRANSPORT_CERT = "req_transport_cert"; /** + * Session wrapped security data passed in to the DRM archival service + */ + public static final String REQUEST_SECURITY_DATA = "req_security_data"; + + /** + * Transport Key wrapped session key passed into DRM archival service. + */ + public static final String REQUEST_SESSION_KEY = "req_session_key"; + + /** + * Symmetric Key algorithm OID passed into DRM archival service + */ + public static final String REQUEST_ALGORITHM_OID = "req_algorithm_oid"; + + /** + * Symmetric key algorithm params passed into DRM archival service + */ + public static final String REQUEST_ALGORITHM_PARAMS = "req_algorithm_params"; + + /** * Set Default X509CertInfo in the request. * * @param request profile-based certificate request. diff --git a/base/kra/functional/drmtest.py b/base/kra/functional/drmtest.py index dd7abbf53..08baf5011 100644 --- a/base/kra/functional/drmtest.py +++ b/base/kra/functional/drmtest.py @@ -106,7 +106,7 @@ 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 = "veka6" + client_key_id = "veka9" algorithm = "AES" key_size = 128 usages = [key.SymKeyGenerationRequest.DECRYPT_USAGE, key.SymKeyGenerationRequest.ENCRYPT_USAGE] @@ -132,6 +132,7 @@ def main(): # Test 6: Barbican_decode() - Retrieve while providing trans_wrapped_session_key session_key = crypto.generate_session_key() wrapped_session_key = crypto.asymmetric_wrap(session_key, keyclient.transport_cert) + print "My key id is " + str(key_id) key_data, _unwrapped_key = keyclient.retrieve_key(key_id, trans_wrapped_session_key=wrapped_session_key) print_key_data(key_data) unwrapped_key = crypto.symmetric_unwrap(base64.decodestring(key_data.wrappedPrivateData), @@ -211,5 +212,17 @@ def main(): response = keyclient.generate_symmetric_key(client_key_id) print_key_request(response.requestInfo) + # Test 19: Try to archive key + print "try to archive key" + print "key to archive: " + key1 + client_key_id = "Vek #4" + time.strftime('%X %x %Z') + + # this test is not quite working yet + #response = keyclient.archive_key(client_key_id, keyclient.SYMMETRIC_KEY_TYPE, + # private_data=base64.decodestring(key1), + # key_algorithm=keyclient.AES_ALGORITHM, + # key_size=128) + #print_key_request(response.requestInfo) + if __name__ == "__main__": main() 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 5681c1114..899c78a66 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 @@ -263,8 +263,8 @@ public class DRMTest { byte[] encoded = CryptoUtil.createPKIArchiveOptions(manager, token, transportCert, vek, null, KeyGenAlgorithm.DES3, ivps); - KeyRequestResponse info = keyClient.archiveSecurityData(encoded, clientKeyId, - KeyRequestResource.SYMMETRIC_KEY_TYPE, KeyRequestResource.DES3_ALGORITHM, 0); + KeyRequestResponse info = keyClient.archiveSecurityData(clientKeyId, KeyRequestResource.SYMMETRIC_KEY_TYPE, + KeyRequestResource.DES3_ALGORITHM, 0, encoded); log("Archival Results:"); printRequestInfo(info.getRequestInfo()); keyId = info.getRequestInfo().getKeyId(); @@ -375,8 +375,8 @@ public class DRMTest { try { byte[] encoded = CryptoUtil.createPKIArchiveOptions(manager, token, transportCert, null, passphrase, KeyGenAlgorithm.DES3, ivps); - requestResponse = keyClient.archiveSecurityData(encoded, clientKeyId, - KeyRequestResource.PASS_PHRASE_TYPE, null, 0); + requestResponse = keyClient.archiveSecurityData(clientKeyId, KeyRequestResource.PASS_PHRASE_TYPE, + null, 0, encoded); log("Archival Results:"); printRequestInfo(requestResponse.getRequestInfo()); keyId = requestResponse.getRequestInfo().getKeyId(); @@ -661,8 +661,8 @@ public class DRMTest { byte[] encoded = CryptoUtil.createPKIArchiveOptions(manager, token, transportCert, vek, null, KeyGenAlgorithm.DES3, ivps); - KeyRequestResponse response = keyClient.archiveSecurityData(encoded, clientKeyId, - KeyRequestResource.SYMMETRIC_KEY_TYPE, KeyRequestResource.AES_ALGORITHM, 128); + KeyRequestResponse response = keyClient.archiveSecurityData(clientKeyId, KeyRequestResource.SYMMETRIC_KEY_TYPE, + KeyRequestResource.AES_ALGORITHM, 128, encoded); log("Archival Results:"); printRequestInfo(response.getRequestInfo()); keyId = response.getRequestInfo().getKeyId(); diff --git a/base/kra/src/com/netscape/kra/SecurityDataService.java b/base/kra/src/com/netscape/kra/SecurityDataService.java index 388079f32..37229f09a 100644 --- a/base/kra/src/com/netscape/kra/SecurityDataService.java +++ b/base/kra/src/com/netscape/kra/SecurityDataService.java @@ -84,7 +84,17 @@ public class SecurityDataService implements IService { throws EBaseException { String id = request.getRequestId().toString(); String clientKeyId = request.getExtDataInString(IRequest.SECURITY_DATA_CLIENT_KEY_ID); - String wrappedSecurityData = request.getExtDataInString(IEnrollProfile.REQUEST_ARCHIVE_OPTIONS); + + // one way to get data - unexploded pkiArchiveOptions + String pkiArchiveOptions = request.getExtDataInString(IEnrollProfile.REQUEST_ARCHIVE_OPTIONS); + + // another way - exploded pkiArchiveOptions + String transWrappedSessionKey = request.getExtDataInString(IEnrollProfile.REQUEST_SESSION_KEY); + String wrappedSecurityData = request.getExtDataInString(IEnrollProfile.REQUEST_SECURITY_DATA); + String algParams = request.getExtDataInString(IEnrollProfile.REQUEST_ALGORITHM_PARAMS); + String algStr = request.getExtDataInString(IEnrollProfile.REQUEST_ALGORITHM_OID); + + // prameters if the secret is a symkey String dataType = request.getExtDataInString(IRequest.SECURITY_DATA_TYPE); String algorithm = request.getExtDataInString(IRequest.SECURITY_DATA_ALGORITHM); int strength = request.getExtDataInInteger(IRequest.SECURITY_DATA_STRENGTH); @@ -96,25 +106,50 @@ public class SecurityDataService implements IService { String subjectID = auditSubjectID(); //Check here even though restful layer checks for this. - if(wrappedSecurityData == null || clientKeyId == null || dataType == null) { + if (clientKeyId == null || dataType == null) { auditArchivalRequestProcessed(subjectID, ILogger.FAILURE, request.getRequestId(), clientKeyId, null, "Bad data in request"); throw new EBaseException("Bad data in SecurityDataService.serviceRequest"); } - //We need some info from the PKIArchiveOptions wrapped security data - byte[] encoded = Utils.base64decode(wrappedSecurityData); + if (wrappedSecurityData != null) { + if (transWrappedSessionKey == null || algStr == null || algParams == null) { + throw new EBaseException( + "Bad data in SecurityDataService.serviceRequest, no session key"); - ArchiveOptions options = ArchiveOptions.toArchiveOptions(encoded); - - //Check here just in case a null ArchiveOptions makes it this far - if(options == null) { - auditArchivalRequestProcessed(subjectID, ILogger.FAILURE, request.getRequestId(), - clientKeyId, null, "Problem decoding PKIArchiveOptions"); - throw new EBaseException("Problem decoding PKIArchiveOptions."); + } + } else if (pkiArchiveOptions == null) { + throw new EBaseException("No data to archive in SecurityDataService.serviceRequest"); } - String algStr = options.getSymmAlgOID(); + byte[] wrappedSessionKey = null; + byte[] secdata = null; + byte[] sparams = null; + + if (wrappedSecurityData == null) { + // We have PKIArchiveOptions data + + //We need some info from the PKIArchiveOptions wrapped security data + byte[] encoded = Utils.base64decode(pkiArchiveOptions); + + ArchiveOptions options = ArchiveOptions.toArchiveOptions(encoded); + + //Check here just in case a null ArchiveOptions makes it this far + if (options == null) { + auditArchivalRequestProcessed(subjectID, ILogger.FAILURE, request.getRequestId(), + clientKeyId, null, "Problem decoding PKIArchiveOptions"); + throw new EBaseException("Problem decoding PKIArchiveOptions."); + } + algStr = options.getSymmAlgOID(); + wrappedSessionKey = options.getEncSymmKey(); + secdata = options.getEncValue(); + sparams = options.getSymmAlgParams(); + + } else { + wrappedSessionKey = Utils.base64decode(transWrappedSessionKey); + secdata = Utils.base64decode(wrappedSecurityData); + sparams = Utils.base64decode(algParams); + } SymmetricKey securitySymKey = null; byte[] securityData = null; @@ -123,19 +158,21 @@ public class SecurityDataService implements IService { 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(), - KeyRequestService.SYMKEY_TYPES.get(algorithm), - strength); + securitySymKey = mTransportUnit.unwrap_symmetric( + wrappedSessionKey, + algStr, + sparams, + secdata, + KeyRequestService.SYMKEY_TYPES.get(algorithm), + strength); } else if (dataType.equals(KeyRequestResource.PASS_PHRASE_TYPE)) { keyType = KeyRequestResource.PASS_PHRASE_TYPE; - securityData = mTransportUnit.decryptExternalPrivate(options.getEncSymmKey(), - options.getSymmAlgOID(), - options.getSymmAlgParams(), - options.getEncValue()); + securityData = mTransportUnit.decryptExternalPrivate( + wrappedSessionKey, + algStr, + sparams, + secdata); } 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 d84bbd013..93e0018c4 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 @@ -63,6 +63,11 @@ import com.netscape.cms.servlet.request.KeyRequestService; public class KeyRequestDAO extends CMSRequestDAO { private static String REQUEST_ARCHIVE_OPTIONS = IEnrollProfile.REQUEST_ARCHIVE_OPTIONS; + private static String REQUEST_SECURITY_DATA = IEnrollProfile.REQUEST_SECURITY_DATA; + private static String REQUEST_SESSION_KEY = IEnrollProfile.REQUEST_SESSION_KEY; + private static String REQUEST_ALGORITHM_OID = IEnrollProfile.REQUEST_ALGORITHM_OID; + private static String REQUEST_ALGORITHM_PARAMS = IEnrollProfile.REQUEST_ALGORITHM_PARAMS; + public static final String ATTR_SERIALNO = "serialNumber"; private IKeyRepository repo; @@ -140,6 +145,10 @@ public class KeyRequestDAO extends CMSRequestDAO { public KeyRequestResponse submitRequest(KeyArchivalRequest data, UriInfo uriInfo) throws EBaseException { String clientKeyId = data.getClientKeyId(); String wrappedSecurityData = data.getWrappedPrivateData(); + String transWrappedSessionKey = data.getTransWrappedSessionKey(); + String algorithmOID = data.getAlgorithmOID(); + String symkeyParams = data.getSymmetricAlgorithmParams(); + String pkiArchiveOptions = data.getPKIArchiveOptions(); String dataType = data.getDataType(); String keyAlgorithm = data.getKeyAlgorithm(); int keyStrength = data.getKeySize(); @@ -152,7 +161,14 @@ public class KeyRequestDAO extends CMSRequestDAO { IRequest request = queue.newRequest(IRequest.SECURITY_DATA_ENROLLMENT_REQUEST); - request.setExtData(REQUEST_ARCHIVE_OPTIONS, wrappedSecurityData); + if (pkiArchiveOptions != null) { + request.setExtData(REQUEST_ARCHIVE_OPTIONS, pkiArchiveOptions); + } else { + request.setExtData(REQUEST_SECURITY_DATA, wrappedSecurityData); + request.setExtData(REQUEST_SESSION_KEY, transWrappedSessionKey); + request.setExtData(REQUEST_ALGORITHM_PARAMS, symkeyParams); + request.setExtData(REQUEST_ALGORITHM_OID, algorithmOID); + } request.setExtData(IRequest.SECURITY_DATA_CLIENT_KEY_ID, clientKeyId); request.setExtData(IRequest.SECURITY_DATA_TYPE, dataType); request.setExtData(IRequest.SECURITY_DATA_STRENGTH, 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 dd27c2ac7..e2253b6e8 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 @@ -162,12 +162,23 @@ public class KeyRequestService extends PKIService implements KeyRequestResource // auth and authz // Catch this before internal server processing has to deal with it - if (data == null || data.getClientKeyId() == null - || data.getWrappedPrivateData() == null - || data.getDataType() == null) { + if (data == null || data.getClientKeyId() == null || data.getDataType() == null) { throw new BadRequestException("Invalid key archival request."); } + if (data.getWrappedPrivateData() != null) { + if (data.getTransWrappedSessionKey() == null || + data.getAlgorithmOID() == null || + data.getSymmetricAlgorithmParams() == null) { + throw new BadRequestException( + "Invalid key archival request. " + + "Missing wrapped session key, algoriithmOIS or symmetric key parameters"); + } + } else if (data.getPKIArchiveOptions() == null) { + throw new BadRequestException( + "Invalid key archival request. No data to archive"); + } + if (data.getDataType().equals(KeyRequestResource.SYMMETRIC_KEY_TYPE)) { if ((data.getKeyAlgorithm() == null) || (! SYMKEY_TYPES.containsKey(data.getKeyAlgorithm()))) { |