summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--base/common/src/com/netscape/certsrv/key/Key.java48
-rw-r--r--base/common/src/com/netscape/certsrv/key/KeyClient.java53
-rw-r--r--base/common/src/com/netscape/certsrv/key/KeyData.java56
-rw-r--r--base/common/src/com/netscape/certsrv/request/IRequest.java1
-rw-r--r--base/common/src/com/netscape/certsrv/util/CryptoProvider.java10
-rw-r--r--base/common/src/com/netscape/certsrv/util/NSSCryptoProvider.java35
-rw-r--r--base/java-tools/src/com/netscape/cmstools/CRMFPopClient.java2
-rw-r--r--base/kra/src/com/netscape/kra/SecurityDataProcessor.java43
-rw-r--r--base/kra/src/org/dogtagpki/server/kra/rest/KeyService.java21
-rw-r--r--base/util/src/netscape/security/util/WrappingParams.java18
10 files changed, 258 insertions, 29 deletions
diff --git a/base/common/src/com/netscape/certsrv/key/Key.java b/base/common/src/com/netscape/certsrv/key/Key.java
index 60cc1b0c8..1afd54c20 100644
--- a/base/common/src/com/netscape/certsrv/key/Key.java
+++ b/base/common/src/com/netscape/certsrv/key/Key.java
@@ -41,6 +41,18 @@ public class Key {
@XmlElement
private RequestId requestId;
+ @XmlElement
+ private String wrapAlgorithm;
+
+ @XmlElement
+ private String encryptAlgorithmOID;
+
+ @XmlElement
+ private String type;
+
+ @XmlElement
+ private String publicKey;
+
public Key() {
super();
}
@@ -54,6 +66,10 @@ public class Key {
algorithm = data.getAlgorithm();
size = data.getSize();
requestId = data.requestID;
+ wrapAlgorithm = data.getWrapAlgorithm();
+ encryptAlgorithmOID = data.getEncryptAlgorithmOID();
+ type = data.getType();
+ publicKey = data.getPublicKey();
}
public byte[] getEncryptedData() {
@@ -111,4 +127,36 @@ public class Key {
public void setRequestId(RequestId requestId) {
this.requestId = requestId;
}
+
+ public String getWrapAlgorithm() {
+ return wrapAlgorithm;
+ }
+
+ public void setWrapAlgorithm(String wrapAlgorithm) {
+ this.wrapAlgorithm = wrapAlgorithm;
+ }
+
+ public String getEncryptAlgorithmOID() {
+ return encryptAlgorithmOID;
+ }
+
+ public void setEncryptAlgorithmOID(String encryptAlgorithmOID) {
+ this.encryptAlgorithmOID = encryptAlgorithmOID;
+ }
+
+ public String getType() {
+ return type;
+ }
+
+ public void setType(String type) {
+ this.type = type;
+ }
+
+ public String getPublicKey() {
+ return publicKey;
+ }
+
+ public void setPublicKey(String publicKey) {
+ this.publicKey = publicKey;
+ }
}
diff --git a/base/common/src/com/netscape/certsrv/key/KeyClient.java b/base/common/src/com/netscape/certsrv/key/KeyClient.java
index f459737e7..750d27081 100644
--- a/base/common/src/com/netscape/certsrv/key/KeyClient.java
+++ b/base/common/src/com/netscape/certsrv/key/KeyClient.java
@@ -18,7 +18,10 @@
package com.netscape.certsrv.key;
import java.net.URISyntaxException;
+import java.security.KeyFactory;
import java.security.NoSuchAlgorithmException;
+import java.security.PublicKey;
+import java.security.spec.X509EncodedKeySpec;
import java.util.List;
import javax.ws.rs.core.Response;
@@ -401,11 +404,51 @@ public class KeyClient extends Client {
byte[] transWrappedSessionKey = crypto.wrapSessionKeyWithTransportCert(sessionKey, transportCert);
Key data = retrieveKey(keyId, transWrappedSessionKey);
- if (data.getEncryptedData()!= null)
+ processKeyData(data, sessionKey);
+ return data;
+ }
+
+ public void processKeyData(Key data, SymmetricKey sessionKey) throws Exception {
+ if (data.getEncryptedData() == null)
+ return;
+
+ if (data.getWrapAlgorithm() == null) {
+ // data was encrypted
data.setData(crypto.unwrapWithSessionKey(data.getEncryptedData(), sessionKey,
- encryptAlgorithm, data.getNonceData()));
+ encryptAlgorithm, data.getNonceData()));
+ return;
+ }
- return data;
+ // data was key-wrapped and is a private or symmetric key
+ byte[] bytes = null;
+
+ if (data.getType().equalsIgnoreCase(KeyRequestResource.SYMMETRIC_KEY_TYPE)) {
+ bytes = crypto.unwrapSymmetricKeyWithSessionKey(
+ data.getEncryptedData(),
+ sessionKey,
+ wrapAlgorithm,
+ data.getNonceData(),
+ data.getAlgorithm(),
+ data.getSize());
+ } else {
+ // private key in asymmetric key pair
+
+ // get public key from key_info
+ // TODO(alee) This assumes RSA for now
+
+ byte[] pubKeyBytes = Utils.base64decode(data.getPublicKey());
+ PublicKey pubKey = KeyFactory.getInstance("RSA").generatePublic(
+ new X509EncodedKeySpec(pubKeyBytes));
+
+ bytes = crypto.unwrapAsymmetricKeyWithSessionKey(
+ data.getEncryptedData(),
+ sessionKey,
+ wrapAlgorithm,
+ data.getNonceData(),
+ pubKey);
+ }
+
+ data.setData(bytes);
}
public Key retrieveKeyByRequest(RequestId requestId) throws Exception {
@@ -421,9 +464,7 @@ public class KeyClient extends Client {
recoveryRequest.setPayloadEncryptionOID(getEncryptAlgorithmOID());
Key data = retrieveKeyData(recoveryRequest);
- if (data.getEncryptedData() != null)
- data.setData(crypto.unwrapWithSessionKey(data.getEncryptedData(), sessionKey,
- encryptAlgorithm, data.getNonceData()));
+ processKeyData(data, sessionKey);
return data;
}
diff --git a/base/common/src/com/netscape/certsrv/key/KeyData.java b/base/common/src/com/netscape/certsrv/key/KeyData.java
index ee13812b1..abf45caae 100644
--- a/base/common/src/com/netscape/certsrv/key/KeyData.java
+++ b/base/common/src/com/netscape/certsrv/key/KeyData.java
@@ -62,6 +62,18 @@ public class KeyData {
@XmlJavaTypeAdapter(RequestIdAdapter.class)
RequestId requestID;
+ @XmlElement
+ String encryptAlgorithmOID;
+
+ @XmlElement
+ String wrapAlgorithm;
+
+ @XmlElement
+ String type;
+
+ @XmlElement
+ String publicKey;
+
public KeyData() {
// required for JAXB (defaults)
}
@@ -162,4 +174,48 @@ public class KeyData {
public void setRequestID(RequestId requestID) {
this.requestID = requestID;
}
+
+ /**
+ * Symmetric and Asymmetric keys will be returned either encrypted or wrapped
+ * by the client provided symmetric key. Which mechanism is used depends on the
+ * capabilities of the server (and the HSM behind it). One (and only one) of
+ * encryptionAlgorithm or wrapAlgorithm will be set.
+ *
+ * @return OID of encryption algorithm used to wrap the secret.
+ */
+ public String getEncryptAlgorithmOID() {
+ return encryptAlgorithmOID;
+ }
+
+ public void setEncryptAlgorithmOID(String encryptAlgorithmOID) {
+ this.encryptAlgorithmOID = encryptAlgorithmOID;
+ }
+
+ /**
+ * @return name (as known by JSS) of algorithm used to wrap secret if key
+ * wrapping is used
+ */
+ public String getWrapAlgorithm() {
+ return wrapAlgorithm;
+ }
+
+ public void setWrapAlgorithm(String wrapAlgorithm) {
+ this.wrapAlgorithm = wrapAlgorithm;
+ }
+
+ public String getType() {
+ return type;
+ }
+
+ public void setType(String type) {
+ this.type = type;
+ }
+
+ public String getPublicKey() {
+ return publicKey;
+ }
+
+ public void setPublicKey(String publicKey) {
+ this.publicKey = publicKey;
+ }
}
diff --git a/base/common/src/com/netscape/certsrv/request/IRequest.java b/base/common/src/com/netscape/certsrv/request/IRequest.java
index 94fd2fd3f..a57f08eb1 100644
--- a/base/common/src/com/netscape/certsrv/request/IRequest.java
+++ b/base/common/src/com/netscape/certsrv/request/IRequest.java
@@ -181,6 +181,7 @@ public interface IRequest extends Serializable {
public static final String SECURITY_DATA_PASS_WRAPPED_DATA = "passPhraseWrappedData";
public static final String SECURITY_DATA_PL_ENCRYPTION_OID = "payloadEncryptionOID";
public static final String SECURITY_DATA_PL_WRAPPING_NAME = "payloadWrappingName";
+ public static final String SECURITY_DATA_PL_WRAPPED = "payloadWrapped";
// key generation request attributes
public static final String ASYMKEY_GENERATION_REQUEST = "asymkeyGenRequest";
diff --git a/base/common/src/com/netscape/certsrv/util/CryptoProvider.java b/base/common/src/com/netscape/certsrv/util/CryptoProvider.java
index 6746db960..28d619208 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 java.security.PublicKey;
+
import org.mozilla.jss.crypto.EncryptionAlgorithm;
import org.mozilla.jss.crypto.KeyWrapAlgorithm;
import org.mozilla.jss.crypto.SymmetricKey;
@@ -44,4 +46,12 @@ public abstract class CryptoProvider {
public abstract byte[] unwrapWithPassphrase(byte[] wrappedRecoveredKey, String recoveryPassphrase)
throws Exception;
+ public abstract byte[] unwrapSymmetricKeyWithSessionKey(byte[] wrappedRecoveredKey, SymmetricKey recoveryKey,
+ KeyWrapAlgorithm wrapAlgorithm, byte[] nonceData, String algorithm, int size)
+ throws Exception;
+
+ public abstract byte[] unwrapAsymmetricKeyWithSessionKey(byte[] wrappedRecoveredKey, SymmetricKey recoveryKey,
+ KeyWrapAlgorithm wrapAlgorithm, byte[] nonceData, PublicKey pubKey)
+ 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 ec9a13407..1d2edbc77 100644
--- a/base/common/src/com/netscape/certsrv/util/NSSCryptoProvider.java
+++ b/base/common/src/com/netscape/certsrv/util/NSSCryptoProvider.java
@@ -3,6 +3,7 @@ package com.netscape.certsrv.util;
import java.io.File;
import java.security.GeneralSecurityException;
import java.security.NoSuchAlgorithmException;
+import java.security.PublicKey;
import org.mozilla.jss.CertDatabaseException;
import org.mozilla.jss.CryptoManager;
@@ -14,6 +15,7 @@ import org.mozilla.jss.crypto.EncryptionAlgorithm;
import org.mozilla.jss.crypto.IVParameterSpec;
import org.mozilla.jss.crypto.KeyGenAlgorithm;
import org.mozilla.jss.crypto.KeyWrapAlgorithm;
+import org.mozilla.jss.crypto.PrivateKey;
import org.mozilla.jss.crypto.SymmetricKey;
import org.mozilla.jss.crypto.TokenException;
import org.mozilla.jss.util.IncorrectPasswordException;
@@ -163,6 +165,39 @@ public class NSSCryptoProvider extends CryptoProvider {
}
@Override
+ public byte[] unwrapSymmetricKeyWithSessionKey(byte[] wrappedRecoveredKey, SymmetricKey recoveryKey,
+ KeyWrapAlgorithm wrapAlgorithm, byte[] nonceData, String algorithm, int size)
+ throws Exception {
+ if (token == null) {
+ throw new NotInitializedException();
+ }
+ IVParameterSpec ivps = null;
+ if (nonceData != null) {
+ ivps = new IVParameterSpec(nonceData);
+ }
+ SymmetricKey key = CryptoUtil.unwrap(
+ token, SymmetricKey.Type.fromName(algorithm),
+ size, SymmetricKey.Usage.DECRYPT, recoveryKey,
+ wrappedRecoveredKey, wrapAlgorithm, ivps);
+ return key.getEncoded();
+ }
+
+ @Override
+ public byte[] unwrapAsymmetricKeyWithSessionKey(byte[] wrappedRecoveredKey, SymmetricKey recoveryKey,
+ KeyWrapAlgorithm wrapAlgorithm, byte[] nonceData, PublicKey pubKey)
+ throws Exception {
+ if (token == null) {
+ throw new NotInitializedException();
+ }
+ IVParameterSpec ivps = null;
+ if (nonceData != null) {
+ ivps = new IVParameterSpec(nonceData);
+ }
+ PrivateKey key = CryptoUtil.unwrap(token, pubKey, true, recoveryKey, wrappedRecoveredKey, wrapAlgorithm, ivps);
+ return key.getEncoded();
+ }
+
+ @Override
public byte[] unwrapWithPassphrase(byte[] wrappedRecoveredKey, String recoveryPassphrase) throws Exception {
return CryptoUtil.unwrapUsingPassphrase(wrappedRecoveredKey, recoveryPassphrase);
}
diff --git a/base/java-tools/src/com/netscape/cmstools/CRMFPopClient.java b/base/java-tools/src/com/netscape/cmstools/CRMFPopClient.java
index fafe956e7..901528c2f 100644
--- a/base/java-tools/src/com/netscape/cmstools/CRMFPopClient.java
+++ b/base/java-tools/src/com/netscape/cmstools/CRMFPopClient.java
@@ -554,7 +554,7 @@ public class CRMFPopClient {
EncryptionAlgorithm encryptAlg = null;
String keyset = System.getenv("KEY_WRAP_PARAMETER_SET");
- if ((keyset != null) && (keyset.equalsIgnoreCase("0"))) {
+ if (keyset != null && keyset.equalsIgnoreCase("0")) {
// talking to an old server?
encryptAlg = EncryptionAlgorithm.DES3_CBC;
} else {
diff --git a/base/kra/src/com/netscape/kra/SecurityDataProcessor.java b/base/kra/src/com/netscape/kra/SecurityDataProcessor.java
index 6c4851f13..3475eaef9 100644
--- a/base/kra/src/com/netscape/kra/SecurityDataProcessor.java
+++ b/base/kra/src/com/netscape/kra/SecurityDataProcessor.java
@@ -313,8 +313,6 @@ public class SecurityDataProcessor {
throws EBaseException {
CMS.debug("SecurityDataService.recover(): start");
-
- byte iv_in[] = null;
IConfigStore config = null;
try {
@@ -352,11 +350,6 @@ public class SecurityDataProcessor {
wrappedPassPhrase = Utils.base64decode(sessWrappedPassPhraseStr);
}
- String ivInStr = (String) params.get(IRequest.SECURITY_DATA_IV_STRING_IN);
- if (ivInStr != null) {
- iv_in = Utils.base64decode(ivInStr);
- }
-
if (transWrappedSessKeyStr == null && sessWrappedPassPhraseStr == null) {
//We may be in recovery case where no params were initially submitted.
CMS.debug("SecurityDataProcessor.recover(): No params provided.");
@@ -377,22 +370,18 @@ public class SecurityDataProcessor {
if (allowEncDecrypt_recovery == true) {
CMS.debug("Recover symmetric key by decrypting as per allowEncDecrypt_recovery: true.");
unwrappedSecData = recoverSecurityData(keyRecord);
-
} else {
symKey = recoverSymKey(keyRecord);
}
} else if (dataType.equals(KeyRequestResource.PASS_PHRASE_TYPE)) {
unwrappedSecData = recoverSecurityData(keyRecord);
-
} else if (dataType.equals(KeyRequestResource.ASYMMETRIC_KEY_TYPE)) {
try {
if (allowEncDecrypt_recovery == true) {
CMS.debug("Recover asymmetric key by decrypting as per allowEncDecrypt_recovery: true.");
unwrappedSecData = recoverSecurityData(keyRecord);
-
} else {
-
byte[] publicKeyData = keyRecord.getPublicKeyData();
byte[] privateKeyData = keyRecord.getPrivateKeyData();
@@ -475,24 +464,18 @@ public class SecurityDataProcessor {
if (allowEncDecrypt_recovery == true) {
CMS.debug("SecurityDataProcessor.recover(): allowEncDecyypt_recovery: true, symmetric key: create blob with unwrapped key.");
pbeWrappedData = createEncryptedContentInfo(ct, null, unwrappedSecData, null, pass);
-
} else {
- pbeWrappedData = createEncryptedContentInfo(ct, symKey, null, null,
- pass);
+ pbeWrappedData = createEncryptedContentInfo(ct, symKey, null, null, pass);
}
} else if (dataType.equals(KeyRequestResource.PASS_PHRASE_TYPE)) {
CMS.debug("SecurityDataProcessor.recover(): encrypt stored passphrase with transport passphrase");
- pbeWrappedData = createEncryptedContentInfo(ct, null, unwrappedSecData, null,
- pass);
-
+ pbeWrappedData = createEncryptedContentInfo(ct, null, unwrappedSecData, null, pass);
} else if (dataType.equals(KeyRequestResource.ASYMMETRIC_KEY_TYPE)) {
-
if (allowEncDecrypt_recovery == true) {
CMS.debug("SecurityDataProcessor.recover(): allowEncDecyypt_recovery: true, asymmetric key: create blob with unwrapped key.");
pbeWrappedData = createEncryptedContentInfo(ct, null, unwrappedSecData, null, pass);
-
} else {
CMS.debug("SecurityDataProcessor.recover(): wrap stored private key with transport passphrase");
pbeWrappedData = createEncryptedContentInfo(ct, null, null, privateKey,
@@ -603,13 +586,33 @@ public class SecurityDataProcessor {
String wrappedKeyData = Utils.base64encode(key_data);
params.put(IRequest.SECURITY_DATA_SESS_WRAPPED_DATA, wrappedKeyData);
- params.put(IRequest.SECURITY_DATA_IV_STRING_OUT, ivStr);
+ }
+
+ params.put(IRequest.SECURITY_DATA_PL_ENCRYPTION_OID,
+ wrapParams.getPayloadEncryptionAlgorithmName());
+
+ params.put(IRequest.SECURITY_DATA_PL_WRAPPING_NAME,
+ wrapParams.getPayloadWrapAlgorithm().toString());
+
+ if ((allowEncDecrypt_recovery == true) || (dataType.equals(KeyRequestResource.PASS_PHRASE_TYPE))) {
+ params.put(IRequest.SECURITY_DATA_PL_WRAPPED, Boolean.toString(false));
+ if (wrapParams.getPayloadEncryptionIV() != null) {
+ params.put(IRequest.SECURITY_DATA_IV_STRING_OUT, ivStr);
+ }
+ } else {
+ //secret has wrapped using a key wrapping algorithm
+ params.put(IRequest.SECURITY_DATA_PL_WRAPPED, Boolean.toString(true));
+ if (wrapParams.getPayloadWrappingIV() != null) {
+ params.put(IRequest.SECURITY_DATA_IV_STRING_OUT, ivStr);
+ }
}
if(unwrappedSecData != null && unwrappedSecData.length > 0) {
Arrays.fill(unwrappedSecData, (byte)0);
}
+ params.put(IRequest.SECURITY_DATA_TYPE, dataType);
+
auditRecoveryRequestProcessed(auditSubjectID, ILogger.SUCCESS, requestID, serialno.toString(),
"None");
request.setExtData(IRequest.RESULT, IRequest.RES_SUCCESS);
diff --git a/base/kra/src/org/dogtagpki/server/kra/rest/KeyService.java b/base/kra/src/org/dogtagpki/server/kra/rest/KeyService.java
index a8b895fec..e8cb6e9b7 100644
--- a/base/kra/src/org/dogtagpki/server/kra/rest/KeyService.java
+++ b/base/kra/src/org/dogtagpki/server/kra/rest/KeyService.java
@@ -345,17 +345,34 @@ public class KeyService extends SubsystemService implements KeyResource {
keyData.setNonceData(nonceData);
}
- String algorithm = rec.getAlgorithm();
- Integer keySize = rec.getKeySize();
+ keyData.setType((String) requestParams.get(IRequest.SECURITY_DATA_TYPE));
+
+ String payloadWrapped = (String) requestParams.get(IRequest.SECURITY_DATA_PL_WRAPPED);
+ // either wrapAlgorithm or encryptAlgorithm will be set. This will tell the
+ // client which mechanism was used to encrypt the secret
+ if (payloadWrapped.equalsIgnoreCase("true")) {
+ keyData.setWrapAlgorithm(
+ (String) requestParams.get(IRequest.SECURITY_DATA_PL_WRAPPING_NAME));
+ } else {
+ keyData.setEncryptAlgorithmOID(
+ (String) requestParams.get(IRequest.SECURITY_DATA_PL_ENCRYPTION_OID));
+ }
+ String algorithm = rec.getAlgorithm();
if (algorithm != null) {
keyData.setAlgorithm(algorithm);
}
+ Integer keySize = rec.getKeySize();
if (keySize != null) {
keyData.setSize(keySize);
}
+ byte[] pubKeyBytes = rec.getPublicKeyData();
+ if (pubKeyBytes != null) {
+ keyData.setPublicKey(Utils.base64encode(pubKeyBytes));
+ }
+
kra.destroyVolatileRequest(request.getRequestId());
if (!synchronous) {
diff --git a/base/util/src/netscape/security/util/WrappingParams.java b/base/util/src/netscape/security/util/WrappingParams.java
index ab7868097..b2814a356 100644
--- a/base/util/src/netscape/security/util/WrappingParams.java
+++ b/base/util/src/netscape/security/util/WrappingParams.java
@@ -45,6 +45,15 @@ public class WrappingParams {
this.payloadWrappingIV = payloadWrapIV;
}
+ public static EncryptionAlgorithm getEncryptionAlgorithmFromName(String name) throws Exception {
+ String fields[] = name.split("//");
+ String alg = fields[0];
+ String mode = fields[1];
+ String padding = fields[2];
+ int strength = Integer.parseInt(fields[3]);
+ return EncryptionAlgorithm.lookup(alg, mode, padding, strength);
+ }
+
public WrappingParams() {}
public WrappingParams(String encryptOID, String wrapName, String priKeyAlgo, IVParameterSpec encryptIV, IVParameterSpec wrapIV)
@@ -172,6 +181,15 @@ public class WrappingParams {
this.payloadEncryptionAlgorithm = EncryptionAlgorithm.lookup(algName, modeName, paddingName, keyStrength);
}
+ public String getPayloadEncryptionAlgorithmName() {
+ // work around some of the issues with OIDs in JSS
+ int strength = payloadEncryptionAlgorithm.getKeyStrength();
+ String mode = payloadEncryptionAlgorithm.getMode().toString();
+ String padding = payloadEncryptionAlgorithm.getPadding().toString();
+ String alg = payloadEncryptionAlgorithm.getAlg().toString();
+ return alg + "/" + mode + "/" + padding + "/" + Integer.toString(strength);
+ }
+
public KeyWrapAlgorithm getPayloadWrapAlgorithm() {
return payloadWrapAlgorithm;
}