summaryrefslogtreecommitdiffstats
path: root/base/common/src/com
diff options
context:
space:
mode:
authorAde Lee <alee@redhat.com>2017-03-15 17:19:01 -0400
committerAde Lee <alee@redhat.com>2017-03-21 18:49:07 -0400
commit82478227debddbe11bd9b9eeb0e1e2f3bd5282fb (patch)
tree62418ffdfff9d90cec9ca6749f0524a83bf41233 /base/common/src/com
parentf40e0d002e57cadd5dc254d096db52de439ed900 (diff)
Fix Java client to use AES
* Changed the client to use AES-128-CBC-PAD rather than DES-3. Because AES-256-CBC-PAD has no OID defined, we use the following hack: * Pass in the AES-256-CBC OID as the encrypt algorithm OID * Use PKCS#1.5 Padding. * Changed the client to use AES for the wrapping key on retrieval. * Changed the server to implicitly assume PKCS#1.5 (and a key size of 128) when recieving the OID for AES. * Changed the client to send, and the server to pass through the encryption algorithm expected when retrieving the key. * Fixed the generate_iv() function to generate an appropriately sized IV on retrieval. This code has been tested to successfully create and retrieve secrets using AES. Ideally, we'd be using GCM rather than CBC, which then requires no padding - and no hack needed. Hopefully, we can get that working in a subsequent commit. Change-Id: Ic9e8d50169be0fe357a48a5a1b1c452c7a3dfad0
Diffstat (limited to 'base/common/src/com')
-rw-r--r--base/common/src/com/netscape/certsrv/key/KeyClient.java117
-rw-r--r--base/common/src/com/netscape/certsrv/security/WrappingParams.java5
-rw-r--r--base/common/src/com/netscape/certsrv/util/CryptoProvider.java13
-rw-r--r--base/common/src/com/netscape/certsrv/util/NSSCryptoProvider.java52
4 files changed, 153 insertions, 34 deletions
diff --git a/base/common/src/com/netscape/certsrv/key/KeyClient.java b/base/common/src/com/netscape/certsrv/key/KeyClient.java
index 8236d7f6b..a05bb78df 100644
--- a/base/common/src/com/netscape/certsrv/key/KeyClient.java
+++ b/base/common/src/com/netscape/certsrv/key/KeyClient.java
@@ -18,11 +18,16 @@
package com.netscape.certsrv.key;
import java.net.URISyntaxException;
+import java.security.NoSuchAlgorithmException;
import java.util.List;
import javax.ws.rs.core.Response;
+import org.dogtagpki.common.Info;
+import org.dogtagpki.common.InfoResource;
+import org.dogtagpki.common.Version;
import org.mozilla.jss.crypto.EncryptionAlgorithm;
+import org.mozilla.jss.crypto.KeyWrapAlgorithm;
import org.mozilla.jss.crypto.SymmetricKey;
import com.netscape.certsrv.base.ResourceMessage;
@@ -42,19 +47,55 @@ public class KeyClient extends Client {
public KeyResource keyClient;
public KeyRequestResource keyRequestClient;
+ public InfoResource infoClient;
private CryptoProvider crypto;
private String transportCert;
+ private EncryptionAlgorithm encryptAlgorithm;
+ private KeyWrapAlgorithm wrapAlgorithm;
+ private int wrapIVLength;
public KeyClient(PKIClient client, String subsystem) throws Exception {
super(client, subsystem, "key");
init();
- this.crypto = client.getCrypto();
+ crypto = client.getCrypto();
+
+ // TODO(alee) enable this when we figure out why its not working
+ // Version serverVersion = getServerVersion();
+
+ Version serverVersion= new Version("10.4.0");
+ if ((serverVersion.getMajor() >= 10) && (serverVersion.getMinor() >=4)) {
+ encryptAlgorithm = EncryptionAlgorithm.AES_128_CBC_PAD;
+ wrapAlgorithm = KeyWrapAlgorithm.AES_KEY_WRAP_PAD;
+ wrapIVLength = 0;
+ } else {
+ encryptAlgorithm = EncryptionAlgorithm.DES3_CBC;
+ wrapAlgorithm = KeyWrapAlgorithm.DES3_CBC_PAD;
+ wrapIVLength = 8;
+ }
+ }
+
+ private Version getServerVersion() {
+ Version ret = null;
+ try {
+ Response response = infoClient.getInfo();
+ Info info = client.getEntity(response, Info.class);
+ String version = info.getVersion();
+ ret = new Version(version);
+ } catch (Exception e) {
+ // TODO(alee) - narrow the exception here. We should only
+ // return Version(0.0.0) in the case where get a 404 response.
+
+ // old server - may not have the Info service
+ ret = new Version("0.0.0");
+ }
+ return ret;
}
public void init() throws URISyntaxException {
keyClient = createProxy(KeyResource.class);
keyRequestClient = createProxy(KeyRequestResource.class);
+ infoClient = createProxy(InfoResource.class);
}
public CryptoProvider getCrypto() {
@@ -363,13 +404,13 @@ public class KeyClient extends Client {
if (keyId == null) {
throw new IllegalArgumentException("KeyId must be specified.");
}
- SymmetricKey sessionKey = crypto.generateSessionKey();
+ SymmetricKey sessionKey = crypto.generateSessionKey(encryptAlgorithm);
byte[] transWrappedSessionKey = crypto.wrapSessionKeyWithTransportCert(sessionKey, transportCert);
Key data = retrieveKey(keyId, transWrappedSessionKey);
if (data.getEncryptedData()!= null)
data.setData(crypto.unwrapWithSessionKey(data.getEncryptedData(), sessionKey,
- KeyRequestResource.DES3_ALGORITHM, data.getNonceData()));
+ encryptAlgorithm, data.getNonceData()));
return data;
}
@@ -378,17 +419,18 @@ public class KeyClient extends Client {
if (requestId == null) {
throw new IllegalArgumentException("RequestId must be specified.");
}
- SymmetricKey sessionKey = crypto.generateSessionKey();
+ SymmetricKey sessionKey = crypto.generateSessionKey(encryptAlgorithm);
byte[] transWrappedSessionKey = crypto.wrapSessionKeyWithTransportCert(sessionKey, transportCert);
KeyRecoveryRequest recoveryRequest = new KeyRecoveryRequest();
recoveryRequest.setRequestId(requestId);
recoveryRequest.setTransWrappedSessionKey(Utils.base64encode(transWrappedSessionKey));
+ recoveryRequest.setPayloadEncryptionOID(getEncryptAlgorithmOID());
Key data = retrieveKeyData(recoveryRequest);
if (data.getEncryptedData() != null)
data.setData(crypto.unwrapWithSessionKey(data.getEncryptedData(), sessionKey,
- KeyRequestResource.DES3_ALGORITHM, data.getNonceData()));
+ encryptAlgorithm, data.getNonceData()));
return data;
}
@@ -423,6 +465,7 @@ public class KeyClient extends Client {
KeyRecoveryRequest recoveryRequest = new KeyRecoveryRequest();
recoveryRequest.setKeyId(keyId);
recoveryRequest.setTransWrappedSessionKey(Utils.base64encode(transWrappedSessionKey));
+ recoveryRequest.setPayloadEncryptionOID(getEncryptAlgorithmOID());
return retrieveKeyData(recoveryRequest);
}
@@ -453,11 +496,11 @@ public class KeyClient extends Client {
if (passphrase == null) {
throw new IllegalArgumentException("Passphrase must be specified.");
}
- SymmetricKey sessionKey = crypto.generateSessionKey();
- byte[] transWrappedSessionKey = crypto.wrapSessionKeyWithTransportCert(sessionKey, this.transportCert);
- byte[] nonceData = CryptoUtil.getNonceData(8);
+ SymmetricKey sessionKey = crypto.generateSessionKey(encryptAlgorithm);
+ byte[] transWrappedSessionKey = crypto.wrapSessionKeyWithTransportCert(sessionKey, transportCert);
+ byte[] nonceData = CryptoUtil.getNonceData(encryptAlgorithm.getIVLength());
byte[] sessionWrappedPassphrase = crypto.wrapWithSessionKey(passphrase, nonceData, sessionKey,
- KeyRequestResource.DES3_ALGORITHM);
+ encryptAlgorithm);
return retrieveKeyUsingWrappedPassphrase(keyId, transWrappedSessionKey, sessionWrappedPassphrase, nonceData);
}
@@ -470,17 +513,18 @@ public class KeyClient extends Client {
throw new IllegalArgumentException("Passphrase must be specified.");
}
- SymmetricKey sessionKey = crypto.generateSessionKey();
- byte[] transWrappedSessionKey = crypto.wrapSessionKeyWithTransportCert(sessionKey, this.transportCert);
- byte[] nonceData = CryptoUtil.getNonceData(8);
+ SymmetricKey sessionKey = crypto.generateSessionKey(encryptAlgorithm);
+ byte[] transWrappedSessionKey = crypto.wrapSessionKeyWithTransportCert(sessionKey, transportCert);
+ byte[] nonceData = CryptoUtil.getNonceData(encryptAlgorithm.getIVLength());
byte[] sessionWrappedPassphrase = crypto.wrapWithSessionKey(passphrase, nonceData, sessionKey,
- KeyRequestResource.DES3_ALGORITHM);
+ encryptAlgorithm);
KeyRecoveryRequest data = new KeyRecoveryRequest();
data.setRequestId(requestId);
data.setTransWrappedSessionKey(Utils.base64encode(transWrappedSessionKey));
data.setSessionWrappedPassphrase(Utils.base64encode(sessionWrappedPassphrase));
data.setNonceData(Utils.base64encode(nonceData));
+ data.setPayloadEncryptionOID(getEncryptAlgorithmOID());
return retrieveKeyData(data);
}
@@ -528,6 +572,7 @@ public class KeyClient extends Client {
KeyRecoveryRequest data = new KeyRecoveryRequest();
data.setKeyId(keyId);
data.setRequestId(requestId);
+ data.setPayloadEncryptionOID(getEncryptAlgorithmOID());
if (transWrappedSessionKey != null) {
data.setTransWrappedSessionKey(Utils.base64encode(transWrappedSessionKey));
@@ -589,18 +634,34 @@ public class KeyClient extends Client {
*/
public KeyRequestResponse archivePassphrase(String clientKeyId, String passphrase, String realm)
throws Exception {
- // Default algorithm OID for DES_EDE3_CBC
- String algorithmOID = EncryptionAlgorithm.DES3_CBC.toOID().toString();
- byte[] nonceData = CryptoUtil.getNonceData(8);
- SymmetricKey sessionKey = crypto.generateSessionKey();
- byte[] transWrappedSessionKey = crypto.wrapSessionKeyWithTransportCert(sessionKey, this.transportCert);
- byte[] encryptedData = crypto.wrapWithSessionKey(passphrase, nonceData,
- sessionKey, KeyRequestResource.DES3_ALGORITHM);
+ String algorithmOID = getEncryptAlgorithmOID();
+
+ byte[] nonceData = CryptoUtil.getNonceData(encryptAlgorithm.getIVLength());
+ SymmetricKey sessionKey = crypto.generateSessionKey(encryptAlgorithm);
+ byte[] transWrappedSessionKey = crypto.wrapSessionKeyWithTransportCert(sessionKey, transportCert);
+
+ byte[] encryptedData = crypto.wrapWithSessionKey(
+ passphrase,
+ nonceData,
+ sessionKey,
+ encryptAlgorithm);
return archiveEncryptedData(clientKeyId, KeyRequestResource.PASS_PHRASE_TYPE, null, 0, algorithmOID,
nonceData, encryptedData, transWrappedSessionKey, realm);
}
+ private String getEncryptAlgorithmOID() throws NoSuchAlgorithmException {
+ String algorithmOID;
+ if (encryptAlgorithm.getAlg().toString().equalsIgnoreCase("AES")) {
+ // TODO(alee) - horrible hack until we figure out how to do GCM right
+ // We assume the client will have AES 128 CBC with padding
+ algorithmOID = EncryptionAlgorithm.AES_128_CBC.toOID().toString();
+ } else {
+ algorithmOID = encryptAlgorithm.toOID().toString();
+ }
+ return algorithmOID;
+ }
+
/* Old signature for backwards compatibility */
@Deprecated
public KeyRequestResponse archivePassphrase(String clientKeyId, String passphrase) throws Exception {
@@ -626,12 +687,16 @@ public class KeyClient extends Client {
public KeyRequestResponse archiveSymmetricKey(String clientKeyId, SymmetricKey secret, String keyAlgorithm,
int keySize, String realm) throws Exception {
- // Default algorithm OID for DES_EDE3_CBC
- String algorithmOID = EncryptionAlgorithm.DES3_CBC.toOID().toString();
- SymmetricKey sessionKey = crypto.generateSessionKey();
- byte[] nonceData = CryptoUtil.getNonceData(8);
- byte[] encryptedData = crypto.wrapWithSessionKey(secret, sessionKey, nonceData);
- byte[] transWrappedSessionKey = crypto.wrapSessionKeyWithTransportCert(sessionKey, this.transportCert);
+ String algorithmOID = getEncryptAlgorithmOID();
+
+ byte[] nonceData = null;
+ if (wrapIVLength > 0) {
+ nonceData = CryptoUtil.getNonceData(wrapIVLength);
+ }
+
+ SymmetricKey sessionKey = crypto.generateSessionKey(encryptAlgorithm);
+ byte[] encryptedData = crypto.wrapWithSessionKey(secret, sessionKey, nonceData, wrapAlgorithm);
+ byte[] transWrappedSessionKey = crypto.wrapSessionKeyWithTransportCert(sessionKey, transportCert);
return archiveEncryptedData(clientKeyId, KeyRequestResource.SYMMETRIC_KEY_TYPE, keyAlgorithm, keySize,
algorithmOID, nonceData, encryptedData, transWrappedSessionKey, realm);
diff --git a/base/common/src/com/netscape/certsrv/security/WrappingParams.java b/base/common/src/com/netscape/certsrv/security/WrappingParams.java
index 5d8dc3a6e..e1bc83500 100644
--- a/base/common/src/com/netscape/certsrv/security/WrappingParams.java
+++ b/base/common/src/com/netscape/certsrv/security/WrappingParams.java
@@ -59,6 +59,11 @@ public class WrappingParams {
switch (encrypt.getAlg().toString()) {
case "AES":
+ // TODO(alee) - Terrible hack till we figure out why GCM is not working
+ // or a way to detect the padding.
+ // We are going to assume AES-128-PAD
+ encrypt = EncryptionAlgorithm.AES_128_CBC_PAD;
+
this.skType = SymmetricKey.AES;
this.skKeyGenAlgorithm = KeyGenAlgorithm.AES;
if (wrap == null) this.payloadWrapAlgorithm = KeyWrapAlgorithm.AES_KEY_WRAP_PAD;
diff --git a/base/common/src/com/netscape/certsrv/util/CryptoProvider.java b/base/common/src/com/netscape/certsrv/util/CryptoProvider.java
index d0c753ae0..0ec520580 100644
--- a/base/common/src/com/netscape/certsrv/util/CryptoProvider.java
+++ b/base/common/src/com/netscape/certsrv/util/CryptoProvider.java
@@ -1,5 +1,7 @@
package com.netscape.certsrv.util;
+import org.mozilla.jss.crypto.EncryptionAlgorithm;
+import org.mozilla.jss.crypto.KeyWrapAlgorithm;
import org.mozilla.jss.crypto.SymmetricKey;
/**
@@ -17,17 +19,28 @@ public abstract class CryptoProvider {
public abstract SymmetricKey generateSessionKey() throws Exception;
+ public abstract SymmetricKey generateSessionKey(EncryptionAlgorithm algorithm) throws Exception;
+
public abstract byte[] wrapSessionKeyWithTransportCert(SymmetricKey sessionKey, String transportCert)
throws Exception;
public abstract byte[] wrapWithSessionKey(String passphrase, byte[] iv, SymmetricKey key, String keyAlgorithm)
throws Exception;
+ public abstract byte[] wrapWithSessionKey(String passphrase, byte[] iv, SymmetricKey key, EncryptionAlgorithm keyAlgorithm)
+ throws Exception;
+
public abstract byte[] wrapWithSessionKey(SymmetricKey secret, SymmetricKey sessionKey, byte[] iv) throws Exception;
+ public abstract byte[] wrapWithSessionKey(SymmetricKey secret, SymmetricKey sessionKey, byte[] iv,
+ KeyWrapAlgorithm wrapAlg) throws Exception;
+
public abstract byte[] unwrapWithSessionKey(byte[] wrappedRecoveredKey, SymmetricKey recoveryKey,
String keyAlgorithm, byte[] nonceData) throws Exception;
+ public abstract byte[] unwrapWithSessionKey(byte[] wrappedRecoveredKey, SymmetricKey recoveryKey,
+ EncryptionAlgorithm keyAlgorithm, byte[] nonceData) throws Exception;
+
public abstract byte[] unwrapWithPassphrase(byte[] wrappedRecoveredKey, String recoveryPassphrase)
throws Exception;
diff --git a/base/common/src/com/netscape/certsrv/util/NSSCryptoProvider.java b/base/common/src/com/netscape/certsrv/util/NSSCryptoProvider.java
index a2d204347..423ad68e6 100644
--- a/base/common/src/com/netscape/certsrv/util/NSSCryptoProvider.java
+++ b/base/common/src/com/netscape/certsrv/util/NSSCryptoProvider.java
@@ -108,7 +108,14 @@ public class NSSCryptoProvider extends CryptoProvider {
@Override
public SymmetricKey generateSessionKey() throws Exception {
- return generateSymmetricKey(KeyRequestResource.DES3_ALGORITHM, 168);
+ return generateSymmetricKey(KeyRequestResource.AES_ALGORITHM, 128);
+ }
+
+ @Override
+ public SymmetricKey generateSessionKey(EncryptionAlgorithm algorithm) throws Exception {
+ return generateSymmetricKey(
+ algorithm.getAlg().toString(),
+ algorithm.getKeyStrength());
}
@Override
@@ -122,22 +129,37 @@ public class NSSCryptoProvider extends CryptoProvider {
@Override
public byte[] wrapWithSessionKey(String passphrase, byte[] iv, SymmetricKey key, String encryptionAlgorithm)
throws Exception {
+ return wrapWithSessionKey(passphrase, iv, key, getEncryptionAlgorithm(encryptionAlgorithm));
+ }
+
+ @Override
+ public byte[] wrapWithSessionKey(String passphrase, byte[] iv, SymmetricKey key, EncryptionAlgorithm encryptionAlgorithm)
+ throws Exception {
if (token == null) {
throw new NotInitializedException();
}
- return CryptoUtil.wrapPassphrase(token, passphrase, new IVParameterSpec(iv), key,
- getEncryptionAlgorithm(encryptionAlgorithm));
+ return CryptoUtil.wrapPassphrase(token, passphrase, new IVParameterSpec(iv), key, encryptionAlgorithm);
}
@Override
public byte[] unwrapWithSessionKey(byte[] wrappedRecoveredKey, SymmetricKey recoveryKey,
String encryptionAlgorithm, byte[] nonceData) throws Exception {
+ return unwrapWithSessionKey(wrappedRecoveredKey, recoveryKey,
+ getEncryptionAlgorithm(encryptionAlgorithm), nonceData);
+ }
+
+ @Override
+ public byte[] unwrapWithSessionKey(byte[] wrappedRecoveredKey, SymmetricKey recoveryKey,
+ EncryptionAlgorithm encryptionAlgorithm, byte[] nonceData) throws Exception {
if (token == null) {
throw new NotInitializedException();
}
- return CryptoUtil.decryptUsingSymmetricKey(token, new IVParameterSpec(nonceData), wrappedRecoveredKey,
- recoveryKey,
- getEncryptionAlgorithm(encryptionAlgorithm));
+ IVParameterSpec ivps = null;
+ if (nonceData != null) {
+ ivps = new IVParameterSpec(nonceData);
+ }
+ return CryptoUtil.decryptUsingSymmetricKey(token, ivps, wrappedRecoveredKey,
+ recoveryKey, encryptionAlgorithm);
}
@Override
@@ -217,8 +239,22 @@ public class NSSCryptoProvider extends CryptoProvider {
token,
sessionKey,
secret,
- new IVParameterSpec(iv),
- KeyWrapAlgorithm.DES3_CBC_PAD);
+ null,
+ KeyWrapAlgorithm.AES_KEY_WRAP_PAD);
}
+ @Override
+ public byte[] wrapWithSessionKey(SymmetricKey secret, SymmetricKey sessionKey, byte[] iv, KeyWrapAlgorithm wrapAlg)
+ throws Exception {
+ IVParameterSpec ivps = null;
+ if (iv != null) {
+ ivps = new IVParameterSpec(iv);
+ }
+ return CryptoUtil.wrapUsingSymmetricKey(
+ token,
+ sessionKey,
+ secret,
+ ivps,
+ wrapAlg);
+ }
}