diff options
author | David Hook <dgh@cryptoworkshop.com> | 2013-10-28 13:13:21 +0400 |
---|---|---|
committer | David Hook <dgh@cryptoworkshop.com> | 2013-10-28 13:13:21 +0400 |
commit | 20a5f59c79ac194bbe83febc35b87db38213331f (patch) | |
tree | 49d5bffef962e752cdd11f8d14ad9f012e21b000 /pkix/src/main | |
parent | 65d37d6f5dfafecb729f83e45a8df70e6cad1c8c (diff) |
BJA-257 added setValidateKeySize() method on JCE recipients. Modified use of KeySizeProvider to reflect multiple bit sizes for 3DES.
Diffstat (limited to 'pkix/src/main')
-rw-r--r-- | pkix/src/main/java/org/bouncycastle/cms/jcajce/EnvelopedDataHelper.java | 31 | ||||
-rw-r--r-- | pkix/src/main/java/org/bouncycastle/cms/jcajce/JceCMSContentEncryptorBuilder.java | 54 | ||||
-rw-r--r-- | pkix/src/main/java/org/bouncycastle/cms/jcajce/JceKEKRecipient.java | 28 | ||||
-rw-r--r-- | pkix/src/main/java/org/bouncycastle/cms/jcajce/JceKeyTransRecipient.java | 26 | ||||
-rw-r--r-- | pkix/src/main/java/org/bouncycastle/operator/DefaultSecretKeySizeProvider.java (renamed from pkix/src/main/java/org/bouncycastle/operator/DefaultSecretKeyProvider.java) | 26 | ||||
-rw-r--r-- | pkix/src/main/java/org/bouncycastle/operator/SecretKeySizeProvider.java | 9 | ||||
-rw-r--r-- | pkix/src/main/java/org/bouncycastle/pkcs/jcajce/JcePKCSPBEInputDecryptorProviderBuilder.java | 4 | ||||
-rw-r--r-- | pkix/src/main/java/org/bouncycastle/pkcs/jcajce/JcePKCSPBEOutputEncryptorBuilder.java | 4 |
8 files changed, 140 insertions, 42 deletions
diff --git a/pkix/src/main/java/org/bouncycastle/cms/jcajce/EnvelopedDataHelper.java b/pkix/src/main/java/org/bouncycastle/cms/jcajce/EnvelopedDataHelper.java index 915593b5..5c270234 100644 --- a/pkix/src/main/java/org/bouncycastle/cms/jcajce/EnvelopedDataHelper.java +++ b/pkix/src/main/java/org/bouncycastle/cms/jcajce/EnvelopedDataHelper.java @@ -41,12 +41,16 @@ import org.bouncycastle.asn1.x509.AlgorithmIdentifier; import org.bouncycastle.cms.CMSAlgorithm; import org.bouncycastle.cms.CMSEnvelopedDataGenerator; import org.bouncycastle.cms.CMSException; +import org.bouncycastle.operator.DefaultSecretKeySizeProvider; import org.bouncycastle.operator.GenericKey; +import org.bouncycastle.operator.SecretKeySizeProvider; import org.bouncycastle.operator.SymmetricKeyUnwrapper; import org.bouncycastle.operator.jcajce.JceAsymmetricKeyUnwrapper; public class EnvelopedDataHelper { + protected static final SecretKeySizeProvider KEY_SIZE_PROVIDER = DefaultSecretKeySizeProvider.INSTANCE; + protected static final Map BASE_CIPHER_NAMES = new HashMap(); protected static final Map CIPHER_ALG_NAMES = new HashMap(); protected static final Map MAC_ALG_NAMES = new HashMap(); @@ -174,6 +178,33 @@ public class EnvelopedDataHelper throw new IllegalArgumentException("unknown generic key type"); } + public void keySizeCheck(AlgorithmIdentifier keyAlgorithm, Key key) + throws CMSException + { + int expectedKeySize = EnvelopedDataHelper.KEY_SIZE_PROVIDER.getKeySize(keyAlgorithm); + if (expectedKeySize > 0) + { + byte[] keyEnc = null; + + try + { + keyEnc = key.getEncoded(); + } + catch (Exception e) + { + // ignore - we're using a HSM... + } + + if (keyEnc != null) + { + if (keyEnc.length * 8 != expectedKeySize) + { + throw new CMSException("Expected key size for algorithm OID not found in recipient."); + } + } + } + } + Cipher createCipher(ASN1ObjectIdentifier algorithm) throws CMSException { diff --git a/pkix/src/main/java/org/bouncycastle/cms/jcajce/JceCMSContentEncryptorBuilder.java b/pkix/src/main/java/org/bouncycastle/cms/jcajce/JceCMSContentEncryptorBuilder.java index 89d2c650..93d8b72c 100644 --- a/pkix/src/main/java/org/bouncycastle/cms/jcajce/JceCMSContentEncryptorBuilder.java +++ b/pkix/src/main/java/org/bouncycastle/cms/jcajce/JceCMSContentEncryptorBuilder.java @@ -5,8 +5,6 @@ import java.security.AlgorithmParameters; import java.security.GeneralSecurityException; import java.security.Provider; import java.security.SecureRandom; -import java.util.HashMap; -import java.util.Map; import javax.crypto.Cipher; import javax.crypto.CipherOutputStream; @@ -14,40 +12,19 @@ import javax.crypto.KeyGenerator; import javax.crypto.SecretKey; import org.bouncycastle.asn1.ASN1ObjectIdentifier; +import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers; import org.bouncycastle.asn1.x509.AlgorithmIdentifier; -import org.bouncycastle.cms.CMSAlgorithm; import org.bouncycastle.cms.CMSException; +import org.bouncycastle.operator.DefaultSecretKeySizeProvider; import org.bouncycastle.operator.GenericKey; import org.bouncycastle.operator.OutputEncryptor; +import org.bouncycastle.operator.SecretKeySizeProvider; import org.bouncycastle.operator.jcajce.JceGenericKey; -import org.bouncycastle.util.Integers; public class JceCMSContentEncryptorBuilder { - private static Map keySizes = new HashMap(); + private static final SecretKeySizeProvider KEY_SIZE_PROVIDER = DefaultSecretKeySizeProvider.INSTANCE; - static - { - keySizes.put(CMSAlgorithm.AES128_CBC, Integers.valueOf(128)); - keySizes.put(CMSAlgorithm.AES192_CBC, Integers.valueOf(192)); - keySizes.put(CMSAlgorithm.AES256_CBC, Integers.valueOf(256)); - - keySizes.put(CMSAlgorithm.CAMELLIA128_CBC, Integers.valueOf(128)); - keySizes.put(CMSAlgorithm.CAMELLIA192_CBC, Integers.valueOf(192)); - keySizes.put(CMSAlgorithm.CAMELLIA256_CBC, Integers.valueOf(256)); - } - - private static int getKeySize(ASN1ObjectIdentifier oid) - { - Integer size = (Integer)keySizes.get(oid); - - if (size != null) - { - return size.intValue(); - } - - return -1; - } private final ASN1ObjectIdentifier encryptionOID; private final int keySize; @@ -57,13 +34,30 @@ public class JceCMSContentEncryptorBuilder public JceCMSContentEncryptorBuilder(ASN1ObjectIdentifier encryptionOID) { - this(encryptionOID, getKeySize(encryptionOID)); + this(encryptionOID, KEY_SIZE_PROVIDER.getKeySize(encryptionOID)); } public JceCMSContentEncryptorBuilder(ASN1ObjectIdentifier encryptionOID, int keySize) { this.encryptionOID = encryptionOID; this.keySize = keySize; + + int fixedSize = KEY_SIZE_PROVIDER.getKeySize(encryptionOID); + + if (encryptionOID.equals(PKCSObjectIdentifiers.des_EDE3_CBC)) + { + if (keySize != 168 && keySize != fixedSize) + { + throw new IllegalArgumentException("incorrect keySize for encryptionOID passed to builder."); + } + } + else + { + if (fixedSize > 0 && fixedSize != keySize) + { + throw new IllegalArgumentException("incorrect keySize for encryptionOID passed to builder."); + } + } } public JceCMSContentEncryptorBuilder setProvider(Provider provider) @@ -116,6 +110,10 @@ public class JceCMSContentEncryptorBuilder } else { + if (encryptionOID.equals(PKCSObjectIdentifiers.des_EDE3_CBC) && keySize == 192) + { + keySize = 168; + } keyGen.init(keySize, random); } diff --git a/pkix/src/main/java/org/bouncycastle/cms/jcajce/JceKEKRecipient.java b/pkix/src/main/java/org/bouncycastle/cms/jcajce/JceKEKRecipient.java index a01e2799..d0e41644 100644 --- a/pkix/src/main/java/org/bouncycastle/cms/jcajce/JceKEKRecipient.java +++ b/pkix/src/main/java/org/bouncycastle/cms/jcajce/JceKEKRecipient.java @@ -18,6 +18,7 @@ public abstract class JceKEKRecipient protected EnvelopedDataHelper helper = new EnvelopedDataHelper(new DefaultJcaJceExtHelper()); protected EnvelopedDataHelper contentHelper = helper; + protected boolean validateKeySize = false; public JceKEKRecipient(SecretKey recipientKey) { @@ -78,14 +79,37 @@ public abstract class JceKEKRecipient return this; } - protected Key extractSecretKey(AlgorithmIdentifier keyEncryptionAlgorithm, AlgorithmIdentifier contentEncryptionAlgorithm, byte[] encryptedContentEncryptionKey) + /** + * Set validation of retrieved key sizes against the algorithm parameters for the encrypted key where possible - default is off. + * <p> + * This setting will not have any affect if the encryption algorithm in the recipient does not specify a particular key size, or + * if the unwrapper is a HSM and the byte encoding of the unwrapped secret key is not available. + * </p> + * @param doValidate true if unwrapped key's should be validated against the content encryption algorithm, false otherwise. + * @return this recipient. + */ + public JceKEKRecipient setKeySizeValidation(boolean doValidate) + { + this.validateKeySize = doValidate; + + return this; + } + + protected Key extractSecretKey(AlgorithmIdentifier keyEncryptionAlgorithm, AlgorithmIdentifier encryptedKeyAlgorithm, byte[] encryptedContentEncryptionKey) throws CMSException { SymmetricKeyUnwrapper unwrapper = helper.createSymmetricUnwrapper(keyEncryptionAlgorithm, recipientKey); try { - return helper.getJceKey(contentEncryptionAlgorithm.getAlgorithm(), unwrapper.generateUnwrappedKey(contentEncryptionAlgorithm, encryptedContentEncryptionKey)); + Key key = helper.getJceKey(encryptedKeyAlgorithm.getAlgorithm(), unwrapper.generateUnwrappedKey(encryptedKeyAlgorithm, encryptedContentEncryptionKey)); + + if (validateKeySize) + { + helper.keySizeCheck(encryptedKeyAlgorithm, key); + } + + return key; } catch (OperatorException e) { diff --git a/pkix/src/main/java/org/bouncycastle/cms/jcajce/JceKeyTransRecipient.java b/pkix/src/main/java/org/bouncycastle/cms/jcajce/JceKeyTransRecipient.java index 788af8d5..a457ede4 100644 --- a/pkix/src/main/java/org/bouncycastle/cms/jcajce/JceKeyTransRecipient.java +++ b/pkix/src/main/java/org/bouncycastle/cms/jcajce/JceKeyTransRecipient.java @@ -22,6 +22,7 @@ public abstract class JceKeyTransRecipient protected EnvelopedDataHelper helper = new EnvelopedDataHelper(new DefaultJcaJceExtHelper()); protected EnvelopedDataHelper contentHelper = helper; protected Map extraMappings = new HashMap(); + protected boolean validateKeySize = false; public JceKeyTransRecipient(PrivateKey recipientKey) { @@ -105,6 +106,22 @@ public abstract class JceKeyTransRecipient return this; } + /** + * Set validation of retrieved key sizes against the algorithm parameters for the encrypted key where possible - default is off. + * <p> + * This setting will not have any affect if the encryption algorithm in the recipient does not specify a particular key size, or + * if the unwrapper is a HSM and the byte encoding of the unwrapped secret key is not available. + * </p> + * @param doValidate true if unwrapped key's should be validated against the content encryption algorithm, false otherwise. + * @return this recipient. + */ + public JceKeyTransRecipient setKeySizeValidation(boolean doValidate) + { + this.validateKeySize = doValidate; + + return this; + } + protected Key extractSecretKey(AlgorithmIdentifier keyEncryptionAlgorithm, AlgorithmIdentifier encryptedKeyAlgorithm, byte[] encryptedEncryptionKey) throws CMSException { @@ -122,7 +139,14 @@ public abstract class JceKeyTransRecipient try { - return helper.getJceKey(encryptedKeyAlgorithm.getAlgorithm(), unwrapper.generateUnwrappedKey(encryptedKeyAlgorithm, encryptedEncryptionKey)); + Key key = helper.getJceKey(encryptedKeyAlgorithm.getAlgorithm(), unwrapper.generateUnwrappedKey(encryptedKeyAlgorithm, encryptedEncryptionKey)); + + if (validateKeySize) + { + helper.keySizeCheck(encryptedKeyAlgorithm, key); + } + + return key; } catch (OperatorException e) { diff --git a/pkix/src/main/java/org/bouncycastle/operator/DefaultSecretKeyProvider.java b/pkix/src/main/java/org/bouncycastle/operator/DefaultSecretKeySizeProvider.java index 8c419808..a1c6ba11 100644 --- a/pkix/src/main/java/org/bouncycastle/operator/DefaultSecretKeyProvider.java +++ b/pkix/src/main/java/org/bouncycastle/operator/DefaultSecretKeySizeProvider.java @@ -12,10 +12,10 @@ import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers; import org.bouncycastle.asn1.x509.AlgorithmIdentifier; import org.bouncycastle.util.Integers; -public class DefaultSecretKeyProvider +public class DefaultSecretKeySizeProvider implements SecretKeySizeProvider { - public static final SecretKeySizeProvider INSTANCE = new DefaultSecretKeyProvider(); + public static final SecretKeySizeProvider INSTANCE = new DefaultSecretKeySizeProvider(); private static final Map KEY_SIZES; @@ -25,7 +25,7 @@ public class DefaultSecretKeyProvider keySizes.put(new ASN1ObjectIdentifier("1.2.840.113533.7.66.10"), Integers.valueOf(128)); - keySizes.put(PKCSObjectIdentifiers.des_EDE3_CBC.getId(), Integers.valueOf(192)); + keySizes.put(PKCSObjectIdentifiers.des_EDE3_CBC, Integers.valueOf(192)); keySizes.put(NISTObjectIdentifiers.id_aes128_CBC, Integers.valueOf(128)); keySizes.put(NISTObjectIdentifiers.id_aes192_CBC, Integers.valueOf(192)); @@ -42,16 +42,28 @@ public class DefaultSecretKeyProvider public int getKeySize(AlgorithmIdentifier algorithmIdentifier) { - // TODO: not all ciphers/oid relationships are this simple. - Integer keySize = (Integer)KEY_SIZES.get(algorithmIdentifier.getAlgorithm()); + int keySize = getKeySize(algorithmIdentifier.getAlgorithm()); - if (keySize != null) + // just need the OID + if (keySize > 0) { - return keySize.intValue(); + return keySize; } + // TODO: support OID/Parameter key sizes (e.g. RC2). + return -1; } + public int getKeySize(ASN1ObjectIdentifier algorithm) + { + Integer keySize = (Integer)KEY_SIZES.get(algorithm); + if (keySize != null) + { + return keySize.intValue(); + } + + return -1; + } } diff --git a/pkix/src/main/java/org/bouncycastle/operator/SecretKeySizeProvider.java b/pkix/src/main/java/org/bouncycastle/operator/SecretKeySizeProvider.java index 15d7a677..5f92ef03 100644 --- a/pkix/src/main/java/org/bouncycastle/operator/SecretKeySizeProvider.java +++ b/pkix/src/main/java/org/bouncycastle/operator/SecretKeySizeProvider.java @@ -1,8 +1,17 @@ package org.bouncycastle.operator; +import org.bouncycastle.asn1.ASN1ObjectIdentifier; import org.bouncycastle.asn1.x509.AlgorithmIdentifier; public interface SecretKeySizeProvider { int getKeySize(AlgorithmIdentifier algorithmIdentifier); + + /** + * Return the key size implied by the OID, if one exists. + * + * @param algorithm the OID of the algorithm of interest. + * @return -1 if there is no fixed key size associated with the OID, or more information is required. + */ + int getKeySize(ASN1ObjectIdentifier algorithm); } diff --git a/pkix/src/main/java/org/bouncycastle/pkcs/jcajce/JcePKCSPBEInputDecryptorProviderBuilder.java b/pkix/src/main/java/org/bouncycastle/pkcs/jcajce/JcePKCSPBEInputDecryptorProviderBuilder.java index eaddab4d..5379d474 100644 --- a/pkix/src/main/java/org/bouncycastle/pkcs/jcajce/JcePKCSPBEInputDecryptorProviderBuilder.java +++ b/pkix/src/main/java/org/bouncycastle/pkcs/jcajce/JcePKCSPBEInputDecryptorProviderBuilder.java @@ -27,7 +27,7 @@ import org.bouncycastle.jcajce.ProviderJcaJceHelper; import org.bouncycastle.jcajce.provider.symmetric.util.BCPBEKey; import org.bouncycastle.jcajce.spec.GOST28147ParameterSpec; import org.bouncycastle.jcajce.spec.PBKDF2KeySpec; -import org.bouncycastle.operator.DefaultSecretKeyProvider; +import org.bouncycastle.operator.DefaultSecretKeySizeProvider; import org.bouncycastle.operator.InputDecryptor; import org.bouncycastle.operator.InputDecryptorProvider; import org.bouncycastle.operator.OperatorCreationException; @@ -37,7 +37,7 @@ public class JcePKCSPBEInputDecryptorProviderBuilder { private JcaJceHelper helper = new DefaultJcaJceHelper(); private boolean wrongPKCS12Zero = false; - private SecretKeySizeProvider keySizeProvider = DefaultSecretKeyProvider.INSTANCE; + private SecretKeySizeProvider keySizeProvider = DefaultSecretKeySizeProvider.INSTANCE; public JcePKCSPBEInputDecryptorProviderBuilder() { diff --git a/pkix/src/main/java/org/bouncycastle/pkcs/jcajce/JcePKCSPBEOutputEncryptorBuilder.java b/pkix/src/main/java/org/bouncycastle/pkcs/jcajce/JcePKCSPBEOutputEncryptorBuilder.java index b37d2cb0..fe53d588 100644 --- a/pkix/src/main/java/org/bouncycastle/pkcs/jcajce/JcePKCSPBEOutputEncryptorBuilder.java +++ b/pkix/src/main/java/org/bouncycastle/pkcs/jcajce/JcePKCSPBEOutputEncryptorBuilder.java @@ -26,7 +26,7 @@ import org.bouncycastle.jcajce.DefaultJcaJceHelper; import org.bouncycastle.jcajce.JcaJceHelper; import org.bouncycastle.jcajce.NamedJcaJceHelper; import org.bouncycastle.jcajce.ProviderJcaJceHelper; -import org.bouncycastle.operator.DefaultSecretKeyProvider; +import org.bouncycastle.operator.DefaultSecretKeySizeProvider; import org.bouncycastle.operator.GenericKey; import org.bouncycastle.operator.OperatorCreationException; import org.bouncycastle.operator.OutputEncryptor; @@ -38,7 +38,7 @@ public class JcePKCSPBEOutputEncryptorBuilder private ASN1ObjectIdentifier algorithm; private ASN1ObjectIdentifier keyEncAlgorithm; private SecureRandom random; - private SecretKeySizeProvider keySizeProvider = DefaultSecretKeyProvider.INSTANCE; + private SecretKeySizeProvider keySizeProvider = DefaultSecretKeySizeProvider.INSTANCE; public JcePKCSPBEOutputEncryptorBuilder(ASN1ObjectIdentifier algorithm) { |