diff options
author | Sergio Giro <sgiro@google.com> | 2016-02-02 15:27:40 +0000 |
---|---|---|
committer | Sergio Giro <sgiro@google.com> | 2016-02-02 15:30:05 +0000 |
commit | 11975162f2da08e65157d37cd272721485f2b34b (patch) | |
tree | e2d9c4866d82c0e93854d5e9a6200cfce47e6232 /bcprov/src/main/java/org/bouncycastle/jcajce | |
parent | bdb7b3d37025690a0434040b4e0d0623d9fa74af (diff) | |
download | bouncycastle-11975162f2da08e65157d37cd272721485f2b34b.tar.gz |
bouncycastle: Android tree with upstream code for version 1.54.
Adding missing files
Change-Id: Ife77e8b1df7ec05555b29fb48a984f4c0da2e562
Diffstat (limited to 'bcprov/src/main/java/org/bouncycastle/jcajce')
19 files changed, 1834 insertions, 0 deletions
diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/PBKDF1Key.java b/bcprov/src/main/java/org/bouncycastle/jcajce/PBKDF1Key.java new file mode 100644 index 00000000..7f7581c0 --- /dev/null +++ b/bcprov/src/main/java/org/bouncycastle/jcajce/PBKDF1Key.java @@ -0,0 +1,67 @@ +package org.bouncycastle.jcajce; + +import org.bouncycastle.crypto.CharToByteConverter; + +/** + * A password based key for use with PBKDF1 as defined in PKCS#5. + */ +public class PBKDF1Key + implements PBKDFKey +{ + private final char[] password; + private final CharToByteConverter converter; + + /** + * Basic constructor for a password based key with generation parameters for PBKDF1. + * + * @param password password to use. + * @param converter the converter to use to turn the char array into octets. + */ + public PBKDF1Key(char[] password, CharToByteConverter converter) + { + this.password = new char[password.length]; + this.converter = converter; + + System.arraycopy(password, 0, this.password, 0, password.length); + } + + /** + * Return a reference to the char[] array holding the password. + * + * @return a reference to the password array. + */ + public char[] getPassword() + { + return password; + } + + /** + * Return the password based key derivation function this key is for, + * + * @return the string "PBKDF1" + */ + public String getAlgorithm() + { + return "PBKDF1"; + } + + /** + * Return the format encoding. + * + * @return the type name representing a char[] to byte[] conversion. + */ + public String getFormat() + { + return converter.getType(); + } + + /** + * Return the password converted to bytes. + * + * @return the password converted to a byte array. + */ + public byte[] getEncoded() + { + return converter.convert(password); + } +} diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/PBKDF1KeyWithParameters.java b/bcprov/src/main/java/org/bouncycastle/jcajce/PBKDF1KeyWithParameters.java new file mode 100644 index 00000000..d0899c1d --- /dev/null +++ b/bcprov/src/main/java/org/bouncycastle/jcajce/PBKDF1KeyWithParameters.java @@ -0,0 +1,53 @@ +package org.bouncycastle.jcajce; + +import javax.crypto.interfaces.PBEKey; + +import org.bouncycastle.crypto.CharToByteConverter; +import org.bouncycastle.util.Arrays; + +/** + * A password based key for use with PBKDF1 as defined in PKCS#5 with full PBE parameters. + */ +public class PBKDF1KeyWithParameters + extends PBKDF1Key + implements PBEKey +{ + private final byte[] salt; + private final int iterationCount; + + /** + * Basic constructor for a password based key with generation parameters for PBKDF1. + * + * @param password password to use. + * @param converter the converter to use to turn the char array into octets. + * @param salt salt for generation algorithm + * @param iterationCount iteration count for generation algorithm. + */ + public PBKDF1KeyWithParameters(char[] password, CharToByteConverter converter, byte[] salt, int iterationCount) + { + super(password, converter); + + this.salt = Arrays.clone(salt); + this.iterationCount = iterationCount; + } + + /** + * Return the salt to use in the key derivation function. + * + * @return the salt to use in the KDF. + */ + public byte[] getSalt() + { + return salt; + } + + /** + * Return the iteration count to use in the key derivation function. + * + * @return the iteration count to use in the KDF. + */ + public int getIterationCount() + { + return iterationCount; + } +} diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/PBKDF2Key.java b/bcprov/src/main/java/org/bouncycastle/jcajce/PBKDF2Key.java new file mode 100644 index 00000000..d9dc6e75 --- /dev/null +++ b/bcprov/src/main/java/org/bouncycastle/jcajce/PBKDF2Key.java @@ -0,0 +1,65 @@ +package org.bouncycastle.jcajce; + +import org.bouncycastle.crypto.CharToByteConverter; +import org.bouncycastle.util.Arrays; + +/** + * A password based key for use with PBKDF2 as defined in PKCS#5. + */ +public class PBKDF2Key + implements PBKDFKey +{ + private final char[] password; + private final CharToByteConverter converter; + + /** + * Basic constructor for a password based key using PBKDF - secret key generation parameters will be passed separately.. + * + * @param password password to use. + */ + public PBKDF2Key(char[] password, CharToByteConverter converter) + { + this.password = Arrays.clone(password); + this.converter = converter; + } + + /** + * Return a reference to the char[] array holding the password. + * + * @return a reference to the password array. + */ + public char[] getPassword() + { + return password; + } + + /** + * Return the password based key derivation function this key is for, + * + * @return the string "PBKDF2" + */ + public String getAlgorithm() + { + return "PBKDF2"; + } + + /** + * Return the format encoding. + * + * @return the type name representing a char[] to byte[] conversion. + */ + public String getFormat() + { + return converter.getType(); + } + + /** + * Return the password converted to bytes. + * + * @return the password converted to a byte array. + */ + public byte[] getEncoded() + { + return converter.convert(password); + } +} diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/PBKDF2KeyWithParameters.java b/bcprov/src/main/java/org/bouncycastle/jcajce/PBKDF2KeyWithParameters.java new file mode 100644 index 00000000..b356cfbd --- /dev/null +++ b/bcprov/src/main/java/org/bouncycastle/jcajce/PBKDF2KeyWithParameters.java @@ -0,0 +1,53 @@ +package org.bouncycastle.jcajce; + +import javax.crypto.interfaces.PBEKey; + +import org.bouncycastle.crypto.CharToByteConverter; +import org.bouncycastle.util.Arrays; + +/** + * A password based key for use with PBKDF2 as defined in PKCS#5 with full PBE parameters. + */ +public class PBKDF2KeyWithParameters + extends PBKDF2Key + implements PBEKey +{ + private final byte[] salt; + private final int iterationCount; + + /** + * Basic constructor for a password based key with generation parameters using FIPS PBKDF. + * + * @param password password to use. + * @param converter converter to use for transforming characters into bytes. + * @param salt salt for generation algorithm + * @param iterationCount iteration count for generation algorithm. + */ + public PBKDF2KeyWithParameters(char[] password, CharToByteConverter converter, byte[] salt, int iterationCount) + { + super(password, converter); + + this.salt = Arrays.clone(salt); + this.iterationCount = iterationCount; + } + + /** + * Return the salt to use in the key derivation function. + * + * @return the salt to use in the KDF. + */ + public byte[] getSalt() + { + return salt; + } + + /** + * Return the iteration count to use in the key derivation function. + * + * @return the iteration count to use in the KDF. + */ + public int getIterationCount() + { + return iterationCount; + } +} diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/PBKDFKey.java b/bcprov/src/main/java/org/bouncycastle/jcajce/PBKDFKey.java new file mode 100644 index 00000000..ae3d2ebd --- /dev/null +++ b/bcprov/src/main/java/org/bouncycastle/jcajce/PBKDFKey.java @@ -0,0 +1,11 @@ +package org.bouncycastle.jcajce; + +import javax.crypto.SecretKey; + +/** + * Base interface for keys associated with various password based key derivation functions (PBKDF). + */ +public interface PBKDFKey + extends SecretKey +{ +} diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/ec/AlgorithmParametersSpi.java b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/ec/AlgorithmParametersSpi.java new file mode 100644 index 00000000..6af71e80 --- /dev/null +++ b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/ec/AlgorithmParametersSpi.java @@ -0,0 +1,167 @@ +package org.bouncycastle.jcajce.provider.asymmetric.ec; + +import java.io.IOException; +import java.security.spec.AlgorithmParameterSpec; +import java.security.spec.ECGenParameterSpec; +import java.security.spec.ECParameterSpec; +import java.security.spec.InvalidParameterSpecException; + +import org.bouncycastle.asn1.ASN1ObjectIdentifier; +import org.bouncycastle.asn1.DERNull; +import org.bouncycastle.asn1.x9.ECNamedCurveTable; +import org.bouncycastle.asn1.x9.X962Parameters; +import org.bouncycastle.asn1.x9.X9ECParameters; +import org.bouncycastle.jcajce.provider.asymmetric.util.EC5Util; +import org.bouncycastle.jcajce.provider.asymmetric.util.ECUtil; +import org.bouncycastle.jce.provider.BouncyCastleProvider; +import org.bouncycastle.math.ec.ECCurve; + +public class AlgorithmParametersSpi + extends java.security.AlgorithmParametersSpi +{ + private ECParameterSpec ecParameterSpec; + private String curveName; + + protected boolean isASN1FormatString(String format) + { + return format == null || format.equals("ASN.1"); + } + + @Override + protected void engineInit(AlgorithmParameterSpec algorithmParameterSpec) + throws InvalidParameterSpecException + { + if (algorithmParameterSpec instanceof ECGenParameterSpec) + { + ECGenParameterSpec ecGenParameterSpec = (ECGenParameterSpec)algorithmParameterSpec; + X9ECParameters params = ECUtils.getDomainParametersFromGenSpec(ecGenParameterSpec); + + if (params == null) + { + throw new InvalidParameterSpecException("EC curve name not recognized: " + ecGenParameterSpec.getName()); + } + curveName = ecGenParameterSpec.getName(); + ecParameterSpec = EC5Util.convertToSpec(params); + } + else if (algorithmParameterSpec instanceof ECParameterSpec) + { + curveName = null; + ecParameterSpec = (ECParameterSpec)algorithmParameterSpec; + } + else + { + throw new InvalidParameterSpecException("AlgorithmParameterSpec class not recognized: " + algorithmParameterSpec.getClass().getName()); + } + } + + @Override + protected void engineInit(byte[] bytes) + throws IOException + { + engineInit(bytes, "ASN.1"); + } + + @Override + protected void engineInit(byte[] bytes, String format) + throws IOException + { + if (isASN1FormatString(format)) + { + X962Parameters params = X962Parameters.getInstance(bytes); + + ECCurve curve = EC5Util.getCurve(BouncyCastleProvider.CONFIGURATION, params); + + if (params.isNamedCurve()) + { + curveName = ECNamedCurveTable.getName(ASN1ObjectIdentifier.getInstance(params.getParameters())); + } + + ecParameterSpec = EC5Util.convertToSpec(params, curve); + } + else + { + throw new IOException("Unknown encoded parameters format in AlgorithmParameters object: " + format); + } + } + + @Override + protected <T extends AlgorithmParameterSpec> T engineGetParameterSpec(Class<T> paramSpec) + throws InvalidParameterSpecException + { + if (ECParameterSpec.class.isAssignableFrom(paramSpec) || paramSpec == AlgorithmParameterSpec.class) + { + return (T)ecParameterSpec; + } + else if (ECGenParameterSpec.class.isAssignableFrom(paramSpec)) + { + if (curveName != null) + { + ASN1ObjectIdentifier namedCurveOid = ECUtil.getNamedCurveOid(curveName); + + if (namedCurveOid != null) + { + return (T)new ECGenParameterSpec(namedCurveOid.getId()); + } + return (T)new ECGenParameterSpec(curveName); + } + else + { + ASN1ObjectIdentifier namedCurveOid = ECUtil.getNamedCurveOid(EC5Util.convertSpec(ecParameterSpec, false)); + + if (namedCurveOid != null) + { + return (T)new ECGenParameterSpec(namedCurveOid.getId()); + } + } + } + throw new InvalidParameterSpecException("EC AlgorithmParameters cannot convert to " + paramSpec.getName()); + } + + @Override + protected byte[] engineGetEncoded() + throws IOException + { + return engineGetEncoded("ASN.1"); + } + + @Override + protected byte[] engineGetEncoded(String format) + throws IOException + { + if (isASN1FormatString(format)) + { + X962Parameters params; + + if (ecParameterSpec == null) // implicitly CA + { + params = new X962Parameters(DERNull.INSTANCE); + } + else if (curveName != null) + { + params = new X962Parameters(ECUtil.getNamedCurveOid(curveName)); + } + else + { + org.bouncycastle.jce.spec.ECParameterSpec ecSpec = EC5Util.convertSpec(ecParameterSpec, false); + X9ECParameters ecP = new X9ECParameters( + ecSpec.getCurve(), + ecSpec.getG(), + ecSpec.getN(), + ecSpec.getH(), + ecSpec.getSeed()); + + params = new X962Parameters(ecP); + } + + return params.getEncoded(); + } + + throw new IOException("Unknown parameters format in AlgorithmParameters object: " + format); + } + + @Override + protected String engineToString() + { + return "EC AlgorithmParameters "; + } +} diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/ec/ECUtils.java b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/ec/ECUtils.java new file mode 100644 index 00000000..dc92e0e4 --- /dev/null +++ b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/ec/ECUtils.java @@ -0,0 +1,45 @@ +package org.bouncycastle.jcajce.provider.asymmetric.ec; + +import java.security.spec.ECGenParameterSpec; + +import org.bouncycastle.asn1.ASN1ObjectIdentifier; +import org.bouncycastle.asn1.x9.X9ECParameters; +import org.bouncycastle.jcajce.provider.asymmetric.util.ECUtil; + +class ECUtils +{ + static X9ECParameters getDomainParametersFromGenSpec(ECGenParameterSpec genSpec) + { + return getDomainParametersFromName(genSpec.getName()); + } + + static X9ECParameters getDomainParametersFromName(String curveName) + { + X9ECParameters domainParameters; + try + { + if (curveName.charAt(0) >= '0' && curveName.charAt(0) <= '2') + { + ASN1ObjectIdentifier oidID = new ASN1ObjectIdentifier(curveName); + domainParameters = ECUtil.getNamedCurveByOid(oidID); + } + else + { + if (curveName.indexOf(' ') > 0) + { + curveName = curveName.substring(curveName.indexOf(' ') + 1); + domainParameters = ECUtil.getNamedCurveByName(curveName); + } + else + { + domainParameters = ECUtil.getNamedCurveByName(curveName); + } + } + } + catch (IllegalArgumentException ex) + { + domainParameters = ECUtil.getNamedCurveByName(curveName); + } + return domainParameters; + } +} diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/util/BaseAgreementSpi.java b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/util/BaseAgreementSpi.java new file mode 100644 index 00000000..8dc0d2dd --- /dev/null +++ b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/util/BaseAgreementSpi.java @@ -0,0 +1,314 @@ +package org.bouncycastle.jcajce.provider.asymmetric.util; + +import java.math.BigInteger; +import java.security.NoSuchAlgorithmException; +import java.util.HashMap; +import java.util.Hashtable; +import java.util.Map; + +import javax.crypto.KeyAgreementSpi; +import javax.crypto.SecretKey; +import javax.crypto.ShortBufferException; +import javax.crypto.spec.SecretKeySpec; + +import org.bouncycastle.asn1.ASN1ObjectIdentifier; +import org.bouncycastle.asn1.cryptopro.CryptoProObjectIdentifiers; +import org.bouncycastle.asn1.gnu.GNUObjectIdentifiers; +import org.bouncycastle.asn1.kisa.KISAObjectIdentifiers; +import org.bouncycastle.asn1.misc.MiscObjectIdentifiers; +import org.bouncycastle.asn1.nist.NISTObjectIdentifiers; +import org.bouncycastle.asn1.ntt.NTTObjectIdentifiers; +import org.bouncycastle.asn1.oiw.OIWObjectIdentifiers; +import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers; +import org.bouncycastle.crypto.DerivationFunction; +import org.bouncycastle.crypto.agreement.kdf.DHKDFParameters; +import org.bouncycastle.crypto.agreement.kdf.DHKEKGenerator; +import org.bouncycastle.crypto.params.DESParameters; +import org.bouncycastle.crypto.params.KDFParameters; +import org.bouncycastle.util.Integers; +import org.bouncycastle.util.Strings; + +public abstract class BaseAgreementSpi + extends KeyAgreementSpi +{ + private static final Map<String, ASN1ObjectIdentifier> defaultOids = new HashMap<String, ASN1ObjectIdentifier>(); + private static final Map<String, Integer> keySizes = new HashMap<String, Integer>(); + private static final Map<String, String> nameTable = new HashMap<String, String>(); + + private static final Hashtable oids = new Hashtable(); + private static final Hashtable des = new Hashtable(); + + static + { + Integer i64 = Integers.valueOf(64); + Integer i128 = Integers.valueOf(128); + Integer i192 = Integers.valueOf(192); + Integer i256 = Integers.valueOf(256); + + keySizes.put("DES", i64); + keySizes.put("DESEDE", i192); + keySizes.put("BLOWFISH", i128); + keySizes.put("AES", i256); + + keySizes.put(NISTObjectIdentifiers.id_aes128_ECB.getId(), i128); + keySizes.put(NISTObjectIdentifiers.id_aes192_ECB.getId(), i192); + keySizes.put(NISTObjectIdentifiers.id_aes256_ECB.getId(), i256); + keySizes.put(NISTObjectIdentifiers.id_aes128_CBC.getId(), i128); + keySizes.put(NISTObjectIdentifiers.id_aes192_CBC.getId(), i192); + keySizes.put(NISTObjectIdentifiers.id_aes256_CBC.getId(), i256); + keySizes.put(NISTObjectIdentifiers.id_aes128_CFB.getId(), i128); + keySizes.put(NISTObjectIdentifiers.id_aes192_CFB.getId(), i192); + keySizes.put(NISTObjectIdentifiers.id_aes256_CFB.getId(), i256); + keySizes.put(NISTObjectIdentifiers.id_aes128_OFB.getId(), i128); + keySizes.put(NISTObjectIdentifiers.id_aes192_OFB.getId(), i192); + keySizes.put(NISTObjectIdentifiers.id_aes256_OFB.getId(), i256); + keySizes.put(NISTObjectIdentifiers.id_aes128_wrap.getId(), i128); + keySizes.put(NISTObjectIdentifiers.id_aes192_wrap.getId(), i192); + keySizes.put(NISTObjectIdentifiers.id_aes256_wrap.getId(), i256); + keySizes.put(NISTObjectIdentifiers.id_aes128_CCM.getId(), i128); + keySizes.put(NISTObjectIdentifiers.id_aes192_CCM.getId(), i192); + keySizes.put(NISTObjectIdentifiers.id_aes256_CCM.getId(), i256); + keySizes.put(NISTObjectIdentifiers.id_aes128_GCM.getId(), i128); + keySizes.put(NISTObjectIdentifiers.id_aes192_GCM.getId(), i192); + keySizes.put(NISTObjectIdentifiers.id_aes256_GCM.getId(), i256); + keySizes.put(NTTObjectIdentifiers.id_camellia128_wrap.getId(), i128); + keySizes.put(NTTObjectIdentifiers.id_camellia192_wrap.getId(), i192); + keySizes.put(NTTObjectIdentifiers.id_camellia256_wrap.getId(), i256); + keySizes.put(KISAObjectIdentifiers.id_npki_app_cmsSeed_wrap.getId(), i128); + + keySizes.put(PKCSObjectIdentifiers.id_alg_CMS3DESwrap.getId(), i192); + keySizes.put(PKCSObjectIdentifiers.des_EDE3_CBC.getId(), i192); + keySizes.put(OIWObjectIdentifiers.desCBC.getId(), i64); + + keySizes.put(PKCSObjectIdentifiers.id_hmacWithSHA1.getId(), Integers.valueOf(160)); + keySizes.put(PKCSObjectIdentifiers.id_hmacWithSHA256.getId(), i256); + keySizes.put(PKCSObjectIdentifiers.id_hmacWithSHA384.getId(), Integers.valueOf(384)); + keySizes.put(PKCSObjectIdentifiers.id_hmacWithSHA512.getId(), Integers.valueOf(512)); + + defaultOids.put("DESEDE", PKCSObjectIdentifiers.des_EDE3_CBC); + defaultOids.put("AES", NISTObjectIdentifiers.id_aes256_CBC); + defaultOids.put("CAMELLIA", NTTObjectIdentifiers.id_camellia256_cbc); + defaultOids.put("SEED", KISAObjectIdentifiers.id_seedCBC); + defaultOids.put("DES", OIWObjectIdentifiers.desCBC); + + nameTable.put(MiscObjectIdentifiers.cast5CBC.getId(), "CAST5"); + nameTable.put(MiscObjectIdentifiers.as_sys_sec_alg_ideaCBC.getId(), "IDEA"); + nameTable.put(MiscObjectIdentifiers.cryptlib_algorithm_blowfish_ECB.getId(), "Blowfish"); + nameTable.put(MiscObjectIdentifiers.cryptlib_algorithm_blowfish_CBC.getId(), "Blowfish"); + nameTable.put(MiscObjectIdentifiers.cryptlib_algorithm_blowfish_CFB.getId(), "Blowfish"); + nameTable.put(MiscObjectIdentifiers.cryptlib_algorithm_blowfish_OFB.getId(), "Blowfish"); + nameTable.put(OIWObjectIdentifiers.desECB.getId(), "DES"); + nameTable.put(OIWObjectIdentifiers.desCBC.getId(), "DES"); + nameTable.put(OIWObjectIdentifiers.desCFB.getId(), "DES"); + nameTable.put(OIWObjectIdentifiers.desOFB.getId(), "DES"); + nameTable.put(OIWObjectIdentifiers.desEDE.getId(), "DESede"); + nameTable.put(PKCSObjectIdentifiers.des_EDE3_CBC.getId(), "DESede"); + nameTable.put(PKCSObjectIdentifiers.id_alg_CMS3DESwrap.getId(), "DESede"); + nameTable.put(PKCSObjectIdentifiers.id_alg_CMSRC2wrap.getId(), "RC2"); + nameTable.put(PKCSObjectIdentifiers.id_hmacWithSHA1.getId(), "HmacSHA1"); + nameTable.put(PKCSObjectIdentifiers.id_hmacWithSHA224.getId(), "HmacSHA224"); + nameTable.put(PKCSObjectIdentifiers.id_hmacWithSHA256.getId(), "HmacSHA256"); + nameTable.put(PKCSObjectIdentifiers.id_hmacWithSHA384.getId(), "HmacSHA384"); + nameTable.put(PKCSObjectIdentifiers.id_hmacWithSHA512.getId(), "HmacSHA512"); + nameTable.put(NTTObjectIdentifiers.id_camellia128_cbc.getId(), "Camellia"); + nameTable.put(NTTObjectIdentifiers.id_camellia192_cbc.getId(), "Camellia"); + nameTable.put(NTTObjectIdentifiers.id_camellia256_cbc.getId(), "Camellia"); + nameTable.put(NTTObjectIdentifiers.id_camellia128_wrap.getId(), "Camellia"); + nameTable.put(NTTObjectIdentifiers.id_camellia192_wrap.getId(), "Camellia"); + nameTable.put(NTTObjectIdentifiers.id_camellia256_wrap.getId(), "Camellia"); + nameTable.put(KISAObjectIdentifiers.id_npki_app_cmsSeed_wrap.getId(), "SEED"); + nameTable.put(KISAObjectIdentifiers.id_seedCBC.getId(), "SEED"); + nameTable.put(KISAObjectIdentifiers.id_seedMAC.getId(), "SEED"); + nameTable.put(CryptoProObjectIdentifiers.gostR28147_gcfb.getId(), "GOST28147"); + + nameTable.put(NISTObjectIdentifiers.id_aes128_wrap.getId(), "AES"); + nameTable.put(NISTObjectIdentifiers.id_aes128_CCM.getId(), "AES"); + nameTable.put(NISTObjectIdentifiers.id_aes128_CCM.getId(), "AES"); + + oids.put("DESEDE", PKCSObjectIdentifiers.des_EDE3_CBC); + oids.put("AES", NISTObjectIdentifiers.id_aes256_CBC); + oids.put("DES", OIWObjectIdentifiers.desCBC); + + des.put("DES", "DES"); + des.put("DESEDE", "DES"); + des.put(OIWObjectIdentifiers.desCBC.getId(), "DES"); + des.put(PKCSObjectIdentifiers.des_EDE3_CBC.getId(), "DES"); + des.put(PKCSObjectIdentifiers.id_alg_CMS3DESwrap.getId(), "DES"); + } + + private final String kaAlgorithm; + private final DerivationFunction kdf; + + protected BigInteger result; + protected byte[] ukmParameters; + + public BaseAgreementSpi(String kaAlgorithm, DerivationFunction kdf) + { + this.kaAlgorithm = kaAlgorithm; + this.kdf = kdf; + } + + protected static String getAlgorithm(String algDetails) + { + if (algDetails.indexOf('[') > 0) + { + return algDetails.substring(0, algDetails.indexOf('[')); + } + + if (algDetails.startsWith(NISTObjectIdentifiers.aes.getId())) + { + return "AES"; + } + if (algDetails.startsWith(GNUObjectIdentifiers.Serpent.getId())) + { + return "Serpent"; + } + + String name = (String)nameTable.get(Strings.toUpperCase(algDetails)); + + if (name != null) + { + return name; + } + + return algDetails; + } + + protected static int getKeySize(String algDetails) + { + if (algDetails.indexOf('[') > 0) + { + return (Integer.parseInt(algDetails.substring(algDetails.indexOf('[') + 1, algDetails.indexOf(']'))) + 7) / 8; + } + + String algKey = Strings.toUpperCase(algDetails); + if (!keySizes.containsKey(algKey)) + { + return -1; + } + + return ((Integer)keySizes.get(algKey)).intValue(); + } + + protected static byte[] trimZeroes(byte[] secret) + { + if (secret[0] != 0) + { + return secret; + } + else + { + int ind = 0; + while (ind < secret.length && secret[ind] == 0) + { + ind++; + } + + byte[] rv = new byte[secret.length - ind]; + + System.arraycopy(secret, ind, rv, 0, rv.length); + + return rv; + } + } + + protected byte[] engineGenerateSecret() + throws IllegalStateException + { + if (kdf != null) + { + throw new UnsupportedOperationException( + "KDF can only be used when algorithm is known"); + } + + return bigIntToBytes(result); + } + + protected int engineGenerateSecret( + byte[] sharedSecret, + int offset) + throws IllegalStateException, ShortBufferException + { + byte[] secret = engineGenerateSecret(); + + if (sharedSecret.length - offset < secret.length) + { + throw new ShortBufferException(kaAlgorithm + " key agreement: need " + secret.length + " bytes"); + } + + System.arraycopy(secret, 0, sharedSecret, offset, secret.length); + + return secret.length; + } + + protected SecretKey engineGenerateSecret( + String algorithm) + throws NoSuchAlgorithmException + { + byte[] secret = bigIntToBytes(result); + String algKey = Strings.toUpperCase(algorithm); + String oidAlgorithm = algorithm; + + if (oids.containsKey(algKey)) + { + oidAlgorithm = ((ASN1ObjectIdentifier)oids.get(algKey)).getId(); + } + + int keySize = getKeySize(oidAlgorithm); + + if (kdf != null) + { + if (keySize < 0) + { + throw new NoSuchAlgorithmException("unknown algorithm encountered: " + oidAlgorithm); + } + byte[] keyBytes = new byte[keySize / 8]; + + if (kdf instanceof DHKEKGenerator) + { + ASN1ObjectIdentifier oid; + try + { + oid = new ASN1ObjectIdentifier(oidAlgorithm); + } + catch (IllegalArgumentException e) + { + throw new NoSuchAlgorithmException("no OID for algorithm: " + oidAlgorithm); + } + DHKDFParameters params = new DHKDFParameters(oid, keySize, secret, ukmParameters); + + kdf.init(params); + } + else + { + KDFParameters params = new KDFParameters(secret, ukmParameters); + + kdf.init(params); + } + + kdf.generateBytes(keyBytes, 0, keyBytes.length); + + secret = keyBytes; + } + else + { + if (keySize > 0) + { + byte[] keyBytes = new byte[keySize / 8]; + + System.arraycopy(secret, 0, keyBytes, 0, keyBytes.length); + + secret = keyBytes; + } + } + + if (des.containsKey(oidAlgorithm)) + { + DESParameters.setOddParity(secret); + } + + return new SecretKeySpec(secret, getAlgorithm(algorithm)); + } + + protected abstract byte[] bigIntToBytes(BigInteger result); +} diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/util/DESUtil.java b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/util/DESUtil.java new file mode 100644 index 00000000..2409fb03 --- /dev/null +++ b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/util/DESUtil.java @@ -0,0 +1,53 @@ +package org.bouncycastle.jcajce.provider.asymmetric.util; + +import java.util.HashSet; +import java.util.Set; + +import org.bouncycastle.asn1.oiw.OIWObjectIdentifiers; +import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers; +import org.bouncycastle.util.Strings; + +public class DESUtil +{ + private static final Set<String> des = new HashSet<String>(); + + static + { + des.add("DES"); + des.add("DESEDE"); + des.add(OIWObjectIdentifiers.desCBC.getId()); + des.add(PKCSObjectIdentifiers.des_EDE3_CBC.getId()); + des.add(PKCSObjectIdentifiers.des_EDE3_CBC.getId()); + des.add(PKCSObjectIdentifiers.id_alg_CMS3DESwrap.getId()); + } + + public static boolean isDES(String algorithmID) + { + String name = Strings.toUpperCase(algorithmID); + + return des.contains(name); + } + + /** + * DES Keys use the LSB as the odd parity bit. This can + * be used to check for corrupt keys. + * + * @param bytes the byte array to set the parity on. + */ + public static void setOddParity( + byte[] bytes) + { + for (int i = 0; i < bytes.length; i++) + { + int b = bytes[i]; + bytes[i] = (byte)((b & 0xfe) | + ((((b >> 1) ^ + (b >> 2) ^ + (b >> 3) ^ + (b >> 4) ^ + (b >> 5) ^ + (b >> 6) ^ + (b >> 7)) ^ 0x01) & 0x01)); + } + } +} diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/digest/Blake2b.java b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/digest/Blake2b.java new file mode 100644 index 00000000..0eb978a9 --- /dev/null +++ b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/digest/Blake2b.java @@ -0,0 +1,114 @@ +package org.bouncycastle.jcajce.provider.digest; + +import org.bouncycastle.asn1.misc.MiscObjectIdentifiers; +import org.bouncycastle.crypto.digests.Blake2bDigest; +import org.bouncycastle.jcajce.provider.config.ConfigurableProvider; + +public class Blake2b +{ + private Blake2b() + { + + } + + static public class Blake2b512 + extends BCMessageDigest + implements Cloneable + { + public Blake2b512() + { + super(new Blake2bDigest(512)); + } + + public Object clone() + throws CloneNotSupportedException + { + Blake2b512 d = (Blake2b512)super.clone(); + d.digest = new Blake2bDigest((Blake2bDigest)digest); + + return d; + } + } + + static public class Blake2b384 + extends BCMessageDigest + implements Cloneable + { + public Blake2b384() + { + super(new Blake2bDigest(384)); + } + + public Object clone() + throws CloneNotSupportedException + { + Blake2b384 d = (Blake2b384)super.clone(); + d.digest = new Blake2bDigest((Blake2bDigest)digest); + + return d; + } + } + + static public class Blake2b256 + extends BCMessageDigest + implements Cloneable + { + public Blake2b256() + { + super(new Blake2bDigest(256)); + } + + public Object clone() + throws CloneNotSupportedException + { + Blake2b256 d = (Blake2b256)super.clone(); + d.digest = new Blake2bDigest((Blake2bDigest)digest); + + return d; + } + } + + static public class Blake2b160 + extends BCMessageDigest + implements Cloneable + { + public Blake2b160() + { + super(new Blake2bDigest(160)); + } + + public Object clone() + throws CloneNotSupportedException + { + Blake2b160 d = (Blake2b160)super.clone(); + d.digest = new Blake2bDigest((Blake2bDigest)digest); + + return d; + } + } + + public static class Mappings + extends DigestAlgorithmProvider + { + private static final String PREFIX = Blake2b.class.getName(); + + public Mappings() + { + } + + public void configure(ConfigurableProvider provider) + { + provider.addAlgorithm("MessageDigest.BLAKE2B-512", PREFIX + "$Blake2b512"); + provider.addAlgorithm("Alg.Alias.MessageDigest." + MiscObjectIdentifiers.id_blake2b512, "BLAKE2B-512"); + + provider.addAlgorithm("MessageDigest.BLAKE2B-384", PREFIX + "$Blake2b384"); + provider.addAlgorithm("Alg.Alias.MessageDigest." + MiscObjectIdentifiers.id_blake2b384, "BLAKE2B-384"); + + provider.addAlgorithm("MessageDigest.BLAKE2B-256", PREFIX + "$Blake2b256"); + provider.addAlgorithm("Alg.Alias.MessageDigest." + MiscObjectIdentifiers.id_blake2b256, "BLAKE2B-256"); + + provider.addAlgorithm("MessageDigest.BLAKE2B-160", PREFIX + "$Blake2b160"); + provider.addAlgorithm("Alg.Alias.MessageDigest." + MiscObjectIdentifiers.id_blake2b160, "BLAKE2B-160"); + } + } +} diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/digest/Keccak.java b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/digest/Keccak.java new file mode 100644 index 00000000..f8b989bf --- /dev/null +++ b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/digest/Keccak.java @@ -0,0 +1,195 @@ +package org.bouncycastle.jcajce.provider.digest; + +import org.bouncycastle.crypto.CipherKeyGenerator; +import org.bouncycastle.crypto.digests.KeccakDigest; +import org.bouncycastle.crypto.macs.HMac; +import org.bouncycastle.jcajce.provider.config.ConfigurableProvider; +import org.bouncycastle.jcajce.provider.symmetric.util.BaseKeyGenerator; +import org.bouncycastle.jcajce.provider.symmetric.util.BaseMac; + +public class Keccak +{ + private Keccak() + { + + } + + static public class DigestKeccak + extends BCMessageDigest + implements Cloneable + { + public DigestKeccak(int size) + { + super(new KeccakDigest(size)); + } + + public Object clone() + throws CloneNotSupportedException + { + BCMessageDigest d = (BCMessageDigest)super.clone(); + d.digest = new KeccakDigest((KeccakDigest)digest); + + return d; + } + } + + static public class Digest224 + extends DigestKeccak + { + public Digest224() + { + super(224); + } + } + + static public class Digest256 + extends DigestKeccak + { + public Digest256() + { + super(256); + } + } + + static public class Digest288 + extends DigestKeccak + { + public Digest288() + { + super(288); + } + } + + static public class Digest384 + extends DigestKeccak + { + public Digest384() + { + super(384); + } + } + + static public class Digest512 + extends DigestKeccak + { + public Digest512() + { + super(512); + } + } + + public static class HashMac224 + extends BaseMac + { + public HashMac224() + { + super(new HMac(new KeccakDigest(224))); + } + } + + public static class HashMac256 + extends BaseMac + { + public HashMac256() + { + super(new HMac(new KeccakDigest(256))); + } + } + + public static class HashMac288 + extends BaseMac + { + public HashMac288() + { + super(new HMac(new KeccakDigest(288))); + } + } + + public static class HashMac384 + extends BaseMac + { + public HashMac384() + { + super(new HMac(new KeccakDigest(384))); + } + } + + public static class HashMac512 + extends BaseMac + { + public HashMac512() + { + super(new HMac(new KeccakDigest(512))); + } + } + + public static class KeyGenerator224 + extends BaseKeyGenerator + { + public KeyGenerator224() + { + super("HMACKECCAK224", 224, new CipherKeyGenerator()); + } + } + + public static class KeyGenerator256 + extends BaseKeyGenerator + { + public KeyGenerator256() + { + super("HMACKECCAK256", 256, new CipherKeyGenerator()); + } + } + + public static class KeyGenerator288 + extends BaseKeyGenerator + { + public KeyGenerator288() + { + super("HMACKECCAK288", 288, new CipherKeyGenerator()); + } + } + + public static class KeyGenerator384 + extends BaseKeyGenerator + { + public KeyGenerator384() + { + super("HMACKECCAK384", 384, new CipherKeyGenerator()); + } + } + + public static class KeyGenerator512 + extends BaseKeyGenerator + { + public KeyGenerator512() + { + super("HMACKECCAK512", 512, new CipherKeyGenerator()); + } + } + + public static class Mappings + extends DigestAlgorithmProvider + { + private static final String PREFIX = Keccak.class.getName(); + + public Mappings() + { + } + + public void configure(ConfigurableProvider provider) + { + provider.addAlgorithm("MessageDigest.KECCAK-224", PREFIX + "$Digest224"); + provider.addAlgorithm("MessageDigest.KECCAK-288", PREFIX + "$Digest288"); + provider.addAlgorithm("MessageDigest.KECCAK-256", PREFIX + "$Digest256"); + provider.addAlgorithm("MessageDigest.KECCAK-384", PREFIX + "$Digest384"); + provider.addAlgorithm("MessageDigest.KECCAK-512", PREFIX + "$Digest512"); + + addHMACAlgorithm(provider, "KECCAK224", PREFIX + "$HashMac224", PREFIX + "$KeyGenerator224"); + addHMACAlgorithm(provider, "KECCAK256", PREFIX + "$HashMac256", PREFIX + "$KeyGenerator256"); + addHMACAlgorithm(provider, "KECCAK288", PREFIX + "$HashMac288", PREFIX + "$KeyGenerator288"); + addHMACAlgorithm(provider, "KECCAK384", PREFIX + "$HashMac384", PREFIX + "$KeyGenerator384"); + addHMACAlgorithm(provider, "KECCAK512", PREFIX + "$HashMac512", PREFIX + "$KeyGenerator512"); + } + } +} diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/GcmSpecUtil.java b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/GcmSpecUtil.java new file mode 100644 index 00000000..5ccc8ff0 --- /dev/null +++ b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/GcmSpecUtil.java @@ -0,0 +1,78 @@ +package org.bouncycastle.jcajce.provider.symmetric; + +import java.lang.reflect.Constructor; +import java.lang.reflect.Method; +import java.security.spec.AlgorithmParameterSpec; +import java.security.spec.InvalidParameterSpecException; + +import org.bouncycastle.asn1.ASN1Primitive; +import org.bouncycastle.asn1.cms.GCMParameters; +import org.bouncycastle.util.Integers; + +class GcmSpecUtil +{ + static final Class gcmSpecClass = lookup("javax.crypto.spec.GCMParameterSpec"); + + static boolean gcmSpecExists() + { + return gcmSpecClass != null; + } + + static boolean isGcmSpec(AlgorithmParameterSpec paramSpec) + { + return gcmSpecClass != null && gcmSpecClass.isInstance(paramSpec); + } + + static boolean isGcmSpec(Class paramSpecClass) + { + return gcmSpecClass == paramSpecClass; + } + + static AlgorithmParameterSpec extractGcmSpec(ASN1Primitive spec) + throws InvalidParameterSpecException + { + try + { + GCMParameters gcmParams = GCMParameters.getInstance(spec); + Constructor constructor = gcmSpecClass.getConstructor(new Class[]{Integer.TYPE, byte[].class}); + + return (AlgorithmParameterSpec)constructor.newInstance(new Object[] { Integers.valueOf(gcmParams.getIcvLen() * 8), gcmParams.getNonce() }); + } + catch (NoSuchMethodException e) + { + throw new InvalidParameterSpecException("No constructor found!"); // should never happen + } + catch (Exception e) + { + throw new InvalidParameterSpecException("Construction failed: " + e.getMessage()); // should never happen + } + } + + static GCMParameters extractGcmParameters(AlgorithmParameterSpec paramSpec) + throws InvalidParameterSpecException + { + try + { + Method tLen = gcmSpecClass.getDeclaredMethod("getTLen", new Class[0]); + Method iv= gcmSpecClass.getDeclaredMethod("getIV", new Class[0]); + + return new GCMParameters((byte[])iv.invoke(paramSpec, new Object[0]), ((Integer)tLen.invoke(paramSpec, new Object[0])).intValue() / 8); + } + catch (Exception e) + { + throw new InvalidParameterSpecException("Cannot process GCMParameterSpec"); + } + } + + private static Class lookup(String className) + { + try + { + return GcmSpecUtil.class.getClassLoader().loadClass(className); + } + catch (Exception e) + { + return null; + } + } +} diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/OpenSSLPBKDF.java b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/OpenSSLPBKDF.java new file mode 100644 index 00000000..5888adfa --- /dev/null +++ b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/OpenSSLPBKDF.java @@ -0,0 +1,86 @@ +package org.bouncycastle.jcajce.provider.symmetric; + +import java.security.spec.InvalidKeySpecException; +import java.security.spec.KeySpec; + +import javax.crypto.SecretKey; +import javax.crypto.spec.PBEKeySpec; +import javax.crypto.spec.SecretKeySpec; + +import org.bouncycastle.crypto.generators.OpenSSLPBEParametersGenerator; +import org.bouncycastle.crypto.params.KeyParameter; +import org.bouncycastle.jcajce.provider.config.ConfigurableProvider; +import org.bouncycastle.jcajce.provider.symmetric.util.BaseSecretKeyFactory; +import org.bouncycastle.jcajce.provider.util.AlgorithmProvider; +import org.bouncycastle.util.Strings; + +public final class OpenSSLPBKDF +{ + private OpenSSLPBKDF() + { + } + + public static class PBKDF + extends BaseSecretKeyFactory + { + public PBKDF() + { + super("PBKDF-OpenSSL", null); + } + + protected SecretKey engineGenerateSecret( + KeySpec keySpec) + throws InvalidKeySpecException + { + if (keySpec instanceof PBEKeySpec) + { + PBEKeySpec pbeSpec = (PBEKeySpec)keySpec; + + if (pbeSpec.getSalt() == null) + { + throw new InvalidKeySpecException("missing required salt"); + } + + if (pbeSpec.getIterationCount() <= 0) + { + throw new InvalidKeySpecException("positive iteration count required: " + + pbeSpec.getIterationCount()); + } + + if (pbeSpec.getKeyLength() <= 0) + { + throw new InvalidKeySpecException("positive key length required: " + + pbeSpec.getKeyLength()); + } + + if (pbeSpec.getPassword().length == 0) + { + throw new IllegalArgumentException("password empty"); + } + + OpenSSLPBEParametersGenerator pGen = new OpenSSLPBEParametersGenerator(); + + pGen.init(Strings.toByteArray(pbeSpec.getPassword()), pbeSpec.getSalt()); + + return new SecretKeySpec(((KeyParameter)pGen.generateDerivedParameters(pbeSpec.getKeyLength())).getKey(), "OpenSSLPBKDF"); + } + + throw new InvalidKeySpecException("Invalid KeySpec"); + } + } + + public static class Mappings + extends AlgorithmProvider + { + private static final String PREFIX = OpenSSLPBKDF.class.getName(); + + public Mappings() + { + } + + public void configure(ConfigurableProvider provider) + { + provider.addAlgorithm("SecretKeyFactory.PBKDF-OPENSSL", PREFIX + "$PBKDF"); + } + } +} diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/SM4.java b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/SM4.java new file mode 100644 index 00000000..05e037ab --- /dev/null +++ b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/SM4.java @@ -0,0 +1,162 @@ +package org.bouncycastle.jcajce.provider.symmetric; + +import java.security.AlgorithmParameters; +import java.security.InvalidAlgorithmParameterException; +import java.security.SecureRandom; +import java.security.spec.AlgorithmParameterSpec; + +import javax.crypto.spec.IvParameterSpec; + +import org.bouncycastle.crypto.BlockCipher; +import org.bouncycastle.crypto.CipherKeyGenerator; +import org.bouncycastle.crypto.engines.SM4Engine; +import org.bouncycastle.crypto.generators.Poly1305KeyGenerator; +import org.bouncycastle.crypto.macs.CMac; +import org.bouncycastle.crypto.macs.GMac; +import org.bouncycastle.crypto.modes.GCMBlockCipher; +import org.bouncycastle.jcajce.provider.config.ConfigurableProvider; +import org.bouncycastle.jcajce.provider.symmetric.util.BaseAlgorithmParameterGenerator; +import org.bouncycastle.jcajce.provider.symmetric.util.BaseBlockCipher; +import org.bouncycastle.jcajce.provider.symmetric.util.BaseKeyGenerator; +import org.bouncycastle.jcajce.provider.symmetric.util.BaseMac; +import org.bouncycastle.jcajce.provider.symmetric.util.BlockCipherProvider; +import org.bouncycastle.jcajce.provider.symmetric.util.IvAlgorithmParameters; + +public final class SM4 +{ + private SM4() + { + } + + public static class ECB + extends BaseBlockCipher + { + public ECB() + { + super(new BlockCipherProvider() + { + public BlockCipher get() + { + return new SM4Engine(); + } + }); + } + } + + public static class KeyGen + extends BaseKeyGenerator + { + public KeyGen() + { + super("SM4", 128, new CipherKeyGenerator()); + } + } + + public static class CMAC + extends BaseMac + { + public CMAC() + { + super(new CMac(new SM4Engine())); + } + } + + public static class GMAC + extends BaseMac + { + public GMAC() + { + super(new GMac(new GCMBlockCipher(new SM4Engine()))); + } + } + + public static class Poly1305 + extends BaseMac + { + public Poly1305() + { + super(new org.bouncycastle.crypto.macs.Poly1305(new SM4Engine())); + } + } + + public static class Poly1305KeyGen + extends BaseKeyGenerator + { + public Poly1305KeyGen() + { + super("Poly1305-SM4", 256, new Poly1305KeyGenerator()); + } + } + + public static class AlgParamGen + extends BaseAlgorithmParameterGenerator + { + protected void engineInit( + AlgorithmParameterSpec genParamSpec, + SecureRandom random) + throws InvalidAlgorithmParameterException + { + throw new InvalidAlgorithmParameterException("No supported AlgorithmParameterSpec for SM4 parameter generation."); + } + + protected AlgorithmParameters engineGenerateParameters() + { + byte[] iv = new byte[16]; + + if (random == null) + { + random = new SecureRandom(); + } + + random.nextBytes(iv); + + AlgorithmParameters params; + + try + { + params = createParametersInstance("SM4"); + params.init(new IvParameterSpec(iv)); + } + catch (Exception e) + { + throw new RuntimeException(e.getMessage()); + } + + return params; + } + } + + public static class AlgParams + extends IvAlgorithmParameters + { + protected String engineToString() + { + return "SM4 IV"; + } + } + + public static class Mappings + extends SymmetricAlgorithmProvider + { + private static final String PREFIX = SM4.class.getName(); + + public Mappings() + { + } + + public void configure(ConfigurableProvider provider) + { + provider.addAlgorithm("AlgorithmParameters.SM4", PREFIX + "$AlgParams"); + + provider.addAlgorithm("AlgorithmParameterGenerator.SM4", PREFIX + "$AlgParamGen"); + + provider.addAlgorithm("Cipher.SM4", PREFIX + "$ECB"); + + provider.addAlgorithm("KeyGenerator.SM4", PREFIX + "$KeyGen"); + + addCMacAlgorithm(provider, "SM4", PREFIX + "$CMAC", PREFIX + "$KeyGen"); + addGMacAlgorithm(provider, "SM4", PREFIX + "$GMAC", PREFIX + "$KeyGen"); + addPoly1305Algorithm(provider, "SM4", PREFIX + "$Poly1305", PREFIX + "$Poly1305KeyGen"); + } + } +} diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/spec/KTSParameterSpec.java b/bcprov/src/main/java/org/bouncycastle/jcajce/spec/KTSParameterSpec.java new file mode 100644 index 00000000..a6d1a8d2 --- /dev/null +++ b/bcprov/src/main/java/org/bouncycastle/jcajce/spec/KTSParameterSpec.java @@ -0,0 +1,157 @@ +package org.bouncycastle.jcajce.spec; + +import java.security.spec.AlgorithmParameterSpec; + +import org.bouncycastle.asn1.nist.NISTObjectIdentifiers; +import org.bouncycastle.asn1.x509.AlgorithmIdentifier; +import org.bouncycastle.asn1.x9.X9ObjectIdentifiers; +import org.bouncycastle.util.Arrays; + +/** + * Parameter spec for doing KTS based wrapping via the Cipher API. + */ +public class KTSParameterSpec + implements AlgorithmParameterSpec +{ + private final String wrappingKeyAlgorithm; + private final int keySizeInBits; + private final AlgorithmParameterSpec parameterSpec; + private final AlgorithmIdentifier kdfAlgorithm; + private byte[] otherInfo; + + /** + * Builder class for creating a KTSParameterSpec. + */ + public static final class Builder + { + private final String algorithmName; + private final int keySizeInBits; + + private AlgorithmParameterSpec parameterSpec; + private AlgorithmIdentifier kdfAlgorithm; + private byte[] otherInfo; + + /** + * Basic builder. + * + * @param algorithmName the algorithm name for the secret key we use for wrapping. + * @param keySizeInBits the size of the wrapping key we want to produce in bits. + */ + public Builder(String algorithmName, int keySizeInBits) + { + this(algorithmName, keySizeInBits, null); + } + + /** + * Basic builder. + * + * @param algorithmName the algorithm name for the secret key we use for wrapping. + * @param keySizeInBits the size of the wrapping key we want to produce in bits. + * @param otherInfo the otherInfo/IV encoding to be applied to the KDF. + */ + public Builder(String algorithmName, int keySizeInBits, byte[] otherInfo) + { + this.algorithmName = algorithmName; + this.keySizeInBits = keySizeInBits; + this.kdfAlgorithm = new AlgorithmIdentifier(X9ObjectIdentifiers.id_kdf_kdf3, new AlgorithmIdentifier(NISTObjectIdentifiers.id_sha256)); + this.otherInfo = (otherInfo == null) ? new byte[0] : Arrays.clone(otherInfo); + } + + /** + * Set the algorithm parameter spec to be used with the wrapper. + * + * @param parameterSpec the algorithm parameter spec to be used in wrapping/unwrapping. + * @return the current Builder instance. + */ + public Builder withParameterSpec(AlgorithmParameterSpec parameterSpec) + { + this.parameterSpec = parameterSpec; + + return this; + } + + /** + * Set the KDF algorithm and digest algorithm for wrap key generation. + * + * @param kdfAlgorithm the KDF algorithm to apply. + * @return the current Builder instance. + */ + public Builder withKdfAlgorithm(AlgorithmIdentifier kdfAlgorithm) + { + this.kdfAlgorithm = kdfAlgorithm; + + return this; + } + + /** + * Build the new parameter spec. + * + * @return a new parameter spec configured according to the builder state. + */ + public KTSParameterSpec build() + { + return new KTSParameterSpec(algorithmName, keySizeInBits, parameterSpec, kdfAlgorithm, otherInfo); + } + } + + private KTSParameterSpec( + String wrappingKeyAlgorithm, int keySizeInBits, + AlgorithmParameterSpec parameterSpec, AlgorithmIdentifier kdfAlgorithm, byte[] otherInfo) + { + this.wrappingKeyAlgorithm = wrappingKeyAlgorithm; + this.keySizeInBits = keySizeInBits; + this.parameterSpec = parameterSpec; + this.kdfAlgorithm = kdfAlgorithm; + this.otherInfo = otherInfo; + } + + /** + * Return the name of the algorithm for the wrapping key this key spec should use. + * + * @return the key algorithm. + */ + public String getKeyAlgorithmName() + { + return wrappingKeyAlgorithm; + } + + /** + * Return the size of the key (in bits) for the wrapping key this key spec should use. + * + * @return length in bits of the key to be calculated. + */ + public int getKeySize() + { + return keySizeInBits; + } + + /** + * Return the algorithm parameter spec to be applied with the private key when the encapsulation is decrypted. + * + * @return the algorithm parameter spec to be used with the private key. + */ + public AlgorithmParameterSpec getParameterSpec() + { + return parameterSpec; + } + + /** + * Return the AlgorithmIdentifier for the KDF to do key derivation after extracting the secret. + * + * @return the AlgorithmIdentifier for the SecretKeyFactory's KDF. + */ + public AlgorithmIdentifier getKdfAlgorithm() + { + return kdfAlgorithm; + } + + /** + * Return the otherInfo data for initialising the KDF. + * + * @return the otherInfo data. + */ + public byte[] getOtherInfo() + { + return Arrays.clone(otherInfo); + } +} diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/spec/MQVParameterSpec.java b/bcprov/src/main/java/org/bouncycastle/jcajce/spec/MQVParameterSpec.java new file mode 100644 index 00000000..907abfb4 --- /dev/null +++ b/bcprov/src/main/java/org/bouncycastle/jcajce/spec/MQVParameterSpec.java @@ -0,0 +1,70 @@ +package org.bouncycastle.jcajce.spec; + +import java.security.KeyPair; +import java.security.PrivateKey; +import java.security.PublicKey; +import java.security.spec.AlgorithmParameterSpec; + +import org.bouncycastle.util.Arrays; + +public class MQVParameterSpec + implements AlgorithmParameterSpec +{ + private final PublicKey ephemeralPublicKey; + private final PrivateKey ephemeralPrivateKey; + private final PublicKey otherPartyEphemeralKey; + private final byte[] userKeyingMaterial; + + public MQVParameterSpec(PublicKey ephemeralPublicKey, PrivateKey ephemeralPrivateKey, PublicKey otherPartyEphemeralKey, byte[] userKeyingMaterial) + { + this.ephemeralPublicKey = ephemeralPublicKey; + this.ephemeralPrivateKey = ephemeralPrivateKey; + this.otherPartyEphemeralKey = otherPartyEphemeralKey; + this.userKeyingMaterial = Arrays.clone(userKeyingMaterial); + } + + public MQVParameterSpec(PublicKey ephemeralPublicKey, PrivateKey ephemeralPrivateKey, PublicKey otherPartyEphemeralKey) + { + this(ephemeralPublicKey, ephemeralPrivateKey, otherPartyEphemeralKey, null); + } + + public MQVParameterSpec(KeyPair ephemeralKeyPair, PublicKey otherPartyEphemeralKey, byte[] userKeyingMaterial) + { + this(ephemeralKeyPair.getPublic(), ephemeralKeyPair.getPrivate(), otherPartyEphemeralKey, userKeyingMaterial); + } + + public MQVParameterSpec(PrivateKey ephemeralPrivateKey, PublicKey otherPartyEphemeralKey, byte[] userKeyingMaterial) + { + this(null, ephemeralPrivateKey, otherPartyEphemeralKey, userKeyingMaterial); + } + + public MQVParameterSpec(KeyPair ephemeralKeyPair, PublicKey otherPartyEphemeralKey) + { + this(ephemeralKeyPair.getPublic(), ephemeralKeyPair.getPrivate(), otherPartyEphemeralKey, null); + } + + public MQVParameterSpec(PrivateKey ephemeralPrivateKey, PublicKey otherPartyEphemeralKey) + { + this(null, ephemeralPrivateKey, otherPartyEphemeralKey, null); + } + + public PrivateKey getEphemeralPrivateKey() + { + return ephemeralPrivateKey; + } + + public PublicKey getEphemeralPublicKey() + { + return ephemeralPublicKey; + } + + public PublicKey getOtherPartyEphemeralKey() + { + return otherPartyEphemeralKey; + } + + public byte[] getUserKeyingMaterial() + { + return Arrays.clone(userKeyingMaterial); + } +} diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/spec/UserKeyingMaterialSpec.java b/bcprov/src/main/java/org/bouncycastle/jcajce/spec/UserKeyingMaterialSpec.java new file mode 100644 index 00000000..d8135310 --- /dev/null +++ b/bcprov/src/main/java/org/bouncycastle/jcajce/spec/UserKeyingMaterialSpec.java @@ -0,0 +1,21 @@ +package org.bouncycastle.jcajce.spec; + +import java.security.spec.AlgorithmParameterSpec; + +import org.bouncycastle.util.Arrays; + +public class UserKeyingMaterialSpec + implements AlgorithmParameterSpec +{ + private final byte[] userKeyingMaterial; + + public UserKeyingMaterialSpec(byte[] userKeyingMaterial) + { + this.userKeyingMaterial = Arrays.clone(userKeyingMaterial); + } + + public byte[] getUserKeyingMaterial() + { + return Arrays.clone(userKeyingMaterial); + } +} diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/util/AlgorithmParametersUtils.java b/bcprov/src/main/java/org/bouncycastle/jcajce/util/AlgorithmParametersUtils.java new file mode 100644 index 00000000..4a1a92a5 --- /dev/null +++ b/bcprov/src/main/java/org/bouncycastle/jcajce/util/AlgorithmParametersUtils.java @@ -0,0 +1,68 @@ +/***************************************************************/ +/****** DO NOT EDIT THIS CLASS bc-java SOURCE FILE ******/ +/***************************************************************/ +package org.bouncycastle.jcajce.util; + +import java.io.IOException; +import java.security.AlgorithmParameters; + +import org.bouncycastle.asn1.ASN1Encodable; +import org.bouncycastle.asn1.ASN1Primitive; + +/** + * General JCA/JCE utility methods. + */ +public class AlgorithmParametersUtils +{ + + + private AlgorithmParametersUtils() + { + + } + + /** + * Extract an ASN.1 encodable from an AlgorithmParameters object. + * + * @param params the object to get the encoding used to create the return value. + * @return an ASN.1 object representing the primitives making up the params parameter. + * @throws IOException if an encoding cannot be extracted. + */ + public static ASN1Encodable extractParameters(AlgorithmParameters params) + throws IOException + { + // we try ASN.1 explicitly first just in case and then role back to the default. + ASN1Encodable asn1Params; + try + { + asn1Params = ASN1Primitive.fromByteArray(params.getEncoded("ASN.1")); + } + catch (Exception ex) + { + asn1Params = ASN1Primitive.fromByteArray(params.getEncoded()); + } + + return asn1Params; + } + + /** + * Load an AlgorithmParameters object with the passed in ASN.1 encodable - if possible. + * + * @param params the AlgorithmParameters object to be initialised. + * @param sParams the ASN.1 encodable to initialise params with. + * @throws IOException if the parameters cannot be initialised. + */ + public static void loadParameters(AlgorithmParameters params, ASN1Encodable sParams) + throws IOException + { + // we try ASN.1 explicitly first just in case and then role back to the default. + try + { + params.init(sParams.toASN1Primitive().getEncoded(), "ASN.1"); + } + catch (Exception ex) + { + params.init(sParams.toASN1Primitive().getEncoded()); + } + } +} diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/util/MessageDigestUtils.java b/bcprov/src/main/java/org/bouncycastle/jcajce/util/MessageDigestUtils.java new file mode 100644 index 00000000..1bf8b31b --- /dev/null +++ b/bcprov/src/main/java/org/bouncycastle/jcajce/util/MessageDigestUtils.java @@ -0,0 +1,55 @@ +package org.bouncycastle.jcajce.util; + +import java.util.HashMap; +import java.util.Map; + +import org.bouncycastle.asn1.ASN1ObjectIdentifier; +import org.bouncycastle.asn1.cryptopro.CryptoProObjectIdentifiers; +import org.bouncycastle.asn1.gnu.GNUObjectIdentifiers; +import org.bouncycastle.asn1.iso.ISOIECObjectIdentifiers; +import org.bouncycastle.asn1.nist.NISTObjectIdentifiers; +import org.bouncycastle.asn1.oiw.OIWObjectIdentifiers; +import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers; +import org.bouncycastle.asn1.teletrust.TeleTrusTObjectIdentifiers; + +public class MessageDigestUtils +{ + private static Map<ASN1ObjectIdentifier, String> digestOidMap = new HashMap<ASN1ObjectIdentifier, String>(); + + static + { + digestOidMap.put(PKCSObjectIdentifiers.md2, "MD2"); + digestOidMap.put(PKCSObjectIdentifiers.md4, "MD4"); + digestOidMap.put(PKCSObjectIdentifiers.md5, "MD5"); + digestOidMap.put(OIWObjectIdentifiers.idSHA1, "SHA-1"); + digestOidMap.put(NISTObjectIdentifiers.id_sha224, "SHA-224"); + digestOidMap.put(NISTObjectIdentifiers.id_sha256, "SHA-256"); + digestOidMap.put(NISTObjectIdentifiers.id_sha384, "SHA-384"); + digestOidMap.put(NISTObjectIdentifiers.id_sha512, "SHA-512"); + digestOidMap.put(TeleTrusTObjectIdentifiers.ripemd128, "RIPEMD-128"); + digestOidMap.put(TeleTrusTObjectIdentifiers.ripemd160, "RIPEMD-160"); + digestOidMap.put(TeleTrusTObjectIdentifiers.ripemd256, "RIPEMD-128"); + digestOidMap.put(ISOIECObjectIdentifiers.ripemd128, "RIPEMD-128"); + digestOidMap.put(ISOIECObjectIdentifiers.ripemd160, "RIPEMD-160"); + digestOidMap.put(CryptoProObjectIdentifiers.gostR3411, "GOST3411"); + digestOidMap.put(GNUObjectIdentifiers.Tiger_192, "Tiger"); + digestOidMap.put(ISOIECObjectIdentifiers.whirlpool, "Whirlpool"); + } + + /** + * Attempt to find a standard JCA name for the digest represented by the passed in OID. + * + * @param digestAlgOID the OID of the digest algorithm of interest. + * @return a string representing the standard name - the OID as a string if none available. + */ + public static String getDigestName(ASN1ObjectIdentifier digestAlgOID) + { + String name = (String)digestOidMap.get(digestAlgOID); // for pre 1.5 JDK + if (name != null) + { + return name; + } + + return digestAlgOID.getId(); + } +} |