diff options
author | Ade Lee <alee@redhat.com> | 2017-04-11 14:18:32 -0400 |
---|---|---|
committer | Ade Lee <alee@redhat.com> | 2017-04-12 15:19:34 -0400 |
commit | eb7c9139c1ab017a8749d87e163e9dcc42037fb2 (patch) | |
tree | 3f2b2ab15fe3427b29275c55da35501627dce445 /base | |
parent | 20a307e4683e62b033f7662ed4aa2f18dfad6226 (diff) | |
download | pki-eb7c9139c1ab017a8749d87e163e9dcc42037fb2.tar.gz pki-eb7c9139c1ab017a8749d87e163e9dcc42037fb2.tar.xz pki-eb7c9139c1ab017a8749d87e163e9dcc42037fb2.zip |
Modified CRMFPopClient to use correct wrapping for encrypt case
When the server cannot do key wrapping using the AES KeyWrap,
probably because the backend HSM cannot do key wrapping, then
there is a setting to allow it to use encrypt/decrypt instead.
If the key wrap algorithm is something simple like 3DES or AES-CBC,
then the client can just use key wrapping to wrap the key on its
token, and the server can use an encryption algorithm to decrypt.
The client does not need to know that the server cannot handle a
key wrap, because keywrapping and encryption are pretty much the
same mechanism - just either in server memory or not.
When we do key wrapping using AES KeyWrap though, there is no
corresponding encryption algorithm used to decrypt. So the server
cannot simply decrypt a message wrapped with AES Keywrap (or at least
not in any obvious way). So in this case, the client needs to know
if the server can handle keywrap.
The patch therefore does the following:
1. For CRMFPopClient, adds a command line option to specify if key
wrapping or encryption is required.
2. Reads an environment variable if no option is provided.
3. If encryption is specified, uses key wrapping using AES-CBC
which can be decrypted on the server side.
4. For cert-client, contacts the server to determine from the
CAInfoResource if keywrapping is supported.
Change-Id: If66f51c929cfde1c0ff3b9f39cb57b92fcdc150c
Diffstat (limited to 'base')
5 files changed, 69 insertions, 23 deletions
diff --git a/base/common/src/com/netscape/certsrv/key/KeyClient.java b/base/common/src/com/netscape/certsrv/key/KeyClient.java index 750d27081..dea44b148 100644 --- a/base/common/src/com/netscape/certsrv/key/KeyClient.java +++ b/base/common/src/com/netscape/certsrv/key/KeyClient.java @@ -27,6 +27,7 @@ import java.util.List; import javax.ws.rs.core.Response; import org.dogtagpki.common.Info; +import org.dogtagpki.common.KRAInfoResource; import org.dogtagpki.common.Version; import org.mozilla.jss.crypto.EncryptionAlgorithm; import org.mozilla.jss.crypto.KeyWrapAlgorithm; @@ -49,6 +50,7 @@ public class KeyClient extends Client { public KeyResource keyClient; public KeyRequestResource keyRequestClient; + public KRAInfoResource kraInfoClient; private CryptoProvider crypto; private String transportCert; @@ -92,6 +94,7 @@ public class KeyClient extends Client { public void init() throws URISyntaxException { keyClient = createProxy(KeyResource.class); keyRequestClient = createProxy(KeyRequestResource.class); + kraInfoClient = createProxy(KRAInfoResource.class); } public CryptoProvider getCrypto() { diff --git a/base/common/src/com/netscape/certsrv/util/NSSCryptoProvider.java b/base/common/src/com/netscape/certsrv/util/NSSCryptoProvider.java index 1d2edbc77..be8dd2455 100644 --- a/base/common/src/com/netscape/certsrv/util/NSSCryptoProvider.java +++ b/base/common/src/com/netscape/certsrv/util/NSSCryptoProvider.java @@ -140,7 +140,7 @@ public class NSSCryptoProvider extends CryptoProvider { if (token == null) { throw new NotInitializedException(); } - return CryptoUtil.wrapPassphrase(token, passphrase, new IVParameterSpec(iv), key, encryptionAlgorithm); + return CryptoUtil.encryptPassphrase(token, passphrase, new IVParameterSpec(iv), key, encryptionAlgorithm); } @Override diff --git a/base/java-tools/src/com/netscape/cmstools/CRMFPopClient.java b/base/java-tools/src/com/netscape/cmstools/CRMFPopClient.java index 9d81a72a6..c5da9cf3a 100644 --- a/base/java-tools/src/com/netscape/cmstools/CRMFPopClient.java +++ b/base/java-tools/src/com/netscape/cmstools/CRMFPopClient.java @@ -40,6 +40,7 @@ import org.apache.http.HttpResponse; import org.apache.http.client.methods.HttpGet; import org.apache.http.impl.client.DefaultHttpClient; import org.apache.http.util.EntityUtils; +import org.dogtagpki.common.KRAInfoResource; import org.mozilla.jss.CryptoManager; import org.mozilla.jss.asn1.ASN1Util; import org.mozilla.jss.asn1.BIT_STRING; @@ -182,6 +183,10 @@ public class CRMFPopClient { option.setArgName("extractable"); options.addOption(option); + option = new Option("g", true, "KeyWrap"); + option.setArgName("keyWrap"); + options.addOption(option); + options.addOption("v", "verbose", false, "Run in verbose mode."); options.addOption(null, "help", false, "Show help message."); @@ -210,6 +215,9 @@ public class CRMFPopClient { System.out.println(" - POP_NONE: without POP"); System.out.println(" - POP_SUCCESS: with valid POP"); System.out.println(" - POP_FAIL: with invalid POP (for testing)"); + System.out.println(" -g <true|false> Use KeyWrapping to wrap private key (default: true)"); + System.out.println(" - true: use a key wrapping algorithm"); + System.out.println(" - false: use an encryption algorithm"); System.out.println(" -b <transport cert> PEM transport certificate (default: transport.txt)"); System.out.println(" -v, --verbose Run in verbose mode."); System.out.println(" --help Show help message."); @@ -302,6 +310,16 @@ public class CRMFPopClient { int sensitive = Integer.parseInt(cmd.getOptionValue("s", "-1")); int extractable = Integer.parseInt(cmd.getOptionValue("e", "-1")); + boolean keyWrap = true; + if (cmd.hasOption("g")) { + keyWrap = Boolean.parseBoolean(cmd.getOptionValue("g")); + } else { + String useKeyWrap = System.getenv("KEY_ARCHIVAL_USE_KEY_WRAPPING"); + if (useKeyWrap != null) { + keyWrap = Boolean.parseBoolean(useKeyWrap); + } + } + String output = cmd.getOptionValue("o"); String hostPort = cmd.getOptionValue("m"); @@ -440,8 +458,11 @@ public class CRMFPopClient { String kid = CryptoUtil.byte2string(id); System.out.println("Keypair private key id: " + kid); + String archivalMechanism = keyWrap ? KRAInfoResource.KEYWRAP_MECHANISM : + KRAInfoResource.ENCRYPT_MECHANISM; if (verbose) System.out.println("Creating certificate request"); - CertRequest certRequest = client.createCertRequest(token, transportCert, algorithm, keyPair, subject); + CertRequest certRequest = client.createCertRequest( + token, transportCert, algorithm, keyPair, subject, archivalMechanism); ProofOfPossession pop = null; @@ -550,7 +571,8 @@ public class CRMFPopClient { X509Certificate transportCert, String algorithm, KeyPair keyPair, - Name subject) throws Exception { + Name subject, + String archivalMechanism) throws Exception { EncryptionAlgorithm encryptAlg = null; String keyset = System.getenv("KEY_WRAP_PARAMETER_SET"); @@ -563,7 +585,7 @@ public class CRMFPopClient { byte[] iv = CryptoUtil.getNonceData(encryptAlg.getIVLength()); AlgorithmIdentifier aid = new AlgorithmIdentifier(encryptAlg.toOID(), new OCTET_STRING(iv)); - WrappingParams params = getWrappingParams(encryptAlg, iv); + WrappingParams params = getWrappingParams(encryptAlg, iv, archivalMechanism); PKIArchiveOptions opts = CryptoUtil.createPKIArchiveOptions( token, @@ -583,12 +605,23 @@ public class CRMFPopClient { return new CertRequest(new INTEGER(1), certTemplate, seq); } - private WrappingParams getWrappingParams(EncryptionAlgorithm encryptAlg, byte[] wrapIV) throws Exception { + private WrappingParams getWrappingParams(EncryptionAlgorithm encryptAlg, byte[] wrapIV, + String archivalMechanism) throws Exception { if (encryptAlg.getAlg().toString().equalsIgnoreCase("AES")) { + KeyWrapAlgorithm wrapAlg = null; + IVParameterSpec wrapIVS = null; + if (archivalMechanism.equals(KRAInfoResource.ENCRYPT_MECHANISM)) { + // We will use AES_CBC_PAD as the a key wrap mechanism. This + // can be decrypted using the same mechanism on the server. + wrapAlg = KeyWrapAlgorithm.AES_CBC_PAD; + wrapIVS = new IVParameterSpec(wrapIV); + } else { + wrapAlg = KeyWrapAlgorithm.AES_KEY_WRAP_PAD; + } return new WrappingParams( SymmetricKey.AES, KeyGenAlgorithm.AES, 128, KeyWrapAlgorithm.RSA, encryptAlg, - KeyWrapAlgorithm.AES_KEY_WRAP_PAD, null, null); + wrapAlg, wrapIVS, wrapIVS); } else if (encryptAlg.getAlg().toString().equalsIgnoreCase("DESede")) { return new WrappingParams( SymmetricKey.DES3, KeyGenAlgorithm.DES3, 168, diff --git a/base/java-tools/src/com/netscape/cmstools/client/ClientCertRequestCLI.java b/base/java-tools/src/com/netscape/cmstools/client/ClientCertRequestCLI.java index 6562699cf..8ca857bcb 100644 --- a/base/java-tools/src/com/netscape/cmstools/client/ClientCertRequestCLI.java +++ b/base/java-tools/src/com/netscape/cmstools/client/ClientCertRequestCLI.java @@ -29,6 +29,8 @@ import java.util.Vector; import org.apache.commons.cli.CommandLine; import org.apache.commons.cli.Option; import org.apache.commons.io.FileUtils; +import org.dogtagpki.common.CAInfoClient; +import org.dogtagpki.common.KRAInfoResource; import org.mozilla.jss.CryptoManager; import org.mozilla.jss.crypto.CryptoToken; import org.mozilla.jss.crypto.Signature; @@ -245,8 +247,26 @@ public class ClientCertRequestCLI extends CLI { CryptoManager manager = CryptoManager.getInstance(); X509Certificate transportCert = manager.importCACertPackage(transportCertData); + // get archival mechanism + CAInfoClient infoClient = new CAInfoClient(client, "ca"); + String archivalMechanism = KRAInfoResource.KEYWRAP_MECHANISM; + try { + archivalMechanism = infoClient.getInfo().getArchivalMechanism(); + } catch (Exception e) { + // this could be an older server, check for environment variable. + String useKeyWrapping = System.getenv("KEY_ARCHIVAL_USE_KEY_WRAPPING"); + if (useKeyWrapping != null) { + if (Boolean.parseBoolean(useKeyWrapping)) { + archivalMechanism = KRAInfoResource.KEYWRAP_MECHANISM; + } else { + archivalMechanism = KRAInfoResource.ENCRYPT_MECHANISM; + } + } + } + csr = generateCrmfRequest(transportCert, subjectDN, attributeEncoding, - algorithm, length, curve, sslECDH, temporary, sensitive, extractable, withPop); + algorithm, length, curve, sslECDH, temporary, sensitive, extractable, withPop, + archivalMechanism); } else { throw new Exception("Unknown request type: " + requestType); @@ -387,7 +407,8 @@ public class ClientCertRequestCLI extends CLI { boolean temporary, int sensitive, int extractable, - boolean withPop + boolean withPop, + String archivalMechanism ) throws Exception { CryptoManager manager = CryptoManager.getInstance(); @@ -408,7 +429,8 @@ public class ClientCertRequestCLI extends CLI { throw new Exception("Unknown algorithm: " + algorithm); } - CertRequest certRequest = client.createCertRequest(token, transportCert, algorithm, keyPair, subject); + CertRequest certRequest = client.createCertRequest( + token, transportCert, algorithm, keyPair, subject, archivalMechanism); ProofOfPossession pop = null; if (withPop) { diff --git a/base/util/src/com/netscape/cmsutil/crypto/CryptoUtil.java b/base/util/src/com/netscape/cmsutil/crypto/CryptoUtil.java index 35888522f..d22856db5 100644 --- a/base/util/src/com/netscape/cmsutil/crypto/CryptoUtil.java +++ b/base/util/src/com/netscape/cmsutil/crypto/CryptoUtil.java @@ -1962,7 +1962,7 @@ public class CryptoUtil { return decodedData; } - public static byte[] wrapPassphrase(CryptoToken token, String passphrase, IVParameterSpec IV, SymmetricKey sk, + public static byte[] encryptPassphrase(CryptoToken token, String passphrase, IVParameterSpec IV, SymmetricKey sk, EncryptionAlgorithm alg) throws NoSuchAlgorithmException, TokenException, InvalidKeyException, InvalidAlgorithmParameterException, IllegalBlockSizeException, BadPaddingException, IOException { @@ -2010,17 +2010,6 @@ public class CryptoUtil { return encodePKIArchiveOptions(opts); } - /* Used to create PKIArchiveOptions for wrapped symmetric key */ - public static PKIArchiveOptions createPKIArchiveOptions( - CryptoToken token, - PublicKey wrappingKey, - SymmetricKey data, - WrappingParams params, - AlgorithmIdentifier aid) throws Exception { - return createPKIArchiveOptionsInternal( - token, wrappingKey, null, null, data, params, aid); - } - public static byte[] createEncodedPKIArchiveOptions( CryptoToken token, PublicKey wrappingKey, @@ -2068,10 +2057,9 @@ public class CryptoUtil { params.getSkLength(), null, false); - byte[] key_data; if (passphraseData != null) { - key_data = wrapPassphrase( + key_data = encryptPassphrase( token, passphraseData, params.getPayloadEncryptionIV(), |