From 02f9be1caa6310b5758b96d56d946e04557459c7 Mon Sep 17 00:00:00 2001 From: Ade Lee Date: Tue, 4 Feb 2014 13:17:18 -0500 Subject: 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. --- .../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 + 5 files changed, 111 insertions(+), 14 deletions(-) (limited to 'base/kra') 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 e1e730d82..05995f614 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 usages = new ArrayList(); 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 c082a784f..71bd1d781 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 50f163dfa..f3b7709e7 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 428dd660b..bbea11c32 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 3ebf1bed0..32dc1ceb9 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); -- cgit