diff --git a/crypto/src/asn1/Asn1Object.cs b/crypto/src/asn1/Asn1Object.cs
index a86fdbb4a..4faa81ac8 100644
--- a/crypto/src/asn1/Asn1Object.cs
+++ b/crypto/src/asn1/Asn1Object.cs
@@ -6,11 +6,13 @@ namespace Org.BouncyCastle.Asn1
public abstract class Asn1Object
: Asn1Encodable
{
- /// <summary>Create a base ASN.1 object from a byte array.</summary>
- /// <param name="data">The byte array to parse.</param>
- /// <returns>The base ASN.1 object represented by the byte array.</returns>
- /// <exception cref="IOException">If there is a problem parsing the data.</exception>
- public static Asn1Object FromByteArray(
+ /// <summary>Create a base ASN.1 object from a byte array.</summary>
+ /// <param name="data">The byte array to parse.</param>
+ /// <returns>The base ASN.1 object represented by the byte array.</returns>
+ /// <exception cref="IOException">
+ /// If there is a problem parsing the data, or parsing an object did not exhaust the available data.
+ /// </exception>
+ public static Asn1Object FromByteArray(
byte[] data)
{
try
diff --git a/crypto/src/asn1/crmf/CertReqMsg.cs b/crypto/src/asn1/crmf/CertReqMsg.cs
index 20fd4179a..03ce32d99 100644
--- a/crypto/src/asn1/crmf/CertReqMsg.cs
+++ b/crypto/src/asn1/crmf/CertReqMsg.cs
@@ -39,6 +39,13 @@ namespace Org.BouncyCastle.Asn1.Crmf
return null;
}
+ public static CertReqMsg GetInstance(
+ Asn1TaggedObject obj,
+ bool isExplicit)
+ {
+ return GetInstance(Asn1Sequence.GetInstance(obj, isExplicit));
+ }
+
/**
* Creates a new CertReqMsg.
* @param certReq CertRequest
diff --git a/crypto/src/asn1/gm/GMNamedCurves.cs b/crypto/src/asn1/gm/GMNamedCurves.cs
new file mode 100644
index 000000000..e2ec6d854
--- /dev/null
+++ b/crypto/src/asn1/gm/GMNamedCurves.cs
@@ -0,0 +1,157 @@
+using System;
+using System.Collections;
+
+using Org.BouncyCastle.Asn1.X9;
+using Org.BouncyCastle.Math;
+using Org.BouncyCastle.Math.EC;
+using Org.BouncyCastle.Math.EC.Endo;
+using Org.BouncyCastle.Utilities;
+using Org.BouncyCastle.Utilities.Collections;
+using Org.BouncyCastle.Utilities.Encoders;
+
+namespace Org.BouncyCastle.Asn1.GM
+{
+ public sealed class GMNamedCurves
+ {
+ private GMNamedCurves()
+ {
+ }
+
+ private static ECCurve ConfigureCurve(ECCurve curve)
+ {
+ return curve;
+ }
+
+ private static BigInteger FromHex(string hex)
+ {
+ return new BigInteger(1, Hex.Decode(hex));
+ }
+
+ /*
+ * sm2p256v1
+ */
+ internal class SM2P256V1Holder
+ : X9ECParametersHolder
+ {
+ private SM2P256V1Holder() {}
+
+ internal static readonly X9ECParametersHolder Instance = new SM2P256V1Holder();
+
+ protected override X9ECParameters CreateParameters()
+ {
+ BigInteger p = FromHex("FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000FFFFFFFFFFFFFFFF");
+ BigInteger a = FromHex("FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000FFFFFFFFFFFFFFFC");
+ BigInteger b = FromHex("28E9FA9E9D9F5E344D5A9E4BCF6509A7F39789F515AB8F92DDBCBD414D940E93");
+ byte[] S = null;
+ BigInteger n = FromHex("FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFF7203DF6B21C6052B53BBF40939D54123");
+ BigInteger h = BigInteger.One;
+
+ ECCurve curve = ConfigureCurve(new FpCurve(p, a, b, n, h));
+ X9ECPoint G = new X9ECPoint(curve, Hex.Decode("04"
+ + "32C4AE2C1F1981195F9904466A39C9948FE30BBFF2660BE1715A4589334C74C7"
+ + "BC3736A2F4F6779C59BDCEE36B692153D0A9877CC62A474002DF32E52139F0A0"));
+
+ return new X9ECParameters(curve, G, n, h, S);
+ }
+ }
+
+ /*
+ * wapip192v1
+ */
+ internal class WapiP192V1Holder
+ : X9ECParametersHolder
+ {
+ private WapiP192V1Holder() { }
+
+ internal static readonly X9ECParametersHolder Instance = new WapiP192V1Holder();
+
+ protected override X9ECParameters CreateParameters()
+ {
+ BigInteger p = FromHex("BDB6F4FE3E8B1D9E0DA8C0D46F4C318CEFE4AFE3B6B8551F");
+ BigInteger a = FromHex("BB8E5E8FBC115E139FE6A814FE48AAA6F0ADA1AA5DF91985");
+ BigInteger b = FromHex("1854BEBDC31B21B7AEFC80AB0ECD10D5B1B3308E6DBF11C1");
+ byte[] S = null;
+ BigInteger n = FromHex("BDB6F4FE3E8B1D9E0DA8C0D40FC962195DFAE76F56564677");
+ BigInteger h = BigInteger.One;
+
+ ECCurve curve = ConfigureCurve(new FpCurve(p, a, b, n, h));
+ X9ECPoint G = new X9ECPoint(curve, Hex.Decode("04"
+ + "4AD5F7048DE709AD51236DE6" + "5E4D4B482C836DC6E4106640"
+ + "02BB3A02D4AAADACAE24817A" + "4CA3A1B014B5270432DB27D2"));
+
+ return new X9ECParameters(curve, G, n, h, S);
+ }
+ }
+
+
+ private static readonly IDictionary objIds = Platform.CreateHashtable();
+ private static readonly IDictionary curves = Platform.CreateHashtable();
+ private static readonly IDictionary names = Platform.CreateHashtable();
+
+ private static void DefineCurve(
+ string name,
+ DerObjectIdentifier oid,
+ X9ECParametersHolder holder)
+ {
+ objIds.Add(Platform.ToUpperInvariant(name), oid);
+ names.Add(oid, name);
+ curves.Add(oid, holder);
+ }
+
+ static GMNamedCurves()
+ {
+ DefineCurve("wapip192v1", GMObjectIdentifiers.wapip192v1, WapiP192V1Holder.Instance);
+ DefineCurve("sm2p256v1", GMObjectIdentifiers.sm2p256v1, SM2P256V1Holder.Instance);
+ }
+
+ public static X9ECParameters GetByName(
+ string name)
+ {
+ DerObjectIdentifier oid = GetOid(name);
+ return oid == null ? null : GetByOid(oid);
+ }
+
+ /**
+ * return the X9ECParameters object for the named curve represented by
+ * the passed in object identifier. Null if the curve isn't present.
+ *
+ * @param oid an object identifier representing a named curve, if present.
+ */
+ public static X9ECParameters GetByOid(
+ DerObjectIdentifier oid)
+ {
+ X9ECParametersHolder holder = (X9ECParametersHolder)curves[oid];
+ return holder == null ? null : holder.Parameters;
+ }
+
+ /**
+ * return the object identifier signified by the passed in name. Null
+ * if there is no object identifier associated with name.
+ *
+ * @return the object identifier associated with name, if present.
+ */
+ public static DerObjectIdentifier GetOid(
+ string name)
+ {
+ return (DerObjectIdentifier)objIds[Platform.ToUpperInvariant(name)];
+ }
+
+ /**
+ * return the named curve name represented by the given object identifier.
+ */
+ public static string GetName(
+ DerObjectIdentifier oid)
+ {
+ return (string)names[oid];
+ }
+
+ /**
+ * returns an enumeration containing the name strings for curves
+ * contained in this structure.
+ */
+ public static IEnumerable Names
+ {
+ get { return new EnumerableProxy(names.Values); }
+ }
+ }
+}
diff --git a/crypto/src/asn1/gm/GMObjectIdentifiers.cs b/crypto/src/asn1/gm/GMObjectIdentifiers.cs
new file mode 100644
index 000000000..edb3a41c5
--- /dev/null
+++ b/crypto/src/asn1/gm/GMObjectIdentifiers.cs
@@ -0,0 +1,85 @@
+using System;
+
+namespace Org.BouncyCastle.Asn1.GM
+{
+ public abstract class GMObjectIdentifiers
+ {
+ public static readonly DerObjectIdentifier sm_scheme = new DerObjectIdentifier("1.2.156.10197.1");
+
+ public static readonly DerObjectIdentifier sm6_ecb = sm_scheme.Branch("101.1");
+ public static readonly DerObjectIdentifier sm6_cbc = sm_scheme.Branch("101.2");
+ public static readonly DerObjectIdentifier sm6_ofb128 = sm_scheme.Branch("101.3");
+ public static readonly DerObjectIdentifier sm6_cfb128 = sm_scheme.Branch("101.4");
+
+ public static readonly DerObjectIdentifier sm1_ecb = sm_scheme.Branch("102.1");
+ public static readonly DerObjectIdentifier sm1_cbc = sm_scheme.Branch("102.2");
+ public static readonly DerObjectIdentifier sm1_ofb128 = sm_scheme.Branch("102.3");
+ public static readonly DerObjectIdentifier sm1_cfb128 = sm_scheme.Branch("102.4");
+ public static readonly DerObjectIdentifier sm1_cfb1 = sm_scheme.Branch("102.5");
+ public static readonly DerObjectIdentifier sm1_cfb8 = sm_scheme.Branch("102.6");
+
+ public static readonly DerObjectIdentifier ssf33_ecb = sm_scheme.Branch("103.1");
+ public static readonly DerObjectIdentifier ssf33_cbc = sm_scheme.Branch("103.2");
+ public static readonly DerObjectIdentifier ssf33_ofb128 = sm_scheme.Branch("103.3");
+ public static readonly DerObjectIdentifier ssf33_cfb128 = sm_scheme.Branch("103.4");
+ public static readonly DerObjectIdentifier ssf33_cfb1 = sm_scheme.Branch("103.5");
+ public static readonly DerObjectIdentifier ssf33_cfb8 = sm_scheme.Branch("103.6");
+
+ public static readonly DerObjectIdentifier sms4_ecb = sm_scheme.Branch("104.1");
+ public static readonly DerObjectIdentifier sms4_cbc = sm_scheme.Branch("104.2");
+ public static readonly DerObjectIdentifier sms4_ofb128 = sm_scheme.Branch("104.3");
+ public static readonly DerObjectIdentifier sms4_cfb128 = sm_scheme.Branch("104.4");
+ public static readonly DerObjectIdentifier sms4_cfb1 = sm_scheme.Branch("104.5");
+ public static readonly DerObjectIdentifier sms4_cfb8 = sm_scheme.Branch("104.6");
+ public static readonly DerObjectIdentifier sms4_ctr = sm_scheme.Branch("104.7");
+ public static readonly DerObjectIdentifier sms4_gcm = sm_scheme.Branch("104.8");
+ public static readonly DerObjectIdentifier sms4_ccm = sm_scheme.Branch("104.9");
+ public static readonly DerObjectIdentifier sms4_xts = sm_scheme.Branch("104.10");
+ public static readonly DerObjectIdentifier sms4_wrap = sm_scheme.Branch("104.11");
+ public static readonly DerObjectIdentifier sms4_wrap_pad = sm_scheme.Branch("104.12");
+ public static readonly DerObjectIdentifier sms4_ocb = sm_scheme.Branch("104.100");
+
+ public static readonly DerObjectIdentifier sm5 = sm_scheme.Branch("201");
+
+ public static readonly DerObjectIdentifier sm2p256v1 = sm_scheme.Branch("301");
+ public static readonly DerObjectIdentifier sm2sign = sm_scheme.Branch("301.1");
+ public static readonly DerObjectIdentifier sm2exchange = sm_scheme.Branch("301.2");
+ public static readonly DerObjectIdentifier sm2encrypt = sm_scheme.Branch("301.3");
+
+ public static readonly DerObjectIdentifier wapip192v1 = sm_scheme.Branch("301.101");
+
+ public static readonly DerObjectIdentifier sm2encrypt_recommendedParameters = sm2encrypt.Branch("1");
+ public static readonly DerObjectIdentifier sm2encrypt_specifiedParameters = sm2encrypt.Branch("2");
+ public static readonly DerObjectIdentifier sm2encrypt_with_sm3 = sm2encrypt.Branch("2.1");
+ public static readonly DerObjectIdentifier sm2encrypt_with_sha1 = sm2encrypt.Branch("2.2");
+ public static readonly DerObjectIdentifier sm2encrypt_with_sha224 = sm2encrypt.Branch("2.3");
+ public static readonly DerObjectIdentifier sm2encrypt_with_sha256 = sm2encrypt.Branch("2.4");
+ public static readonly DerObjectIdentifier sm2encrypt_with_sha384 = sm2encrypt.Branch("2.5");
+ public static readonly DerObjectIdentifier sm2encrypt_with_sha512 = sm2encrypt.Branch("2.6");
+ public static readonly DerObjectIdentifier sm2encrypt_with_rmd160 = sm2encrypt.Branch("2.7");
+ public static readonly DerObjectIdentifier sm2encrypt_with_whirlpool = sm2encrypt.Branch("2.8");
+ public static readonly DerObjectIdentifier sm2encrypt_with_blake2b512 = sm2encrypt.Branch("2.9");
+ public static readonly DerObjectIdentifier sm2encrypt_with_blake2s256 = sm2encrypt.Branch("2.10");
+ public static readonly DerObjectIdentifier sm2encrypt_with_md5 = sm2encrypt.Branch("2.11");
+
+ public static readonly DerObjectIdentifier id_sm9PublicKey = sm_scheme.Branch("302");
+ public static readonly DerObjectIdentifier sm9sign = sm_scheme.Branch("302.1");
+ public static readonly DerObjectIdentifier sm9keyagreement = sm_scheme.Branch("302.2");
+ public static readonly DerObjectIdentifier sm9encrypt = sm_scheme.Branch("302.3");
+
+ public static readonly DerObjectIdentifier sm3 = sm_scheme.Branch("401");
+
+ public static readonly DerObjectIdentifier hmac_sm3 = sm3.Branch("2");
+
+ public static readonly DerObjectIdentifier sm2sign_with_sm3 = sm_scheme.Branch("501");
+ public static readonly DerObjectIdentifier sm2sign_with_sha1 = sm_scheme.Branch("502");
+ public static readonly DerObjectIdentifier sm2sign_with_sha256 = sm_scheme.Branch("503");
+ public static readonly DerObjectIdentifier sm2sign_with_sha512 = sm_scheme.Branch("504");
+ public static readonly DerObjectIdentifier sm2sign_with_sha224 = sm_scheme.Branch("505");
+ public static readonly DerObjectIdentifier sm2sign_with_sha384 = sm_scheme.Branch("506");
+ public static readonly DerObjectIdentifier sm2sign_with_rmd160 = sm_scheme.Branch("507");
+ public static readonly DerObjectIdentifier sm2sign_with_whirlpool = sm_scheme.Branch("520");
+ public static readonly DerObjectIdentifier sm2sign_with_blake2b512 = sm_scheme.Branch("521");
+ public static readonly DerObjectIdentifier sm2sign_with_blake2s256 = sm_scheme.Branch("522");
+ }
+}
\ No newline at end of file
diff --git a/crypto/src/asn1/gnu/GNUObjectIdentifiers.cs b/crypto/src/asn1/gnu/GNUObjectIdentifiers.cs
index 9311a3ac1..b322ef233 100644
--- a/crypto/src/asn1/gnu/GNUObjectIdentifiers.cs
+++ b/crypto/src/asn1/gnu/GNUObjectIdentifiers.cs
@@ -27,5 +27,10 @@ namespace Org.BouncyCastle.Asn1.Gnu
public static readonly DerObjectIdentifier Serpent256Cfb = new DerObjectIdentifier("1.3.6.1.4.1.11591.13.2.44"); // Serpent-256-CFB
public static readonly DerObjectIdentifier Crc = new DerObjectIdentifier("1.3.6.1.4.1.11591.14"); // CRC algorithms
public static readonly DerObjectIdentifier Crc32 = new DerObjectIdentifier("1.3.6.1.4.1.11591.14.1"); // CRC 32
+
+ /** 1.3.6.1.4.1.11591.15 - ellipticCurve */
+ public static readonly DerObjectIdentifier EllipticCurve = new DerObjectIdentifier("1.3.6.1.4.1.11591.15");
+
+ public static readonly DerObjectIdentifier Ed25519 = EllipticCurve.Branch("1");
}
}
diff --git a/crypto/src/asn1/pkcs/CertificationRequest.cs b/crypto/src/asn1/pkcs/CertificationRequest.cs
index 35bdd56eb..98caa2268 100644
--- a/crypto/src/asn1/pkcs/CertificationRequest.cs
+++ b/crypto/src/asn1/pkcs/CertificationRequest.cs
@@ -47,7 +47,8 @@ namespace Org.BouncyCastle.Asn1.Pkcs
this.sigBits = signature;
}
- public CertificationRequest(
+ [Obsolete("Use 'GetInstance' instead")]
+ public CertificationRequest(
Asn1Sequence seq)
{
if (seq.Count != 3)
diff --git a/crypto/src/asn1/pkcs/CertificationRequestInfo.cs b/crypto/src/asn1/pkcs/CertificationRequestInfo.cs
index d57753235..6d980131e 100644
--- a/crypto/src/asn1/pkcs/CertificationRequestInfo.cs
+++ b/crypto/src/asn1/pkcs/CertificationRequestInfo.cs
@@ -1,7 +1,6 @@
using System;
using Org.BouncyCastle.Asn1.X509;
-using Org.BouncyCastle.Utilities;
namespace Org.BouncyCastle.Asn1.Pkcs
{
@@ -31,20 +30,13 @@ namespace Org.BouncyCastle.Asn1.Pkcs
internal SubjectPublicKeyInfo subjectPKInfo;
internal Asn1Set attributes;
- public static CertificationRequestInfo GetInstance(
- object obj)
+ public static CertificationRequestInfo GetInstance(object obj)
{
if (obj is CertificationRequestInfo)
- {
- return (CertificationRequestInfo) obj;
- }
-
- if (obj is Asn1Sequence)
- {
- return new CertificationRequestInfo((Asn1Sequence) obj);
- }
-
- throw new ArgumentException("Unknown object in factory: " + Platform.GetTypeName(obj), "obj");
+ return (CertificationRequestInfo)obj;
+ if (obj != null)
+ return new CertificationRequestInfo(Asn1Sequence.GetInstance(obj));
+ return null;
}
public CertificationRequestInfo(
@@ -56,7 +48,9 @@ namespace Org.BouncyCastle.Asn1.Pkcs
this.subjectPKInfo = pkInfo;
this.attributes = attributes;
- if (subject == null || version == null || subjectPKInfo == null)
+ ValidateAttributes(attributes);
+
+ if (subject == null || version == null || subjectPKInfo == null)
{
throw new ArgumentException(
"Not all mandatory fields set in CertificationRequestInfo generator.");
@@ -81,7 +75,9 @@ namespace Org.BouncyCastle.Asn1.Pkcs
attributes = Asn1Set.GetInstance(tagobj, false);
}
- if (subject == null || version == null || subjectPKInfo == null)
+ ValidateAttributes(attributes);
+
+ if (subject == null || version == null || subjectPKInfo == null)
{
throw new ArgumentException(
"Not all mandatory fields set in CertificationRequestInfo generator.");
@@ -120,5 +116,22 @@ namespace Org.BouncyCastle.Asn1.Pkcs
return new DerSequence(v);
}
+
+ private static void ValidateAttributes(Asn1Set attributes)
+ {
+ if (attributes == null)
+ return;
+
+ foreach (Asn1Encodable ae in attributes)
+ {
+ Asn1Object obj = ae.ToAsn1Object();
+ AttributePkcs attr = AttributePkcs.GetInstance(obj);
+ if (attr.AttrType.Equals(PkcsObjectIdentifiers.Pkcs9AtChallengePassword))
+ {
+ if (attr.AttrValues.Count != 1)
+ throw new ArgumentException("challengePassword attribute must have one value");
+ }
+ }
+ }
}
}
diff --git a/crypto/src/asn1/pkcs/PKCSObjectIdentifiers.cs b/crypto/src/asn1/pkcs/PKCSObjectIdentifiers.cs
index 042911a06..1a9a03e9f 100644
--- a/crypto/src/asn1/pkcs/PKCSObjectIdentifiers.cs
+++ b/crypto/src/asn1/pkcs/PKCSObjectIdentifiers.cs
@@ -9,23 +9,28 @@ namespace Org.BouncyCastle.Asn1.Pkcs
// iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) 1 }
//
public const string Pkcs1 = "1.2.840.113549.1.1";
+ internal static readonly DerObjectIdentifier Pkcs1Oid = new DerObjectIdentifier(Pkcs1);
+
+ public static readonly DerObjectIdentifier RsaEncryption = Pkcs1Oid.Branch("1");
+ public static readonly DerObjectIdentifier MD2WithRsaEncryption = Pkcs1Oid.Branch("2");
+ public static readonly DerObjectIdentifier MD4WithRsaEncryption = Pkcs1Oid.Branch("3");
+ public static readonly DerObjectIdentifier MD5WithRsaEncryption = Pkcs1Oid.Branch("4");
+ public static readonly DerObjectIdentifier Sha1WithRsaEncryption = Pkcs1Oid.Branch("5");
+ public static readonly DerObjectIdentifier SrsaOaepEncryptionSet = Pkcs1Oid.Branch("6");
+ public static readonly DerObjectIdentifier IdRsaesOaep = Pkcs1Oid.Branch("7");
+ public static readonly DerObjectIdentifier IdMgf1 = Pkcs1Oid.Branch("8");
+ public static readonly DerObjectIdentifier IdPSpecified = Pkcs1Oid.Branch("9");
+ public static readonly DerObjectIdentifier IdRsassaPss = Pkcs1Oid.Branch("10");
+ public static readonly DerObjectIdentifier Sha256WithRsaEncryption = Pkcs1Oid.Branch("11");
+ public static readonly DerObjectIdentifier Sha384WithRsaEncryption = Pkcs1Oid.Branch("12");
+ public static readonly DerObjectIdentifier Sha512WithRsaEncryption = Pkcs1Oid.Branch("13");
+ public static readonly DerObjectIdentifier Sha224WithRsaEncryption = Pkcs1Oid.Branch("14");
+ /** PKCS#1: 1.2.840.113549.1.1.15 */
+ public static readonly DerObjectIdentifier Sha512_224WithRSAEncryption = Pkcs1Oid.Branch("15");
+ /** PKCS#1: 1.2.840.113549.1.1.16 */
+ public static readonly DerObjectIdentifier Sha512_256WithRSAEncryption = Pkcs1Oid.Branch("16");
- public static readonly DerObjectIdentifier RsaEncryption = new DerObjectIdentifier(Pkcs1 + ".1");
- public static readonly DerObjectIdentifier MD2WithRsaEncryption = new DerObjectIdentifier(Pkcs1 + ".2");
- public static readonly DerObjectIdentifier MD4WithRsaEncryption = new DerObjectIdentifier(Pkcs1 + ".3");
- public static readonly DerObjectIdentifier MD5WithRsaEncryption = new DerObjectIdentifier(Pkcs1 + ".4");
- public static readonly DerObjectIdentifier Sha1WithRsaEncryption = new DerObjectIdentifier(Pkcs1 + ".5");
- public static readonly DerObjectIdentifier SrsaOaepEncryptionSet = new DerObjectIdentifier(Pkcs1 + ".6");
- public static readonly DerObjectIdentifier IdRsaesOaep = new DerObjectIdentifier(Pkcs1 + ".7");
- public static readonly DerObjectIdentifier IdMgf1 = new DerObjectIdentifier(Pkcs1 + ".8");
- public static readonly DerObjectIdentifier IdPSpecified = new DerObjectIdentifier(Pkcs1 + ".9");
- public static readonly DerObjectIdentifier IdRsassaPss = new DerObjectIdentifier(Pkcs1 + ".10");
- public static readonly DerObjectIdentifier Sha256WithRsaEncryption = new DerObjectIdentifier(Pkcs1 + ".11");
- public static readonly DerObjectIdentifier Sha384WithRsaEncryption = new DerObjectIdentifier(Pkcs1 + ".12");
- public static readonly DerObjectIdentifier Sha512WithRsaEncryption = new DerObjectIdentifier(Pkcs1 + ".13");
- public static readonly DerObjectIdentifier Sha224WithRsaEncryption = new DerObjectIdentifier(Pkcs1 + ".14");
-
- //
+ //
// pkcs-3 OBJECT IDENTIFIER ::= {
// iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) 3 }
//
@@ -195,6 +200,7 @@ namespace Org.BouncyCastle.Asn1.Pkcs
// rsadsi(113549) pkcs(1) pkcs-9(9) smime(16) attributes(2)}
//
public const string IdAA = "1.2.840.113549.1.9.16.2";
+ public static readonly DerObjectIdentifier IdAAOid = new DerObjectIdentifier(IdAA);
public static readonly DerObjectIdentifier IdAAContentHint = new DerObjectIdentifier(IdAA + ".4"); // See RFC 2634
public static readonly DerObjectIdentifier IdAAMsgSigDigest = new DerObjectIdentifier(IdAA + ".5");
@@ -229,6 +235,20 @@ namespace Org.BouncyCastle.Asn1.Pkcs
public static readonly DerObjectIdentifier IdAAEtsCertCrlTimestamp = new DerObjectIdentifier(IdAA + ".26");
public static readonly DerObjectIdentifier IdAAEtsArchiveTimestamp = new DerObjectIdentifier(IdAA + ".27");
+ /** PKCS#9: 1.2.840.113549.1.9.16.6.2.37 - <a href="https://tools.ietf.org/html/rfc4108#section-2.2.5">RFC 4108</a> */
+ public static readonly DerObjectIdentifier IdAADecryptKeyID = IdAAOid.Branch("37");
+
+ /** PKCS#9: 1.2.840.113549.1.9.16.6.2.38 - <a href="https://tools.ietf.org/html/rfc4108#section-2.2.6">RFC 4108</a> */
+ public static readonly DerObjectIdentifier IdAAImplCryptoAlgs = IdAAOid.Branch("38");
+
+ /** PKCS#9: 1.2.840.113549.1.9.16.2.54 <a href="https://tools.ietf.org/html/rfc7030">RFC7030</a>*/
+ public static readonly DerObjectIdentifier IdAAAsymmDecryptKeyID = IdAAOid.Branch("54");
+
+ /** PKCS#9: 1.2.840.113549.1.9.16.2.43 <a href="https://tools.ietf.org/html/rfc7030">RFC7030</a>*/
+ public static readonly DerObjectIdentifier IdAAImplCompressAlgs = IdAAOid.Branch("43");
+ /** PKCS#9: 1.2.840.113549.1.9.16.2.40 <a href="https://tools.ietf.org/html/rfc7030">RFC7030</a>*/
+ public static readonly DerObjectIdentifier IdAACommunityIdentifiers = IdAAOid.Branch("40");
+
[Obsolete("Use 'IdAAEtsSigPolicyID' instead")]
public static readonly DerObjectIdentifier IdAASigPolicyID = IdAAEtsSigPolicyID;
[Obsolete("Use 'IdAAEtsCommitmentType' instead")]
diff --git a/crypto/src/asn1/x509/KeyPurposeId.cs b/crypto/src/asn1/x509/KeyPurposeId.cs
index 4b48a9b51..1a564b97a 100644
--- a/crypto/src/asn1/x509/KeyPurposeId.cs
+++ b/crypto/src/asn1/x509/KeyPurposeId.cs
@@ -32,5 +32,7 @@ namespace Org.BouncyCastle.Asn1.X509
// microsoft key purpose ids
//
public static readonly KeyPurposeID IdKPSmartCardLogon = new KeyPurposeID("1.3.6.1.4.1.311.20.2.2");
+
+ public static readonly KeyPurposeID IdKPMacAddress = new KeyPurposeID("1.3.6.1.1.1.1.22");
}
}
diff --git a/crypto/src/asn1/x509/X509Extensions.cs b/crypto/src/asn1/x509/X509Extensions.cs
index 2ef73f629..049d728bb 100644
--- a/crypto/src/asn1/x509/X509Extensions.cs
+++ b/crypto/src/asn1/x509/X509Extensions.cs
@@ -164,6 +164,11 @@ namespace Org.BouncyCastle.Asn1.X509
*/
public static readonly DerObjectIdentifier TargetInformation = new DerObjectIdentifier("2.5.29.55");
+ /**
+ * Expired Certificates on CRL extension
+ */
+ public static readonly DerObjectIdentifier ExpiredCertsOnCrl = new DerObjectIdentifier("2.5.29.60");
+
private readonly IDictionary extensions = Platform.CreateHashtable();
private readonly IList ordering;
diff --git a/crypto/src/asn1/x9/ECNamedCurveTable.cs b/crypto/src/asn1/x9/ECNamedCurveTable.cs
index 92d4393a8..317ef17b4 100644
--- a/crypto/src/asn1/x9/ECNamedCurveTable.cs
+++ b/crypto/src/asn1/x9/ECNamedCurveTable.cs
@@ -2,6 +2,7 @@
using System.Collections;
using Org.BouncyCastle.Asn1.Anssi;
+using Org.BouncyCastle.Asn1.GM;
using Org.BouncyCastle.Asn1.Nist;
using Org.BouncyCastle.Asn1.Sec;
using Org.BouncyCastle.Asn1.TeleTrust;
@@ -25,27 +26,26 @@ namespace Org.BouncyCastle.Asn1.X9
public static X9ECParameters GetByName(string name)
{
X9ECParameters ecP = X962NamedCurves.GetByName(name);
-
if (ecP == null)
{
ecP = SecNamedCurves.GetByName(name);
}
-
if (ecP == null)
{
ecP = NistNamedCurves.GetByName(name);
}
-
if (ecP == null)
{
ecP = TeleTrusTNamedCurves.GetByName(name);
}
-
if (ecP == null)
{
ecP = AnssiNamedCurves.GetByName(name);
}
-
+ if (ecP == null)
+ {
+ ecP = GMNamedCurves.GetByName(name);
+ }
return ecP;
}
@@ -68,6 +68,10 @@ namespace Org.BouncyCastle.Asn1.X9
{
name = AnssiNamedCurves.GetName(oid);
}
+ if (name == null)
+ {
+ name = GMNamedCurves.GetName(oid);
+ }
return name;
}
@@ -80,27 +84,26 @@ namespace Org.BouncyCastle.Asn1.X9
public static DerObjectIdentifier GetOid(string name)
{
DerObjectIdentifier oid = X962NamedCurves.GetOid(name);
-
if (oid == null)
{
oid = SecNamedCurves.GetOid(name);
}
-
if (oid == null)
{
oid = NistNamedCurves.GetOid(name);
}
-
if (oid == null)
{
oid = TeleTrusTNamedCurves.GetOid(name);
}
-
if (oid == null)
{
oid = AnssiNamedCurves.GetOid(name);
}
-
+ if (oid == null)
+ {
+ oid = GMNamedCurves.GetOid(name);
+ }
return oid;
}
@@ -114,7 +117,6 @@ namespace Org.BouncyCastle.Asn1.X9
public static X9ECParameters GetByOid(DerObjectIdentifier oid)
{
X9ECParameters ecP = X962NamedCurves.GetByOid(oid);
-
if (ecP == null)
{
ecP = SecNamedCurves.GetByOid(oid);
@@ -126,12 +128,14 @@ namespace Org.BouncyCastle.Asn1.X9
{
ecP = TeleTrusTNamedCurves.GetByOid(oid);
}
-
if (ecP == null)
{
ecP = AnssiNamedCurves.GetByOid(oid);
}
-
+ if (ecP == null)
+ {
+ ecP = GMNamedCurves.GetByOid(oid);
+ }
return ecP;
}
@@ -150,6 +154,7 @@ namespace Org.BouncyCastle.Asn1.X9
CollectionUtilities.AddRange(v, NistNamedCurves.Names);
CollectionUtilities.AddRange(v, TeleTrusTNamedCurves.Names);
CollectionUtilities.AddRange(v, AnssiNamedCurves.Names);
+ CollectionUtilities.AddRange(v, GMNamedCurves.Names);
return v;
}
}
diff --git a/crypto/src/bcpg/ArmoredOutputStream.cs b/crypto/src/bcpg/ArmoredOutputStream.cs
index 1f0e412d8..7a5066ec3 100644
--- a/crypto/src/bcpg/ArmoredOutputStream.cs
+++ b/crypto/src/bcpg/ArmoredOutputStream.cs
@@ -20,6 +20,8 @@ namespace Org.BouncyCastle.Bcpg
public class ArmoredOutputStream
: BaseOutputStream
{
+ public static readonly string HeaderVersion = "Version";
+
private static readonly byte[] encodingTable =
{
(byte)'A', (byte)'B', (byte)'C', (byte)'D', (byte)'E', (byte)'F', (byte)'G',
@@ -101,44 +103,58 @@ namespace Org.BouncyCastle.Bcpg
private static readonly string footerStart = "-----END PGP ";
private static readonly string footerTail = "-----";
- private static readonly string version = "BCPG C# v" + AssemblyInfo.Version;
+ private static readonly string Version = "BCPG C# v" + AssemblyInfo.Version;
private readonly IDictionary headers;
public ArmoredOutputStream(Stream outStream)
{
this.outStream = outStream;
- this.headers = Platform.CreateHashtable();
- this.headers["Version"] = version;
+ this.headers = Platform.CreateHashtable(1);
+ this.headers.Add(HeaderVersion, Version);
}
public ArmoredOutputStream(Stream outStream, IDictionary headers)
{
this.outStream = outStream;
this.headers = Platform.CreateHashtable(headers);
- this.headers["Version"] = version;
+ if (!this.headers.Contains(HeaderVersion))
+ {
+ this.headers.Add(HeaderVersion, Version);
+ }
}
/**
- * Set an additional header entry.
+ * Set an additional header entry. A null value will clear the entry for name.
*
* @param name the name of the header entry.
* @param v the value of the header entry.
*/
- public void SetHeader(
- string name,
- string v)
+ public void SetHeader(string name, string v)
{
- headers[name] = v;
+ if (v == null)
+ {
+ headers.Remove(name);
+ }
+ else
+ {
+ headers[name] = v;
+ }
}
/**
- * Reset the headers to only contain a Version string.
+ * Reset the headers to only contain a Version string (if one is present).
*/
public void ResetHeaders()
{
+ string version = (string)headers[HeaderVersion];
+
headers.Clear();
- headers["Version"] = version;
+
+ if (version != null)
+ {
+ headers[HeaderVersion] = Version;
+ }
}
/**
@@ -248,14 +264,17 @@ namespace Org.BouncyCastle.Bcpg
}
DoWrite(headerStart + type + headerTail + nl);
- WriteHeaderEntry("Version", (string) headers["Version"]);
+ if (headers.Contains(HeaderVersion))
+ {
+ WriteHeaderEntry(HeaderVersion, (string)headers[HeaderVersion]);
+ }
foreach (DictionaryEntry de in headers)
{
- string k = (string) de.Key;
- if (k != "Version")
+ string k = (string)de.Key;
+ if (k != HeaderVersion)
{
- string v = (string) de.Value;
+ string v = (string)de.Value;
WriteHeaderEntry(k, v);
}
}
diff --git a/crypto/src/crypto/agreement/DHAgreement.cs b/crypto/src/crypto/agreement/DHAgreement.cs
index d214caafe..e988c0d53 100644
--- a/crypto/src/crypto/agreement/DHAgreement.cs
+++ b/crypto/src/crypto/agreement/DHAgreement.cs
@@ -81,13 +81,19 @@ namespace Org.BouncyCastle.Crypto.Agreement
throw new ArgumentNullException("message");
if (!pub.Parameters.Equals(dhParams))
- {
throw new ArgumentException("Diffie-Hellman public key has wrong parameters.");
- }
- BigInteger p = dhParams.P;
+ BigInteger p = dhParams.P;
- return message.ModPow(key.X, p).Multiply(pub.Y.ModPow(privateValue, p)).Mod(p);
- }
- }
+ BigInteger peerY = pub.Y;
+ if (peerY == null || peerY.CompareTo(BigInteger.One) <= 0 || peerY.CompareTo(p.Subtract(BigInteger.One)) >= 0)
+ throw new ArgumentException("Diffie-Hellman public key is weak");
+
+ BigInteger result = peerY.ModPow(privateValue, p);
+ if (result.Equals(BigInteger.One))
+ throw new InvalidOperationException("Shared key can't be 1");
+
+ return message.ModPow(key.X, p).Multiply(result).Mod(p);
+ }
+ }
}
diff --git a/crypto/src/crypto/agreement/DHBasicAgreement.cs b/crypto/src/crypto/agreement/DHBasicAgreement.cs
index 75b5e9db5..6c3fe6595 100644
--- a/crypto/src/crypto/agreement/DHBasicAgreement.cs
+++ b/crypto/src/crypto/agreement/DHBasicAgreement.cs
@@ -54,11 +54,19 @@ namespace Org.BouncyCastle.Crypto.Agreement
DHPublicKeyParameters pub = (DHPublicKeyParameters)pubKey;
if (!pub.Parameters.Equals(dhParams))
- {
throw new ArgumentException("Diffie-Hellman public key has wrong parameters.");
- }
- return pub.Y.ModPow(key.X, dhParams.P);
+ BigInteger p = dhParams.P;
+
+ BigInteger peerY = pub.Y;
+ if (peerY == null || peerY.CompareTo(BigInteger.One) <= 0 || peerY.CompareTo(p.Subtract(BigInteger.One)) >= 0)
+ throw new ArgumentException("Diffie-Hellman public key is weak");
+
+ BigInteger result = peerY.ModPow(key.X, p);
+ if (result.Equals(BigInteger.One))
+ throw new InvalidOperationException("Shared key can't be 1");
+
+ return result;
}
}
}
diff --git a/crypto/src/crypto/agreement/DHStandardGroups.cs b/crypto/src/crypto/agreement/DHStandardGroups.cs
index 93b65af98..425a9784c 100644
--- a/crypto/src/crypto/agreement/DHStandardGroups.cs
+++ b/crypto/src/crypto/agreement/DHStandardGroups.cs
@@ -161,6 +161,11 @@ namespace Org.BouncyCastle.Crypto.Agreement
+ "909D0D2263F80A76A6A24C087A091F531DBF0A0169B6A28A" + "D662A4D18E73AFA32D779D5918D08BC8858F4DCEF97C2A24"
+ "855E6EEB22B3B2E5";
private static readonly string rfc5114_1024_160_q = "F518AA8781A8DF278ABA4E7D64B7CB9D49462353";
+
+ /// <remarks>
+ /// Existence of a "hidden SNFS" backdoor cannot be ruled out. see https://eprint.iacr.org/2016/961.pdf .
+ /// </remarks>
+ [Obsolete("Existence of a 'hidden SNFS' backdoor cannot be ruled out.")]
public static readonly DHParameters rfc5114_1024_160 = FromPGQ(rfc5114_1024_160_p, rfc5114_1024_160_g,
rfc5114_1024_160_q);
@@ -177,6 +182,11 @@ namespace Org.BouncyCastle.Crypto.Agreement
+ "10E183EDD19963DDD9E263E4770589EF6AA21E7F5F2FF381" + "B539CCE3409D13CD566AFBB48D6C019181E1BCFE94B30269"
+ "EDFE72FE9B6AA4BD7B5A0F1C71CFFF4C19C418E1F6EC0179" + "81BC087F2A7065B384B890D3191F2BFA";
private static readonly string rfc5114_2048_224_q = "801C0D34C58D93FE997177101F80535A4738CEBCBF389A99B36371EB";
+
+ /// <remarks>
+ /// Existence of a "hidden SNFS" backdoor cannot be ruled out. see https://eprint.iacr.org/2016/961.pdf .
+ /// </remarks>
+ [Obsolete("Existence of a 'hidden SNFS' backdoor cannot be ruled out.")]
public static readonly DHParameters rfc5114_2048_224 = FromPGQ(rfc5114_2048_224_p, rfc5114_2048_224_g,
rfc5114_2048_224_q);
@@ -194,6 +204,11 @@ namespace Org.BouncyCastle.Crypto.Agreement
+ "184B523D1DB246C32F63078490F00EF8D647D148D4795451" + "5E2327CFEF98C582664B4C0F6CC41659";
private static readonly string rfc5114_2048_256_q = "8CF83642A709A097B447997640129DA299B1A47D1EB3750B"
+ "A308B0FE64F5FBD3";
+
+ /// <remarks>
+ /// Existence of a "hidden SNFS" backdoor cannot be ruled out. see https://eprint.iacr.org/2016/961.pdf .
+ /// </remarks>
+ [Obsolete("Existence of a 'hidden SNFS' backdoor cannot be ruled out.")]
public static readonly DHParameters rfc5114_2048_256 = FromPGQ(rfc5114_2048_256_p, rfc5114_2048_256_g,
rfc5114_2048_256_q);
diff --git a/crypto/src/crypto/digests/DSTU7564Digest.cs b/crypto/src/crypto/digests/DSTU7564Digest.cs
new file mode 100644
index 000000000..9de41dd6b
--- /dev/null
+++ b/crypto/src/crypto/digests/DSTU7564Digest.cs
@@ -0,0 +1,562 @@
+using System;
+
+using Org.BouncyCastle.Crypto.Engines;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Crypto.Utilities;
+//using Org.BouncyCastle.Utilities;
+
+
+using Org.BouncyCastle.Utilities.Encoders;
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.Crypto.Digests
+{
+ /**
+ * implementation of Ukrainian DSTU 7564 hash function
+ */
+ public class Dstu7564Digest : IDigest, IMemoable
+ {
+ private const int ROWS = 8;
+ private const int REDUCTION_POLYNOMIAL = 0x011d;
+ private const int BITS_IN_BYTE = 8;
+
+
+ private const int NB_512 = 8; //Number of 8-byte words in state for <=256-bit hash code.
+ private const int NB_1024 = 16; //Number of 8-byte words in state for <=512-bit hash code.
+
+ private const int NR_512 = 10; //Number of rounds for 512-bit state.
+ private const int NR_1024 = 14; //Number of rounds for 1024-bit state.
+
+ private const int STATE_BYTE_SIZE_512 = ROWS * NB_512;
+ private const int STATE_BYTE_SIZE_1024 = ROWS * NB_1024;
+
+ private int hashSize;
+ private int blockSize;
+
+
+
+ private int columns;
+ private int rounds;
+
+
+ private byte[] padded_;
+
+ private byte[][] state_;
+
+ private ulong inputLength;
+ private int bufOff;
+ private byte[] buf;
+
+ public Dstu7564Digest(Dstu7564Digest digest)
+ {
+ copyIn(digest);
+ }
+
+ private void copyIn(Dstu7564Digest digest)
+ {
+ this.hashSize = digest.hashSize;
+ this.blockSize = digest.blockSize;
+
+ this.columns = digest.columns;
+ this.rounds = digest.rounds;
+
+ this.padded_ = Arrays.Clone(digest.padded_);
+ this.state_ = new byte[digest.state_.Length][];
+ for (int i = 0; i != this.state_.Length; i++)
+ {
+ this.state_[i] = Arrays.Clone(digest.state_[i]);
+ }
+
+ this.inputLength = digest.inputLength;
+ this.bufOff = digest.bufOff;
+ this.buf = Arrays.Clone(digest.buf);
+ }
+
+ public Dstu7564Digest(int hashSizeBits)
+ {
+ if (hashSizeBits == 256 || hashSizeBits == 384 || hashSizeBits == 512)
+ {
+ this.hashSize = hashSizeBits / 8;
+ }
+ else
+ {
+ throw new ArgumentException("Hash size is not recommended. Use 256 or 384 or 512 size");
+ }
+
+ if (hashSizeBits > 256)
+ {
+ this.blockSize = 1024 / 8;
+ this.columns = NB_1024;
+ this.rounds = NR_1024;
+ this.state_ = new byte[STATE_BYTE_SIZE_1024][];
+
+ }
+ else
+ {
+ this.blockSize = 512 / 8;
+ this.columns = NB_512;
+ this.rounds = NR_512;
+ this.state_ = new byte[STATE_BYTE_SIZE_512][];
+
+ }
+
+ //Console.WriteLine("length: " + state_.Length);
+
+ for (int i = 0; i < state_.Length; i++)
+ {
+ this.state_[i] = new byte[columns];
+ }
+
+ this.state_[0][0] = (byte)state_.Length;
+
+ this.hashSize = hashSizeBits / 8;
+
+ this.padded_ = null;
+ this.buf = new byte[blockSize];
+ }
+
+ public string AlgorithmName
+ {
+ get { return "DSTU7564"; }
+ }
+
+
+ public virtual void BlockUpdate(byte[] input, int inOff, int length)
+ {
+ while (bufOff != 0 && length > 0)
+ {
+ Update(input[inOff++]);
+ length--;
+ }
+
+ if (length > 0)
+ {
+ while (length > blockSize)
+ {
+ ProcessBlock(input, inOff);
+ inOff += blockSize;
+ inputLength += (ulong)blockSize;
+ length -= blockSize;
+ }
+
+ while (length > 0)
+ {
+ Update(input[inOff++]);
+ length--;
+ }
+ }
+ }
+
+ protected byte[] Pad(byte[] input, int inOff, int length)
+ {
+ //Console.WriteLine(length);
+
+ byte[] padded;
+ if (blockSize - length < 13) // terminator byte + 96 bits of length
+ {
+ padded = new byte[2 * blockSize];
+ }
+ else
+ {
+ padded = new byte[blockSize];
+ }
+
+
+ Array.Copy(input, inOff, padded, 0, length);
+ padded[length] = 0x80;
+ Pack.UInt64_To_LE(inputLength * 8, padded, padded.Length - 12);
+
+ return padded;
+ }
+
+ protected void ProcessBlock(byte[] input, int inOff)
+ {
+ byte[][] temp1 = new byte[STATE_BYTE_SIZE_1024][];
+ byte[][] temp2 = new byte[STATE_BYTE_SIZE_1024][];
+
+ for (int i = 0; i < state_.Length; i++)
+ {
+ temp1[i] = new byte[ROWS];
+ temp2[i] = new byte[ROWS];
+ }
+
+ for (int i = 0; i < ROWS; ++i)
+ {
+ for (int j = 0; j < columns; ++j)
+ {
+ //Console.WriteLine("row = {0}, column = {1}", i, j);
+
+ temp1[j][i] = (byte)(state_[j][i] ^ input[j * ROWS + i + inOff]);
+ temp2[j][i] = input[j * ROWS + i + inOff];
+
+ }
+
+ }
+
+ P(temp1);
+
+ Q(temp2);
+
+ for (int i = 0; i < ROWS; ++i)
+ {
+ for (int j = 0; j < columns; ++j)
+ {
+ state_[j][i] ^= (byte)(temp1[j][i] ^ temp2[j][i]);
+
+ }
+
+ }
+ }
+
+ public int DoFinal(byte[] output, int outOff)
+ {
+ padded_ = Pad(buf, 0, bufOff);
+
+ int paddedLen = padded_.Length;
+ int paddedOff = 0;
+
+ while (paddedLen != 0)
+ {
+ ProcessBlock(padded_, paddedOff);
+ paddedOff += blockSize;
+ paddedLen -= blockSize;
+ }
+
+
+ //Console.WriteLine(stateLine.Length);
+
+ byte[][] temp = new byte[STATE_BYTE_SIZE_1024][];
+ for (int i = 0; i < state_.Length; i++)
+ {
+ temp[i] = new byte[ROWS];
+ Array.Copy(state_[i], temp[i], ROWS);
+ }
+
+ P(temp);
+
+ for (int i = 0; i < ROWS; ++i)
+ {
+ for (int j = 0; j < columns; ++j)
+ {
+ state_[j][i] ^= temp[j][i];
+ //Console.Write("{0:x} ", state_[j][i]);
+ }
+ //Console.WriteLine();
+ }
+
+ byte[] stateLine = new byte[ROWS * columns];
+ int stateLineIndex = 0;
+ for (int j = 0; j < columns; ++j)
+ {
+ for (int i = 0; i < ROWS; ++i)
+ {
+
+ stateLine[stateLineIndex] = state_[j][i];
+ stateLineIndex++;
+
+ //Console.WriteLine("index = {0}, row = {1}, column = {2}", stateLineIndex, i, j);
+
+ }
+ }
+
+ //Console.WriteLine("final: " + Hex.ToHexString(stateLine));
+ //Console.WriteLine(stateLine.Length);
+
+ Array.Copy(stateLine, stateLine.Length - hashSize, output, outOff, hashSize);
+
+ Reset();
+
+ return hashSize;
+ }
+
+ public void Reset()
+ {
+ for (int bufferIndex = 0; bufferIndex < state_.Length; bufferIndex++)
+ {
+ state_[bufferIndex] = new byte[columns];
+ }
+
+ state_[0][0] = (byte)state_.Length;
+
+ inputLength = 0;
+ bufOff = 0;
+
+ Arrays.Fill(buf, (byte)0);
+
+ if (padded_ != null)
+ {
+ Arrays.Fill(padded_, (byte)0);
+ }
+ }
+
+ public int GetDigestSize()
+ {
+ return hashSize;
+ }
+
+ public int GetByteLength()
+ {
+ return blockSize;
+ }
+
+ public void Update(byte input)
+ {
+ buf[bufOff++] = input;
+ if (bufOff == blockSize)
+ {
+ ProcessBlock(buf, 0);
+ bufOff = 0;
+ }
+ inputLength++;
+ }
+
+ void SubBytes(byte[][] state)
+ {
+ int i, j;
+ for (i = 0; i < ROWS; ++i)
+ {
+ for (j = 0; j < columns; ++j)
+ {
+ state[j][i] = sBoxes[i % 4][state[j][i]];
+ }
+ }
+ }
+
+ void ShiftBytes(byte[][] state)
+ {
+ int i, j;
+ byte[] temp = new byte[NB_1024];
+ int shift = -1;
+ for (i = 0; i < ROWS; ++i)
+ {
+ if ((i == ROWS - 1) && (columns == NB_1024))
+ {
+ shift = 11;
+ }
+ else
+ {
+ ++shift;
+ }
+ for (j = 0; j < columns; ++j)
+ {
+ temp[(j + shift) % columns] = state[j][i];
+ }
+ for (j = 0; j < columns; ++j)
+ {
+ state[j][i] = temp[j];
+ }
+ }
+ }
+
+ byte MultiplyGF(byte x, byte y)
+ {
+ int i;
+ byte r = 0;
+ byte hbit = 0;
+ for (i = 0; i < BITS_IN_BYTE; ++i)
+ {
+ if ((y & 0x1) == 1)
+ {
+ r ^= x;
+ }
+
+ hbit = (byte)(x & 0x80);
+
+ x <<= 1;
+
+ if (hbit == 0x80)
+ {
+ x = (byte)((int)x ^ REDUCTION_POLYNOMIAL);
+ }
+
+ y >>= 1;
+ }
+ return r;
+ }
+
+ private void MixColumns(byte[][] state)
+ {
+ int i, row, col, b;
+ byte product;
+ byte[] result = new byte[ROWS];
+
+ for (col = 0; col < columns; ++col)
+ {
+ Array.Clear(result, 0, ROWS);
+ for (row = ROWS - 1; row >= 0; --row)
+ {
+ product = 0;
+ for (b = ROWS - 1; b >= 0; --b)
+ {
+ product ^= MultiplyGF(state[col][b], mds_matrix[row][b]);
+ }
+ result[row] = product;
+ }
+ for (i = 0; i < ROWS; ++i)
+ {
+ state[col][i] = result[i];
+ }
+ }
+ }
+
+ void AddRoundConstantP(byte[][] state, int round)
+ {
+ int i;
+ for (i = 0; i < columns; ++i)
+ {
+ state[i][0] ^= (byte)((i * 0x10) ^ round);
+ }
+ }
+
+ void AddRoundConstantQ(byte[][] state, int round)
+ {
+ int j;
+ UInt64[] s = new UInt64[columns];
+
+ for (j = 0; j < columns; j++)
+ {
+ s[j] = Pack.LE_To_UInt64(state[j]);
+
+ s[j] = s[j] + (0x00F0F0F0F0F0F0F3UL ^ ((((UInt64)(columns - j - 1) * 0x10UL) ^ (UInt64)round) << (7 * 8)));
+
+ state[j] = Pack.UInt64_To_LE(s[j]);
+ }
+ }
+
+ void P(byte[][] state)
+ {
+ int i;
+ for (i = 0; i < rounds; ++i)
+ {
+ AddRoundConstantP(state, i);
+ SubBytes(state);
+ ShiftBytes(state);
+ MixColumns(state);
+ }
+ }
+
+ void Q(byte[][] state)
+ {
+ int i;
+ for (i = 0; i < rounds; ++i)
+ {
+ AddRoundConstantQ(state, i);
+ SubBytes(state);
+ ShiftBytes(state);
+ MixColumns(state);
+ }
+ }
+
+ public IMemoable Copy()
+ {
+ return new Dstu7564Digest(this);
+ }
+
+ public void Reset(IMemoable other)
+ {
+ Dstu7564Digest d = (Dstu7564Digest)other;
+
+ copyIn(d);
+ }
+
+ private readonly byte[][] mds_matrix = new byte[][]
+ {
+ new byte[] {0x01, 0x01, 0x05, 0x01, 0x08, 0x06, 0x07, 0x04},
+ new byte[] {0x04, 0x01, 0x01, 0x05, 0x01, 0x08, 0x06, 0x07},
+ new byte[] {0x07, 0x04, 0x01, 0x01, 0x05, 0x01, 0x08, 0x06},
+ new byte[] {0x06, 0x07, 0x04, 0x01, 0x01, 0x05, 0x01, 0x08},
+ new byte[] {0x08, 0x06, 0x07, 0x04, 0x01, 0x01, 0x05, 0x01},
+ new byte[] {0x01, 0x08, 0x06, 0x07, 0x04, 0x01, 0x01, 0x05},
+ new byte[] {0x05, 0x01, 0x08, 0x06, 0x07, 0x04, 0x01, 0x01},
+ new byte[] {0x01, 0x05, 0x01, 0x08, 0x06, 0x07, 0x04, 0x01}
+ };
+
+
+
+
+ private readonly byte[][] sBoxes = new byte[][]
+ {
+ new byte[]
+ {
+ 0xa8, 0x43, 0x5f, 0x06, 0x6b, 0x75, 0x6c, 0x59, 0x71, 0xdf, 0x87, 0x95, 0x17, 0xf0, 0xd8, 0x09,
+ 0x6d, 0xf3, 0x1d, 0xcb, 0xc9, 0x4d, 0x2c, 0xaf, 0x79, 0xe0, 0x97, 0xfd, 0x6f, 0x4b, 0x45, 0x39,
+ 0x3e, 0xdd, 0xa3, 0x4f, 0xb4, 0xb6, 0x9a, 0x0e, 0x1f, 0xbf, 0x15, 0xe1, 0x49, 0xd2, 0x93, 0xc6,
+ 0x92, 0x72, 0x9e, 0x61, 0xd1, 0x63, 0xfa, 0xee, 0xf4, 0x19, 0xd5, 0xad, 0x58, 0xa4, 0xbb, 0xa1,
+ 0xdc, 0xf2, 0x83, 0x37, 0x42, 0xe4, 0x7a, 0x32, 0x9c, 0xcc, 0xab, 0x4a, 0x8f, 0x6e, 0x04, 0x27,
+ 0x2e, 0xe7, 0xe2, 0x5a, 0x96, 0x16, 0x23, 0x2b, 0xc2, 0x65, 0x66, 0x0f, 0xbc, 0xa9, 0x47, 0x41,
+ 0x34, 0x48, 0xfc, 0xb7, 0x6a, 0x88, 0xa5, 0x53, 0x86, 0xf9, 0x5b, 0xdb, 0x38, 0x7b, 0xc3, 0x1e,
+ 0x22, 0x33, 0x24, 0x28, 0x36, 0xc7, 0xb2, 0x3b, 0x8e, 0x77, 0xba, 0xf5, 0x14, 0x9f, 0x08, 0x55,
+ 0x9b, 0x4c, 0xfe, 0x60, 0x5c, 0xda, 0x18, 0x46, 0xcd, 0x7d, 0x21, 0xb0, 0x3f, 0x1b, 0x89, 0xff,
+ 0xeb, 0x84, 0x69, 0x3a, 0x9d, 0xd7, 0xd3, 0x70, 0x67, 0x40, 0xb5, 0xde, 0x5d, 0x30, 0x91, 0xb1,
+ 0x78, 0x11, 0x01, 0xe5, 0x00, 0x68, 0x98, 0xa0, 0xc5, 0x02, 0xa6, 0x74, 0x2d, 0x0b, 0xa2, 0x76,
+ 0xb3, 0xbe, 0xce, 0xbd, 0xae, 0xe9, 0x8a, 0x31, 0x1c, 0xec, 0xf1, 0x99, 0x94, 0xaa, 0xf6, 0x26,
+ 0x2f, 0xef, 0xe8, 0x8c, 0x35, 0x03, 0xd4, 0x7f, 0xfb, 0x05, 0xc1, 0x5e, 0x90, 0x20, 0x3d, 0x82,
+ 0xf7, 0xea, 0x0a, 0x0d, 0x7e, 0xf8, 0x50, 0x1a, 0xc4, 0x07, 0x57, 0xb8, 0x3c, 0x62, 0xe3, 0xc8,
+ 0xac, 0x52, 0x64, 0x10, 0xd0, 0xd9, 0x13, 0x0c, 0x12, 0x29, 0x51, 0xb9, 0xcf, 0xd6, 0x73, 0x8d,
+ 0x81, 0x54, 0xc0, 0xed, 0x4e, 0x44, 0xa7, 0x2a, 0x85, 0x25, 0xe6, 0xca, 0x7c, 0x8b, 0x56, 0x80
+ },
+
+ new byte[]
+ {
+ 0xce, 0xbb, 0xeb, 0x92, 0xea, 0xcb, 0x13, 0xc1, 0xe9, 0x3a, 0xd6, 0xb2, 0xd2, 0x90, 0x17, 0xf8,
+ 0x42, 0x15, 0x56, 0xb4, 0x65, 0x1c, 0x88, 0x43, 0xc5, 0x5c, 0x36, 0xba, 0xf5, 0x57, 0x67, 0x8d,
+ 0x31, 0xf6, 0x64, 0x58, 0x9e, 0xf4, 0x22, 0xaa, 0x75, 0x0f, 0x02, 0xb1, 0xdf, 0x6d, 0x73, 0x4d,
+ 0x7c, 0x26, 0x2e, 0xf7, 0x08, 0x5d, 0x44, 0x3e, 0x9f, 0x14, 0xc8, 0xae, 0x54, 0x10, 0xd8, 0xbc,
+ 0x1a, 0x6b, 0x69, 0xf3, 0xbd, 0x33, 0xab, 0xfa, 0xd1, 0x9b, 0x68, 0x4e, 0x16, 0x95, 0x91, 0xee,
+ 0x4c, 0x63, 0x8e, 0x5b, 0xcc, 0x3c, 0x19, 0xa1, 0x81, 0x49, 0x7b, 0xd9, 0x6f, 0x37, 0x60, 0xca,
+ 0xe7, 0x2b, 0x48, 0xfd, 0x96, 0x45, 0xfc, 0x41, 0x12, 0x0d, 0x79, 0xe5, 0x89, 0x8c, 0xe3, 0x20,
+ 0x30, 0xdc, 0xb7, 0x6c, 0x4a, 0xb5, 0x3f, 0x97, 0xd4, 0x62, 0x2d, 0x06, 0xa4, 0xa5, 0x83, 0x5f,
+ 0x2a, 0xda, 0xc9, 0x00, 0x7e, 0xa2, 0x55, 0xbf, 0x11, 0xd5, 0x9c, 0xcf, 0x0e, 0x0a, 0x3d, 0x51,
+ 0x7d, 0x93, 0x1b, 0xfe, 0xc4, 0x47, 0x09, 0x86, 0x0b, 0x8f, 0x9d, 0x6a, 0x07, 0xb9, 0xb0, 0x98,
+ 0x18, 0x32, 0x71, 0x4b, 0xef, 0x3b, 0x70, 0xa0, 0xe4, 0x40, 0xff, 0xc3, 0xa9, 0xe6, 0x78, 0xf9,
+ 0x8b, 0x46, 0x80, 0x1e, 0x38, 0xe1, 0xb8, 0xa8, 0xe0, 0x0c, 0x23, 0x76, 0x1d, 0x25, 0x24, 0x05,
+ 0xf1, 0x6e, 0x94, 0x28, 0x9a, 0x84, 0xe8, 0xa3, 0x4f, 0x77, 0xd3, 0x85, 0xe2, 0x52, 0xf2, 0x82,
+ 0x50, 0x7a, 0x2f, 0x74, 0x53, 0xb3, 0x61, 0xaf, 0x39, 0x35, 0xde, 0xcd, 0x1f, 0x99, 0xac, 0xad,
+ 0x72, 0x2c, 0xdd, 0xd0, 0x87, 0xbe, 0x5e, 0xa6, 0xec, 0x04, 0xc6, 0x03, 0x34, 0xfb, 0xdb, 0x59,
+ 0xb6, 0xc2, 0x01, 0xf0, 0x5a, 0xed, 0xa7, 0x66, 0x21, 0x7f, 0x8a, 0x27, 0xc7, 0xc0, 0x29, 0xd7
+ },
+
+ new byte[]
+ {
+ 0x93, 0xd9, 0x9a, 0xb5, 0x98, 0x22, 0x45, 0xfc, 0xba, 0x6a, 0xdf, 0x02, 0x9f, 0xdc, 0x51, 0x59,
+ 0x4a, 0x17, 0x2b, 0xc2, 0x94, 0xf4, 0xbb, 0xa3, 0x62, 0xe4, 0x71, 0xd4, 0xcd, 0x70, 0x16, 0xe1,
+ 0x49, 0x3c, 0xc0, 0xd8, 0x5c, 0x9b, 0xad, 0x85, 0x53, 0xa1, 0x7a, 0xc8, 0x2d, 0xe0, 0xd1, 0x72,
+ 0xa6, 0x2c, 0xc4, 0xe3, 0x76, 0x78, 0xb7, 0xb4, 0x09, 0x3b, 0x0e, 0x41, 0x4c, 0xde, 0xb2, 0x90,
+ 0x25, 0xa5, 0xd7, 0x03, 0x11, 0x00, 0xc3, 0x2e, 0x92, 0xef, 0x4e, 0x12, 0x9d, 0x7d, 0xcb, 0x35,
+ 0x10, 0xd5, 0x4f, 0x9e, 0x4d, 0xa9, 0x55, 0xc6, 0xd0, 0x7b, 0x18, 0x97, 0xd3, 0x36, 0xe6, 0x48,
+ 0x56, 0x81, 0x8f, 0x77, 0xcc, 0x9c, 0xb9, 0xe2, 0xac, 0xb8, 0x2f, 0x15, 0xa4, 0x7c, 0xda, 0x38,
+ 0x1e, 0x0b, 0x05, 0xd6, 0x14, 0x6e, 0x6c, 0x7e, 0x66, 0xfd, 0xb1, 0xe5, 0x60, 0xaf, 0x5e, 0x33,
+ 0x87, 0xc9, 0xf0, 0x5d, 0x6d, 0x3f, 0x88, 0x8d, 0xc7, 0xf7, 0x1d, 0xe9, 0xec, 0xed, 0x80, 0x29,
+ 0x27, 0xcf, 0x99, 0xa8, 0x50, 0x0f, 0x37, 0x24, 0x28, 0x30, 0x95, 0xd2, 0x3e, 0x5b, 0x40, 0x83,
+ 0xb3, 0x69, 0x57, 0x1f, 0x07, 0x1c, 0x8a, 0xbc, 0x20, 0xeb, 0xce, 0x8e, 0xab, 0xee, 0x31, 0xa2,
+ 0x73, 0xf9, 0xca, 0x3a, 0x1a, 0xfb, 0x0d, 0xc1, 0xfe, 0xfa, 0xf2, 0x6f, 0xbd, 0x96, 0xdd, 0x43,
+ 0x52, 0xb6, 0x08, 0xf3, 0xae, 0xbe, 0x19, 0x89, 0x32, 0x26, 0xb0, 0xea, 0x4b, 0x64, 0x84, 0x82,
+ 0x6b, 0xf5, 0x79, 0xbf, 0x01, 0x5f, 0x75, 0x63, 0x1b, 0x23, 0x3d, 0x68, 0x2a, 0x65, 0xe8, 0x91,
+ 0xf6, 0xff, 0x13, 0x58, 0xf1, 0x47, 0x0a, 0x7f, 0xc5, 0xa7, 0xe7, 0x61, 0x5a, 0x06, 0x46, 0x44,
+ 0x42, 0x04, 0xa0, 0xdb, 0x39, 0x86, 0x54, 0xaa, 0x8c, 0x34, 0x21, 0x8b, 0xf8, 0x0c, 0x74, 0x67
+ },
+
+ new byte[]
+ {
+ 0x68, 0x8d, 0xca, 0x4d, 0x73, 0x4b, 0x4e, 0x2a, 0xd4, 0x52, 0x26, 0xb3, 0x54, 0x1e, 0x19, 0x1f,
+ 0x22, 0x03, 0x46, 0x3d, 0x2d, 0x4a, 0x53, 0x83, 0x13, 0x8a, 0xb7, 0xd5, 0x25, 0x79, 0xf5, 0xbd,
+ 0x58, 0x2f, 0x0d, 0x02, 0xed, 0x51, 0x9e, 0x11, 0xf2, 0x3e, 0x55, 0x5e, 0xd1, 0x16, 0x3c, 0x66,
+ 0x70, 0x5d, 0xf3, 0x45, 0x40, 0xcc, 0xe8, 0x94, 0x56, 0x08, 0xce, 0x1a, 0x3a, 0xd2, 0xe1, 0xdf,
+ 0xb5, 0x38, 0x6e, 0x0e, 0xe5, 0xf4, 0xf9, 0x86, 0xe9, 0x4f, 0xd6, 0x85, 0x23, 0xcf, 0x32, 0x99,
+ 0x31, 0x14, 0xae, 0xee, 0xc8, 0x48, 0xd3, 0x30, 0xa1, 0x92, 0x41, 0xb1, 0x18, 0xc4, 0x2c, 0x71,
+ 0x72, 0x44, 0x15, 0xfd, 0x37, 0xbe, 0x5f, 0xaa, 0x9b, 0x88, 0xd8, 0xab, 0x89, 0x9c, 0xfa, 0x60,
+ 0xea, 0xbc, 0x62, 0x0c, 0x24, 0xa6, 0xa8, 0xec, 0x67, 0x20, 0xdb, 0x7c, 0x28, 0xdd, 0xac, 0x5b,
+ 0x34, 0x7e, 0x10, 0xf1, 0x7b, 0x8f, 0x63, 0xa0, 0x05, 0x9a, 0x43, 0x77, 0x21, 0xbf, 0x27, 0x09,
+ 0xc3, 0x9f, 0xb6, 0xd7, 0x29, 0xc2, 0xeb, 0xc0, 0xa4, 0x8b, 0x8c, 0x1d, 0xfb, 0xff, 0xc1, 0xb2,
+ 0x97, 0x2e, 0xf8, 0x65, 0xf6, 0x75, 0x07, 0x04, 0x49, 0x33, 0xe4, 0xd9, 0xb9, 0xd0, 0x42, 0xc7,
+ 0x6c, 0x90, 0x00, 0x8e, 0x6f, 0x50, 0x01, 0xc5, 0xda, 0x47, 0x3f, 0xcd, 0x69, 0xa2, 0xe2, 0x7a,
+ 0xa7, 0xc6, 0x93, 0x0f, 0x0a, 0x06, 0xe6, 0x2b, 0x96, 0xa3, 0x1c, 0xaf, 0x6a, 0x12, 0x84, 0x39,
+ 0xe7, 0xb0, 0x82, 0xf7, 0xfe, 0x9d, 0x87, 0x5c, 0x81, 0x35, 0xde, 0xb4, 0xa5, 0xfc, 0x80, 0xef,
+ 0xcb, 0xbb, 0x6b, 0x76, 0xba, 0x5a, 0x7d, 0x78, 0x0b, 0x95, 0xe3, 0xad, 0x74, 0x98, 0x3b, 0x36,
+ 0x64, 0x6d, 0xdc, 0xf0, 0x59, 0xa9, 0x4c, 0x17, 0x7f, 0x91, 0xb8, 0xc9, 0x57, 0x1b, 0xe0, 0x61
+ }
+ };
+
+
+ }
+}
diff --git a/crypto/src/crypto/ec/CustomNamedCurves.cs b/crypto/src/crypto/ec/CustomNamedCurves.cs
index 8a0c50a47..4b7600e09 100644
--- a/crypto/src/crypto/ec/CustomNamedCurves.cs
+++ b/crypto/src/crypto/ec/CustomNamedCurves.cs
@@ -2,11 +2,13 @@ using System;
using System.Collections;
using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.GM;
using Org.BouncyCastle.Asn1.Sec;
using Org.BouncyCastle.Asn1.X9;
using Org.BouncyCastle.Math;
using Org.BouncyCastle.Math.EC;
using Org.BouncyCastle.Math.EC.Custom.Djb;
+using Org.BouncyCastle.Math.EC.Custom.GM;
using Org.BouncyCastle.Math.EC.Custom.Sec;
using Org.BouncyCastle.Math.EC.Endo;
using Org.BouncyCastle.Utilities;
@@ -746,6 +748,27 @@ namespace Org.BouncyCastle.Crypto.EC
}
};
+ /*
+ * sm2p256v1
+ */
+ internal class SM2P256V1Holder
+ : X9ECParametersHolder
+ {
+ private SM2P256V1Holder() { }
+
+ internal static readonly X9ECParametersHolder Instance = new SM2P256V1Holder();
+
+ protected override X9ECParameters CreateParameters()
+ {
+ byte[] S = null;
+ ECCurve curve = ConfigureCurve(new SM2P256V1Curve());
+ X9ECPoint G = new X9ECPoint(curve, Hex.Decode("04"
+ + "32C4AE2C1F1981195F9904466A39C9948FE30BBFF2660BE1715A4589334C74C7"
+ + "BC3736A2F4F6779C59BDCEE36B692153D0A9877CC62A474002DF32E52139F0A0"));
+ return new X9ECParameters(curve, G, curve.Order, curve.Cofactor, S);
+ }
+ }
+
private static readonly IDictionary nameToCurve = Platform.CreateHashtable();
private static readonly IDictionary nameToOid = Platform.CreateHashtable();
@@ -820,6 +843,8 @@ namespace Org.BouncyCastle.Crypto.EC
DefineCurveWithOid("sect571k1", SecObjectIdentifiers.SecT571k1, SecT571K1Holder.Instance);
DefineCurveWithOid("sect571r1", SecObjectIdentifiers.SecT571r1, SecT571R1Holder.Instance);
+ DefineCurveWithOid("sm2p256v1", GMObjectIdentifiers.sm2p256v1, SM2P256V1Holder.Instance);
+
DefineCurveAlias("B-163", SecObjectIdentifiers.SecT163r2);
DefineCurveAlias("B-233", SecObjectIdentifiers.SecT233r1);
DefineCurveAlias("B-283", SecObjectIdentifiers.SecT283r1);
diff --git a/crypto/src/crypto/encodings/OaepEncoding.cs b/crypto/src/crypto/encodings/OaepEncoding.cs
index cb23b1710..287876f12 100644
--- a/crypto/src/crypto/encodings/OaepEncoding.cs
+++ b/crypto/src/crypto/encodings/OaepEncoding.cs
@@ -3,6 +3,7 @@ using System;
using Org.BouncyCastle.Crypto.Digests;
using Org.BouncyCastle.Crypto.Parameters;
using Org.BouncyCastle.Security;
+using Org.BouncyCastle.Utilities;
namespace Org.BouncyCastle.Crypto.Encodings
{
@@ -13,7 +14,6 @@ namespace Org.BouncyCastle.Crypto.Encodings
: IAsymmetricBlockCipher
{
private byte[] defHash;
- private IDigest hash;
private IDigest mgf1Hash;
private IAsymmetricBlockCipher engine;
@@ -48,10 +48,11 @@ namespace Org.BouncyCastle.Crypto.Encodings
byte[] encodingParams)
{
this.engine = cipher;
- this.hash = hash;
this.mgf1Hash = mgf1Hash;
this.defHash = new byte[hash.GetDigestSize()];
+ hash.Reset();
+
if (encodingParams != null)
{
hash.BlockUpdate(encodingParams, 0, encodingParams.Length);
@@ -137,6 +138,8 @@ namespace Org.BouncyCastle.Crypto.Encodings
int inOff,
int inLen)
{
+ Check.DataLength(inLen > GetInputBlockSize(), "input data too long");
+
byte[] block = new byte[GetInputBlockSize() + 1 + 2 * defHash.Length];
//
@@ -202,28 +205,17 @@ namespace Org.BouncyCastle.Crypto.Encodings
int inLen)
{
byte[] data = engine.ProcessBlock(inBytes, inOff, inLen);
- byte[] block;
+ byte[] block = new byte[engine.GetOutputBlockSize()];
//
// as we may have zeros in our leading bytes for the block we produced
// on encryption, we need to make sure our decrypted block comes back
// the same size.
//
- if (data.Length < engine.GetOutputBlockSize())
- {
- block = new byte[engine.GetOutputBlockSize()];
- Array.Copy(data, 0, block, block.Length - data.Length, data.Length);
- }
- else
- {
- block = data;
- }
+ Array.Copy(data, 0, block, block.Length - data.Length, data.Length);
- if (block.Length < (2 * defHash.Length) + 1)
- {
- throw new InvalidCipherTextException("data too short");
- }
+ bool shortData = (block.Length < (2 * defHash.Length) + 1);
//
// unmask the seed.
@@ -250,36 +242,39 @@ namespace Org.BouncyCastle.Crypto.Encodings
// check the hash of the encoding params.
// long check to try to avoid this been a source of a timing attack.
//
+ bool defHashWrong = false;
+
+ for (int i = 0; i != defHash.Length; i++)
{
- int diff = 0;
- for (int i = 0; i < defHash.Length; ++i)
+ if (defHash[i] != block[defHash.Length + i])
{
- diff |= (byte)(defHash[i] ^ block[defHash.Length + i]);
+ defHashWrong = true;
}
-
- if (diff != 0)
- throw new InvalidCipherTextException("data hash wrong");
}
//
// find the data block
//
- int start;
- for (start = 2 * defHash.Length; start != block.Length; start++)
+ int start = block.Length;
+
+ for (int index = 2 * defHash.Length; index != block.Length; index++)
{
- if (block[start] != 0)
+ if (block[index] != 0 & start == block.Length)
{
- break;
+ start = index;
}
}
- if (start > (block.Length - 1) || block[start] != 1)
- {
- throw new InvalidCipherTextException("data start wrong " + start);
- }
+ bool dataStartWrong = (start > (block.Length - 1) | block[start] != 1);
start++;
+ if (defHashWrong | shortData | dataStartWrong)
+ {
+ Arrays.Fill(block, 0);
+ throw new InvalidCipherTextException("data wrong");
+ }
+
//
// extract the data block
//
@@ -317,9 +312,9 @@ namespace Org.BouncyCastle.Crypto.Encodings
byte[] C = new byte[4];
int counter = 0;
- hash.Reset();
+ mgf1Hash.Reset();
- do
+ while (counter < (length / hashBuf.Length))
{
ItoOSP(counter, C);
@@ -328,8 +323,9 @@ namespace Org.BouncyCastle.Crypto.Encodings
mgf1Hash.DoFinal(hashBuf, 0);
Array.Copy(hashBuf, 0, mask, counter * hashBuf.Length, hashBuf.Length);
+
+ counter++;
}
- while (++counter < (length / hashBuf.Length));
if ((counter * hashBuf.Length) < length)
{
diff --git a/crypto/src/crypto/encodings/Pkcs1Encoding.cs b/crypto/src/crypto/encodings/Pkcs1Encoding.cs
index 35fd96abe..b2d60fe4c 100644
--- a/crypto/src/crypto/encodings/Pkcs1Encoding.cs
+++ b/crypto/src/crypto/encodings/Pkcs1Encoding.cs
@@ -45,16 +45,18 @@ namespace Org.BouncyCastle.Crypto.Encodings
}
- private SecureRandom random;
- private IAsymmetricBlockCipher engine;
- private bool forEncryption;
- private bool forPrivateKey;
- private bool useStrictLength;
- private int pLen = -1;
- private byte[] fallback = null;
+ private SecureRandom random;
+ private IAsymmetricBlockCipher engine;
+ private bool forEncryption;
+ private bool forPrivateKey;
+ private bool useStrictLength;
+ private int pLen = -1;
+ private byte[] fallback = null;
+ private byte[] blockBuffer = null;
/**
* Basic constructor.
+ *
* @param cipher
*/
public Pkcs1Encoding(
@@ -104,9 +106,7 @@ namespace Org.BouncyCastle.Crypto.Encodings
get { return engine.AlgorithmName + "/PKCS1Padding"; }
}
- public void Init(
- bool forEncryption,
- ICipherParameters parameters)
+ public void Init(bool forEncryption, ICipherParameters parameters)
{
AsymmetricKeyParameter kParam;
if (parameters is ParametersWithRandom)
@@ -126,6 +126,10 @@ namespace Org.BouncyCastle.Crypto.Encodings
this.forPrivateKey = kParam.IsPrivate;
this.forEncryption = forEncryption;
+ this.blockBuffer = new byte[engine.GetOutputBlockSize()];
+
+ if (pLen > 0 && fallback == null && random == null)
+ throw new ArgumentException("encoder requires random");
}
public int GetInputBlockSize()
@@ -255,7 +259,6 @@ namespace Org.BouncyCastle.Crypto.Encodings
* @param inLen Length of the encrypted block.
* @param pLen Length of the desired output.
* @return The plaintext without padding, or a random value if the padding was incorrect.
- *
* @throws InvalidCipherTextException
*/
private byte[] DecodeBlockOrRandom(byte[] input, int inOff, int inLen)
@@ -264,7 +267,7 @@ namespace Org.BouncyCastle.Crypto.Encodings
throw new InvalidCipherTextException("sorry, this method is only for decryption, not for signing");
byte[] block = engine.ProcessBlock(input, inOff, inLen);
- byte[] random = null;
+ byte[] random;
if (this.fallback == null)
{
random = new byte[this.pLen];
@@ -275,37 +278,25 @@ namespace Org.BouncyCastle.Crypto.Encodings
random = fallback;
}
- /*
- * TODO: This is a potential dangerous side channel. However, you can
- * fix this by changing the RSA engine in a way, that it will always
- * return blocks of the same length and prepend them with 0 bytes if
- * needed.
- */
- if (block.Length < GetOutputBlockSize())
- throw new InvalidCipherTextException("block truncated");
+ byte[] data = (useStrictLength & (block.Length != engine.GetOutputBlockSize())) ? blockBuffer : block;
- /*
- * TODO: Potential side channel. Fix it by making the engine always
- * return blocks of the correct length.
- */
- if (useStrictLength && block.Length != engine.GetOutputBlockSize())
- throw new InvalidCipherTextException("block incorrect size");
-
- /*
- * Check the padding.
- */
- int correct = Pkcs1Encoding.CheckPkcs1Encoding(block, this.pLen);
+ /*
+ * Check the padding.
+ */
+ int correct = CheckPkcs1Encoding(data, this.pLen);
- /*
- * Now, to a constant time constant memory copy of the decrypted value
- * or the random value, depending on the validity of the padding.
- */
+ /*
+ * Now, to a constant time constant memory copy of the decrypted value
+ * or the random value, depending on the validity of the padding.
+ */
byte[] result = new byte[this.pLen];
for (int i = 0; i < this.pLen; i++)
{
- result[i] = (byte)((block[i+(block.Length-pLen)]&(~correct)) | (random[i]&correct));
+ result[i] = (byte)((data[i + (data.Length - pLen)] & (~correct)) | (random[i] & correct));
}
+ Arrays.Fill(data, 0);
+
return result;
}
@@ -327,56 +318,67 @@ namespace Org.BouncyCastle.Crypto.Encodings
}
byte[] block = engine.ProcessBlock(input, inOff, inLen);
+ bool incorrectLength = (useStrictLength & (block.Length != engine.GetOutputBlockSize()));
+ byte[] data;
if (block.Length < GetOutputBlockSize())
{
- throw new InvalidCipherTextException("block truncated");
+ data = blockBuffer;
}
-
- byte type = block[0];
-
- if (type != 1 && type != 2)
+ else
{
- throw new InvalidCipherTextException("unknown block type");
+ data = block;
}
- if (useStrictLength && block.Length != engine.GetOutputBlockSize())
- {
- throw new InvalidCipherTextException("block incorrect size");
- }
+ byte expectedType = (byte)(forPrivateKey ? 2 : 1);
+ byte type = data[0];
+
+ bool badType = (type != expectedType);
//
// find and extract the message block.
//
- int start;
- for (start = 1; start != block.Length; start++)
- {
- byte pad = block[start];
+ int start = FindStart(type, data);
- if (pad == 0)
- {
- break;
- }
+ start++; // data should start at the next byte
- if (type == 1 && pad != (byte)0xff)
- {
- throw new InvalidCipherTextException("block padding incorrect");
- }
+ if (badType | (start < HeaderLength))
+ {
+ Arrays.Fill(data, 0);
+ throw new InvalidCipherTextException("block incorrect");
}
- start++; // data should start at the next byte
-
- if (start > block.Length || start < HeaderLength)
+ // if we get this far, it's likely to be a genuine encoding error
+ if (incorrectLength)
{
- throw new InvalidCipherTextException("no data in block");
+ Arrays.Fill(data, 0);
+ throw new InvalidCipherTextException("block incorrect size");
}
- byte[] result = new byte[block.Length - start];
+ byte[] result = new byte[data.Length - start];
- Array.Copy(block, start, result, 0, result.Length);
+ Array.Copy(data, start, result, 0, result.Length);
return result;
}
- }
+ private int FindStart(byte type, byte[] block)
+ {
+ int start = -1;
+ bool padErr = false;
+
+ for (int i = 1; i != block.Length; i++)
+ {
+ byte pad = block[i];
+
+ if (pad == 0 & start < 0)
+ {
+ start = i;
+ }
+ padErr |= ((type == 1) & (start < 0) & (pad != (byte)0xff));
+ }
+
+ return padErr ? -1 : start;
+ }
+ }
}
diff --git a/crypto/src/crypto/engines/AesEngine.cs b/crypto/src/crypto/engines/AesEngine.cs
index ba62af4da..91bdf69ef 100644
--- a/crypto/src/crypto/engines/AesEngine.cs
+++ b/crypto/src/crypto/engines/AesEngine.cs
@@ -429,6 +429,8 @@ namespace Org.BouncyCastle.Crypto.Engines
private uint C0, C1, C2, C3;
private bool forEncryption;
+ private byte[] s;
+
private const int BLOCK_SIZE = 16;
/**
@@ -459,6 +461,7 @@ namespace Org.BouncyCastle.Crypto.Engines
WorkingKey = GenerateWorkingKey(keyParameter.GetKey(), forEncryption);
this.forEncryption = forEncryption;
+ this.s = Arrays.Clone(forEncryption ? S : Si);
}
public virtual string AlgorithmName
@@ -560,10 +563,10 @@ namespace Org.BouncyCastle.Crypto.Engines
// the final round's table is a simple function of S so we don't use a whole other four tables for it
kw = KW[r];
- this.C0 = (uint)S[r0 & 255] ^ (((uint)S[(r1 >> 8) & 255]) << 8) ^ (((uint)S[(r2 >> 16) & 255]) << 16) ^ (((uint)S[(r3 >> 24) & 255]) << 24) ^ kw[0];
- this.C1 = (uint)S[r1 & 255] ^ (((uint)S[(r2 >> 8) & 255]) << 8) ^ (((uint)S[(r3 >> 16) & 255]) << 16) ^ (((uint)S[(r0 >> 24) & 255]) << 24) ^ kw[1];
- this.C2 = (uint)S[r2 & 255] ^ (((uint)S[(r3 >> 8) & 255]) << 8) ^ (((uint)S[(r0 >> 16) & 255]) << 16) ^ (((uint)S[(r1 >> 24) & 255]) << 24) ^ kw[2];
- this.C3 = (uint)S[r3 & 255] ^ (((uint)S[(r0 >> 8) & 255]) << 8) ^ (((uint)S[(r1 >> 16) & 255]) << 16) ^ (((uint)S[(r2 >> 24) & 255]) << 24) ^ kw[3];
+ this.C0 = (uint)S[r0 & 255] ^ (((uint)S[(r1 >> 8) & 255]) << 8) ^ (((uint)s[(r2 >> 16) & 255]) << 16) ^ (((uint)s[(r3 >> 24) & 255]) << 24) ^ kw[0];
+ this.C1 = (uint)s[r1 & 255] ^ (((uint)S[(r2 >> 8) & 255]) << 8) ^ (((uint)S[(r3 >> 16) & 255]) << 16) ^ (((uint)s[(r0 >> 24) & 255]) << 24) ^ kw[1];
+ this.C2 = (uint)s[r2 & 255] ^ (((uint)S[(r3 >> 8) & 255]) << 8) ^ (((uint)S[(r0 >> 16) & 255]) << 16) ^ (((uint)S[(r1 >> 24) & 255]) << 24) ^ kw[2];
+ this.C3 = (uint)s[r3 & 255] ^ (((uint)s[(r0 >> 8) & 255]) << 8) ^ (((uint)s[(r1 >> 16) & 255]) << 16) ^ (((uint)S[(r2 >> 24) & 255]) << 24) ^ kw[3];
}
private void DecryptBlock(uint[][] KW)
@@ -598,10 +601,10 @@ namespace Org.BouncyCastle.Crypto.Engines
// the final round's table is a simple function of Si so we don't use a whole other four tables for it
kw = KW[0];
- this.C0 = (uint)Si[r0 & 255] ^ (((uint)Si[(r3 >> 8) & 255]) << 8) ^ (((uint)Si[(r2 >> 16) & 255]) << 16) ^ (((uint)Si[(r1 >> 24) & 255]) << 24) ^ kw[0];
- this.C1 = (uint)Si[r1 & 255] ^ (((uint)Si[(r0 >> 8) & 255]) << 8) ^ (((uint)Si[(r3 >> 16) & 255]) << 16) ^ (((uint)Si[(r2 >> 24) & 255]) << 24) ^ kw[1];
- this.C2 = (uint)Si[r2 & 255] ^ (((uint)Si[(r1 >> 8) & 255]) << 8) ^ (((uint)Si[(r0 >> 16) & 255]) << 16) ^ (((uint)Si[(r3 >> 24) & 255]) << 24) ^ kw[2];
- this.C3 = (uint)Si[r3 & 255] ^ (((uint)Si[(r2 >> 8) & 255]) << 8) ^ (((uint)Si[(r1 >> 16) & 255]) << 16) ^ (((uint)Si[(r0 >> 24) & 255]) << 24) ^ kw[3];
+ this.C0 = (uint)Si[r0 & 255] ^ (((uint)s[(r3 >> 8) & 255]) << 8) ^ (((uint)s[(r2 >> 16) & 255]) << 16) ^ (((uint)Si[(r1 >> 24) & 255]) << 24) ^ kw[0];
+ this.C1 = (uint)s[r1 & 255] ^ (((uint)s[(r0 >> 8) & 255]) << 8) ^ (((uint)Si[(r3 >> 16) & 255]) << 16) ^ (((uint)s[(r2 >> 24) & 255]) << 24) ^ kw[1];
+ this.C2 = (uint)s[r2 & 255] ^ (((uint)Si[(r1 >> 8) & 255]) << 8) ^ (((uint)Si[(r0 >> 16) & 255]) << 16) ^ (((uint)s[(r3 >> 24) & 255]) << 24) ^ kw[2];
+ this.C3 = (uint)Si[r3 & 255] ^ (((uint)s[(r2 >> 8) & 255]) << 8) ^ (((uint)s[(r1 >> 16) & 255]) << 16) ^ (((uint)s[(r0 >> 24) & 255]) << 24) ^ kw[3];
}
}
}
diff --git a/crypto/src/crypto/engines/AesFastEngine.cs b/crypto/src/crypto/engines/AesFastEngine.cs
index 3a9c3a89e..9d3a86fd2 100644
--- a/crypto/src/crypto/engines/AesFastEngine.cs
+++ b/crypto/src/crypto/engines/AesFastEngine.cs
@@ -31,6 +31,11 @@ namespace Org.BouncyCastle.Crypto.Engines
* This file contains the fast version with 8Kbytes of static tables for round precomputation
* </p>
*/
+ /// <remarks>
+ /// Unfortunately this class has a few side channel issues.
+ /// In an environment where encryption/decryption may be closely observed it should not be used.
+ /// </remarks>
+ [Obsolete("Use AesEngine instead")]
public class AesFastEngine
: IBlockCipher
{
diff --git a/crypto/src/crypto/engines/ChaCha7539Engine.cs b/crypto/src/crypto/engines/ChaCha7539Engine.cs
index 5a12be016..af4163a02 100644
--- a/crypto/src/crypto/engines/ChaCha7539Engine.cs
+++ b/crypto/src/crypto/engines/ChaCha7539Engine.cs
@@ -19,7 +19,7 @@ namespace Org.BouncyCastle.Crypto.Engines
public override string AlgorithmName
{
- get { return "ChaCha" + rounds; }
+ get { return "ChaCha7539" + rounds; }
}
protected override int NonceSize
diff --git a/crypto/src/crypto/engines/Dstu7624Engine.cs b/crypto/src/crypto/engines/Dstu7624Engine.cs
new file mode 100644
index 000000000..422b5574a
--- /dev/null
+++ b/crypto/src/crypto/engines/Dstu7624Engine.cs
@@ -0,0 +1,855 @@
+using System;
+using System.Collections;
+
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Utilities;
+using Org.BouncyCastle.Crypto.Utilities;
+
+namespace Org.BouncyCastle.Crypto.Engines
+{
+ /**
+ * implementation of DSTU 7624 (Kalyna)
+ */
+ public class Dstu7624Engine
+ : IBlockCipher
+ {
+ private static readonly int BITS_IN_WORD = 64;
+ private static readonly int BITS_IN_BYTE = 8;
+
+ private static readonly int REDUCTION_POLYNOMIAL = 0x011d; /* x^8 + x^4 + x^3 + x^2 + 1 */
+
+ private ulong[] internalState;
+ private ulong[] workingKey;
+ private ulong[][] roundKeys;
+
+ /* Number of 64-bit words in block */
+ private int wordsInBlock;
+
+ /* Number of 64-bit words in key */
+ private int wordsInKey;
+
+ /* Number of encryption rounds depending on key length */
+ private static int ROUNDS_128 = 10;
+ private static int ROUNDS_256 = 14;
+ private static int ROUNDS_512 = 18;
+
+ private int blockSizeBits;
+ private int roundsAmount;
+
+ private bool forEncryption;
+
+ private byte[] internalStateBytes;
+ private byte[] tempInternalStateBytes;
+
+ public Dstu7624Engine(int blockSizeBits)
+ {
+ /* DSTU7624 supports 128 | 256 | 512 key/block sizes */
+ if (blockSizeBits != 128 && blockSizeBits != 256 && blockSizeBits != 512)
+ {
+ throw new ArgumentException("Unsupported block length: only 128/256/512 are allowed");
+ }
+ this.blockSizeBits = blockSizeBits;
+
+ wordsInBlock = blockSizeBits / BITS_IN_WORD;
+ internalState = new ulong[wordsInBlock];
+
+ internalStateBytes = new byte[internalState.Length * 64 / BITS_IN_BYTE];
+ tempInternalStateBytes = new byte[internalState.Length * 64 / BITS_IN_BYTE];
+ }
+
+ #region INITIALIZATION
+ public virtual void Init(bool forEncryption, ICipherParameters parameters)
+ {
+ if (parameters is KeyParameter)
+ {
+ this.forEncryption = forEncryption;
+
+ byte[] keyBytes = ((KeyParameter)parameters).GetKey();
+ int keyBitLength = keyBytes.Length * BITS_IN_BYTE;
+ int blockBitLength = wordsInBlock * BITS_IN_WORD;
+
+ if (keyBitLength != 128 && keyBitLength != 256 && keyBitLength != 512)
+ {
+ throw new ArgumentException("unsupported key length: only 128/256/512 are allowed");
+ }
+
+ /* Limitations on key lengths depending on block lengths. See table 6.1 in standard */
+ if (blockBitLength == 128)
+ {
+ if (keyBitLength == 512)
+ {
+ throw new ArgumentException("Unsupported key length");
+ }
+ }
+
+ if (blockBitLength == 256)
+ {
+ if (keyBitLength == 128)
+ {
+ throw new ArgumentException("Unsupported key length");
+ }
+ }
+
+ if (blockBitLength == 512)
+ {
+ if (keyBitLength != 512)
+ {
+ throw new ArgumentException("Unsupported key length");
+ }
+ }
+
+ switch (keyBitLength)
+ {
+ case 128:
+ roundsAmount = ROUNDS_128;
+ break;
+ case 256:
+ roundsAmount = ROUNDS_256;
+ break;
+ case 512:
+ roundsAmount = ROUNDS_512;
+ break;
+ }
+
+ wordsInKey = keyBitLength / BITS_IN_WORD;
+
+ /* +1 round key as defined in standard */
+ roundKeys = new ulong[roundsAmount + 1][];
+ for (int roundKeyIndex = 0; roundKeyIndex < roundKeys.Length; roundKeyIndex++)
+ {
+ roundKeys[roundKeyIndex] = new ulong[wordsInBlock];
+ }
+
+ workingKey = new ulong[wordsInKey];
+
+ if (keyBytes.Length != wordsInKey * BITS_IN_WORD / BITS_IN_BYTE)
+ {
+ throw new ArgumentException("Invalid key parameter passed to DSTU7624Engine init");
+ }
+
+ /* Unpack encryption key bytes to words */
+ Pack.LE_To_UInt64(keyBytes, 0, workingKey);
+
+ ulong[] kt = new ulong[wordsInBlock];
+
+ KeyExpandKT(workingKey, kt);
+
+ KeyExpandEven(workingKey, kt);
+
+ KeyExpandOdd();
+
+ }
+ else if (parameters != null)
+ {
+ throw new ArgumentException("invalid parameter passed to Dstu7624 init - "
+ + Platform.GetTypeName(parameters));
+ }
+
+ this.forEncryption = forEncryption;
+ }
+
+ private void KeyExpandKT(ulong[] key, ulong[] kt)
+ {
+ ulong[] k0 = new ulong[wordsInBlock];
+ ulong[] k1 = new ulong[wordsInBlock];
+
+ internalState = new ulong[wordsInBlock];
+ internalState[0] += (ulong)(wordsInBlock + wordsInKey + 1);
+
+ if (wordsInBlock == wordsInKey)
+ {
+ Array.Copy(key, k0, k0.Length);
+ Array.Copy(key, k1, k1.Length);
+ }
+ else
+ {
+ Array.Copy(key, 0, k0, 0, wordsInBlock);
+ Array.Copy(key, wordsInBlock, k1, 0, wordsInBlock);
+ }
+
+ AddRoundKeyExpand(k0);
+
+ EncryptionRound();
+
+ XorRoundKeyExpand(k1);
+
+ EncryptionRound();
+
+ AddRoundKeyExpand(k0);
+
+ EncryptionRound();
+
+ Array.Copy(internalState, kt, wordsInBlock);
+ }
+
+ private void KeyExpandEven(ulong[] key, ulong[] kt)
+ {
+ ulong[] initial_data = new ulong[wordsInKey];
+
+ ulong[] kt_round = new ulong[wordsInBlock];
+
+ ulong[] tmv = new ulong[wordsInBlock];
+
+ int round = 0;
+
+ Array.Copy(key, initial_data, wordsInKey);
+
+ for (int i = 0; i < wordsInBlock; i++)
+ {
+ tmv[i] = 0x0001000100010001;
+ }
+
+ while (true)
+ {
+ Array.Copy(kt, internalState, wordsInBlock);
+
+ AddRoundKeyExpand(tmv);
+
+ Array.Copy(internalState, kt_round, wordsInBlock);
+ Array.Copy(initial_data, internalState, wordsInBlock);
+
+ AddRoundKeyExpand(kt_round);
+
+ EncryptionRound();
+
+ XorRoundKeyExpand(kt_round);
+
+ EncryptionRound();
+
+ AddRoundKeyExpand(kt_round);
+
+ Array.Copy(internalState, roundKeys[round], wordsInBlock);
+
+ if (roundsAmount == round)
+ {
+ break;
+ }
+ if (wordsInKey != wordsInBlock)
+ {
+ round += 2;
+
+ ShiftLeft(tmv);
+
+ Array.Copy(kt, internalState, wordsInBlock);
+
+ AddRoundKeyExpand(tmv);
+
+ Array.Copy(internalState, kt_round, wordsInBlock);
+ Array.Copy(initial_data, wordsInBlock, internalState, 0, wordsInBlock);
+
+ AddRoundKeyExpand(kt_round);
+
+ EncryptionRound();
+
+ XorRoundKeyExpand(kt_round);
+
+ EncryptionRound();
+
+ AddRoundKeyExpand(kt_round);
+
+ Array.Copy(internalState, roundKeys[round], wordsInBlock);
+
+ if (roundsAmount == round)
+ {
+ break;
+ }
+ }
+
+ round += 2;
+ ShiftLeft(tmv);
+
+ //Rotate initial data array on 1 element left
+ ulong temp = initial_data[0];
+ Array.Copy(initial_data, 1, initial_data, 0, initial_data.Length - 1);
+ initial_data[initial_data.Length - 1] = temp;
+ }
+ }
+ private void KeyExpandOdd()
+ {
+ for (int i = 1; i < roundsAmount; i += 2)
+ {
+ Array.Copy(roundKeys[i - 1], roundKeys[i], wordsInBlock);
+ RotateLeft(roundKeys[i]);
+ }
+ }
+ #endregion
+
+
+ public virtual int ProcessBlock(byte[] input, int inOff, byte[] output, int outOff)
+ {
+ if (workingKey == null)
+ throw new InvalidOperationException("Dstu7624 engine not initialised");
+
+ Check.DataLength(input, inOff, GetBlockSize(), "input buffer too short");
+ Check.OutputLength(output, outOff, GetBlockSize(), "output buffer too short");
+
+ if (forEncryption)
+ {
+ Encrypt(input, inOff, output, outOff);
+ }
+ else
+ {
+ Decrypt(input, inOff, output, outOff);
+ }
+
+ return GetBlockSize();
+ }
+
+ private void Encrypt(byte[] plain, int inOff, byte[] cipherText, int outOff)
+ {
+ int round = 0;
+
+ Array.Copy(plain, inOff, plain, 0, blockSizeBits / BITS_IN_BYTE);
+ Array.Resize(ref plain, blockSizeBits / BITS_IN_BYTE);
+
+ ulong[] plain_ = BytesToWords(plain);
+
+ Array.Copy(plain_, internalState, wordsInBlock);
+
+ AddRoundKey(round);
+
+ for (round = 1; round < roundsAmount; round++)
+ {
+ EncryptionRound();
+
+ XorRoundKey(round);
+
+ }
+ EncryptionRound();
+
+ AddRoundKey(roundsAmount);
+
+ ulong[] cipherText_ = new ulong[internalState.Length];
+
+ Array.Copy(internalState, cipherText_, wordsInBlock);
+
+ byte[] temp = WordsToBytes(cipherText_);
+
+ Array.Copy(temp, 0, cipherText, outOff, temp.Length);
+
+ }
+ private void Decrypt(byte[] cipherText, int inOff, byte[] decryptedText, int outOff)
+ {
+ Array.Copy(cipherText, inOff, cipherText, 0, blockSizeBits / BITS_IN_BYTE);
+ Array.Resize(ref cipherText, blockSizeBits / BITS_IN_BYTE);
+
+ int round = roundsAmount;
+
+ ulong[] cipherText_ = BytesToWords(cipherText);
+
+ Array.Copy(cipherText_, internalState, wordsInBlock);
+
+ SubRoundKey(round);
+
+ for (round = roundsAmount - 1; round > 0; round--)
+ {
+ DecryptionRound();
+ XorRoundKey(round);
+ }
+
+ DecryptionRound();
+ SubRoundKey(0);
+
+ ulong[] decryptedText_ = new ulong[internalState.Length];
+
+ Array.Copy(internalState, decryptedText_, wordsInBlock);
+
+
+ byte[] temp = WordsToBytes(decryptedText_);
+ Array.Copy(temp, 0, decryptedText, outOff, temp.Length);
+
+
+ }
+
+
+
+
+
+
+
+
+
+ private void AddRoundKeyExpand(ulong[] value)
+ {
+ for (int i = 0; i < wordsInBlock; i++)
+ {
+ internalState[i] += value[i];
+ }
+ }
+
+ private void EncryptionRound()
+ {
+ SubBytes();
+ ShiftRows();
+ MixColumns();
+ }
+
+ private void DecryptionRound()
+ {
+ InvMixColumns();
+ InvShiftRows();
+ InvSubBytes();
+ }
+
+ private void RotateLeft(ulong[] state_value)
+ {
+ int rotateBytesLength = 2 * state_value.Length + 3;
+ int bytesLength = state_value.Length * (BITS_IN_WORD / BITS_IN_BYTE);
+
+
+ byte[] bytes = WordsToBytes(state_value);
+ byte[] buffer = new byte[rotateBytesLength];
+
+ Array.Copy(bytes, buffer, rotateBytesLength);
+
+ Buffer.BlockCopy(bytes, rotateBytesLength, bytes, 0, bytesLength - rotateBytesLength);
+
+ Array.Copy(buffer, 0, bytes, bytesLength - rotateBytesLength, rotateBytesLength);
+
+ var temp = BytesToWords(bytes);
+ Array.Copy(temp, state_value, state_value.Length);
+ }
+
+ private void ShiftLeft(ulong[] state_value)
+ {
+ for (int i = 0; i < state_value.Length; i++)
+ {
+ state_value[i] <<= 1;
+ }
+ Array.Reverse(state_value);
+ }
+
+ private void XorRoundKeyExpand(ulong[] value)
+ {
+ for (int i = 0; i < wordsInBlock; i++)
+ {
+ internalState[i] ^= value[i];
+ }
+ }
+
+ private void XorRoundKey(int round)
+ {
+ for (int i = 0; i < wordsInBlock; i++)
+ {
+ internalState[i] ^= roundKeys[round][i];
+ }
+ }
+
+ private void ShiftRows()
+ {
+ int row, col;
+ int shift = -1;
+
+ byte[] stateBytes = WordsToBytes(internalState);
+
+ byte[] nstate = new byte[wordsInBlock * sizeof(ulong)];
+
+ for (row = 0; row < sizeof(ulong); row++)
+ {
+ if (row % (sizeof(ulong) / wordsInBlock) == 0)
+ {
+ shift += 1;
+ }
+
+ for (col = 0; col < wordsInBlock; col++)
+ {
+ nstate[row + ((col + shift) % wordsInBlock) * sizeof(ulong)] = stateBytes[row + col * sizeof(ulong)];
+ }
+ }
+
+ internalState = BytesToWords(nstate);
+
+ }
+
+ private void InvShiftRows()
+ {
+ int row, col;
+ int shift = -1;
+
+ byte[] stateBytes = WordsToBytes(internalState);
+ byte[] nstate = new byte[wordsInBlock * sizeof(ulong)];
+
+ for (row = 0; row < sizeof(ulong); row++)
+ {
+ if (row % (sizeof(ulong) / wordsInBlock) == 0)
+ {
+ shift += 1;
+ }
+
+ for (col = 0; col < wordsInBlock; col++)
+ {
+ nstate[row + col * sizeof(ulong)] = stateBytes[row + ((col + shift) % wordsInBlock) * sizeof(ulong)];
+ }
+ }
+
+ internalState = BytesToWords(nstate);
+ }
+
+ private ulong[] BytesToWords(byte[] bytes)
+ {
+ ulong[] words = new ulong[bytes.Length / sizeof(ulong)];
+
+ for (int i = 0; i < words.Length; i++)
+ {
+ words[i] = BitConverter.ToUInt64(bytes, i * sizeof(ulong));
+
+ if (!BitConverter.IsLittleEndian)
+ {
+ words[i] = ReverseWord(words[i]);
+ }
+ }
+
+ return words;
+ }
+
+ private byte[] WordsToBytes(ulong[] words)
+ {
+ byte[] bytes = new byte[words.Length * sizeof(ulong)];
+
+ byte[] tempBytes = new byte[sizeof(ulong)];
+
+ for (int i = 0; i < words.Length; ++i)
+ {
+ if (!BitConverter.IsLittleEndian)
+ {
+ words[i] = ReverseWord(words[i]);
+ }
+
+ tempBytes = BitConverter.GetBytes(words[i]);
+ Array.Copy(tempBytes, 0, bytes, i * tempBytes.Length, tempBytes.Length);
+ }
+ return bytes;
+ }
+
+ private ulong ReverseWord(ulong x)
+ {
+ byte[] bytes = BitConverter.GetBytes(x);
+ Array.Reverse(bytes);
+ return BitConverter.ToUInt64(bytes, 0);
+ }
+
+ private void AddRoundKey(int round)
+ {
+ for (int i = 0; i < wordsInBlock; ++i)
+ {
+ internalState[i] += roundKeys[round][i];
+ }
+ }
+
+ private void SubRoundKey(int round)
+ {
+ for (int i = 0; i < wordsInBlock; ++i)
+ {
+ internalState[i] -= roundKeys[round][i];
+ }
+ }
+
+ private void MixColumns()
+ {
+ MatrixMultiply(mdsMatrix);
+ }
+
+ private void InvMixColumns()
+ {
+ MatrixMultiply(mdsInvMatrix);
+ }
+
+ private void MatrixMultiply(byte[][] matrix)
+ {
+ int col, row, b;
+ byte product;
+ ulong result;
+ byte[] stateBytes = WordsToBytes(internalState);
+
+ for (col = 0; col < wordsInBlock; ++col)
+ {
+ result = 0;
+ for (row = sizeof(ulong) - 1; row >= 0; --row)
+ {
+ product = 0;
+ for (b = sizeof(ulong) - 1; b >= 0; --b)
+ {
+ product ^= MultiplyGF(stateBytes[b + col * sizeof(ulong)], matrix[row][b]);
+ }
+ result |= (ulong)product << (row * sizeof(ulong));
+ }
+ internalState[col] = result;
+ }
+ }
+
+ private byte MultiplyGF(byte x, byte y)
+ {
+ byte r = 0;
+ byte hbit = 0;
+
+ for (int i = 0; i < BITS_IN_BYTE; i++)
+ {
+ if ((y & 0x01) == 1)
+ {
+ r ^= x;
+ }
+
+ hbit = (byte)(x & 0x80);
+
+ x <<= 1;
+
+ if (hbit == 0x80)
+ {
+ x = (byte)((int)x ^ REDUCTION_POLYNOMIAL);
+ }
+ y >>= 1;
+ }
+ return r;
+ }
+
+ private void SubBytes()
+ {
+ for (int i = 0; i < wordsInBlock; i++)
+ {
+ internalState[i] = sboxesForEncryption[0][internalState[i] & 0x00000000000000FF] |
+ ((ulong)sboxesForEncryption[1][(internalState[i] & 0x000000000000FF00) >> 8] << 8) |
+ ((ulong)sboxesForEncryption[2][(internalState[i] & 0x0000000000FF0000) >> 16] << 16) |
+ ((ulong)sboxesForEncryption[3][(internalState[i] & 0x00000000FF000000) >> 24] << 24) |
+ ((ulong)sboxesForEncryption[0][(internalState[i] & 0x000000FF00000000) >> 32] << 32) |
+ ((ulong)sboxesForEncryption[1][(internalState[i] & 0x0000FF0000000000) >> 40] << 40) |
+ ((ulong)sboxesForEncryption[2][(internalState[i] & 0x00FF000000000000) >> 48] << 48) |
+ ((ulong)sboxesForEncryption[3][(internalState[i] & 0xFF00000000000000) >> 56] << 56);
+ }
+ }
+
+ private void InvSubBytes()
+ {
+ for (int i = 0; i < wordsInBlock; i++)
+ {
+ internalState[i] = sboxesForDecryption[0][internalState[i] & 0x00000000000000FF] |
+ ((ulong)sboxesForDecryption[1][(internalState[i] & 0x000000000000FF00) >> 8] << 8) |
+ ((ulong)sboxesForDecryption[2][(internalState[i] & 0x0000000000FF0000) >> 16] << 16) |
+ ((ulong)sboxesForDecryption[3][(internalState[i] & 0x00000000FF000000) >> 24] << 24) |
+ ((ulong)sboxesForDecryption[0][(internalState[i] & 0x000000FF00000000) >> 32] << 32) |
+ ((ulong)sboxesForDecryption[1][(internalState[i] & 0x0000FF0000000000) >> 40] << 40) |
+ ((ulong)sboxesForDecryption[2][(internalState[i] & 0x00FF000000000000) >> 48] << 48) |
+ ((ulong)sboxesForDecryption[3][(internalState[i] & 0xFF00000000000000) >> 56] << 56);
+ }
+ }
+
+
+ #region TABLES AND S-BOXES
+
+ private byte[][] mdsMatrix =
+ {
+ new byte[] { 0x01, 0x01, 0x05, 0x01, 0x08, 0x06, 0x07, 0x04 },
+ new byte[] { 0x04, 0x01, 0x01, 0x05, 0x01, 0x08, 0x06, 0x07 },
+ new byte[] { 0x07, 0x04, 0x01, 0x01, 0x05, 0x01, 0x08, 0x06 },
+ new byte[] { 0x06, 0x07, 0x04, 0x01, 0x01, 0x05, 0x01, 0x08 },
+ new byte[] { 0x08, 0x06, 0x07, 0x04, 0x01, 0x01, 0x05, 0x01 },
+ new byte[] { 0x01, 0x08, 0x06, 0x07, 0x04, 0x01, 0x01, 0x05 },
+ new byte[] { 0x05, 0x01, 0x08, 0x06, 0x07, 0x04, 0x01, 0x01 },
+ new byte[] { 0x01, 0x05, 0x01, 0x08, 0x06, 0x07, 0x04, 0x01 },
+ };
+
+ private byte[][] mdsInvMatrix =
+ {
+ new byte[] { 0xAD, 0x95, 0x76, 0xA8, 0x2F, 0x49, 0xD7, 0xCA },
+ new byte[] { 0xCA, 0xAD, 0x95, 0x76, 0xA8, 0x2F, 0x49, 0xD7 },
+ new byte[] { 0xD7, 0xCA, 0xAD, 0x95, 0x76, 0xA8, 0x2F, 0x49 },
+ new byte[] { 0x49, 0xD7, 0xCA, 0xAD, 0x95, 0x76, 0xA8, 0x2F },
+ new byte[] { 0x2F, 0x49, 0xD7, 0xCA, 0xAD, 0x95, 0x76, 0xA8 },
+ new byte[] { 0xA8, 0x2F, 0x49, 0xD7, 0xCA, 0xAD, 0x95, 0x76 },
+ new byte[] { 0x76, 0xA8, 0x2F, 0x49, 0xD7, 0xCA, 0xAD, 0x95 },
+ new byte[] { 0x95, 0x76, 0xA8, 0x2F, 0x49, 0xD7, 0xCA, 0xAD },
+ };
+
+
+ private byte[][] sboxesForEncryption =
+ {
+ new byte[]
+ {
+ 0xa8, 0x43, 0x5f, 0x06, 0x6b, 0x75, 0x6c, 0x59, 0x71, 0xdf, 0x87, 0x95, 0x17, 0xf0, 0xd8, 0x09,
+ 0x6d, 0xf3, 0x1d, 0xcb, 0xc9, 0x4d, 0x2c, 0xaf, 0x79, 0xe0, 0x97, 0xfd, 0x6f, 0x4b, 0x45, 0x39,
+ 0x3e, 0xdd, 0xa3, 0x4f, 0xb4, 0xb6, 0x9a, 0x0e, 0x1f, 0xbf, 0x15, 0xe1, 0x49, 0xd2, 0x93, 0xc6,
+ 0x92, 0x72, 0x9e, 0x61, 0xd1, 0x63, 0xfa, 0xee, 0xf4, 0x19, 0xd5, 0xad, 0x58, 0xa4, 0xbb, 0xa1,
+ 0xdc, 0xf2, 0x83, 0x37, 0x42, 0xe4, 0x7a, 0x32, 0x9c, 0xcc, 0xab, 0x4a, 0x8f, 0x6e, 0x04, 0x27,
+ 0x2e, 0xe7, 0xe2, 0x5a, 0x96, 0x16, 0x23, 0x2b, 0xc2, 0x65, 0x66, 0x0f, 0xbc, 0xa9, 0x47, 0x41,
+ 0x34, 0x48, 0xfc, 0xb7, 0x6a, 0x88, 0xa5, 0x53, 0x86, 0xf9, 0x5b, 0xdb, 0x38, 0x7b, 0xc3, 0x1e,
+ 0x22, 0x33, 0x24, 0x28, 0x36, 0xc7, 0xb2, 0x3b, 0x8e, 0x77, 0xba, 0xf5, 0x14, 0x9f, 0x08, 0x55,
+ 0x9b, 0x4c, 0xfe, 0x60, 0x5c, 0xda, 0x18, 0x46, 0xcd, 0x7d, 0x21, 0xb0, 0x3f, 0x1b, 0x89, 0xff,
+ 0xeb, 0x84, 0x69, 0x3a, 0x9d, 0xd7, 0xd3, 0x70, 0x67, 0x40, 0xb5, 0xde, 0x5d, 0x30, 0x91, 0xb1,
+ 0x78, 0x11, 0x01, 0xe5, 0x00, 0x68, 0x98, 0xa0, 0xc5, 0x02, 0xa6, 0x74, 0x2d, 0x0b, 0xa2, 0x76,
+ 0xb3, 0xbe, 0xce, 0xbd, 0xae, 0xe9, 0x8a, 0x31, 0x1c, 0xec, 0xf1, 0x99, 0x94, 0xaa, 0xf6, 0x26,
+ 0x2f, 0xef, 0xe8, 0x8c, 0x35, 0x03, 0xd4, 0x7f, 0xfb, 0x05, 0xc1, 0x5e, 0x90, 0x20, 0x3d, 0x82,
+ 0xf7, 0xea, 0x0a, 0x0d, 0x7e, 0xf8, 0x50, 0x1a, 0xc4, 0x07, 0x57, 0xb8, 0x3c, 0x62, 0xe3, 0xc8,
+ 0xac, 0x52, 0x64, 0x10, 0xd0, 0xd9, 0x13, 0x0c, 0x12, 0x29, 0x51, 0xb9, 0xcf, 0xd6, 0x73, 0x8d,
+ 0x81, 0x54, 0xc0, 0xed, 0x4e, 0x44, 0xa7, 0x2a, 0x85, 0x25, 0xe6, 0xca, 0x7c, 0x8b, 0x56, 0x80
+ },
+
+ new byte[]
+ {
+ 0xce, 0xbb, 0xeb, 0x92, 0xea, 0xcb, 0x13, 0xc1, 0xe9, 0x3a, 0xd6, 0xb2, 0xd2, 0x90, 0x17, 0xf8,
+ 0x42, 0x15, 0x56, 0xb4, 0x65, 0x1c, 0x88, 0x43, 0xc5, 0x5c, 0x36, 0xba, 0xf5, 0x57, 0x67, 0x8d,
+ 0x31, 0xf6, 0x64, 0x58, 0x9e, 0xf4, 0x22, 0xaa, 0x75, 0x0f, 0x02, 0xb1, 0xdf, 0x6d, 0x73, 0x4d,
+ 0x7c, 0x26, 0x2e, 0xf7, 0x08, 0x5d, 0x44, 0x3e, 0x9f, 0x14, 0xc8, 0xae, 0x54, 0x10, 0xd8, 0xbc,
+ 0x1a, 0x6b, 0x69, 0xf3, 0xbd, 0x33, 0xab, 0xfa, 0xd1, 0x9b, 0x68, 0x4e, 0x16, 0x95, 0x91, 0xee,
+ 0x4c, 0x63, 0x8e, 0x5b, 0xcc, 0x3c, 0x19, 0xa1, 0x81, 0x49, 0x7b, 0xd9, 0x6f, 0x37, 0x60, 0xca,
+ 0xe7, 0x2b, 0x48, 0xfd, 0x96, 0x45, 0xfc, 0x41, 0x12, 0x0d, 0x79, 0xe5, 0x89, 0x8c, 0xe3, 0x20,
+ 0x30, 0xdc, 0xb7, 0x6c, 0x4a, 0xb5, 0x3f, 0x97, 0xd4, 0x62, 0x2d, 0x06, 0xa4, 0xa5, 0x83, 0x5f,
+ 0x2a, 0xda, 0xc9, 0x00, 0x7e, 0xa2, 0x55, 0xbf, 0x11, 0xd5, 0x9c, 0xcf, 0x0e, 0x0a, 0x3d, 0x51,
+ 0x7d, 0x93, 0x1b, 0xfe, 0xc4, 0x47, 0x09, 0x86, 0x0b, 0x8f, 0x9d, 0x6a, 0x07, 0xb9, 0xb0, 0x98,
+ 0x18, 0x32, 0x71, 0x4b, 0xef, 0x3b, 0x70, 0xa0, 0xe4, 0x40, 0xff, 0xc3, 0xa9, 0xe6, 0x78, 0xf9,
+ 0x8b, 0x46, 0x80, 0x1e, 0x38, 0xe1, 0xb8, 0xa8, 0xe0, 0x0c, 0x23, 0x76, 0x1d, 0x25, 0x24, 0x05,
+ 0xf1, 0x6e, 0x94, 0x28, 0x9a, 0x84, 0xe8, 0xa3, 0x4f, 0x77, 0xd3, 0x85, 0xe2, 0x52, 0xf2, 0x82,
+ 0x50, 0x7a, 0x2f, 0x74, 0x53, 0xb3, 0x61, 0xaf, 0x39, 0x35, 0xde, 0xcd, 0x1f, 0x99, 0xac, 0xad,
+ 0x72, 0x2c, 0xdd, 0xd0, 0x87, 0xbe, 0x5e, 0xa6, 0xec, 0x04, 0xc6, 0x03, 0x34, 0xfb, 0xdb, 0x59,
+ 0xb6, 0xc2, 0x01, 0xf0, 0x5a, 0xed, 0xa7, 0x66, 0x21, 0x7f, 0x8a, 0x27, 0xc7, 0xc0, 0x29, 0xd7
+ },
+
+ new byte[]
+ {
+ 0x93, 0xd9, 0x9a, 0xb5, 0x98, 0x22, 0x45, 0xfc, 0xba, 0x6a, 0xdf, 0x02, 0x9f, 0xdc, 0x51, 0x59,
+ 0x4a, 0x17, 0x2b, 0xc2, 0x94, 0xf4, 0xbb, 0xa3, 0x62, 0xe4, 0x71, 0xd4, 0xcd, 0x70, 0x16, 0xe1,
+ 0x49, 0x3c, 0xc0, 0xd8, 0x5c, 0x9b, 0xad, 0x85, 0x53, 0xa1, 0x7a, 0xc8, 0x2d, 0xe0, 0xd1, 0x72,
+ 0xa6, 0x2c, 0xc4, 0xe3, 0x76, 0x78, 0xb7, 0xb4, 0x09, 0x3b, 0x0e, 0x41, 0x4c, 0xde, 0xb2, 0x90,
+ 0x25, 0xa5, 0xd7, 0x03, 0x11, 0x00, 0xc3, 0x2e, 0x92, 0xef, 0x4e, 0x12, 0x9d, 0x7d, 0xcb, 0x35,
+ 0x10, 0xd5, 0x4f, 0x9e, 0x4d, 0xa9, 0x55, 0xc6, 0xd0, 0x7b, 0x18, 0x97, 0xd3, 0x36, 0xe6, 0x48,
+ 0x56, 0x81, 0x8f, 0x77, 0xcc, 0x9c, 0xb9, 0xe2, 0xac, 0xb8, 0x2f, 0x15, 0xa4, 0x7c, 0xda, 0x38,
+ 0x1e, 0x0b, 0x05, 0xd6, 0x14, 0x6e, 0x6c, 0x7e, 0x66, 0xfd, 0xb1, 0xe5, 0x60, 0xaf, 0x5e, 0x33,
+ 0x87, 0xc9, 0xf0, 0x5d, 0x6d, 0x3f, 0x88, 0x8d, 0xc7, 0xf7, 0x1d, 0xe9, 0xec, 0xed, 0x80, 0x29,
+ 0x27, 0xcf, 0x99, 0xa8, 0x50, 0x0f, 0x37, 0x24, 0x28, 0x30, 0x95, 0xd2, 0x3e, 0x5b, 0x40, 0x83,
+ 0xb3, 0x69, 0x57, 0x1f, 0x07, 0x1c, 0x8a, 0xbc, 0x20, 0xeb, 0xce, 0x8e, 0xab, 0xee, 0x31, 0xa2,
+ 0x73, 0xf9, 0xca, 0x3a, 0x1a, 0xfb, 0x0d, 0xc1, 0xfe, 0xfa, 0xf2, 0x6f, 0xbd, 0x96, 0xdd, 0x43,
+ 0x52, 0xb6, 0x08, 0xf3, 0xae, 0xbe, 0x19, 0x89, 0x32, 0x26, 0xb0, 0xea, 0x4b, 0x64, 0x84, 0x82,
+ 0x6b, 0xf5, 0x79, 0xbf, 0x01, 0x5f, 0x75, 0x63, 0x1b, 0x23, 0x3d, 0x68, 0x2a, 0x65, 0xe8, 0x91,
+ 0xf6, 0xff, 0x13, 0x58, 0xf1, 0x47, 0x0a, 0x7f, 0xc5, 0xa7, 0xe7, 0x61, 0x5a, 0x06, 0x46, 0x44,
+ 0x42, 0x04, 0xa0, 0xdb, 0x39, 0x86, 0x54, 0xaa, 0x8c, 0x34, 0x21, 0x8b, 0xf8, 0x0c, 0x74, 0x67
+ },
+
+ new byte[]
+ {
+ 0x68, 0x8d, 0xca, 0x4d, 0x73, 0x4b, 0x4e, 0x2a, 0xd4, 0x52, 0x26, 0xb3, 0x54, 0x1e, 0x19, 0x1f,
+ 0x22, 0x03, 0x46, 0x3d, 0x2d, 0x4a, 0x53, 0x83, 0x13, 0x8a, 0xb7, 0xd5, 0x25, 0x79, 0xf5, 0xbd,
+ 0x58, 0x2f, 0x0d, 0x02, 0xed, 0x51, 0x9e, 0x11, 0xf2, 0x3e, 0x55, 0x5e, 0xd1, 0x16, 0x3c, 0x66,
+ 0x70, 0x5d, 0xf3, 0x45, 0x40, 0xcc, 0xe8, 0x94, 0x56, 0x08, 0xce, 0x1a, 0x3a, 0xd2, 0xe1, 0xdf,
+ 0xb5, 0x38, 0x6e, 0x0e, 0xe5, 0xf4, 0xf9, 0x86, 0xe9, 0x4f, 0xd6, 0x85, 0x23, 0xcf, 0x32, 0x99,
+ 0x31, 0x14, 0xae, 0xee, 0xc8, 0x48, 0xd3, 0x30, 0xa1, 0x92, 0x41, 0xb1, 0x18, 0xc4, 0x2c, 0x71,
+ 0x72, 0x44, 0x15, 0xfd, 0x37, 0xbe, 0x5f, 0xaa, 0x9b, 0x88, 0xd8, 0xab, 0x89, 0x9c, 0xfa, 0x60,
+ 0xea, 0xbc, 0x62, 0x0c, 0x24, 0xa6, 0xa8, 0xec, 0x67, 0x20, 0xdb, 0x7c, 0x28, 0xdd, 0xac, 0x5b,
+ 0x34, 0x7e, 0x10, 0xf1, 0x7b, 0x8f, 0x63, 0xa0, 0x05, 0x9a, 0x43, 0x77, 0x21, 0xbf, 0x27, 0x09,
+ 0xc3, 0x9f, 0xb6, 0xd7, 0x29, 0xc2, 0xeb, 0xc0, 0xa4, 0x8b, 0x8c, 0x1d, 0xfb, 0xff, 0xc1, 0xb2,
+ 0x97, 0x2e, 0xf8, 0x65, 0xf6, 0x75, 0x07, 0x04, 0x49, 0x33, 0xe4, 0xd9, 0xb9, 0xd0, 0x42, 0xc7,
+ 0x6c, 0x90, 0x00, 0x8e, 0x6f, 0x50, 0x01, 0xc5, 0xda, 0x47, 0x3f, 0xcd, 0x69, 0xa2, 0xe2, 0x7a,
+ 0xa7, 0xc6, 0x93, 0x0f, 0x0a, 0x06, 0xe6, 0x2b, 0x96, 0xa3, 0x1c, 0xaf, 0x6a, 0x12, 0x84, 0x39,
+ 0xe7, 0xb0, 0x82, 0xf7, 0xfe, 0x9d, 0x87, 0x5c, 0x81, 0x35, 0xde, 0xb4, 0xa5, 0xfc, 0x80, 0xef,
+ 0xcb, 0xbb, 0x6b, 0x76, 0xba, 0x5a, 0x7d, 0x78, 0x0b, 0x95, 0xe3, 0xad, 0x74, 0x98, 0x3b, 0x36,
+ 0x64, 0x6d, 0xdc, 0xf0, 0x59, 0xa9, 0x4c, 0x17, 0x7f, 0x91, 0xb8, 0xc9, 0x57, 0x1b, 0xe0, 0x61
+ }
+
+ };
+
+
+ private byte[][] sboxesForDecryption =
+ {
+ new byte[]
+ {
+ 0xa4, 0xa2, 0xa9, 0xc5, 0x4e, 0xc9, 0x03, 0xd9, 0x7e, 0x0f, 0xd2, 0xad, 0xe7, 0xd3, 0x27, 0x5b,
+ 0xe3, 0xa1, 0xe8, 0xe6, 0x7c, 0x2a, 0x55, 0x0c, 0x86, 0x39, 0xd7, 0x8d, 0xb8, 0x12, 0x6f, 0x28,
+ 0xcd, 0x8a, 0x70, 0x56, 0x72, 0xf9, 0xbf, 0x4f, 0x73, 0xe9, 0xf7, 0x57, 0x16, 0xac, 0x50, 0xc0,
+ 0x9d, 0xb7, 0x47, 0x71, 0x60, 0xc4, 0x74, 0x43, 0x6c, 0x1f, 0x93, 0x77, 0xdc, 0xce, 0x20, 0x8c,
+ 0x99, 0x5f, 0x44, 0x01, 0xf5, 0x1e, 0x87, 0x5e, 0x61, 0x2c, 0x4b, 0x1d, 0x81, 0x15, 0xf4, 0x23,
+ 0xd6, 0xea, 0xe1, 0x67, 0xf1, 0x7f, 0xfe, 0xda, 0x3c, 0x07, 0x53, 0x6a, 0x84, 0x9c, 0xcb, 0x02,
+ 0x83, 0x33, 0xdd, 0x35, 0xe2, 0x59, 0x5a, 0x98, 0xa5, 0x92, 0x64, 0x04, 0x06, 0x10, 0x4d, 0x1c,
+ 0x97, 0x08, 0x31, 0xee, 0xab, 0x05, 0xaf, 0x79, 0xa0, 0x18, 0x46, 0x6d, 0xfc, 0x89, 0xd4, 0xc7,
+ 0xff, 0xf0, 0xcf, 0x42, 0x91, 0xf8, 0x68, 0x0a, 0x65, 0x8e, 0xb6, 0xfd, 0xc3, 0xef, 0x78, 0x4c,
+ 0xcc, 0x9e, 0x30, 0x2e, 0xbc, 0x0b, 0x54, 0x1a, 0xa6, 0xbb, 0x26, 0x80, 0x48, 0x94, 0x32, 0x7d,
+ 0xa7, 0x3f, 0xae, 0x22, 0x3d, 0x66, 0xaa, 0xf6, 0x00, 0x5d, 0xbd, 0x4a, 0xe0, 0x3b, 0xb4, 0x17,
+ 0x8b, 0x9f, 0x76, 0xb0, 0x24, 0x9a, 0x25, 0x63, 0xdb, 0xeb, 0x7a, 0x3e, 0x5c, 0xb3, 0xb1, 0x29,
+ 0xf2, 0xca, 0x58, 0x6e, 0xd8, 0xa8, 0x2f, 0x75, 0xdf, 0x14, 0xfb, 0x13, 0x49, 0x88, 0xb2, 0xec,
+ 0xe4, 0x34, 0x2d, 0x96, 0xc6, 0x3a, 0xed, 0x95, 0x0e, 0xe5, 0x85, 0x6b, 0x40, 0x21, 0x9b, 0x09,
+ 0x19, 0x2b, 0x52, 0xde, 0x45, 0xa3, 0xfa, 0x51, 0xc2, 0xb5, 0xd1, 0x90, 0xb9, 0xf3, 0x37, 0xc1,
+ 0x0d, 0xba, 0x41, 0x11, 0x38, 0x7b, 0xbe, 0xd0, 0xd5, 0x69, 0x36, 0xc8, 0x62, 0x1b, 0x82, 0x8f
+ },
+
+ new byte[]
+ {
+ 0x83, 0xf2, 0x2a, 0xeb, 0xe9, 0xbf, 0x7b, 0x9c, 0x34, 0x96, 0x8d, 0x98, 0xb9, 0x69, 0x8c, 0x29,
+ 0x3d, 0x88, 0x68, 0x06, 0x39, 0x11, 0x4c, 0x0e, 0xa0, 0x56, 0x40, 0x92, 0x15, 0xbc, 0xb3, 0xdc,
+ 0x6f, 0xf8, 0x26, 0xba, 0xbe, 0xbd, 0x31, 0xfb, 0xc3, 0xfe, 0x80, 0x61, 0xe1, 0x7a, 0x32, 0xd2,
+ 0x70, 0x20, 0xa1, 0x45, 0xec, 0xd9, 0x1a, 0x5d, 0xb4, 0xd8, 0x09, 0xa5, 0x55, 0x8e, 0x37, 0x76,
+ 0xa9, 0x67, 0x10, 0x17, 0x36, 0x65, 0xb1, 0x95, 0x62, 0x59, 0x74, 0xa3, 0x50, 0x2f, 0x4b, 0xc8,
+ 0xd0, 0x8f, 0xcd, 0xd4, 0x3c, 0x86, 0x12, 0x1d, 0x23, 0xef, 0xf4, 0x53, 0x19, 0x35, 0xe6, 0x7f,
+ 0x5e, 0xd6, 0x79, 0x51, 0x22, 0x14, 0xf7, 0x1e, 0x4a, 0x42, 0x9b, 0x41, 0x73, 0x2d, 0xc1, 0x5c,
+ 0xa6, 0xa2, 0xe0, 0x2e, 0xd3, 0x28, 0xbb, 0xc9, 0xae, 0x6a, 0xd1, 0x5a, 0x30, 0x90, 0x84, 0xf9,
+ 0xb2, 0x58, 0xcf, 0x7e, 0xc5, 0xcb, 0x97, 0xe4, 0x16, 0x6c, 0xfa, 0xb0, 0x6d, 0x1f, 0x52, 0x99,
+ 0x0d, 0x4e, 0x03, 0x91, 0xc2, 0x4d, 0x64, 0x77, 0x9f, 0xdd, 0xc4, 0x49, 0x8a, 0x9a, 0x24, 0x38,
+ 0xa7, 0x57, 0x85, 0xc7, 0x7c, 0x7d, 0xe7, 0xf6, 0xb7, 0xac, 0x27, 0x46, 0xde, 0xdf, 0x3b, 0xd7,
+ 0x9e, 0x2b, 0x0b, 0xd5, 0x13, 0x75, 0xf0, 0x72, 0xb6, 0x9d, 0x1b, 0x01, 0x3f, 0x44, 0xe5, 0x87,
+ 0xfd, 0x07, 0xf1, 0xab, 0x94, 0x18, 0xea, 0xfc, 0x3a, 0x82, 0x5f, 0x05, 0x54, 0xdb, 0x00, 0x8b,
+ 0xe3, 0x48, 0x0c, 0xca, 0x78, 0x89, 0x0a, 0xff, 0x3e, 0x5b, 0x81, 0xee, 0x71, 0xe2, 0xda, 0x2c,
+ 0xb8, 0xb5, 0xcc, 0x6e, 0xa8, 0x6b, 0xad, 0x60, 0xc6, 0x08, 0x04, 0x02, 0xe8, 0xf5, 0x4f, 0xa4,
+ 0xf3, 0xc0, 0xce, 0x43, 0x25, 0x1c, 0x21, 0x33, 0x0f, 0xaf, 0x47, 0xed, 0x66, 0x63, 0x93, 0xaa
+ },
+
+ new byte[]
+ {
+ 0x45, 0xd4, 0x0b, 0x43, 0xf1, 0x72, 0xed, 0xa4, 0xc2, 0x38, 0xe6, 0x71, 0xfd, 0xb6, 0x3a, 0x95,
+ 0x50, 0x44, 0x4b, 0xe2, 0x74, 0x6b, 0x1e, 0x11, 0x5a, 0xc6, 0xb4, 0xd8, 0xa5, 0x8a, 0x70, 0xa3,
+ 0xa8, 0xfa, 0x05, 0xd9, 0x97, 0x40, 0xc9, 0x90, 0x98, 0x8f, 0xdc, 0x12, 0x31, 0x2c, 0x47, 0x6a,
+ 0x99, 0xae, 0xc8, 0x7f, 0xf9, 0x4f, 0x5d, 0x96, 0x6f, 0xf4, 0xb3, 0x39, 0x21, 0xda, 0x9c, 0x85,
+ 0x9e, 0x3b, 0xf0, 0xbf, 0xef, 0x06, 0xee, 0xe5, 0x5f, 0x20, 0x10, 0xcc, 0x3c, 0x54, 0x4a, 0x52,
+ 0x94, 0x0e, 0xc0, 0x28, 0xf6, 0x56, 0x60, 0xa2, 0xe3, 0x0f, 0xec, 0x9d, 0x24, 0x83, 0x7e, 0xd5,
+ 0x7c, 0xeb, 0x18, 0xd7, 0xcd, 0xdd, 0x78, 0xff, 0xdb, 0xa1, 0x09, 0xd0, 0x76, 0x84, 0x75, 0xbb,
+ 0x1d, 0x1a, 0x2f, 0xb0, 0xfe, 0xd6, 0x34, 0x63, 0x35, 0xd2, 0x2a, 0x59, 0x6d, 0x4d, 0x77, 0xe7,
+ 0x8e, 0x61, 0xcf, 0x9f, 0xce, 0x27, 0xf5, 0x80, 0x86, 0xc7, 0xa6, 0xfb, 0xf8, 0x87, 0xab, 0x62,
+ 0x3f, 0xdf, 0x48, 0x00, 0x14, 0x9a, 0xbd, 0x5b, 0x04, 0x92, 0x02, 0x25, 0x65, 0x4c, 0x53, 0x0c,
+ 0xf2, 0x29, 0xaf, 0x17, 0x6c, 0x41, 0x30, 0xe9, 0x93, 0x55, 0xf7, 0xac, 0x68, 0x26, 0xc4, 0x7d,
+ 0xca, 0x7a, 0x3e, 0xa0, 0x37, 0x03, 0xc1, 0x36, 0x69, 0x66, 0x08, 0x16, 0xa7, 0xbc, 0xc5, 0xd3,
+ 0x22, 0xb7, 0x13, 0x46, 0x32, 0xe8, 0x57, 0x88, 0x2b, 0x81, 0xb2, 0x4e, 0x64, 0x1c, 0xaa, 0x91,
+ 0x58, 0x2e, 0x9b, 0x5c, 0x1b, 0x51, 0x73, 0x42, 0x23, 0x01, 0x6e, 0xf3, 0x0d, 0xbe, 0x3d, 0x0a,
+ 0x2d, 0x1f, 0x67, 0x33, 0x19, 0x7b, 0x5e, 0xea, 0xde, 0x8b, 0xcb, 0xa9, 0x8c, 0x8d, 0xad, 0x49,
+ 0x82, 0xe4, 0xba, 0xc3, 0x15, 0xd1, 0xe0, 0x89, 0xfc, 0xb1, 0xb9, 0xb5, 0x07, 0x79, 0xb8, 0xe1
+ },
+
+ new byte[]
+ {
+ 0xb2, 0xb6, 0x23, 0x11, 0xa7, 0x88, 0xc5, 0xa6, 0x39, 0x8f, 0xc4, 0xe8, 0x73, 0x22, 0x43, 0xc3,
+ 0x82, 0x27, 0xcd, 0x18, 0x51, 0x62, 0x2d, 0xf7, 0x5c, 0x0e, 0x3b, 0xfd, 0xca, 0x9b, 0x0d, 0x0f,
+ 0x79, 0x8c, 0x10, 0x4c, 0x74, 0x1c, 0x0a, 0x8e, 0x7c, 0x94, 0x07, 0xc7, 0x5e, 0x14, 0xa1, 0x21,
+ 0x57, 0x50, 0x4e, 0xa9, 0x80, 0xd9, 0xef, 0x64, 0x41, 0xcf, 0x3c, 0xee, 0x2e, 0x13, 0x29, 0xba,
+ 0x34, 0x5a, 0xae, 0x8a, 0x61, 0x33, 0x12, 0xb9, 0x55, 0xa8, 0x15, 0x05, 0xf6, 0x03, 0x06, 0x49,
+ 0xb5, 0x25, 0x09, 0x16, 0x0c, 0x2a, 0x38, 0xfc, 0x20, 0xf4, 0xe5, 0x7f, 0xd7, 0x31, 0x2b, 0x66,
+ 0x6f, 0xff, 0x72, 0x86, 0xf0, 0xa3, 0x2f, 0x78, 0x00, 0xbc, 0xcc, 0xe2, 0xb0, 0xf1, 0x42, 0xb4,
+ 0x30, 0x5f, 0x60, 0x04, 0xec, 0xa5, 0xe3, 0x8b, 0xe7, 0x1d, 0xbf, 0x84, 0x7b, 0xe6, 0x81, 0xf8,
+ 0xde, 0xd8, 0xd2, 0x17, 0xce, 0x4b, 0x47, 0xd6, 0x69, 0x6c, 0x19, 0x99, 0x9a, 0x01, 0xb3, 0x85,
+ 0xb1, 0xf9, 0x59, 0xc2, 0x37, 0xe9, 0xc8, 0xa0, 0xed, 0x4f, 0x89, 0x68, 0x6d, 0xd5, 0x26, 0x91,
+ 0x87, 0x58, 0xbd, 0xc9, 0x98, 0xdc, 0x75, 0xc0, 0x76, 0xf5, 0x67, 0x6b, 0x7e, 0xeb, 0x52, 0xcb,
+ 0xd1, 0x5b, 0x9f, 0x0b, 0xdb, 0x40, 0x92, 0x1a, 0xfa, 0xac, 0xe4, 0xe1, 0x71, 0x1f, 0x65, 0x8d,
+ 0x97, 0x9e, 0x95, 0x90, 0x5d, 0xb7, 0xc1, 0xaf, 0x54, 0xfb, 0x02, 0xe0, 0x35, 0xbb, 0x3a, 0x4d,
+ 0xad, 0x2c, 0x3d, 0x56, 0x08, 0x1b, 0x4a, 0x93, 0x6a, 0xab, 0xb8, 0x7a, 0xf2, 0x7d, 0xda, 0x3f,
+ 0xfe, 0x3e, 0xbe, 0xea, 0xaa, 0x44, 0xc6, 0xd0, 0x36, 0x48, 0x70, 0x96, 0x77, 0x24, 0x53, 0xdf,
+ 0xf3, 0x83, 0x28, 0x32, 0x45, 0x1e, 0xa4, 0xd3, 0xa2, 0x46, 0x6e, 0x9c, 0xdd, 0x63, 0xd4, 0x9d
+ }
+ };
+ #endregion
+
+
+
+ public virtual string AlgorithmName
+ {
+ get { return "Dstu7624"; }
+ }
+
+ public virtual int GetBlockSize()
+ {
+ return blockSizeBits / BITS_IN_BYTE;
+ }
+
+ public virtual bool IsPartialBlockOkay
+ {
+ get { return false; }
+ }
+
+ public virtual void Reset()
+ {
+
+ }
+
+ }
+}
diff --git a/crypto/src/crypto/engines/Dstu7624WrapEngine.cs b/crypto/src/crypto/engines/Dstu7624WrapEngine.cs
new file mode 100644
index 000000000..5d21f6e85
--- /dev/null
+++ b/crypto/src/crypto/engines/Dstu7624WrapEngine.cs
@@ -0,0 +1,263 @@
+using System;
+
+using Org.BouncyCastle.Crypto.Parameters;
+using System.Collections.Generic;
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.Crypto.Engines
+{
+ public class Dstu7624WrapEngine : IWrapper
+ {
+ private const int BYTES_IN_INTEGER = 4;
+
+ private KeyParameter param;
+ private Dstu7624Engine engine;
+ private bool forWrapping;
+ private int blockSize;
+
+ private byte[] buffer;
+ private byte[] intArray;
+
+ private readonly byte[] checkSumArray, zeroArray;
+
+
+ public Dstu7624WrapEngine(int blockSizeBits)
+ {
+ engine = new Dstu7624Engine(blockSizeBits);
+ param = null;
+
+ blockSize = blockSizeBits / 8;
+ buffer = new byte[blockSize];
+
+ intArray = new byte[BYTES_IN_INTEGER];
+
+ checkSumArray = new byte[blockSize];
+ zeroArray = new byte[blockSize];
+ }
+
+
+ public string AlgorithmName
+ {
+ get { return "Dstu7624WrapEngine"; }
+ }
+
+ public void Init(bool forWrapping, ICipherParameters parameters)
+ {
+ this.forWrapping = forWrapping;
+
+ if (parameters is KeyParameter)
+ {
+ this.param = (KeyParameter)parameters;
+
+ engine.Init(forWrapping, param);
+ }
+ else
+ {
+ throw new ArgumentException("Bad parameters passed to Dstu7624WrapEngine");
+ }
+ }
+
+ public byte[] Wrap(byte[] input, int inOff, int length)
+ {
+ if (!forWrapping)
+ {
+ throw new InvalidOperationException("Not set for wrapping");
+ }
+
+ if ((input.Length - inOff) % blockSize != 0)
+ {
+ throw new ArgumentException("Padding not supported");
+ }
+
+ int n = 2 * (1 + input.Length / blockSize);
+
+ int V = (n - 1) * 6;
+
+ buffer = new byte[input.Length - inOff + blockSize];
+ Array.Copy(input, inOff, buffer, 0, input.Length - inOff);
+ //Console.WriteLine(Org.BouncyCastle.Utilities.Encoders.Hex.ToHexString(buffer));
+
+
+
+ byte[] B = new byte[blockSize / 2];
+ Array.Copy(buffer, 0, B, 0, blockSize / 2);
+ //Console.WriteLine("B0: "+ Org.BouncyCastle.Utilities.Encoders.Hex.ToHexString(B));
+
+
+ List<byte[]> bTemp = new List<byte[]>();
+
+ int bHalfBlocksLen = buffer.Length - blockSize / 2;
+ int bufOff = blockSize / 2;
+ while (bHalfBlocksLen != 0)
+ {
+ byte[] temp = new byte[blockSize / 2];
+ Array.Copy(buffer, bufOff, temp, 0, blockSize / 2);
+ //Console.WriteLine(Org.BouncyCastle.Utilities.Encoders.Hex.ToHexString(buffer));
+ //Console.WriteLine(buffer.Length);
+ //Console.WriteLine("b: " + Org.BouncyCastle.Utilities.Encoders.Hex.ToHexString(temp));
+
+ bTemp.Add(temp);
+
+ bHalfBlocksLen -= blockSize / 2;
+ bufOff += blockSize / 2;
+ }
+
+
+
+ for (int j = 0; j < V; j++)
+ {
+ Array.Copy(B, 0, buffer, 0, blockSize / 2);
+ Array.Copy(bTemp[0], 0, buffer, blockSize / 2, blockSize / 2);
+
+ engine.ProcessBlock(buffer, 0, buffer, 0);
+
+ intTobytes(j + 1, intArray, 0);
+ for (int byteNum = 0; byteNum < BYTES_IN_INTEGER; byteNum++)
+ {
+ buffer[byteNum + blockSize / 2] ^= intArray[byteNum];
+ }
+
+ Array.Copy(buffer, blockSize / 2, B, 0, blockSize / 2);
+
+ for (int i = 2; i < n; i++)
+ {
+ Array.Copy(bTemp[i - 1], 0, bTemp[i - 2], 0, blockSize / 2);
+ }
+
+ Array.Copy(buffer, 0, bTemp[n - 2], 0, blockSize / 2);
+
+ //Console.WriteLine("B" + j.ToString() + ": " + Org.BouncyCastle.Utilities.Encoders.Hex.ToHexString(B));
+ //Console.WriteLine("b: " + Org.BouncyCastle.Utilities.Encoders.Hex.ToHexString(bTemp[0]));
+ //Console.WriteLine("b: " + Org.BouncyCastle.Utilities.Encoders.Hex.ToHexString(bTemp[1]));
+ //Console.WriteLine("b: " + Org.BouncyCastle.Utilities.Encoders.Hex.ToHexString(bTemp[2]));
+
+ //Console.WriteLine(Org.BouncyCastle.Utilities.Encoders.Hex.ToHexString(buffer));
+ }
+
+
+ Array.Copy(B, 0, buffer, 0, blockSize / 2);
+ bufOff = blockSize / 2;
+
+ for (int i = 0; i < n - 1; i++)
+ {
+ Array.Copy(bTemp[i], 0, buffer, bufOff, blockSize / 2);
+ bufOff += blockSize / 2;
+ }
+
+ return buffer;
+ }
+
+ public byte[] Unwrap(byte[] input, int inOff, int length)
+ {
+ if (forWrapping)
+ {
+ throw new InvalidOperationException("not set for unwrapping");
+ }
+
+ if ((input.Length - inOff) % blockSize != 0)
+ {
+ throw new ArgumentException("Padding not supported");
+ }
+
+ int n = 2 * input.Length / blockSize;
+
+ int V = (n - 1) * 6;
+
+ buffer = new byte[input.Length - inOff];
+ Array.Copy(input, inOff, buffer, 0, input.Length - inOff);
+
+ byte[] B = new byte[blockSize / 2];
+ Array.Copy(buffer, 0, B, 0, blockSize / 2);
+ //Console.WriteLine("B18: " + Org.BouncyCastle.Utilities.Encoders.Hex.ToHexString(B));
+
+ List<byte[]> bTemp = new List<byte[]>();
+
+ int bHalfBlocksLen = buffer.Length - blockSize / 2;
+ int bufOff = blockSize / 2;
+ while (bHalfBlocksLen != 0)
+ {
+ byte[] temp = new byte[blockSize / 2];
+ Array.Copy(buffer, bufOff, temp, 0, blockSize / 2);
+ //Console.WriteLine(Org.BouncyCastle.Utilities.Encoders.Hex.ToHexString(buffer));
+ //Console.WriteLine(buffer.Length);
+ //Console.WriteLine("b: " + Org.BouncyCastle.Utilities.Encoders.Hex.ToHexString(temp));
+
+ bTemp.Add(temp);
+
+ bHalfBlocksLen -= blockSize / 2;
+ bufOff += blockSize / 2;
+ }
+
+
+ for (int j = 0; j < V; j++)
+ {
+ Array.Copy(bTemp[n - 2], 0, buffer, 0, blockSize / 2);
+ Array.Copy(B, 0, buffer, blockSize / 2, blockSize / 2);
+ intTobytes(V - j, intArray, 0);
+ for (int byteNum = 0; byteNum < BYTES_IN_INTEGER; byteNum++)
+ {
+ buffer[byteNum + blockSize / 2] ^= intArray[byteNum];
+ }
+
+ //Console.WriteLine(Org.BouncyCastle.Utilities.Encoders.Hex.ToHexString(buffer));
+
+ engine.ProcessBlock(buffer, 0, buffer, 0);
+
+ //Console.WriteLine(Org.BouncyCastle.Utilities.Encoders.Hex.ToHexString(buffer));
+
+ Array.Copy(buffer, 0, B, 0, blockSize / 2);
+
+ for (int i = 2; i < n; i++)
+ {
+ Array.Copy(bTemp[n - i - 1], 0, bTemp[n - i], 0, blockSize / 2);
+ }
+
+ Array.Copy(buffer, blockSize / 2, bTemp[0], 0, blockSize / 2);
+
+ //Console.WriteLine("B" + (V - j - 1).ToString() + ": " + Org.BouncyCastle.Utilities.Encoders.Hex.ToHexString(B));
+ //Console.WriteLine("b: " + Org.BouncyCastle.Utilities.Encoders.Hex.ToHexString(bTemp[0]));
+ //Console.WriteLine("b: " + Org.BouncyCastle.Utilities.Encoders.Hex.ToHexString(bTemp[1]));
+ //Console.WriteLine("b: " + Org.BouncyCastle.Utilities.Encoders.Hex.ToHexString(bTemp[2]));
+
+ //Console.WriteLine(Org.BouncyCastle.Utilities.Encoders.Hex.ToHexString(buffer));
+ }
+
+
+ Array.Copy(B, 0, buffer, 0, blockSize / 2);
+ bufOff = blockSize / 2;
+
+ for (int i = 0; i < n - 1; i++)
+ {
+ Array.Copy(bTemp[i], 0, buffer, bufOff, blockSize / 2);
+ bufOff += blockSize / 2;
+ }
+
+
+ Array.Copy(buffer, buffer.Length - blockSize, checkSumArray, 0, blockSize);
+
+
+ if (!Arrays.AreEqual(checkSumArray, zeroArray))
+ {
+ throw new InvalidCipherTextException("checksum failed");
+ }
+ else
+ {
+ Array.Resize(ref buffer, buffer.Length - blockSize);
+ }
+
+ return buffer;
+ }
+
+ //int to array of bytes
+ private static void intTobytes(
+ int num,
+ byte[] outBytes,
+ int outOff)
+ {
+ outBytes[outOff + 3] = (byte)(num >> 24);
+ outBytes[outOff + 2] = (byte)(num >> 16);
+ outBytes[outOff + 1] = (byte)(num >> 8);
+ outBytes[outOff] = (byte)num;
+ }
+ }
+}
diff --git a/crypto/src/crypto/macs/DSTU7564Mac.cs b/crypto/src/crypto/macs/DSTU7564Mac.cs
new file mode 100644
index 000000000..907355487
--- /dev/null
+++ b/crypto/src/crypto/macs/DSTU7564Mac.cs
@@ -0,0 +1,156 @@
+using System;
+
+using Org.BouncyCastle.Crypto.Digests;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Crypto.Utilities;
+
+namespace Org.BouncyCastle.Crypto.Macs
+{
+ /// <summary>
+ /// Implementation of DSTU7564 mac mode
+ /// </summary>
+ public class Dstu7564Mac : IMac
+ {
+ private Dstu7564Digest engine;
+ private int macSize;
+
+ private ulong inputLength;
+
+ byte[] paddedKey;
+ byte[] invertedKey;
+ byte[] paddedInput;
+
+ public string AlgorithmName
+ {
+ get
+ {
+ return "DSTU7564Mac";
+ }
+ }
+
+ public Dstu7564Mac(int macSizeBits)
+ {
+ engine = new Dstu7564Digest(macSizeBits);
+ macSize = macSizeBits / 8;
+ }
+
+ public void Init(ICipherParameters parameters)
+ {
+ if (parameters is KeyParameter)
+ {
+ byte[] key = ((KeyParameter)parameters).GetKey();
+
+ invertedKey = new byte[key.Length];
+
+ paddedKey = PadKey(key);
+
+ for (int byteIndex = 0; byteIndex < invertedKey.Length; byteIndex++)
+ {
+ invertedKey[byteIndex] = (byte)(key[byteIndex] ^ (byte)0xFF);
+ }
+ }
+ else
+ {
+ throw new ArgumentException("Bad parameter passed");
+ }
+
+ engine.BlockUpdate(paddedKey, 0, paddedKey.Length);
+ }
+
+ public int GetMacSize()
+ {
+ return macSize;
+ }
+
+ public void BlockUpdate(byte[] input, int inOff, int len)
+ {
+ if (input.Length - inOff < len)
+ {
+ throw new DataLengthException("Input buffer too short");
+ }
+
+ if (paddedKey == null)
+ {
+ throw new InvalidOperationException(AlgorithmName + " not initialised");
+ }
+
+ engine.BlockUpdate(input, inOff, len);
+ inputLength += (ulong)len;
+
+ }
+
+ public void Update(byte input)
+ {
+ engine.Update(input);
+ inputLength++;
+ }
+
+ public int DoFinal(byte[] output, int outOff)
+ {
+ if (output.Length - outOff < macSize)
+ {
+ throw new DataLengthException("Output buffer too short");
+ }
+ if (paddedKey == null)
+ {
+ throw new InvalidOperationException(AlgorithmName + " not initialised");
+ }
+
+ Pad();
+
+ engine.BlockUpdate(invertedKey, 0, invertedKey.Length);
+
+ inputLength = 0;
+
+ return engine.DoFinal(output, outOff);
+ }
+
+ public void Reset()
+ {
+ inputLength = 0;
+ engine.Reset();
+ if (paddedKey != null)
+ {
+ engine.BlockUpdate(paddedKey, 0, paddedKey.Length);
+ }
+ }
+
+ private void Pad()
+ {
+ int extra = engine.GetByteLength() - (int)(inputLength % (ulong)engine.GetByteLength());
+ if (extra < 13) // terminator byte + 96 bits of length
+ {
+ extra += engine.GetByteLength();
+ }
+
+ byte[] padded = new byte[extra];
+
+ padded[0] = (byte)0x80; // Defined in standard;
+
+ // Defined in standard;
+ Pack.UInt64_To_LE(inputLength * 8, padded, padded.Length - 12);
+
+ engine.BlockUpdate(padded, 0, padded.Length);
+ }
+
+ private byte[] PadKey(byte[] input)
+ {
+ int paddedLen = ((input.Length + engine.GetByteLength() - 1) / engine.GetByteLength()) *engine.GetByteLength();
+
+ int extra = engine.GetByteLength() - (int)(input.Length % engine.GetByteLength());
+ if (extra < 13) // terminator byte + 96 bits of length
+ {
+ paddedLen += engine.GetByteLength();
+ }
+
+ byte[] padded = new byte[paddedLen];
+
+ Array.Copy(input, 0, padded, 0, input.Length);
+
+ padded[input.Length] = (byte)0x80; // Defined in standard;
+ Pack.UInt32_To_LE((uint)(input.Length * 8), padded, padded.Length - 12); // Defined in standard;
+
+ return padded;
+ }
+ }
+}
diff --git a/crypto/src/crypto/macs/DSTU7624Mac.cs b/crypto/src/crypto/macs/DSTU7624Mac.cs
new file mode 100644
index 000000000..953d8164f
--- /dev/null
+++ b/crypto/src/crypto/macs/DSTU7624Mac.cs
@@ -0,0 +1,160 @@
+using System;
+
+using Org.BouncyCastle.Utilities;
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Crypto.Engines;
+using Org.BouncyCastle.Crypto.Parameters;
+
+
+namespace Org.BouncyCastle.Crypto.Macs
+{
+ /**
+ * implementation of DSTU 7624 MAC
+ */
+ public class Dstu7624Mac : IMac
+ {
+ private int macSize;
+
+ private Dstu7624Engine engine;
+ private int blockSize;
+
+ private byte[] c, cTemp, kDelta;
+ private byte[] buf;
+ private int bufOff;
+
+ public Dstu7624Mac(int blockSizeBits, int q)
+ {
+ engine = new Dstu7624Engine(blockSizeBits);
+
+ blockSize = blockSizeBits / 8;
+
+ macSize = q / 8;
+
+ c = new byte[blockSize];
+
+ cTemp = new byte[blockSize];
+
+ kDelta = new byte[blockSize];
+ buf = new byte[blockSize];
+ }
+
+ public void Init(ICipherParameters parameters)
+ {
+ if (parameters is KeyParameter)
+ {
+ engine.Init(true, (KeyParameter)parameters);
+
+ engine.ProcessBlock(kDelta, 0, kDelta, 0);
+ }
+ else
+ {
+ throw new ArgumentException("invalid parameter passed to Dstu7624Mac init - "
+ + Platform.GetTypeName(parameters));
+ }
+ }
+
+ public string AlgorithmName
+ {
+ get { return "Dstu7624Mac"; }
+ }
+
+ public int GetMacSize()
+ {
+ return macSize;
+ }
+
+ public void Update(byte input)
+ {
+ if (bufOff == buf.Length)
+ {
+ processBlock(buf, 0);
+ bufOff = 0;
+ }
+
+ buf[bufOff++] = input;
+ }
+
+ public void BlockUpdate(byte[] input, int inOff, int len)
+ {
+ if (len < 0)
+ {
+ throw new ArgumentException(
+ "Can't have a negative input length!");
+ }
+
+ int blockSize = engine.GetBlockSize();
+ int gapLen = blockSize - bufOff;
+
+ if (len > gapLen)
+ {
+ Array.Copy(input, inOff, buf, bufOff, gapLen);
+
+ processBlock(buf, 0);
+
+ bufOff = 0;
+ len -= gapLen;
+ inOff += gapLen;
+
+ while (len > blockSize)
+ {
+ processBlock(input, inOff);
+
+ len -= blockSize;
+ inOff += blockSize;
+ }
+ }
+
+ Array.Copy(input, inOff, buf, bufOff, len);
+
+ bufOff += len;
+ }
+
+ private void processBlock(byte[] input, int inOff)
+ {
+ Xor(c, 0, input, inOff, cTemp);
+
+ engine.ProcessBlock(cTemp, 0, c, 0);
+ }
+
+ private void Xor(byte[] c, int cOff, byte[] input, int inOff, byte[] xorResult)
+ {
+ for (int byteIndex = 0; byteIndex < blockSize; byteIndex++)
+ {
+ xorResult[byteIndex] = (byte)(c[byteIndex + cOff] ^ input[byteIndex + inOff]);
+ }
+ }
+
+ public int DoFinal(byte[] output, int outOff)
+ {
+ if (bufOff % buf.Length != 0)
+ {
+ throw new DataLengthException("Input must be a multiple of blocksize");
+ }
+
+ //Last block
+ Xor(c, 0, buf, 0, cTemp);
+ Xor(cTemp, 0, kDelta, 0, c);
+ engine.ProcessBlock(c, 0, c, 0);
+
+ if (macSize + outOff > output.Length)
+ {
+ throw new DataLengthException("Output buffer too short");
+ }
+
+ Array.Copy(c, 0, output, outOff, macSize);
+
+ return macSize;
+ }
+
+ public void Reset()
+ {
+ Arrays.Fill(c, (byte)0x00);
+ Arrays.Fill(cTemp, (byte)0x00);
+ Arrays.Fill(kDelta, (byte)0x00);
+ Arrays.Fill(buf, (byte)0x00);
+ engine.Reset();
+ engine.ProcessBlock(kDelta, 0, kDelta, 0);
+ bufOff = 0;
+ }
+ }
+}
diff --git a/crypto/src/crypto/modes/GCMBlockCipher.cs b/crypto/src/crypto/modes/GCMBlockCipher.cs
index 9d940fe75..a6cd00401 100644
--- a/crypto/src/crypto/modes/GCMBlockCipher.cs
+++ b/crypto/src/crypto/modes/GCMBlockCipher.cs
@@ -23,7 +23,9 @@ namespace Org.BouncyCastle.Crypto.Modes
// These fields are set by Init and not modified by processing
private bool forEncryption;
+ private bool initialised;
private int macSize;
+ private byte[] lastKey;
private byte[] nonce;
private byte[] initialAssociatedText;
private byte[] H;
@@ -90,14 +92,16 @@ namespace Org.BouncyCastle.Crypto.Modes
{
this.forEncryption = forEncryption;
this.macBlock = null;
+ this.initialised = true;
KeyParameter keyParam;
+ byte[] newNonce = null;
if (parameters is AeadParameters)
{
AeadParameters param = (AeadParameters)parameters;
- nonce = param.GetNonce();
+ newNonce = param.GetNonce();
initialAssociatedText = param.GetAssociatedText();
int macSizeBits = param.MacSize;
@@ -113,7 +117,7 @@ namespace Org.BouncyCastle.Crypto.Modes
{
ParametersWithIV param = (ParametersWithIV)parameters;
- nonce = param.GetIV();
+ newNonce = param.GetIV();
initialAssociatedText = null;
macSize = 16;
keyParam = (KeyParameter)param.Parameters;
@@ -126,11 +130,32 @@ namespace Org.BouncyCastle.Crypto.Modes
int bufLength = forEncryption ? BlockSize : (BlockSize + macSize);
this.bufBlock = new byte[bufLength];
- if (nonce == null || nonce.Length < 1)
+ if (newNonce == null || newNonce.Length < 1)
{
throw new ArgumentException("IV must be at least 1 byte");
}
+ if (forEncryption)
+ {
+ if (nonce != null && Arrays.AreEqual(nonce, newNonce))
+ {
+ if (keyParam == null)
+ {
+ throw new ArgumentException("cannot reuse nonce for GCM encryption");
+ }
+ if (lastKey != null && Arrays.AreEqual(lastKey, keyParam.GetKey()))
+ {
+ throw new ArgumentException("cannot reuse nonce for GCM encryption");
+ }
+ }
+ }
+
+ nonce = newNonce;
+ if (keyParam != null)
+ {
+ lastKey = keyParam.GetKey();
+ }
+
// TODO Restrict macSize to 16 if nonce length not 12?
// Cipher always used in forward mode
@@ -186,7 +211,9 @@ namespace Org.BouncyCastle.Crypto.Modes
public virtual byte[] GetMac()
{
- return Arrays.Clone(macBlock);
+ return macBlock == null
+ ? new byte[macSize]
+ : Arrays.Clone(macBlock);
}
public virtual int GetOutputSize(
@@ -219,6 +246,8 @@ namespace Org.BouncyCastle.Crypto.Modes
public virtual void ProcessAadByte(byte input)
{
+ CheckStatus();
+
atBlock[atBlockPos] = input;
if (++atBlockPos == BlockSize)
{
@@ -231,6 +260,8 @@ namespace Org.BouncyCastle.Crypto.Modes
public virtual void ProcessAadBytes(byte[] inBytes, int inOff, int len)
{
+ CheckStatus();
+
for (int i = 0; i < len; ++i)
{
atBlock[atBlockPos] = inBytes[inOff + i];
@@ -270,6 +301,8 @@ namespace Org.BouncyCastle.Crypto.Modes
byte[] output,
int outOff)
{
+ CheckStatus();
+
bufBlock[bufOff] = input;
if (++bufOff == bufBlock.Length)
{
@@ -286,6 +319,8 @@ namespace Org.BouncyCastle.Crypto.Modes
byte[] output,
int outOff)
{
+ CheckStatus();
+
if (input.Length < (inOff + len))
throw new DataLengthException("Input buffer too short");
@@ -325,6 +360,8 @@ namespace Org.BouncyCastle.Crypto.Modes
public int DoFinal(byte[] output, int outOff)
{
+ CheckStatus();
+
if (totalLength == 0)
{
InitCipher();
@@ -441,6 +478,8 @@ namespace Org.BouncyCastle.Crypto.Modes
{
cipher.Reset();
+ // note: we do not reset the nonce.
+
S = new byte[BlockSize];
S_at = new byte[BlockSize];
S_atPre = new byte[BlockSize];
@@ -463,9 +502,16 @@ namespace Org.BouncyCastle.Crypto.Modes
macBlock = null;
}
- if (initialAssociatedText != null)
+ if (forEncryption)
{
- ProcessAadBytes(initialAssociatedText, 0, initialAssociatedText.Length);
+ initialised = false;
+ }
+ else
+ {
+ if (initialAssociatedText != null)
+ {
+ ProcessAadBytes(initialAssociatedText, 0, initialAssociatedText.Length);
+ }
}
}
@@ -532,5 +578,17 @@ namespace Org.BouncyCastle.Crypto.Modes
cipher.ProcessBlock(counter, 0, tmp, 0);
return tmp;
}
+
+ private void CheckStatus()
+ {
+ if (!initialised)
+ {
+ if (forEncryption)
+ {
+ throw new InvalidOperationException("GCM cipher cannot be reused for encryption");
+ }
+ throw new InvalidOperationException("GCM cipher needs to be initialised");
+ }
+ }
}
}
diff --git a/crypto/src/crypto/modes/GOFBBlockCipher.cs b/crypto/src/crypto/modes/GOFBBlockCipher.cs
index 4299f11a9..436b58a1d 100644
--- a/crypto/src/crypto/modes/GOFBBlockCipher.cs
+++ b/crypto/src/crypto/modes/GOFBBlockCipher.cs
@@ -171,7 +171,10 @@ namespace Org.BouncyCastle.Crypto.Modes
N4 += C1;
if (N4 < C1) // addition is mod (2**32 - 1)
{
- N4++;
+ if (N4 > 0)
+ {
+ N4++;
+ }
}
intTobytes(N3, ofbV, 0);
intTobytes(N4, ofbV, 4);
diff --git a/crypto/src/crypto/modes/KCtrBlockCipher.cs b/crypto/src/crypto/modes/KCtrBlockCipher.cs
new file mode 100644
index 000000000..ff0249a6c
--- /dev/null
+++ b/crypto/src/crypto/modes/KCtrBlockCipher.cs
@@ -0,0 +1,235 @@
+using System;
+
+using Org.BouncyCastle.Crypto.Parameters;
+
+namespace Org.BouncyCastle.Crypto.Modes
+{
+ /**
+ * Implements a Gamming or Counter (CTR) mode on top of a DSTU 7624 block cipher.
+ */
+ public class KCtrBlockCipher : IStreamCipher, IBlockCipher
+ {
+ private byte[] IV;
+ private byte[] ofbV;
+ private byte[] ofbOutV;
+ private bool initialised;
+
+ private int byteCount;
+
+ private readonly int blockSize;
+ private readonly IBlockCipher cipher;
+
+ /**
+ * Basic constructor.
+ *
+ * @param cipher the block cipher to be used as the basis of the
+ * feedback mode.
+ */
+ public KCtrBlockCipher(IBlockCipher cipher)
+ {
+ this.cipher = cipher;
+ this.IV = new byte[cipher.GetBlockSize()];
+ this.blockSize = cipher.GetBlockSize();
+
+ this.ofbV = new byte[cipher.GetBlockSize()];
+ this.ofbOutV = new byte[cipher.GetBlockSize()];
+ }
+
+ /**
+ * return the underlying block cipher that we are wrapping.
+ *
+ * @return the underlying block cipher that we are wrapping.
+ */
+ public IBlockCipher GetUnderlyingCipher()
+ {
+ return cipher;
+ }
+ /**
+ * Initialise the cipher and, possibly, the initialisation vector (IV).
+ * If an IV isn't passed as part of the parameter, the IV will be all zeros.
+ * An IV which is too short is handled in FIPS compliant fashion.
+ *
+ * @param forEncryption if true the cipher is initialised for
+ * encryption, if false for decryption.
+ * @param param the key and other data required by the cipher.
+ * @exception ArgumentException if the parameters argument is
+ * inappropriate.
+ */
+ public void Init(
+ bool forEncryption,
+ ICipherParameters parameters)
+ {
+ this.initialised = true;
+ if (parameters is ParametersWithIV)
+ {
+ ParametersWithIV ivParam = (ParametersWithIV)parameters;
+ byte[] iv = ivParam.GetIV();
+ int diff = IV.Length - iv.Length;
+
+ Array.Clear(IV, 0, IV.Length);
+ Array.Copy(iv, 0, IV, diff, iv.Length);
+
+ parameters = ivParam.Parameters;
+ }
+ else
+ {
+ throw new ArgumentException("Invalid parameter passed");
+ }
+
+ // if it's null, key is to be reused.
+ if (parameters != null)
+ {
+ cipher.Init(true, parameters);
+ }
+
+ Reset();
+ }
+
+ /**
+ * return the algorithm name and mode.
+ *
+ * @return the name of the underlying algorithm followed by "/KCTR"
+ * and the block size in bits.
+ */
+ public string AlgorithmName
+ {
+ get { return cipher.AlgorithmName + "/KCTR"; }
+ }
+
+ public bool IsPartialBlockOkay
+ {
+ get { return true; }
+ }
+
+ /**
+ * return the block size we are operating at.
+ *
+ * @return the block size we are operating at (in bytes).
+ */
+ public int GetBlockSize()
+ {
+ return cipher.GetBlockSize();
+ }
+
+ public byte ReturnByte(byte input)
+ {
+ return CalculateByte(input);
+ }
+
+ public void ProcessBytes(byte[] input, int inOff, int len, byte[] output, int outOff)
+ {
+ if (outOff + len > output.Length)
+ {
+ throw new DataLengthException("Output buffer too short");
+ }
+
+ if (inOff + len > input.Length)
+ {
+ throw new DataLengthException("Input buffer too small");
+ }
+
+ int inStart = inOff;
+ int inEnd = inOff + len;
+ int outStart = outOff;
+
+ while (inStart<inEnd)
+ {
+ output[outStart++] = CalculateByte(input[inStart++]);
+ }
+ }
+
+ protected byte CalculateByte(byte b)
+ {
+ if (byteCount == 0)
+ {
+ incrementCounterAt(0);
+
+ checkCounter();
+
+ cipher.ProcessBlock(ofbV, 0, ofbOutV, 0);
+
+ return (byte)(ofbOutV[byteCount++] ^ b);
+ }
+
+ byte rv = (byte)(ofbOutV[byteCount++] ^ b);
+
+ if (byteCount == ofbV.Length)
+ {
+ byteCount = 0;
+ }
+
+ return rv;
+ }
+
+ /**
+ * Process one block of input from the array in and write it to
+ * the out array.
+ *
+ * @param input the array containing the input data.
+ * @param inOff offset into the in array the data starts at.
+ * @param output the array the output data will be copied into.
+ * @param outOff the offset into the out array the output will start at.
+ * @exception DataLengthException if there isn't enough data in in, or
+ * space in out.
+ * @exception InvalidOperationException if the cipher isn't initialised.
+ * @return the number of bytes processed and produced.
+ */
+ public int ProcessBlock(byte[] input, int inOff, byte[] output, int outOff)
+ {
+ if (input.Length - inOff< GetBlockSize())
+ {
+ throw new DataLengthException("Input buffer too short");
+ }
+ if (output.Length - outOff< GetBlockSize())
+ {
+ throw new DataLengthException("Output buffer too short");
+ }
+
+ ProcessBytes(input, inOff, GetBlockSize(), output, outOff);
+
+ return GetBlockSize();
+ }
+
+ /**
+ * reset the chaining vector back to the IV and reset the underlying
+ * cipher.
+ */
+ public void Reset()
+ {
+ if (initialised)
+ {
+ cipher.ProcessBlock(IV, 0, ofbV, 0);
+ }
+ cipher.Reset();
+ byteCount = 0;
+ }
+
+ private void incrementCounterAt(int pos)
+ {
+ int i = pos;
+ while (i < ofbV.Length)
+ {
+ if (++ofbV[i++] != 0)
+ {
+ break;
+ }
+ }
+ }
+
+ private void checkCounter()
+ {
+ // TODO:
+ // if the IV is the same as the blocksize we assume the user knows what they are doing
+ // if (IV.length < ofbV.length)
+ // {
+ // for (int i = 0; i != IV.length; i++)
+ // {
+ // if (ofbV[i] != IV[i])
+ // {
+ // throw new IllegalStateException("Counter in KCTR mode out of range.");
+ // }
+ // }
+ // }
+ }
+ }
+}
diff --git a/crypto/src/crypto/modes/OCBBlockCipher.cs b/crypto/src/crypto/modes/OCBBlockCipher.cs
index e7dc466e6..91fdfff18 100644
--- a/crypto/src/crypto/modes/OCBBlockCipher.cs
+++ b/crypto/src/crypto/modes/OCBBlockCipher.cs
@@ -237,7 +237,9 @@ namespace Org.BouncyCastle.Crypto.Modes
public virtual byte[] GetMac()
{
- return Arrays.Clone(macBlock);
+ return macBlock == null
+ ? new byte[macSize]
+ : Arrays.Clone(macBlock);
}
public virtual int GetOutputSize(int len)
diff --git a/crypto/src/crypto/parameters/DHPublicKeyParameters.cs b/crypto/src/crypto/parameters/DHPublicKeyParameters.cs
index e79375f71..e7aeeff19 100644
--- a/crypto/src/crypto/parameters/DHPublicKeyParameters.cs
+++ b/crypto/src/crypto/parameters/DHPublicKeyParameters.cs
@@ -8,6 +8,25 @@ namespace Org.BouncyCastle.Crypto.Parameters
public class DHPublicKeyParameters
: DHKeyParameters
{
+ private static BigInteger Validate(BigInteger y, DHParameters dhParams)
+ {
+ if (y == null)
+ throw new ArgumentNullException("y");
+
+ // TLS check
+ if (y.CompareTo(BigInteger.Two) < 0 || y.CompareTo(dhParams.P.Subtract(BigInteger.Two)) > 0)
+ throw new ArgumentException("invalid DH public key", "y");
+
+ // we can't validate without Q.
+ if (dhParams.Q != null
+ && !y.ModPow(dhParams.Q, dhParams.P).Equals(BigInteger.One))
+ {
+ throw new ArgumentException("y value does not appear to be in correct group", "y");
+ }
+
+ return y;
+ }
+
private readonly BigInteger y;
public DHPublicKeyParameters(
@@ -15,10 +34,7 @@ namespace Org.BouncyCastle.Crypto.Parameters
DHParameters parameters)
: base(false, parameters)
{
- if (y == null)
- throw new ArgumentNullException("y");
-
- this.y = y;
+ this.y = Validate(y, parameters);
}
public DHPublicKeyParameters(
@@ -27,13 +43,10 @@ namespace Org.BouncyCastle.Crypto.Parameters
DerObjectIdentifier algorithmOid)
: base(false, parameters, algorithmOid)
{
- if (y == null)
- throw new ArgumentNullException("y");
-
- this.y = y;
+ this.y = Validate(y, parameters);
}
- public BigInteger Y
+ public virtual BigInteger Y
{
get { return y; }
}
diff --git a/crypto/src/crypto/parameters/DsaPublicKeyParameters.cs b/crypto/src/crypto/parameters/DsaPublicKeyParameters.cs
index f11f858f3..3a81bfdd0 100644
--- a/crypto/src/crypto/parameters/DsaPublicKeyParameters.cs
+++ b/crypto/src/crypto/parameters/DsaPublicKeyParameters.cs
@@ -7,6 +7,22 @@ namespace Org.BouncyCastle.Crypto.Parameters
public class DsaPublicKeyParameters
: DsaKeyParameters
{
+ private static BigInteger Validate(BigInteger y, DsaParameters parameters)
+ {
+ // we can't validate without params, fortunately we can't use the key either...
+ if (parameters != null)
+ {
+ if (y.CompareTo(BigInteger.Two) < 0
+ || y.CompareTo(parameters.P.Subtract(BigInteger.Two)) > 0
+ || !y.ModPow(parameters.Q, parameters.P).Equals(BigInteger.One))
+ {
+ throw new ArgumentException("y value does not appear to be in correct group");
+ }
+ }
+
+ return y;
+ }
+
private readonly BigInteger y;
public DsaPublicKeyParameters(
@@ -17,7 +33,7 @@ namespace Org.BouncyCastle.Crypto.Parameters
if (y == null)
throw new ArgumentNullException("y");
- this.y = y;
+ this.y = Validate(y, parameters);
}
public BigInteger Y
diff --git a/crypto/src/crypto/parameters/ECPublicKeyParameters.cs b/crypto/src/crypto/parameters/ECPublicKeyParameters.cs
index 1eb665da9..474e5d82c 100644
--- a/crypto/src/crypto/parameters/ECPublicKeyParameters.cs
+++ b/crypto/src/crypto/parameters/ECPublicKeyParameters.cs
@@ -9,6 +9,21 @@ namespace Org.BouncyCastle.Crypto.Parameters
public class ECPublicKeyParameters
: ECKeyParameters
{
+ private static ECPoint Validate(ECPoint q)
+ {
+ if (q == null)
+ throw new ArgumentNullException("q");
+ if (q.IsInfinity)
+ throw new ArgumentException("point at infinity", "q");
+
+ q = q.Normalize();
+
+ if (!q.IsValid())
+ throw new ArgumentException("point not on curve", "q");
+
+ return q;
+ }
+
private readonly ECPoint q;
public ECPublicKeyParameters(
@@ -27,7 +42,7 @@ namespace Org.BouncyCastle.Crypto.Parameters
if (q == null)
throw new ArgumentNullException("q");
- this.q = q.Normalize();
+ this.q = Validate(q);
}
public ECPublicKeyParameters(
@@ -39,7 +54,7 @@ namespace Org.BouncyCastle.Crypto.Parameters
if (q == null)
throw new ArgumentNullException("q");
- this.q = q.Normalize();
+ this.q = Validate(q);
}
public ECPublicKeyParameters(
@@ -51,7 +66,7 @@ namespace Org.BouncyCastle.Crypto.Parameters
if (q == null)
throw new ArgumentNullException("q");
- this.q = q.Normalize();
+ this.q = Validate(q);
}
public ECPoint Q
diff --git a/crypto/src/crypto/parameters/RsaKeyParameters.cs b/crypto/src/crypto/parameters/RsaKeyParameters.cs
index 72c0d806f..5480f0561 100644
--- a/crypto/src/crypto/parameters/RsaKeyParameters.cs
+++ b/crypto/src/crypto/parameters/RsaKeyParameters.cs
@@ -8,6 +8,26 @@ namespace Org.BouncyCastle.Crypto.Parameters
public class RsaKeyParameters
: AsymmetricKeyParameter
{
+ // the value is the product of the 132 smallest primes from 3 to 751
+ private static BigInteger SmallPrimesProduct = new BigInteger(
+ "8138E8A0FCF3A4E84A771D40FD305D7F4AA59306D7251DE54D98AF8FE95729A1" +
+ "F73D893FA424CD2EDC8636A6C3285E022B0E3866A565AE8108EED8591CD4FE8D" +
+ "2CE86165A978D719EBF647F362D33FCA29CD179FB42401CBAF3DF0C614056F9C" +
+ "8F3CFD51E474AFB6BC6974F78DB8ABA8E9E517FDED658591AB7502BD41849462F",
+ 16);
+
+ private static BigInteger Validate(BigInteger modulus)
+ {
+ if ((modulus.IntValue & 1) == 0)
+ throw new ArgumentException("RSA modulus is even", "modulus");
+ if (!modulus.Gcd(SmallPrimesProduct).Equals(BigInteger.One))
+ throw new ArgumentException("RSA modulus has a small prime factor");
+
+ // TODO: add additional primePower/Composite test - expensive!!
+
+ return modulus;
+ }
+
private readonly BigInteger modulus;
private readonly BigInteger exponent;
@@ -25,8 +45,10 @@ namespace Org.BouncyCastle.Crypto.Parameters
throw new ArgumentException("Not a valid RSA modulus", "modulus");
if (exponent.SignValue <= 0)
throw new ArgumentException("Not a valid RSA exponent", "exponent");
+ if (!isPrivate && (exponent.IntValue & 1) == 0)
+ throw new ArgumentException("RSA publicExponent is even", "exponent");
- this.modulus = modulus;
+ this.modulus = Validate(modulus);
this.exponent = exponent;
}
diff --git a/crypto/src/crypto/prng/SP800SecureRandom.cs b/crypto/src/crypto/prng/SP800SecureRandom.cs
index 5c5bda399..30c838c1b 100644
--- a/crypto/src/crypto/prng/SP800SecureRandom.cs
+++ b/crypto/src/crypto/prng/SP800SecureRandom.cs
@@ -76,5 +76,20 @@ namespace Org.BouncyCastle.Crypto.Prng
{
return EntropyUtilities.GenerateSeed(mEntropySource, numBytes);
}
+
+ /// <summary>Force a reseed of the DRBG.</summary>
+ /// <param name="additionalInput">optional additional input</param>
+ public virtual void Reseed(byte[] additionalInput)
+ {
+ lock (this)
+ {
+ if (mDrbg == null)
+ {
+ mDrbg = mDrbgProvider.Get(mEntropySource);
+ }
+
+ mDrbg.Reseed(additionalInput);
+ }
+ }
}
}
diff --git a/crypto/src/crypto/signers/Iso9796d2PssSigner.cs b/crypto/src/crypto/signers/Iso9796d2PssSigner.cs
index 3aa2e3719..6b8037095 100644
--- a/crypto/src/crypto/signers/Iso9796d2PssSigner.cs
+++ b/crypto/src/crypto/signers/Iso9796d2PssSigner.cs
@@ -516,6 +516,7 @@ namespace Org.BouncyCastle.Crypto.Signers
if (!isOkay)
{
fullMessage = false;
+ messageLength = 0;
ClearBlock(recoveredMessage);
return false;
}
@@ -528,12 +529,14 @@ namespace Org.BouncyCastle.Crypto.Signers
{
if (!IsSameAs(mBuf, recoveredMessage))
{
+ messageLength = 0;
ClearBlock(mBuf);
return false;
}
- messageLength = 0;
}
+ messageLength = 0;
+
ClearBlock(mBuf);
return true;
}
diff --git a/crypto/src/crypto/signers/Iso9796d2Signer.cs b/crypto/src/crypto/signers/Iso9796d2Signer.cs
index b90ed8f0b..303913068 100644
--- a/crypto/src/crypto/signers/Iso9796d2Signer.cs
+++ b/crypto/src/crypto/signers/Iso9796d2Signer.cs
@@ -360,6 +360,8 @@ namespace Org.BouncyCastle.Crypto.Signers
byte[] b = cipher.ProcessBlock(block, 0, block.Length);
+ messageLength = 0;
+
ClearBlock(mBuf);
ClearBlock(block);
@@ -526,11 +528,15 @@ namespace Org.BouncyCastle.Crypto.Signers
ClearBlock(mBuf);
ClearBlock(block);
+ messageLength = 0;
+
return true;
}
private bool ReturnFalse(byte[] block)
{
+ messageLength = 0;
+
ClearBlock(mBuf);
ClearBlock(block);
diff --git a/crypto/src/crypto/tls/EncryptionAlgorithm.cs b/crypto/src/crypto/tls/EncryptionAlgorithm.cs
index 96037ed20..45eef18e3 100644
--- a/crypto/src/crypto/tls/EncryptionAlgorithm.cs
+++ b/crypto/src/crypto/tls/EncryptionAlgorithm.cs
@@ -56,10 +56,9 @@ namespace Org.BouncyCastle.Crypto.Tls
public const int CAMELLIA_256_GCM = 20;
/*
- * draft-ietf-tls-chacha20-poly1305-04
+ * RFC 7905
*/
- public const int CHACHA20_POLY1305 = 102;
- [Obsolete] public const int AEAD_CHACHA20_POLY1305 = CHACHA20_POLY1305;
+ public const int CHACHA20_POLY1305 = 21;
/*
* draft-zauner-tls-aes-ocb-04
diff --git a/crypto/src/crypto/tls/ExtensionType.cs b/crypto/src/crypto/tls/ExtensionType.cs
index bff9332a0..f17210b80 100644
--- a/crypto/src/crypto/tls/ExtensionType.cs
+++ b/crypto/src/crypto/tls/ExtensionType.cs
@@ -99,6 +99,16 @@ namespace Org.BouncyCastle.Crypto.Tls
public const int extended_master_secret = 23;
/*
+ * draft-ietf-tokbind-negotiation-08
+ */
+ public static readonly int DRAFT_token_binding = 24;
+
+ /*
+ * RFC 7924
+ */
+ public const int cached_info = 25;
+
+ /*
* RFC 5077 7.
*/
public const int session_ticket = 35;
diff --git a/crypto/src/crypto/tls/RecordStream.cs b/crypto/src/crypto/tls/RecordStream.cs
index 46673cf7e..5d556ad06 100644
--- a/crypto/src/crypto/tls/RecordStream.cs
+++ b/crypto/src/crypto/tls/RecordStream.cs
@@ -21,7 +21,7 @@ namespace Org.BouncyCastle.Crypto.Tls
private Stream mOutput;
private TlsCompression mPendingCompression = null, mReadCompression = null, mWriteCompression = null;
private TlsCipher mPendingCipher = null, mReadCipher = null, mWriteCipher = null;
- private long mReadSeqNo = 0, mWriteSeqNo = 0;
+ private SequenceNumber mReadSeqNo = new SequenceNumber(), mWriteSeqNo = new SequenceNumber();
private MemoryStream mBuffer = new MemoryStream();
private TlsHandshakeHash mHandshakeHash = null;
@@ -100,7 +100,7 @@ namespace Org.BouncyCastle.Crypto.Tls
this.mWriteCompression = this.mPendingCompression;
this.mWriteCipher = this.mPendingCipher;
- this.mWriteSeqNo = 0;
+ this.mWriteSeqNo = new SequenceNumber();
}
internal virtual void ReceivedReadCipherSpec()
@@ -110,7 +110,7 @@ namespace Org.BouncyCastle.Crypto.Tls
this.mReadCompression = this.mPendingCompression;
this.mReadCipher = this.mPendingCipher;
- this.mReadSeqNo = 0;
+ this.mReadSeqNo = new SequenceNumber();
}
internal virtual void FinaliseHandshake()
@@ -203,7 +203,9 @@ namespace Org.BouncyCastle.Crypto.Tls
internal virtual byte[] DecodeAndVerify(byte type, Stream input, int len)
{
byte[] buf = TlsUtilities.ReadFully(len, input);
- byte[] decoded = mReadCipher.DecodeCiphertext(mReadSeqNo++, type, buf, 0, buf.Length);
+
+ long seqNo = mReadSeqNo.NextValue(AlertDescription.unexpected_message);
+ byte[] decoded = mReadCipher.DecodeCiphertext(seqNo, type, buf, 0, buf.Length);
CheckLength(decoded.Length, mCompressedLimit, AlertDescription.record_overflow);
@@ -262,10 +264,12 @@ namespace Org.BouncyCastle.Crypto.Tls
Stream cOut = mWriteCompression.Compress(mBuffer);
+ long seqNo = mWriteSeqNo.NextValue(AlertDescription.internal_error);
+
byte[] ciphertext;
if (cOut == mBuffer)
{
- ciphertext = mWriteCipher.EncodePlaintext(mWriteSeqNo++, type, plaintext, plaintextOffset, plaintextLength);
+ ciphertext = mWriteCipher.EncodePlaintext(seqNo, type, plaintext, plaintextOffset, plaintextLength);
}
else
{
@@ -279,7 +283,7 @@ namespace Org.BouncyCastle.Crypto.Tls
*/
CheckLength(compressed.Length, plaintextLength + 1024, AlertDescription.internal_error);
- ciphertext = mWriteCipher.EncodePlaintext(mWriteSeqNo++, type, compressed, 0, compressed.Length);
+ ciphertext = mWriteCipher.EncodePlaintext(seqNo, type, compressed, 0, compressed.Length);
}
/*
@@ -384,5 +388,25 @@ namespace Org.BouncyCastle.Crypto.Tls
mOuter.mHandshakeHash.BlockUpdate(buf, off, len);
}
}
+
+ private class SequenceNumber
+ {
+ private long value = 0L;
+ private bool exhausted = false;
+
+ internal long NextValue(byte alertDescription)
+ {
+ if (exhausted)
+ {
+ throw new TlsFatalAlert(alertDescription);
+ }
+ long result = value;
+ if (++value == 0)
+ {
+ exhausted = true;
+ }
+ return result;
+ }
+ }
}
}
diff --git a/crypto/src/crypto/tls/TlsDHKeyExchange.cs b/crypto/src/crypto/tls/TlsDHKeyExchange.cs
index eec9daaca..d179068bb 100644
--- a/crypto/src/crypto/tls/TlsDHKeyExchange.cs
+++ b/crypto/src/crypto/tls/TlsDHKeyExchange.cs
@@ -151,6 +151,9 @@ namespace Org.BouncyCastle.Crypto.Tls
public override void ValidateCertificateRequest(CertificateRequest certificateRequest)
{
+ if (mKeyExchange == KeyExchangeAlgorithm.DH_anon)
+ throw new TlsFatalAlert(AlertDescription.handshake_failure);
+
byte[] types = certificateRequest.CertificateTypes;
for (int i = 0; i < types.Length; ++i)
{
diff --git a/crypto/src/crypto/tls/TlsECDHKeyExchange.cs b/crypto/src/crypto/tls/TlsECDHKeyExchange.cs
index 03c162904..c508fb993 100644
--- a/crypto/src/crypto/tls/TlsECDHKeyExchange.cs
+++ b/crypto/src/crypto/tls/TlsECDHKeyExchange.cs
@@ -153,6 +153,9 @@ namespace Org.BouncyCastle.Crypto.Tls
public override void ValidateCertificateRequest(CertificateRequest certificateRequest)
{
+ if (mKeyExchange == KeyExchangeAlgorithm.ECDH_anon)
+ throw new TlsFatalAlert(AlertDescription.handshake_failure);
+
/*
* RFC 4492 3. [...] The ECDSA_fixed_ECDH and RSA_fixed_ECDH mechanisms are usable with
* ECDH_ECDSA and ECDH_RSA. Their use with ECDHE_ECDSA and ECDHE_RSA is prohibited because
diff --git a/crypto/src/crypto/tls/TlsException.cs b/crypto/src/crypto/tls/TlsException.cs
new file mode 100644
index 000000000..cea9e3e77
--- /dev/null
+++ b/crypto/src/crypto/tls/TlsException.cs
@@ -0,0 +1,14 @@
+using System;
+using System.IO;
+
+namespace Org.BouncyCastle.Crypto.Tls
+{
+ public class TlsException
+ : IOException
+ {
+ public TlsException(string message, Exception cause)
+ : base(message, cause)
+ {
+ }
+ }
+}
diff --git a/crypto/src/crypto/tls/TlsFatalAlert.cs b/crypto/src/crypto/tls/TlsFatalAlert.cs
index 55d784dd9..6f1898179 100644
--- a/crypto/src/crypto/tls/TlsFatalAlert.cs
+++ b/crypto/src/crypto/tls/TlsFatalAlert.cs
@@ -1,10 +1,9 @@
using System;
-using System.IO;
namespace Org.BouncyCastle.Crypto.Tls
{
public class TlsFatalAlert
- : IOException
+ : TlsException
{
private readonly byte alertDescription;
diff --git a/crypto/src/crypto/tls/TlsFatalAlertReceived.cs b/crypto/src/crypto/tls/TlsFatalAlertReceived.cs
new file mode 100644
index 000000000..044fc8027
--- /dev/null
+++ b/crypto/src/crypto/tls/TlsFatalAlertReceived.cs
@@ -0,0 +1,21 @@
+using System;
+
+namespace Org.BouncyCastle.Crypto.Tls
+{
+ public class TlsFatalAlertReceived
+ : TlsException
+ {
+ private readonly byte alertDescription;
+
+ public TlsFatalAlertReceived(byte alertDescription)
+ : base(Tls.AlertDescription.GetText(alertDescription), null)
+ {
+ this.alertDescription = alertDescription;
+ }
+
+ public virtual byte AlertDescription
+ {
+ get { return alertDescription; }
+ }
+ }
+}
diff --git a/crypto/src/crypto/tls/TlsNoCloseNotifyException.cs b/crypto/src/crypto/tls/TlsNoCloseNotifyException.cs
index 72159ba47..0bafd820b 100644
--- a/crypto/src/crypto/tls/TlsNoCloseNotifyException.cs
+++ b/crypto/src/crypto/tls/TlsNoCloseNotifyException.cs
@@ -15,5 +15,9 @@ namespace Org.BouncyCastle.Crypto.Tls
public class TlsNoCloseNotifyException
: EndOfStreamException
{
+ public TlsNoCloseNotifyException()
+ : base("No close_notify alert received before connection closed")
+ {
+ }
}
}
diff --git a/crypto/src/crypto/tls/TlsProtocol.cs b/crypto/src/crypto/tls/TlsProtocol.cs
index 490580fad..72151d414 100644
--- a/crypto/src/crypto/tls/TlsProtocol.cs
+++ b/crypto/src/crypto/tls/TlsProtocol.cs
@@ -10,8 +10,6 @@ namespace Org.BouncyCastle.Crypto.Tls
{
public abstract class TlsProtocol
{
- private static readonly string TLS_ERROR_MESSAGE = "Internal TLS error, this could be an attack";
-
/*
* Our Connection states
*/
@@ -110,16 +108,95 @@ namespace Org.BouncyCastle.Crypto.Tls
protected abstract TlsPeer Peer { get; }
+ protected virtual void HandleAlertMessage(byte alertLevel, byte alertDescription)
+ {
+ Peer.NotifyAlertReceived(alertLevel, alertDescription);
+
+ if (alertLevel == AlertLevel.warning)
+ {
+ HandleAlertWarningMessage(alertDescription);
+ }
+ else
+ {
+ HandleFailure();
+
+ throw new TlsFatalAlertReceived(alertDescription);
+ }
+ }
+
+ protected virtual void HandleAlertWarningMessage(byte alertDescription)
+ {
+ /*
+ * RFC 5246 7.2.1. The other party MUST respond with a close_notify alert of its own
+ * and close down the connection immediately, discarding any pending writes.
+ */
+ if (alertDescription == AlertDescription.close_notify)
+ {
+ if (!mAppDataReady)
+ throw new TlsFatalAlert(AlertDescription.handshake_failure);
+
+ HandleClose(false);
+ }
+ }
+
protected virtual void HandleChangeCipherSpecMessage()
{
}
- protected abstract void HandleHandshakeMessage(byte type, MemoryStream buf);
+ protected virtual void HandleClose(bool user_canceled)
+ {
+ if (!mClosed)
+ {
+ this.mClosed = true;
+
+ if (user_canceled && !mAppDataReady)
+ {
+ RaiseAlertWarning(AlertDescription.user_canceled, "User canceled handshake");
+ }
+
+ RaiseAlertWarning(AlertDescription.close_notify, "Connection closed");
+
+ mRecordStream.SafeClose();
+
+ if (!mAppDataReady)
+ {
+ CleanupHandshake();
+ }
+ }
+ }
+
+ protected virtual void HandleException(byte alertDescription, string message, Exception cause)
+ {
+ if (!mClosed)
+ {
+ RaiseAlertFatal(alertDescription, message, cause);
+
+ HandleFailure();
+ }
+ }
- protected virtual void HandleWarningMessage(byte description)
+ protected virtual void HandleFailure()
{
+ this.mClosed = true;
+ this.mFailedWithError = true;
+
+ /*
+ * RFC 2246 7.2.1. The session becomes unresumable if any connection is terminated
+ * without proper close_notify messages with level equal to warning.
+ */
+ // TODO This isn't quite in the right place. Also, as of TLS 1.1 the above is obsolete.
+ InvalidateSession();
+
+ mRecordStream.SafeClose();
+
+ if (!mAppDataReady)
+ {
+ CleanupHandshake();
+ }
}
+ protected abstract void HandleHandshakeMessage(byte type, MemoryStream buf);
+
protected virtual void ApplyMaxFragmentLengthExtension()
{
if (mSecurityParameters.maxFragmentLength >= 0)
@@ -368,47 +445,11 @@ namespace Org.BouncyCastle.Crypto.Tls
/*
* An alert is always 2 bytes. Read the alert.
*/
- byte[] tmp = mAlertQueue.RemoveData(2, 0);
- byte level = tmp[0];
- byte description = tmp[1];
-
- Peer.NotifyAlertReceived(level, description);
-
- if (level == AlertLevel.fatal)
- {
- /*
- * RFC 2246 7.2.1. The session becomes unresumable if any connection is terminated
- * without proper close_notify messages with level equal to warning.
- */
- InvalidateSession();
-
- this.mFailedWithError = true;
- this.mClosed = true;
-
- mRecordStream.SafeClose();
-
- throw new IOException(TLS_ERROR_MESSAGE);
- }
- else
- {
- /*
- * RFC 5246 7.2.1. The other party MUST respond with a close_notify alert of its own
- * and close down the connection immediately, discarding any pending writes.
- */
- if (description == AlertDescription.close_notify)
- {
- if (!mAppDataReady)
- {
- throw new TlsFatalAlert(AlertDescription.handshake_failure);
- }
- HandleClose(false);
- }
+ byte[] alert = mAlertQueue.RemoveData(2, 0);
+ byte alertLevel = alert[0];
+ byte alertDescription = alert[1];
- /*
- * If it is just a warning, we continue.
- */
- HandleWarningMessage(description);
- }
+ HandleAlertMessage(alertLevel, alertDescription);
}
}
@@ -464,22 +505,14 @@ namespace Org.BouncyCastle.Crypto.Tls
while (mApplicationDataQueue.Available == 0)
{
- /*
- * We need to read some data.
- */
if (this.mClosed)
{
if (this.mFailedWithError)
- {
- /*
- * Something went terribly wrong, we should throw an IOException
- */
- throw new IOException(TLS_ERROR_MESSAGE);
- }
+ throw new IOException("Cannot read application data on failed TLS connection");
+
+ if (!mAppDataReady)
+ throw new InvalidOperationException("Cannot read application data until initial handshake completed.");
- /*
- * Connection has been closed, there is no more data to read.
- */
return 0;
}
@@ -499,45 +532,55 @@ namespace Org.BouncyCastle.Crypto.Tls
}
catch (TlsFatalAlert e)
{
- this.FailWithError(AlertLevel.fatal, e.AlertDescription, "Failed to read record", e);
+ HandleException(e.AlertDescription, "Failed to read record", e);
throw e;
}
- catch (Exception e)
+ catch (IOException e)
{
- this.FailWithError(AlertLevel.fatal, AlertDescription.internal_error, "Failed to read record", e);
+ HandleException(AlertDescription.internal_error, "Failed to read record", e);
throw e;
}
+ catch (Exception e)
+ {
+ HandleException(AlertDescription.internal_error, "Failed to read record", e);
+ throw new TlsFatalAlert(AlertDescription.internal_error, e);
+ }
}
protected virtual void SafeReadRecord()
{
try
{
- if (!mRecordStream.ReadRecord())
- {
- if (!mAppDataReady)
- {
- throw new TlsFatalAlert(AlertDescription.handshake_failure);
- }
- throw new TlsNoCloseNotifyException();
- }
+ if (mRecordStream.ReadRecord())
+ return;
+
+ if (!mAppDataReady)
+ throw new TlsFatalAlert(AlertDescription.handshake_failure);
+ }
+ catch (TlsFatalAlertReceived e)
+ {
+ // Connection failure already handled at source
+ throw e;
}
catch (TlsFatalAlert e)
{
- if (!mClosed)
- {
- this.FailWithError(AlertLevel.fatal, e.AlertDescription, "Failed to read record", e);
- }
+ HandleException(e.AlertDescription, "Failed to read record", e);
throw e;
}
- catch (Exception e)
+ catch (IOException e)
{
- if (!mClosed)
- {
- this.FailWithError(AlertLevel.fatal, AlertDescription.internal_error, "Failed to read record", e);
- }
+ HandleException(AlertDescription.internal_error, "Failed to read record", e);
throw e;
}
+ catch (Exception e)
+ {
+ HandleException(AlertDescription.internal_error, "Failed to read record", e);
+ throw new TlsFatalAlert(AlertDescription.internal_error, e);
+ }
+
+ HandleFailure();
+
+ throw new TlsNoCloseNotifyException();
}
protected virtual void SafeWriteRecord(byte type, byte[] buf, int offset, int len)
@@ -548,20 +591,19 @@ namespace Org.BouncyCastle.Crypto.Tls
}
catch (TlsFatalAlert e)
{
- if (!mClosed)
- {
- this.FailWithError(AlertLevel.fatal, e.AlertDescription, "Failed to write record", e);
- }
+ HandleException(e.AlertDescription, "Failed to write record", e);
throw e;
}
- catch (Exception e)
+ catch (IOException e)
{
- if (!mClosed)
- {
- this.FailWithError(AlertLevel.fatal, AlertDescription.internal_error, "Failed to write record", e);
- }
+ HandleException(AlertDescription.internal_error, "Failed to write record", e);
throw e;
}
+ catch (Exception e)
+ {
+ HandleException(AlertDescription.internal_error, "Failed to write record", e);
+ throw new TlsFatalAlert(AlertDescription.internal_error, e);
+ }
}
/**
@@ -577,12 +619,7 @@ namespace Org.BouncyCastle.Crypto.Tls
protected internal virtual void WriteData(byte[] buf, int offset, int len)
{
if (this.mClosed)
- {
- if (this.mFailedWithError)
- throw new IOException(TLS_ERROR_MESSAGE);
-
- throw new IOException("Sorry, connection has been closed, you cannot write more data");
- }
+ throw new IOException("Cannot write application data on closed/failed TLS connection");
while (len > 0)
{
@@ -843,50 +880,6 @@ namespace Org.BouncyCastle.Crypto.Tls
return mOutputBuffer.Read(buffer, offset, length);
}
- /**
- * Terminate this connection with an alert. Can be used for normal closure too.
- *
- * @param alertLevel
- * See {@link AlertLevel} for values.
- * @param alertDescription
- * See {@link AlertDescription} for values.
- * @throws IOException
- * If alert was fatal.
- */
- protected virtual void FailWithError(byte alertLevel, byte alertDescription, string message, Exception cause)
- {
- /*
- * Check if the connection is still open.
- */
- if (!mClosed)
- {
- /*
- * Prepare the message
- */
- this.mClosed = true;
-
- if (alertLevel == AlertLevel.fatal)
- {
- /*
- * RFC 2246 7.2.1. The session becomes unresumable if any connection is terminated
- * without proper close_notify messages with level equal to warning.
- */
- // TODO This isn't quite in the right place. Also, as of TLS 1.1 the above is obsolete.
- InvalidateSession();
-
- this.mFailedWithError = true;
- }
- RaiseAlert(alertLevel, alertDescription, message, cause);
- mRecordStream.SafeClose();
- if (alertLevel != AlertLevel.fatal)
- {
- return;
- }
- }
-
- throw new IOException(TLS_ERROR_MESSAGE);
- }
-
protected virtual void InvalidateSession()
{
if (this.mSessionParameters != null)
@@ -923,18 +916,29 @@ namespace Org.BouncyCastle.Crypto.Tls
}
}
- protected virtual void RaiseAlert(byte alertLevel, byte alertDescription, string message, Exception cause)
+ protected virtual void RaiseAlertFatal(byte alertDescription, string message, Exception cause)
{
- Peer.NotifyAlertRaised(alertLevel, alertDescription, message, cause);
+ Peer.NotifyAlertRaised(AlertLevel.fatal, alertDescription, message, cause);
- byte[] error = new byte[]{ alertLevel, alertDescription };
+ byte[] alert = new byte[]{ AlertLevel.fatal, alertDescription };
- SafeWriteRecord(ContentType.alert, error, 0, 2);
+ try
+ {
+ mRecordStream.WriteRecord(ContentType.alert, alert, 0, 2);
+ }
+ catch (Exception)
+ {
+ // We are already processing an exception, so just ignore this
+ }
}
- protected virtual void RaiseWarning(byte alertDescription, string message)
+ protected virtual void RaiseAlertWarning(byte alertDescription, string message)
{
- RaiseAlert(AlertLevel.warning, alertDescription, message, null);
+ Peer.NotifyAlertRaised(AlertLevel.warning, alertDescription, message, null);
+
+ byte[] alert = new byte[]{ AlertLevel.warning, alertDescription };
+
+ SafeWriteRecord(ContentType.alert, alert, 0, 2);
}
protected virtual void SendCertificateMessage(Certificate certificate)
@@ -953,7 +957,7 @@ namespace Org.BouncyCastle.Crypto.Tls
if (serverVersion.IsSsl)
{
string errorMessage = serverVersion.ToString() + " client didn't provide credentials";
- RaiseWarning(AlertDescription.no_certificate, errorMessage);
+ RaiseAlertWarning(AlertDescription.no_certificate, errorMessage);
return;
}
}
@@ -1012,18 +1016,6 @@ namespace Org.BouncyCastle.Crypto.Tls
HandleClose(true);
}
- protected virtual void HandleClose(bool user_canceled)
- {
- if (!mClosed)
- {
- if (user_canceled && !mAppDataReady)
- {
- RaiseWarning(AlertDescription.user_canceled, "User canceled handshake");
- }
- this.FailWithError(AlertLevel.warning, AlertDescription.close_notify, "Connection closed", null);
- }
- }
-
protected internal virtual void Flush()
{
mRecordStream.Flush();
@@ -1059,7 +1051,7 @@ namespace Org.BouncyCastle.Crypto.Tls
if (TlsUtilities.IsSsl(Context))
throw new TlsFatalAlert(AlertDescription.handshake_failure);
- RaiseWarning(AlertDescription.no_renegotiation, "Renegotiation not supported");
+ RaiseAlertWarning(AlertDescription.no_renegotiation, "Renegotiation not supported");
}
/**
diff --git a/crypto/src/crypto/tls/TlsServerProtocol.cs b/crypto/src/crypto/tls/TlsServerProtocol.cs
index 5f3ce18e2..c2bfbcb74 100644
--- a/crypto/src/crypto/tls/TlsServerProtocol.cs
+++ b/crypto/src/crypto/tls/TlsServerProtocol.cs
@@ -386,28 +386,39 @@ namespace Org.BouncyCastle.Crypto.Tls
}
}
- protected override void HandleWarningMessage(byte description)
+ protected override void HandleAlertWarningMessage(byte alertDescription)
{
- switch (description)
+ base.HandleAlertWarningMessage(alertDescription);
+
+ switch (alertDescription)
{
case AlertDescription.no_certificate:
{
/*
- * SSL 3.0 If the server has sent a certificate request Message, the client must Send
+ * SSL 3.0 If the server has sent a certificate request Message, the client must send
* either the certificate message or a no_certificate alert.
*/
- if (TlsUtilities.IsSsl(Context) && mCertificateRequest != null)
+ if (TlsUtilities.IsSsl(Context) && this.mCertificateRequest != null)
{
- NotifyClientCertificate(Certificate.EmptyChain);
+ switch (this.mConnectionState)
+ {
+ case CS_SERVER_HELLO_DONE:
+ case CS_CLIENT_SUPPLEMENTAL_DATA:
+ {
+ if (mConnectionState < CS_CLIENT_SUPPLEMENTAL_DATA)
+ {
+ mTlsServer.ProcessClientSupplementalData(null);
+ }
+
+ NotifyClientCertificate(Certificate.EmptyChain);
+ this.mConnectionState = CS_CLIENT_CERTIFICATE;
+ return;
+ }
+ }
}
- break;
- }
- default:
- {
- base.HandleWarningMessage(description);
- break;
- }
+ throw new TlsFatalAlert(AlertDescription.unexpected_message);
}
+ }
}
protected virtual void NotifyClientCertificate(Certificate clientCertificate)
diff --git a/crypto/src/crypto/util/Pack.cs b/crypto/src/crypto/util/Pack.cs
index 96f293d72..ebe5b7af1 100644
--- a/crypto/src/crypto/util/Pack.cs
+++ b/crypto/src/crypto/util/Pack.cs
@@ -298,5 +298,14 @@ namespace Org.BouncyCastle.Crypto.Utilities
uint hi = LE_To_UInt32(bs, off + 4);
return ((ulong)hi << 32) | (ulong)lo;
}
+
+ internal static void LE_To_UInt64(byte[] bs, int off, ulong[] ns)
+ {
+ for (int i = 0; i < ns.Length; ++i)
+ {
+ ns[i] = LE_To_UInt64(bs, off);
+ off += 8;
+ }
+ }
}
}
diff --git a/crypto/src/math/ec/custom/gm/SM2P256V1Curve.cs b/crypto/src/math/ec/custom/gm/SM2P256V1Curve.cs
new file mode 100644
index 000000000..70b1190c9
--- /dev/null
+++ b/crypto/src/math/ec/custom/gm/SM2P256V1Curve.cs
@@ -0,0 +1,77 @@
+using System;
+
+using Org.BouncyCastle.Utilities.Encoders;
+
+namespace Org.BouncyCastle.Math.EC.Custom.GM
+{
+ internal class SM2P256V1Curve
+ : AbstractFpCurve
+ {
+ public static readonly BigInteger q = new BigInteger(1,
+ Hex.Decode("FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000FFFFFFFFFFFFFFFF"));
+
+ private const int SM2P256V1_DEFAULT_COORDS = COORD_JACOBIAN;
+
+ protected readonly SM2P256V1Point m_infinity;
+
+ public SM2P256V1Curve()
+ : base(q)
+ {
+ this.m_infinity = new SM2P256V1Point(this, null, null);
+
+ this.m_a = FromBigInteger(new BigInteger(1,
+ Hex.Decode("FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000FFFFFFFFFFFFFFFC")));
+ this.m_b = FromBigInteger(new BigInteger(1,
+ Hex.Decode("28E9FA9E9D9F5E344D5A9E4BCF6509A7F39789F515AB8F92DDBCBD414D940E93")));
+ this.m_order = new BigInteger(1, Hex.Decode("FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFF7203DF6B21C6052B53BBF40939D54123"));
+ this.m_cofactor = BigInteger.One;
+ this.m_coord = SM2P256V1_DEFAULT_COORDS;
+ }
+
+ protected override ECCurve CloneCurve()
+ {
+ return new SM2P256V1Curve();
+ }
+
+ public override bool SupportsCoordinateSystem(int coord)
+ {
+ switch (coord)
+ {
+ case COORD_JACOBIAN:
+ return true;
+ default:
+ return false;
+ }
+ }
+
+ public virtual BigInteger Q
+ {
+ get { return q; }
+ }
+
+ public override ECPoint Infinity
+ {
+ get { return m_infinity; }
+ }
+
+ public override int FieldSize
+ {
+ get { return q.BitLength; }
+ }
+
+ public override ECFieldElement FromBigInteger(BigInteger x)
+ {
+ return new SM2P256V1FieldElement(x);
+ }
+
+ protected internal override ECPoint CreateRawPoint(ECFieldElement x, ECFieldElement y, bool withCompression)
+ {
+ return new SM2P256V1Point(this, x, y, withCompression);
+ }
+
+ protected internal override ECPoint CreateRawPoint(ECFieldElement x, ECFieldElement y, ECFieldElement[] zs, bool withCompression)
+ {
+ return new SM2P256V1Point(this, x, y, zs, withCompression);
+ }
+ }
+}
diff --git a/crypto/src/math/ec/custom/gm/SM2P256V1Field.cs b/crypto/src/math/ec/custom/gm/SM2P256V1Field.cs
new file mode 100644
index 000000000..b1d232347
--- /dev/null
+++ b/crypto/src/math/ec/custom/gm/SM2P256V1Field.cs
@@ -0,0 +1,307 @@
+using System;
+using System.Diagnostics;
+
+using Org.BouncyCastle.Math.Raw;
+
+namespace Org.BouncyCastle.Math.EC.Custom.GM
+{
+ internal class SM2P256V1Field
+ {
+ // 2^256 - 2^224 - 2^96 + 2^64 - 1
+ internal static readonly uint[] P = new uint[]{ 0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+ 0xFFFFFFFF, 0xFFFFFFFE };
+ internal static readonly uint[] PExt = new uint[]{ 00000001, 0x00000000, 0xFFFFFFFE, 0x00000001, 0x00000001,
+ 0xFFFFFFFE, 0x00000000, 0x00000002, 0xFFFFFFFE, 0xFFFFFFFD, 0x00000003, 0xFFFFFFFE, 0xFFFFFFFF, 0xFFFFFFFF,
+ 0x00000000, 0xFFFFFFFE };
+ internal const uint P7 = 0xFFFFFFFE;
+ internal const uint PExt15 = 0xFFFFFFFE;
+
+ public static void Add(uint[] x, uint[] y, uint[] z)
+ {
+ uint c = Nat256.Add(x, y, z);
+ if (c != 0 || (z[7] >= P7 && Nat256.Gte(z, P)))
+ {
+ AddPInvTo(z);
+ }
+ }
+
+ public static void AddExt(uint[] xx, uint[] yy, uint[] zz)
+ {
+ uint c = Nat.Add(16, xx, yy, zz);
+ if (c != 0 || (zz[15] >= PExt15 && Nat.Gte(16, zz, PExt)))
+ {
+ Nat.SubFrom(16, PExt, zz);
+ }
+ }
+
+ public static void AddOne(uint[] x, uint[] z)
+ {
+ uint c = Nat.Inc(8, x, z);
+ if (c != 0 || (z[7] >= P7 && Nat256.Gte(z, P)))
+ {
+ AddPInvTo(z);
+ }
+ }
+
+ public static uint[] FromBigInteger(BigInteger x)
+ {
+ uint[] z = Nat256.FromBigInteger(x);
+ if (z[7] >= P7 && Nat256.Gte(z, P))
+ {
+ Nat256.SubFrom(P, z);
+ }
+ return z;
+ }
+
+ public static void Half(uint[] x, uint[] z)
+ {
+ if ((x[0] & 1) == 0)
+ {
+ Nat.ShiftDownBit(8, x, 0, z);
+ }
+ else
+ {
+ uint c = Nat256.Add(x, P, z);
+ Nat.ShiftDownBit(8, z, c);
+ }
+ }
+
+ public static void Multiply(uint[] x, uint[] y, uint[] z)
+ {
+ uint[] tt = Nat256.CreateExt();
+ Nat256.Mul(x, y, tt);
+ Reduce(tt, z);
+ }
+
+ public static void MultiplyAddToExt(uint[] x, uint[] y, uint[] zz)
+ {
+ uint c = Nat256.MulAddTo(x, y, zz);
+ if (c != 0 || (zz[15] >= PExt15 && Nat.Gte(16, zz, PExt)))
+ {
+ Nat.SubFrom(16, PExt, zz);
+ }
+ }
+
+ public static void Negate(uint[] x, uint[] z)
+ {
+ if (Nat256.IsZero(x))
+ {
+ Nat256.Zero(z);
+ }
+ else
+ {
+ Nat256.Sub(P, x, z);
+ }
+ }
+
+ public static void Reduce(uint[] xx, uint[] z)
+ {
+ long xx08 = xx[8], xx09 = xx[9], xx10 = xx[10], xx11 = xx[11];
+ long xx12 = xx[12], xx13 = xx[13], xx14 = xx[14], xx15 = xx[15];
+
+ long t0 = xx08 + xx09;
+ long t1 = xx10 + xx11;
+ long t2 = xx12 + xx15;
+ long t3 = xx13 + xx14;
+ long t4 = t3 + (xx15 << 1);
+
+ long ts = t0 + t3;
+ long tt = t1 + t2 + ts;
+
+ long cc = 0;
+ cc += (long)xx[0] + tt + xx13 + xx14 + xx15;
+ z[0] = (uint)cc;
+ cc >>= 32;
+ cc += (long)xx[1] + tt - xx08 + xx14 + xx15;
+ z[1] = (uint)cc;
+ cc >>= 32;
+ cc += (long)xx[2] - ts;
+ z[2] = (uint)cc;
+ cc >>= 32;
+ cc += (long)xx[3] + tt - xx09 - xx10 + xx13;
+ z[3] = (uint)cc;
+ cc >>= 32;
+ cc += (long)xx[4] + tt - t1 - xx08 + xx14;
+ z[4] = (uint)cc;
+ cc >>= 32;
+ cc += (long)xx[5] + t4 + xx10;
+ z[5] = (uint)cc;
+ cc >>= 32;
+ cc += (long)xx[6] + xx11 + xx14 + xx15;
+ z[6] = (uint)cc;
+ cc >>= 32;
+ cc += (long)xx[7] + tt + t4 + xx12;
+ z[7] = (uint)cc;
+ cc >>= 32;
+
+ Debug.Assert(cc >= 0);
+
+ Reduce32((uint)cc, z);
+ }
+
+ public static void Reduce32(uint x, uint[] z)
+ {
+ long cc = 0;
+
+ if (x != 0)
+ {
+ long xx08 = x;
+
+ cc += (long)z[0] + xx08;
+ z[0] = (uint)cc;
+ cc >>= 32;
+ if (cc != 0)
+ {
+ cc += (long)z[1];
+ z[1] = (uint)cc;
+ cc >>= 32;
+ }
+ cc += (long)z[2] - xx08;
+ z[2] = (uint)cc;
+ cc >>= 32;
+ cc += (long)z[3] + xx08;
+ z[3] = (uint)cc;
+ cc >>= 32;
+ if (cc != 0)
+ {
+ cc += (long)z[4];
+ z[4] = (uint)cc;
+ cc >>= 32;
+ cc += (long)z[5];
+ z[5] = (uint)cc;
+ cc >>= 32;
+ cc += (long)z[6];
+ z[6] = (uint)cc;
+ cc >>= 32;
+ }
+ cc += (long)z[7] + xx08;
+ z[7] = (uint)cc;
+ cc >>= 32;
+
+ Debug.Assert(cc == 0 || cc == 1);
+ }
+
+ if (cc != 0 || (z[7] >= P7 && Nat256.Gte(z, P)))
+ {
+ AddPInvTo(z);
+ }
+ }
+
+ public static void Square(uint[] x, uint[] z)
+ {
+ uint[] tt = Nat256.CreateExt();
+ Nat256.Square(x, tt);
+ Reduce(tt, z);
+ }
+
+ public static void SquareN(uint[] x, int n, uint[] z)
+ {
+ Debug.Assert(n > 0);
+
+ uint[] tt = Nat256.CreateExt();
+ Nat256.Square(x, tt);
+ Reduce(tt, z);
+
+ while (--n > 0)
+ {
+ Nat256.Square(z, tt);
+ Reduce(tt, z);
+ }
+ }
+
+ public static void Subtract(uint[] x, uint[] y, uint[] z)
+ {
+ int c = Nat256.Sub(x, y, z);
+ if (c != 0)
+ {
+ SubPInvFrom(z);
+ }
+ }
+
+ public static void SubtractExt(uint[] xx, uint[] yy, uint[] zz)
+ {
+ int c = Nat.Sub(16, xx, yy, zz);
+ if (c != 0)
+ {
+ Nat.AddTo(16, PExt, zz);
+ }
+ }
+
+ public static void Twice(uint[] x, uint[] z)
+ {
+ uint c = Nat.ShiftUpBit(8, x, 0, z);
+ if (c != 0 || (z[7] >= P7 && Nat256.Gte(z, P)))
+ {
+ AddPInvTo(z);
+ }
+ }
+
+ private static void AddPInvTo(uint[] z)
+ {
+ long c = (long)z[0] + 1;
+ z[0] = (uint)c;
+ c >>= 32;
+ if (c != 0)
+ {
+ c += (long)z[1];
+ z[1] = (uint)c;
+ c >>= 32;
+ }
+ c += (long)z[2] - 1;
+ z[2] = (uint)c;
+ c >>= 32;
+ c += (long)z[3] + 1;
+ z[3] = (uint)c;
+ c >>= 32;
+ if (c != 0)
+ {
+ c += (long)z[4];
+ z[4] = (uint)c;
+ c >>= 32;
+ c += (long)z[5];
+ z[5] = (uint)c;
+ c >>= 32;
+ c += (long)z[6];
+ z[6] = (uint)c;
+ c >>= 32;
+ }
+ c += (long)z[7] + 1;
+ z[7] = (uint)c;
+ //c >>= 32;
+ }
+
+ private static void SubPInvFrom(uint[] z)
+ {
+ long c = (long)z[0] - 1;
+ z[0] = (uint)c;
+ c >>= 32;
+ if (c != 0)
+ {
+ c += (long)z[1];
+ z[1] = (uint)c;
+ c >>= 32;
+ }
+ c += (long)z[2] + 1;
+ z[2] = (uint)c;
+ c >>= 32;
+ c += (long)z[3] - 1;
+ z[3] = (uint)c;
+ c >>= 32;
+ if (c != 0)
+ {
+ c += (long)z[4];
+ z[4] = (uint)c;
+ c >>= 32;
+ c += (long)z[5];
+ z[5] = (uint)c;
+ c >>= 32;
+ c += (long)z[6];
+ z[6] = (uint)c;
+ c >>= 32;
+ }
+ c += (long)z[7] - 1;
+ z[7] = (uint)c;
+ //c >>= 32;
+ }
+ }
+}
diff --git a/crypto/src/math/ec/custom/gm/SM2P256V1FieldElement.cs b/crypto/src/math/ec/custom/gm/SM2P256V1FieldElement.cs
new file mode 100644
index 000000000..4f6428f9e
--- /dev/null
+++ b/crypto/src/math/ec/custom/gm/SM2P256V1FieldElement.cs
@@ -0,0 +1,211 @@
+using System;
+
+using Org.BouncyCastle.Math.Raw;
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.Math.EC.Custom.GM
+{
+ internal class SM2P256V1FieldElement
+ : ECFieldElement
+ {
+ public static readonly BigInteger Q = SM2P256V1Curve.q;
+
+ protected internal readonly uint[] x;
+
+ public SM2P256V1FieldElement(BigInteger x)
+ {
+ if (x == null || x.SignValue < 0 || x.CompareTo(Q) >= 0)
+ throw new ArgumentException("value invalid for SM2P256V1FieldElement", "x");
+
+ this.x = SM2P256V1Field.FromBigInteger(x);
+ }
+
+ public SM2P256V1FieldElement()
+ {
+ this.x = Nat256.Create();
+ }
+
+ protected internal SM2P256V1FieldElement(uint[] x)
+ {
+ this.x = x;
+ }
+
+ public override bool IsZero
+ {
+ get { return Nat256.IsZero(x); }
+ }
+
+ public override bool IsOne
+ {
+ get { return Nat256.IsOne(x); }
+ }
+
+ public override bool TestBitZero()
+ {
+ return Nat256.GetBit(x, 0) == 1;
+ }
+
+ public override BigInteger ToBigInteger()
+ {
+ return Nat256.ToBigInteger(x);
+ }
+
+ public override string FieldName
+ {
+ get { return "SM2P256V1Field"; }
+ }
+
+ public override int FieldSize
+ {
+ get { return Q.BitLength; }
+ }
+
+ public override ECFieldElement Add(ECFieldElement b)
+ {
+ uint[] z = Nat256.Create();
+ SM2P256V1Field.Add(x, ((SM2P256V1FieldElement)b).x, z);
+ return new SM2P256V1FieldElement(z);
+ }
+
+ public override ECFieldElement AddOne()
+ {
+ uint[] z = Nat256.Create();
+ SM2P256V1Field.AddOne(x, z);
+ return new SM2P256V1FieldElement(z);
+ }
+
+ public override ECFieldElement Subtract(ECFieldElement b)
+ {
+ uint[] z = Nat256.Create();
+ SM2P256V1Field.Subtract(x, ((SM2P256V1FieldElement)b).x, z);
+ return new SM2P256V1FieldElement(z);
+ }
+
+ public override ECFieldElement Multiply(ECFieldElement b)
+ {
+ uint[] z = Nat256.Create();
+ SM2P256V1Field.Multiply(x, ((SM2P256V1FieldElement)b).x, z);
+ return new SM2P256V1FieldElement(z);
+ }
+
+ public override ECFieldElement Divide(ECFieldElement b)
+ {
+ //return Multiply(b.Invert());
+ uint[] z = Nat256.Create();
+ Mod.Invert(SM2P256V1Field.P, ((SM2P256V1FieldElement)b).x, z);
+ SM2P256V1Field.Multiply(z, x, z);
+ return new SM2P256V1FieldElement(z);
+ }
+
+ public override ECFieldElement Negate()
+ {
+ uint[] z = Nat256.Create();
+ SM2P256V1Field.Negate(x, z);
+ return new SM2P256V1FieldElement(z);
+ }
+
+ public override ECFieldElement Square()
+ {
+ uint[] z = Nat256.Create();
+ SM2P256V1Field.Square(x, z);
+ return new SM2P256V1FieldElement(z);
+ }
+
+ public override ECFieldElement Invert()
+ {
+ //return new SM2P256V1FieldElement(ToBigInteger().ModInverse(Q));
+ uint[] z = Nat256.Create();
+ Mod.Invert(SM2P256V1Field.P, x, z);
+ return new SM2P256V1FieldElement(z);
+ }
+
+ /**
+ * return a sqrt root - the routine verifies that the calculation returns the right value - if
+ * none exists it returns null.
+ */
+ public override ECFieldElement Sqrt()
+ {
+ /*
+ * Raise this element to the exponent 2^254 - 2^222 - 2^94 + 2^62
+ *
+ * Breaking up the exponent's binary representation into "repunits", we get:
+ * { 31 1s } { 1 0s } { 128 1s } { 31 0s } { 1 1s } { 62 0s}
+ *
+ * We use an addition chain for the beginning: [1], 2, 3, 6, 12, [24], 30, [31]
+ */
+
+ uint[] x1 = this.x;
+ if (Nat256.IsZero(x1) || Nat256.IsOne(x1))
+ {
+ return this;
+ }
+
+ uint[] x2 = Nat256.Create();
+ SM2P256V1Field.Square(x1, x2);
+ SM2P256V1Field.Multiply(x2, x1, x2);
+ uint[] x4 = Nat256.Create();
+ SM2P256V1Field.SquareN(x2, 2, x4);
+ SM2P256V1Field.Multiply(x4, x2, x4);
+ uint[] x6 = Nat256.Create();
+ SM2P256V1Field.SquareN(x4, 2, x6);
+ SM2P256V1Field.Multiply(x6, x2, x6);
+ uint[] x12 = x2;
+ SM2P256V1Field.SquareN(x6, 6, x12);
+ SM2P256V1Field.Multiply(x12, x6, x12);
+ uint[] x24 = Nat256.Create();
+ SM2P256V1Field.SquareN(x12, 12, x24);
+ SM2P256V1Field.Multiply(x24, x12, x24);
+ uint[] x30 = x12;
+ SM2P256V1Field.SquareN(x24, 6, x30);
+ SM2P256V1Field.Multiply(x30, x6, x30);
+ uint[] x31 = x6;
+ SM2P256V1Field.Square(x30, x31);
+ SM2P256V1Field.Multiply(x31, x1, x31);
+
+ uint[] t1 = x24;
+ SM2P256V1Field.SquareN(x31, 31, t1);
+
+ uint[] x62 = x30;
+ SM2P256V1Field.Multiply(t1, x31, x62);
+
+ SM2P256V1Field.SquareN(t1, 32, t1);
+ SM2P256V1Field.Multiply(t1, x62, t1);
+ SM2P256V1Field.SquareN(t1, 62, t1);
+ SM2P256V1Field.Multiply(t1, x62, t1);
+ SM2P256V1Field.SquareN(t1, 4, t1);
+ SM2P256V1Field.Multiply(t1, x4, t1);
+ SM2P256V1Field.SquareN(t1, 32, t1);
+ SM2P256V1Field.Multiply(t1, x1, t1);
+ SM2P256V1Field.SquareN(t1, 62, t1);
+
+ uint[] t2 = x4;
+ SM2P256V1Field.Square(t1, t2);
+
+ return Nat256.Eq(x1, t2) ? new SM2P256V1FieldElement(t1) : null;
+ }
+
+ public override bool Equals(object obj)
+ {
+ return Equals(obj as SM2P256V1FieldElement);
+ }
+
+ public override bool Equals(ECFieldElement other)
+ {
+ return Equals(other as SM2P256V1FieldElement);
+ }
+
+ public virtual bool Equals(SM2P256V1FieldElement other)
+ {
+ if (this == other)
+ return true;
+ if (null == other)
+ return false;
+ return Nat256.Eq(x, other.x);
+ }
+
+ public override int GetHashCode()
+ {
+ return Q.GetHashCode() ^ Arrays.GetHashCode(x, 0, 8);
+ }
+ }
+}
diff --git a/crypto/src/math/ec/custom/gm/SM2P256V1Point.cs b/crypto/src/math/ec/custom/gm/SM2P256V1Point.cs
new file mode 100644
index 000000000..916c90633
--- /dev/null
+++ b/crypto/src/math/ec/custom/gm/SM2P256V1Point.cs
@@ -0,0 +1,279 @@
+using System;
+
+using Org.BouncyCastle.Math.Raw;
+
+namespace Org.BouncyCastle.Math.EC.Custom.GM
+{
+ internal class SM2P256V1Point
+ : AbstractFpPoint
+ {
+ /**
+ * Create a point which encodes with point compression.
+ *
+ * @param curve
+ * the curve to use
+ * @param x
+ * affine x co-ordinate
+ * @param y
+ * affine y co-ordinate
+ *
+ * @deprecated Use ECCurve.createPoint to construct points
+ */
+ public SM2P256V1Point(ECCurve curve, ECFieldElement x, ECFieldElement y)
+ : this(curve, x, y, false)
+ {
+ }
+
+ /**
+ * Create a point that encodes with or without point compresion.
+ *
+ * @param curve
+ * the curve to use
+ * @param x
+ * affine x co-ordinate
+ * @param y
+ * affine y co-ordinate
+ * @param withCompression
+ * if true encode with point compression
+ *
+ * @deprecated per-point compression property will be removed, refer
+ * {@link #getEncoded(bool)}
+ */
+ public SM2P256V1Point(ECCurve curve, ECFieldElement x, ECFieldElement y, bool withCompression)
+ : base(curve, x, y, withCompression)
+ {
+ if ((x == null) != (y == null))
+ throw new ArgumentException("Exactly one of the field elements is null");
+ }
+
+ internal SM2P256V1Point(ECCurve curve, ECFieldElement x, ECFieldElement y, ECFieldElement[] zs, bool withCompression)
+ : base(curve, x, y, zs, withCompression)
+ {
+ }
+
+ protected override ECPoint Detach()
+ {
+ return new SM2P256V1Point(null, AffineXCoord, AffineYCoord);
+ }
+
+ public override ECPoint Add(ECPoint b)
+ {
+ if (this.IsInfinity)
+ return b;
+ if (b.IsInfinity)
+ return this;
+ if (this == b)
+ return Twice();
+
+ ECCurve curve = this.Curve;
+
+ SM2P256V1FieldElement X1 = (SM2P256V1FieldElement)this.RawXCoord, Y1 = (SM2P256V1FieldElement)this.RawYCoord;
+ SM2P256V1FieldElement X2 = (SM2P256V1FieldElement)b.RawXCoord, Y2 = (SM2P256V1FieldElement)b.RawYCoord;
+
+ SM2P256V1FieldElement Z1 = (SM2P256V1FieldElement)this.RawZCoords[0];
+ SM2P256V1FieldElement Z2 = (SM2P256V1FieldElement)b.RawZCoords[0];
+
+ uint c;
+ uint[] tt1 = Nat256.CreateExt();
+ uint[] t2 = Nat256.Create();
+ uint[] t3 = Nat256.Create();
+ uint[] t4 = Nat256.Create();
+
+ bool Z1IsOne = Z1.IsOne;
+ uint[] U2, S2;
+ if (Z1IsOne)
+ {
+ U2 = X2.x;
+ S2 = Y2.x;
+ }
+ else
+ {
+ S2 = t3;
+ SM2P256V1Field.Square(Z1.x, S2);
+
+ U2 = t2;
+ SM2P256V1Field.Multiply(S2, X2.x, U2);
+
+ SM2P256V1Field.Multiply(S2, Z1.x, S2);
+ SM2P256V1Field.Multiply(S2, Y2.x, S2);
+ }
+
+ bool Z2IsOne = Z2.IsOne;
+ uint[] U1, S1;
+ if (Z2IsOne)
+ {
+ U1 = X1.x;
+ S1 = Y1.x;
+ }
+ else
+ {
+ S1 = t4;
+ SM2P256V1Field.Square(Z2.x, S1);
+
+ U1 = tt1;
+ SM2P256V1Field.Multiply(S1, X1.x, U1);
+
+ SM2P256V1Field.Multiply(S1, Z2.x, S1);
+ SM2P256V1Field.Multiply(S1, Y1.x, S1);
+ }
+
+ uint[] H = Nat256.Create();
+ SM2P256V1Field.Subtract(U1, U2, H);
+
+ uint[] R = t2;
+ SM2P256V1Field.Subtract(S1, S2, R);
+
+ // Check if b == this or b == -this
+ if (Nat256.IsZero(H))
+ {
+ if (Nat256.IsZero(R))
+ {
+ // this == b, i.e. this must be doubled
+ return this.Twice();
+ }
+
+ // this == -b, i.e. the result is the point at infinity
+ return curve.Infinity;
+ }
+
+ uint[] HSquared = t3;
+ SM2P256V1Field.Square(H, HSquared);
+
+ uint[] G = Nat256.Create();
+ SM2P256V1Field.Multiply(HSquared, H, G);
+
+ uint[] V = t3;
+ SM2P256V1Field.Multiply(HSquared, U1, V);
+
+ SM2P256V1Field.Negate(G, G);
+ Nat256.Mul(S1, G, tt1);
+
+ c = Nat256.AddBothTo(V, V, G);
+ SM2P256V1Field.Reduce32(c, G);
+
+ SM2P256V1FieldElement X3 = new SM2P256V1FieldElement(t4);
+ SM2P256V1Field.Square(R, X3.x);
+ SM2P256V1Field.Subtract(X3.x, G, X3.x);
+
+ SM2P256V1FieldElement Y3 = new SM2P256V1FieldElement(G);
+ SM2P256V1Field.Subtract(V, X3.x, Y3.x);
+ SM2P256V1Field.MultiplyAddToExt(Y3.x, R, tt1);
+ SM2P256V1Field.Reduce(tt1, Y3.x);
+
+ SM2P256V1FieldElement Z3 = new SM2P256V1FieldElement(H);
+ if (!Z1IsOne)
+ {
+ SM2P256V1Field.Multiply(Z3.x, Z1.x, Z3.x);
+ }
+ if (!Z2IsOne)
+ {
+ SM2P256V1Field.Multiply(Z3.x, Z2.x, Z3.x);
+ }
+
+ ECFieldElement[] zs = new ECFieldElement[]{ Z3 };
+
+ return new SM2P256V1Point(curve, X3, Y3, zs, IsCompressed);
+ }
+
+ public override ECPoint Twice()
+ {
+ if (this.IsInfinity)
+ return this;
+
+ ECCurve curve = this.Curve;
+
+ SM2P256V1FieldElement Y1 = (SM2P256V1FieldElement)this.RawYCoord;
+ if (Y1.IsZero)
+ return curve.Infinity;
+
+ SM2P256V1FieldElement X1 = (SM2P256V1FieldElement)this.RawXCoord, Z1 = (SM2P256V1FieldElement)this.RawZCoords[0];
+
+ uint c;
+ uint[] t1 = Nat256.Create();
+ uint[] t2 = Nat256.Create();
+
+ uint[] Y1Squared = Nat256.Create();
+ SM2P256V1Field.Square(Y1.x, Y1Squared);
+
+ uint[] T = Nat256.Create();
+ SM2P256V1Field.Square(Y1Squared, T);
+
+ bool Z1IsOne = Z1.IsOne;
+
+ uint[] Z1Squared = Z1.x;
+ if (!Z1IsOne)
+ {
+ Z1Squared = t2;
+ SM2P256V1Field.Square(Z1.x, Z1Squared);
+ }
+
+ SM2P256V1Field.Subtract(X1.x, Z1Squared, t1);
+
+ uint[] M = t2;
+ SM2P256V1Field.Add(X1.x, Z1Squared, M);
+ SM2P256V1Field.Multiply(M, t1, M);
+ c = Nat256.AddBothTo(M, M, M);
+ SM2P256V1Field.Reduce32(c, M);
+
+ uint[] S = Y1Squared;
+ SM2P256V1Field.Multiply(Y1Squared, X1.x, S);
+ c = Nat.ShiftUpBits(8, S, 2, 0);
+ SM2P256V1Field.Reduce32(c, S);
+
+ c = Nat.ShiftUpBits(8, T, 3, 0, t1);
+ SM2P256V1Field.Reduce32(c, t1);
+
+ SM2P256V1FieldElement X3 = new SM2P256V1FieldElement(T);
+ SM2P256V1Field.Square(M, X3.x);
+ SM2P256V1Field.Subtract(X3.x, S, X3.x);
+ SM2P256V1Field.Subtract(X3.x, S, X3.x);
+
+ SM2P256V1FieldElement Y3 = new SM2P256V1FieldElement(S);
+ SM2P256V1Field.Subtract(S, X3.x, Y3.x);
+ SM2P256V1Field.Multiply(Y3.x, M, Y3.x);
+ SM2P256V1Field.Subtract(Y3.x, t1, Y3.x);
+
+ SM2P256V1FieldElement Z3 = new SM2P256V1FieldElement(M);
+ SM2P256V1Field.Twice(Y1.x, Z3.x);
+ if (!Z1IsOne)
+ {
+ SM2P256V1Field.Multiply(Z3.x, Z1.x, Z3.x);
+ }
+
+ return new SM2P256V1Point(curve, X3, Y3, new ECFieldElement[]{ Z3 }, IsCompressed);
+ }
+
+ public override ECPoint TwicePlus(ECPoint b)
+ {
+ if (this == b)
+ return ThreeTimes();
+ if (this.IsInfinity)
+ return b;
+ if (b.IsInfinity)
+ return Twice();
+
+ ECFieldElement Y1 = this.RawYCoord;
+ if (Y1.IsZero)
+ return b;
+
+ return Twice().Add(b);
+ }
+
+ public override ECPoint ThreeTimes()
+ {
+ if (this.IsInfinity || this.RawYCoord.IsZero)
+ return this;
+
+ // NOTE: Be careful about recursions between TwicePlus and ThreeTimes
+ return Twice().Add(this);
+ }
+
+ public override ECPoint Negate()
+ {
+ if (IsInfinity)
+ return this;
+
+ return new SM2P256V1Point(Curve, RawXCoord, RawYCoord.Negate(), RawZCoords, IsCompressed);
+ }
+ }
+}
diff --git a/crypto/src/math/ec/custom/sec/SecP128R1Field.cs b/crypto/src/math/ec/custom/sec/SecP128R1Field.cs
index ff6fb6b65..d1ac009b3 100644
--- a/crypto/src/math/ec/custom/sec/SecP128R1Field.cs
+++ b/crypto/src/math/ec/custom/sec/SecP128R1Field.cs
@@ -19,7 +19,7 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec
public static void Add(uint[] x, uint[] y, uint[] z)
{
uint c = Nat128.Add(x, y, z);
- if (c != 0 || (z[3] == P3 && Nat128.Gte(z, P)))
+ if (c != 0 || (z[3] >= P3 && Nat128.Gte(z, P)))
{
AddPInvTo(z);
}
@@ -28,7 +28,7 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec
public static void AddExt(uint[] xx, uint[] yy, uint[] zz)
{
uint c = Nat256.Add(xx, yy, zz);
- if (c != 0 || (zz[7] == PExt7 && Nat256.Gte(zz, PExt)))
+ if (c != 0 || (zz[7] >= PExt7 && Nat256.Gte(zz, PExt)))
{
Nat.AddTo(PExtInv.Length, PExtInv, zz);
}
@@ -37,7 +37,7 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec
public static void AddOne(uint[] x, uint[] z)
{
uint c = Nat.Inc(4, x, z);
- if (c != 0 || (z[3] == P3 && Nat128.Gte(z, P)))
+ if (c != 0 || (z[3] >= P3 && Nat128.Gte(z, P)))
{
AddPInvTo(z);
}
@@ -46,7 +46,7 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec
public static uint[] FromBigInteger(BigInteger x)
{
uint[] z = Nat128.FromBigInteger(x);
- if (z[3] == P3 && Nat128.Gte(z, P))
+ if (z[3] >= P3 && Nat128.Gte(z, P))
{
Nat128.SubFrom(P, z);
}
@@ -76,7 +76,7 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec
public static void MultiplyAddToExt(uint[] x, uint[] y, uint[] zz)
{
uint c = Nat128.MulAddTo(x, y, zz);
- if (c != 0 || (zz[7] == PExt7 && Nat256.Gte(zz, PExt)))
+ if (c != 0 || (zz[7] >= PExt7 && Nat256.Gte(zz, PExt)))
{
Nat.AddTo(PExtInv.Length, PExtInv, zz);
}
@@ -179,7 +179,7 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec
public static void Twice(uint[] x, uint[] z)
{
uint c = Nat.ShiftUpBit(4, x, 0, z);
- if (c != 0 || (z[3] == P3 && Nat128.Gte(z, P)))
+ if (c != 0 || (z[3] >= P3 && Nat128.Gte(z, P)))
{
AddPInvTo(z);
}
diff --git a/crypto/src/openpgp/PgpUtilities.cs b/crypto/src/openpgp/PgpUtilities.cs
index d9e7882fa..5ea2907e8 100644
--- a/crypto/src/openpgp/PgpUtilities.cs
+++ b/crypto/src/openpgp/PgpUtilities.cs
@@ -417,7 +417,20 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp
return inputStream;
}
- else
+
+ if (!IsPossiblyBase64(ch))
+ {
+ inputStream.Position = markedPos;
+
+ return new ArmoredInputStream(inputStream);
+ }
+
+ byte[] buf = new byte[ReadAhead];
+ int count = 1;
+ int index = 1;
+
+ buf[0] = (byte)ch;
+ while (count != ReadAhead && (ch = inputStream.ReadByte()) >= 0)
{
if (!IsPossiblyBase64(ch))
{
@@ -426,51 +439,49 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp
return new ArmoredInputStream(inputStream);
}
- byte[] buf = new byte[ReadAhead];
- int count = 1;
- int index = 1;
-
- buf[0] = (byte)ch;
- while (count != ReadAhead && (ch = inputStream.ReadByte()) >= 0)
+ if (ch != '\n' && ch != '\r')
{
- if (!IsPossiblyBase64(ch))
- {
- inputStream.Position = markedPos;
+ buf[index++] = (byte)ch;
+ }
- return new ArmoredInputStream(inputStream);
- }
+ count++;
+ }
- if (ch != '\n' && ch != '\r')
- {
- buf[index++] = (byte)ch;
- }
+ inputStream.Position = markedPos;
- count++;
- }
+ //
+ // nothing but new lines, little else, assume regular armoring
+ //
+ if (count < 4)
+ {
+ return new ArmoredInputStream(inputStream);
+ }
- inputStream.Position = markedPos;
+ //
+ // test our non-blank data
+ //
+ byte[] firstBlock = new byte[8];
- //
- // nothing but new lines, little else, assume regular armoring
- //
- if (count < 4)
- {
- return new ArmoredInputStream(inputStream);
- }
+ Array.Copy(buf, 0, firstBlock, 0, firstBlock.Length);
- //
- // test our non-blank data
- //
- byte[] firstBlock = new byte[8];
- Array.Copy(buf, 0, firstBlock, 0, firstBlock.Length);
- byte[] decoded = Base64.Decode(firstBlock);
+ try
+ {
+ byte[] decoded = Base64.Decode(firstBlock);
- //
+ //
// it's a base64 PGP block.
//
- bool hasHeaders = (decoded[0] & 0x80) == 0;
+ bool hasHeaders = (decoded[0] & 0x80) == 0;
- return new ArmoredInputStream(inputStream, hasHeaders);
+ return new ArmoredInputStream(inputStream, hasHeaders);
+ }
+ catch (IOException e)
+ {
+ throw e;
+ }
+ catch (Exception e)
+ {
+ throw new IOException(e.Message);
}
}
diff --git a/crypto/src/security/CipherUtilities.cs b/crypto/src/security/CipherUtilities.cs
index 3217f3183..de05bc9ef 100644
--- a/crypto/src/security/CipherUtilities.cs
+++ b/crypto/src/security/CipherUtilities.cs
@@ -323,7 +323,7 @@ namespace Org.BouncyCastle.Security
"PBEWITHMD5AND256BITAES-CBC-OPENSSL"))
{
return new PaddedBufferedBlockCipher(
- new CbcBlockCipher(new AesFastEngine()));
+ new CbcBlockCipher(new AesEngine()));
}
}
}
@@ -358,7 +358,7 @@ namespace Org.BouncyCastle.Security
switch (cipherAlgorithm)
{
case CipherAlgorithm.AES:
- blockCipher = new AesFastEngine();
+ blockCipher = new AesEngine();
break;
case CipherAlgorithm.ARC4:
streamCipher = new RC4Engine();
@@ -722,7 +722,7 @@ namespace Org.BouncyCastle.Security
{
switch (cipherAlgorithm)
{
- case CipherAlgorithm.AES: return new AesFastEngine();
+ case CipherAlgorithm.AES: return new AesEngine();
case CipherAlgorithm.BLOWFISH: return new BlowfishEngine();
case CipherAlgorithm.CAMELLIA: return new CamelliaEngine();
case CipherAlgorithm.CAST5: return new Cast5Engine();
diff --git a/crypto/src/security/MacUtilities.cs b/crypto/src/security/MacUtilities.cs
index fab9b1d41..278f3bec1 100644
--- a/crypto/src/security/MacUtilities.cs
+++ b/crypto/src/security/MacUtilities.cs
@@ -136,7 +136,7 @@ namespace Org.BouncyCastle.Security
if (mechanism == "AESCMAC")
{
- return new CMac(new AesFastEngine());
+ return new CMac(new AesEngine());
}
if (mechanism == "DESMAC")
{
diff --git a/crypto/src/security/WrapperUtilities.cs b/crypto/src/security/WrapperUtilities.cs
index ce31ea519..c57632081 100644
--- a/crypto/src/security/WrapperUtilities.cs
+++ b/crypto/src/security/WrapperUtilities.cs
@@ -78,7 +78,7 @@ namespace Org.BouncyCastle.Security
case WrapAlgorithm.RC2WRAP: return new RC2WrapEngine();
case WrapAlgorithm.SEEDWRAP: return new SeedWrapEngine();
case WrapAlgorithm.DESEDERFC3211WRAP: return new Rfc3211WrapEngine(new DesEdeEngine());
- case WrapAlgorithm.AESRFC3211WRAP: return new Rfc3211WrapEngine(new AesFastEngine());
+ case WrapAlgorithm.AESRFC3211WRAP: return new Rfc3211WrapEngine(new AesEngine());
case WrapAlgorithm.CAMELLIARFC3211WRAP: return new Rfc3211WrapEngine(new CamelliaEngine());
}
}
|