diff options
Diffstat (limited to 'crypto/src')
80 files changed, 945 insertions, 647 deletions
diff --git a/crypto/src/AssemblyInfo.cs b/crypto/src/AssemblyInfo.cs index 43935c8dc..f2eec4ad8 100644 --- a/crypto/src/AssemblyInfo.cs +++ b/crypto/src/AssemblyInfo.cs @@ -85,4 +85,4 @@ namespace System.Reflection } } -#endif \ No newline at end of file +#endif diff --git a/crypto/src/asn1/ASN1StreamParser.cs b/crypto/src/asn1/ASN1StreamParser.cs index 3eaaadaee..860dc99b1 100644 --- a/crypto/src/asn1/ASN1StreamParser.cs +++ b/crypto/src/asn1/ASN1StreamParser.cs @@ -59,7 +59,7 @@ namespace Org.BouncyCastle.Asn1 if (_in is IndefiniteLengthInputStream) { if (!constructed) - throw new IOException("indefinite length primitive encoding encountered"); + throw new IOException("indefinite-length primitive encoding encountered"); return ReadIndef(tag); } @@ -134,12 +134,13 @@ namespace Org.BouncyCastle.Asn1 // // calculate length // - int length = Asn1InputStream.ReadLength(_in, _limit); + int length = Asn1InputStream.ReadLength(_in, _limit, + tagNo == Asn1Tags.OctetString || tagNo == Asn1Tags.Sequence || tagNo == Asn1Tags.Set || tagNo == Asn1Tags.External); - if (length < 0) // indefinite length method + if (length < 0) // indefinite-length method { if (!isConstructed) - throw new IOException("indefinite length primitive encoding encountered"); + throw new IOException("indefinite-length primitive encoding encountered"); IndefiniteLengthInputStream indIn = new IndefiniteLengthInputStream(_in, _limit); Asn1StreamParser sp = new Asn1StreamParser(indIn, _limit); @@ -158,7 +159,7 @@ namespace Org.BouncyCastle.Asn1 } else { - DefiniteLengthInputStream defIn = new DefiniteLengthInputStream(_in, length); + DefiniteLengthInputStream defIn = new DefiniteLengthInputStream(_in, length, _limit); if ((tag & Asn1Tags.Application) != 0) { diff --git a/crypto/src/asn1/Asn1InputStream.cs b/crypto/src/asn1/Asn1InputStream.cs index 0c7461c98..4f99301b3 100644 --- a/crypto/src/asn1/Asn1InputStream.cs +++ b/crypto/src/asn1/Asn1InputStream.cs @@ -2,6 +2,7 @@ using System; using System.Diagnostics; using System.IO; +using Org.BouncyCastle.Utilities; using Org.BouncyCastle.Utilities.IO; namespace Org.BouncyCastle.Asn1 @@ -22,10 +23,12 @@ namespace Org.BouncyCastle.Asn1 internal static int FindLimit(Stream input) { if (input is LimitedInputStream) - { - return ((LimitedInputStream)input).GetRemaining(); - } - else if (input is MemoryStream) + return ((LimitedInputStream)input).Limit; + + if (input is Asn1InputStream) + return ((Asn1InputStream)input).Limit; + + if (input is MemoryStream) { MemoryStream mem = (MemoryStream)input; return (int)(mem.Length - mem.Position); @@ -77,7 +80,7 @@ namespace Org.BouncyCastle.Asn1 { bool isConstructed = (tag & Asn1Tags.Constructed) != 0; - DefiniteLengthInputStream defIn = new DefiniteLengthInputStream(this.s, length); + DefiniteLengthInputStream defIn = new DefiniteLengthInputStream(this.s, length, limit); if ((tag & Asn1Tags.Application) != 0) { @@ -95,10 +98,27 @@ namespace Org.BouncyCastle.Asn1 switch (tagNo) { case Asn1Tags.OctetString: + { // // yes, people actually do this... // - return new BerOctetString(ReadVector(defIn)); + Asn1EncodableVector v = ReadVector(defIn); + Asn1OctetString[] strings = new Asn1OctetString[v.Count]; + + for (int i = 0; i != strings.Length; i++) + { + Asn1Encodable asn1Obj = v[i]; + if (!(asn1Obj is Asn1OctetString)) + { + throw new Asn1Exception("unknown object encountered in constructed OCTET STRING: " + + Platform.GetTypeName(asn1Obj)); + } + + strings[i] = (Asn1OctetString)asn1Obj; + } + + return new BerOctetString(strings); + } case Asn1Tags.Sequence: return CreateDerSequence(defIn); case Asn1Tags.Set: @@ -162,12 +182,12 @@ namespace Org.BouncyCastle.Asn1 // // calculate length // - int length = ReadLength(this.s, limit); + int length = ReadLength(this.s, limit, false); - if (length < 0) // indefinite length method + if (length < 0) // indefinite-length method { if (!isConstructed) - throw new IOException("indefinite length primitive encoding encountered"); + throw new IOException("indefinite-length primitive encoding encountered"); IndefiniteLengthInputStream indIn = new IndefiniteLengthInputStream(this.s, limit); Asn1StreamParser sp = new Asn1StreamParser(indIn, limit); @@ -210,6 +230,11 @@ namespace Org.BouncyCastle.Asn1 } } + internal virtual int Limit + { + get { return limit; } + } + internal static int ReadTagNumber( Stream s, int tag) @@ -228,9 +253,7 @@ namespace Org.BouncyCastle.Asn1 // X.690-0207 8.1.2.4.2 // "c) bits 7 to 1 of the first subsequent octet shall not all be zero." if ((b & 0x7f) == 0) // Note: -1 will pass - { - throw new IOException("Corrupted stream - invalid high tag number found"); - } + throw new IOException("corrupted stream - invalid high tag number found"); while ((b >= 0) && ((b & 0x80) != 0)) { @@ -248,9 +271,7 @@ namespace Org.BouncyCastle.Asn1 return tagNo; } - internal static int ReadLength( - Stream s, - int limit) + internal static int ReadLength(Stream s, int limit, bool isParsing) { int length = s.ReadByte(); if (length < 0) @@ -279,18 +300,18 @@ namespace Org.BouncyCastle.Asn1 } if (length < 0) - throw new IOException("Corrupted stream - negative length found"); + throw new IOException("corrupted stream - negative length found"); - if (length >= limit) // after all we must have read at least 1 byte - throw new IOException("Corrupted stream - out of bounds length found"); + if (length >= limit && !isParsing) // after all we must have read at least 1 byte + throw new IOException("corrupted stream - out of bounds length found: " + length + " >= " + limit); } return length; } - internal static byte[] GetBuffer(DefiniteLengthInputStream defIn, byte[][] tmpBuffers) + private static byte[] GetBuffer(DefiniteLengthInputStream defIn, byte[][] tmpBuffers) { - int len = defIn.GetRemaining(); + int len = defIn.Remaining; if (len >= tmpBuffers.Length) { return defIn.ToArray(); @@ -307,6 +328,49 @@ namespace Org.BouncyCastle.Asn1 return buf; } + private static char[] GetBmpCharBuffer(DefiniteLengthInputStream defIn) + { + int remainingBytes = defIn.Remaining; + if (0 != (remainingBytes & 1)) + throw new IOException("malformed BMPString encoding encountered"); + + char[] str = new char[remainingBytes / 2]; + int stringPos = 0; + + byte[] buf = new byte[8]; + while (remainingBytes >= 8) + { + if (Streams.ReadFully(defIn, buf, 0, 8) != 8) + throw new EndOfStreamException("EOF encountered in middle of BMPString"); + + str[stringPos ] = (char)((buf[0] << 8) | (buf[1] & 0xFF)); + str[stringPos + 1] = (char)((buf[2] << 8) | (buf[3] & 0xFF)); + str[stringPos + 2] = (char)((buf[4] << 8) | (buf[5] & 0xFF)); + str[stringPos + 3] = (char)((buf[6] << 8) | (buf[7] & 0xFF)); + stringPos += 4; + remainingBytes -= 8; + } + if (remainingBytes > 0) + { + if (Streams.ReadFully(defIn, buf, 0, remainingBytes) != remainingBytes) + throw new EndOfStreamException("EOF encountered in middle of BMPString"); + + int bufPos = 0; + do + { + int b1 = buf[bufPos++] << 8; + int b2 = buf[bufPos++] & 0xFF; + str[stringPos++] = (char)(b1 | b2); + } + while (bufPos < remainingBytes); + } + + if (0 != defIn.Remaining || str.Length != stringPos) + throw new InvalidOperationException(); + + return str; + } + internal static Asn1Object CreatePrimitiveDerObject( int tagNo, DefiniteLengthInputStream defIn, @@ -314,6 +378,8 @@ namespace Org.BouncyCastle.Asn1 { switch (tagNo) { + case Asn1Tags.BmpString: + return new DerBmpString(GetBmpCharBuffer(defIn)); case Asn1Tags.Boolean: return DerBoolean.FromOctetString(GetBuffer(defIn, tmpBuffers)); case Asn1Tags.Enumerated: @@ -328,8 +394,6 @@ namespace Org.BouncyCastle.Asn1 { case Asn1Tags.BitString: return DerBitString.FromAsn1Octets(bytes); - case Asn1Tags.BmpString: - return new DerBmpString(bytes); case Asn1Tags.GeneralizedTime: return new DerGeneralizedTime(bytes); case Asn1Tags.GeneralString: @@ -339,7 +403,7 @@ namespace Org.BouncyCastle.Asn1 case Asn1Tags.IA5String: return new DerIA5String(bytes); case Asn1Tags.Integer: - return new DerInteger(bytes); + return new DerInteger(bytes, false); case Asn1Tags.Null: return DerNull.Instance; // actual content is ignored (enforce 0 length?) case Asn1Tags.NumericString: diff --git a/crypto/src/asn1/Asn1OctetString.cs b/crypto/src/asn1/Asn1OctetString.cs index 73b6e51bf..da7dfae46 100644 --- a/crypto/src/asn1/Asn1OctetString.cs +++ b/crypto/src/asn1/Asn1OctetString.cs @@ -67,20 +67,7 @@ namespace Org.BouncyCastle.Asn1 this.str = str; } - internal Asn1OctetString( - Asn1Encodable obj) - { - try - { - this.str = obj.GetEncoded(Asn1Encodable.Der); - } - catch (IOException e) - { - throw new ArgumentException("Error processing object : " + e.ToString()); - } - } - - public Stream GetOctetStream() + public Stream GetOctetStream() { return new MemoryStream(str, false); } diff --git a/crypto/src/asn1/BerOctetString.cs b/crypto/src/asn1/BerOctetString.cs index a7c8ad33e..fb4291612 100644 --- a/crypto/src/asn1/BerOctetString.cs +++ b/crypto/src/asn1/BerOctetString.cs @@ -9,66 +9,77 @@ namespace Org.BouncyCastle.Asn1 public class BerOctetString : DerOctetString, IEnumerable { - public static BerOctetString FromSequence(Asn1Sequence seq) - { - IList v = Platform.CreateArrayList(); - - foreach (Asn1Encodable obj in seq) - { - v.Add(obj); - } - - return new BerOctetString(v); - } + private static readonly int DefaultChunkSize = 1000; - private const int MaxLength = 1000; + public static BerOctetString FromSequence(Asn1Sequence seq) + { + int count = seq.Count; + Asn1OctetString[] v = new Asn1OctetString[count]; + for (int i = 0; i < count; ++i) + { + v[i] = Asn1OctetString.GetInstance(seq[i]); + } + return new BerOctetString(v); + } - /** - * convert a vector of octet strings into a single byte string - */ - private static byte[] ToBytes( - IEnumerable octs) + private static byte[] ToBytes(Asn1OctetString[] octs) { MemoryStream bOut = new MemoryStream(); - foreach (DerOctetString o in octs) - { + foreach (Asn1OctetString o in octs) + { byte[] octets = o.GetOctets(); bOut.Write(octets, 0, octets.Length); } - return bOut.ToArray(); + return bOut.ToArray(); + } + + private static Asn1OctetString[] ToOctetStringArray(IEnumerable e) + { + IList list = Platform.CreateArrayList(e); + + int count = list.Count; + Asn1OctetString[] v = new Asn1OctetString[count]; + for (int i = 0; i < count; ++i) + { + v[i] = Asn1OctetString.GetInstance(list[i]); + } + return v; } - private readonly IEnumerable octs; + private readonly int chunkSize; + private readonly Asn1OctetString[] octs; + + [Obsolete("Will be removed")] + public BerOctetString(IEnumerable e) + : this(ToOctetStringArray(e)) + { + } - /// <param name="str">The octets making up the octet string.</param> - public BerOctetString( - byte[] str) - : base(str) + public BerOctetString(byte[] str) + : this(str, DefaultChunkSize) { } - public BerOctetString( - IEnumerable octets) - : base(ToBytes(octets)) + public BerOctetString(Asn1OctetString[] octs) + : this(octs, DefaultChunkSize) { - this.octs = octets; } - public BerOctetString( - Asn1Object obj) - : base(obj) + public BerOctetString(byte[] str, int chunkSize) + : this(str, null, chunkSize) { } - public BerOctetString( - Asn1Encodable obj) - : base(obj.ToAsn1Object()) + public BerOctetString(Asn1OctetString[] octs, int chunkSize) + : this(ToBytes(octs), octs, chunkSize) { } - public override byte[] GetOctets() + private BerOctetString(byte[] str, Asn1OctetString[] octs, int chunkSize) + : base(str) { - return str; + this.octs = octs; + this.chunkSize = chunkSize; } /** @@ -93,17 +104,17 @@ namespace Org.BouncyCastle.Asn1 private IList GenerateOcts() { IList vec = Platform.CreateArrayList(); - for (int i = 0; i < str.Length; i += MaxLength) - { - int end = System.Math.Min(str.Length, i + MaxLength); + for (int i = 0; i < str.Length; i += chunkSize) + { + int end = System.Math.Min(str.Length, i + chunkSize); - byte[] nStr = new byte[end - i]; + byte[] nStr = new byte[end - i]; - Array.Copy(str, i, nStr, 0, nStr.Length); + Array.Copy(str, i, nStr, 0, nStr.Length); - vec.Add(new DerOctetString(nStr)); - } - return vec; + vec.Add(new DerOctetString(nStr)); + } + return vec; } internal override void Encode( @@ -118,7 +129,7 @@ namespace Org.BouncyCastle.Asn1 // // write out the octet array // - foreach (DerOctetString oct in this) + foreach (Asn1OctetString oct in this) { derOut.WriteObject(oct); } diff --git a/crypto/src/asn1/ConstructedOctetStream.cs b/crypto/src/asn1/ConstructedOctetStream.cs index 1773b22cc..829a9a427 100644 --- a/crypto/src/asn1/ConstructedOctetStream.cs +++ b/crypto/src/asn1/ConstructedOctetStream.cs @@ -1,5 +1,6 @@ using System.IO; +using Org.BouncyCastle.Utilities; using Org.BouncyCastle.Utilities.IO; namespace Org.BouncyCastle.Asn1 @@ -25,13 +26,12 @@ namespace Org.BouncyCastle.Asn1 if (!_first) return 0; - Asn1OctetStringParser s = (Asn1OctetStringParser)_parser.ReadObject(); - - if (s == null) - return 0; + Asn1OctetStringParser next = GetNextParser(); + if (next == null) + return 0; _first = false; - _currentStream = s.GetOctetStream(); + _currentStream = next.GetOctetStream(); } int totalRead = 0; @@ -49,15 +49,14 @@ namespace Org.BouncyCastle.Asn1 } else { - Asn1OctetStringParser aos = (Asn1OctetStringParser)_parser.ReadObject(); - - if (aos == null) + Asn1OctetStringParser next = GetNextParser(); + if (next == null) { _currentStream = null; return totalRead; } - _currentStream = aos.GetOctetStream(); + _currentStream = next.GetOctetStream(); } } } @@ -69,13 +68,12 @@ namespace Org.BouncyCastle.Asn1 if (!_first) return 0; - Asn1OctetStringParser s = (Asn1OctetStringParser)_parser.ReadObject(); - - if (s == null) + Asn1OctetStringParser next = GetNextParser(); + if (next == null) return 0; _first = false; - _currentStream = s.GetOctetStream(); + _currentStream = next.GetOctetStream(); } for (;;) @@ -83,20 +81,29 @@ namespace Org.BouncyCastle.Asn1 int b = _currentStream.ReadByte(); if (b >= 0) - { return b; - } - - Asn1OctetStringParser aos = (Asn1OctetStringParser)_parser.ReadObject(); - if (aos == null) + Asn1OctetStringParser next = GetNextParser(); + if (next == null) { _currentStream = null; return -1; } - _currentStream = aos.GetOctetStream(); + _currentStream = next.GetOctetStream(); } } + + private Asn1OctetStringParser GetNextParser() + { + IAsn1Convertible asn1Obj = _parser.ReadObject(); + if (asn1Obj == null) + return null; + + if (asn1Obj is Asn1OctetStringParser) + return (Asn1OctetStringParser)asn1Obj; + + throw new IOException("unknown object encountered: " + Platform.GetTypeName(asn1Obj)); + } } } diff --git a/crypto/src/asn1/DefiniteLengthInputStream.cs b/crypto/src/asn1/DefiniteLengthInputStream.cs index 4ae803c0e..d10ea4d12 100644 --- a/crypto/src/asn1/DefiniteLengthInputStream.cs +++ b/crypto/src/asn1/DefiniteLengthInputStream.cs @@ -13,10 +13,8 @@ namespace Org.BouncyCastle.Asn1 private readonly int _originalLength; private int _remaining; - internal DefiniteLengthInputStream( - Stream inStream, - int length) - : base(inStream, length) + internal DefiniteLengthInputStream(Stream inStream, int length, int limit) + : base(inStream, limit) { if (length < 0) throw new ArgumentException("negative lengths not allowed", "length"); @@ -30,7 +28,7 @@ namespace Org.BouncyCastle.Asn1 } } - internal int Remaining + internal int Remaining { get { return _remaining; } } @@ -80,6 +78,14 @@ namespace Org.BouncyCastle.Asn1 if (_remaining != buf.Length) throw new ArgumentException("buffer length not right for data"); + if (_remaining == 0) + return; + + // make sure it's safe to do this! + int limit = Limit; + if (_remaining >= limit) + throw new IOException("corrupted stream - out of bounds length found: " + _remaining + " >= " + limit); + if ((_remaining -= Streams.ReadFully(_in, buf)) != 0) throw new EndOfStreamException("DEF length " + _originalLength + " object truncated by " + _remaining); SetParentEofDetect(true); @@ -90,7 +96,12 @@ namespace Org.BouncyCastle.Asn1 if (_remaining == 0) return EmptyBytes; - byte[] bytes = new byte[_remaining]; + // make sure it's safe to do this! + int limit = Limit; + if (_remaining >= limit) + throw new IOException("corrupted stream - out of bounds length found: " + _remaining + " >= " + limit); + + byte[] bytes = new byte[_remaining]; if ((_remaining -= Streams.ReadFully(_in, bytes)) != 0) throw new EndOfStreamException("DEF length " + _originalLength + " object truncated by " + _remaining); SetParentEofDetect(true); diff --git a/crypto/src/asn1/DerBMPString.cs b/crypto/src/asn1/DerBMPString.cs index 33d950ff8..061900b9c 100644 --- a/crypto/src/asn1/DerBMPString.cs +++ b/crypto/src/asn1/DerBMPString.cs @@ -55,32 +55,44 @@ namespace Org.BouncyCastle.Asn1 /** * basic constructor - byte encoded string. */ - public DerBmpString( - byte[] str) + [Obsolete("Will become internal")] + public DerBmpString(byte[] str) { if (str == null) throw new ArgumentNullException("str"); - char[] cs = new char[str.Length / 2]; + int byteLen = str.Length; + if (0 != (byteLen & 1)) + throw new ArgumentException("malformed BMPString encoding encountered", "str"); - for (int i = 0; i != cs.Length; i++) + int charLen = byteLen / 2; + char[] cs = new char[charLen]; + + for (int i = 0; i != charLen; i++) { cs[i] = (char)((str[2 * i] << 8) | (str[2 * i + 1] & 0xff)); } - this.str = new string(cs); + this.str = new string(cs); + } + + internal DerBmpString(char[] str) + { + if (str == null) + throw new ArgumentNullException("str"); + + this.str = new string(str); } /** * basic constructor */ - public DerBmpString( - string str) + public DerBmpString(string str) { if (str == null) throw new ArgumentNullException("str"); - this.str = str; + this.str = str; } public override string GetString() diff --git a/crypto/src/asn1/DerInteger.cs b/crypto/src/asn1/DerInteger.cs index 3e19a07b6..4f7b68d35 100644 --- a/crypto/src/asn1/DerInteger.cs +++ b/crypto/src/asn1/DerInteger.cs @@ -145,6 +145,18 @@ namespace Org.BouncyCastle.Asn1 } } + public long LongValueExact + { + get + { + int count = bytes.Length - start; + if (count > 8) + throw new ArithmeticException("ASN.1 Integer out of long range"); + + return LongValue(bytes, start, SignExtSigned); + } + } + internal override void Encode(DerOutputStream derOut) { derOut.WriteEncoded(Asn1Tags.Integer, bytes); @@ -182,6 +194,19 @@ namespace Org.BouncyCastle.Asn1 return val; } + internal static long LongValue(byte[] bytes, int start, int signExt) + { + int length = bytes.Length; + int pos = System.Math.Max(start, length - 8); + + long val = (sbyte)bytes[pos] & signExt; + while (++pos < length) + { + val = (val << 8) | bytes[pos]; + } + return val; + } + /** * Apply the correct validation for an INTEGER primitive following the BER rules. * diff --git a/crypto/src/asn1/DerObjectIdentifier.cs b/crypto/src/asn1/DerObjectIdentifier.cs index fb38d5f05..9a0571b57 100644 --- a/crypto/src/asn1/DerObjectIdentifier.cs +++ b/crypto/src/asn1/DerObjectIdentifier.cs @@ -24,8 +24,18 @@ namespace Org.BouncyCastle.Asn1 { if (obj == null || obj is DerObjectIdentifier) return (DerObjectIdentifier) obj; + + if (obj is Asn1Encodable) + { + Asn1Object asn1Obj = ((Asn1Encodable)obj).ToAsn1Object(); + + if (asn1Obj is DerObjectIdentifier) + return (DerObjectIdentifier)asn1Obj; + } + if (obj is byte[]) return FromOctetString((byte[])obj); + throw new ArgumentException("illegal object in GetInstance: " + Platform.GetTypeName(obj), "obj"); } diff --git a/crypto/src/asn1/DerOctetString.cs b/crypto/src/asn1/DerOctetString.cs index c046c9402..d79607950 100644 --- a/crypto/src/asn1/DerOctetString.cs +++ b/crypto/src/asn1/DerOctetString.cs @@ -1,3 +1,5 @@ +using System; + namespace Org.BouncyCastle.Asn1 { public class DerOctetString @@ -10,9 +12,13 @@ namespace Org.BouncyCastle.Asn1 { } - public DerOctetString( - Asn1Encodable obj) - : base(obj) + public DerOctetString(IAsn1Convertible obj) + : this(obj.ToAsn1Object()) + { + } + + public DerOctetString(Asn1Encodable obj) + : base(obj.GetEncoded(Asn1Encodable.Der)) { } diff --git a/crypto/src/asn1/LimitedInputStream.cs b/crypto/src/asn1/LimitedInputStream.cs index 62486aa77..98a45876d 100644 --- a/crypto/src/asn1/LimitedInputStream.cs +++ b/crypto/src/asn1/LimitedInputStream.cs @@ -8,23 +8,20 @@ namespace Org.BouncyCastle.Asn1 : BaseInputStream { protected readonly Stream _in; - private int _limit; + private int _limit; - internal LimitedInputStream( - Stream inStream, - int limit) + internal LimitedInputStream(Stream inStream, int limit) { this._in = inStream; - this._limit = limit; + this._limit = limit; } - internal virtual int GetRemaining() - { - // TODO: maybe one day this can become more accurate - return _limit; - } + internal virtual int Limit + { + get { return _limit; } + } - protected virtual void SetParentEofDetect(bool on) + protected virtual void SetParentEofDetect(bool on) { if (_in is IndefiniteLengthInputStream) { diff --git a/crypto/src/asn1/cms/SignedData.cs b/crypto/src/asn1/cms/SignedData.cs index dfc1e2829..5eba8390d 100644 --- a/crypto/src/asn1/cms/SignedData.cs +++ b/crypto/src/asn1/cms/SignedData.cs @@ -25,16 +25,13 @@ namespace Org.BouncyCastle.Asn1.Cms private readonly bool certsBer; private readonly bool crlsBer; - public static SignedData GetInstance( - object obj) + public static SignedData GetInstance(object obj) { if (obj is SignedData) - return (SignedData) obj; - - if (obj is Asn1Sequence) - return new SignedData((Asn1Sequence) obj); - - throw new ArgumentException("Unknown object in factory: " + Platform.GetTypeName(obj), "obj"); + return (SignedData)obj; + if (obj == null) + return null; + return new SignedData(Asn1Sequence.GetInstance(obj)); } public SignedData( diff --git a/crypto/src/asn1/cryptopro/GOST3410PublicKeyAlgParameters.cs b/crypto/src/asn1/cryptopro/GOST3410PublicKeyAlgParameters.cs index 32a8fb226..c32025ef6 100644 --- a/crypto/src/asn1/cryptopro/GOST3410PublicKeyAlgParameters.cs +++ b/crypto/src/asn1/cryptopro/GOST3410PublicKeyAlgParameters.cs @@ -49,7 +49,8 @@ namespace Org.BouncyCastle.Asn1.CryptoPro this.encryptionParamSet = encryptionParamSet; } - public Gost3410PublicKeyAlgParameters( + [Obsolete("Use 'GetInstance' instead")] + public Gost3410PublicKeyAlgParameters( Asn1Sequence seq) { this.publicKeyParamSet = (DerObjectIdentifier) seq[0]; diff --git a/crypto/src/asn1/nist/NISTObjectIdentifiers.cs b/crypto/src/asn1/nist/NISTObjectIdentifiers.cs index 840718ccd..417fa8df9 100644 --- a/crypto/src/asn1/nist/NISTObjectIdentifiers.cs +++ b/crypto/src/asn1/nist/NISTObjectIdentifiers.cs @@ -35,6 +35,10 @@ namespace Org.BouncyCastle.Asn1.Nist public static readonly DerObjectIdentifier IdHMacWithSha3_256 = HashAlgs.Branch("14"); public static readonly DerObjectIdentifier IdHMacWithSha3_384 = HashAlgs.Branch("15"); public static readonly DerObjectIdentifier IdHMacWithSha3_512 = HashAlgs.Branch("16"); + public static readonly DerObjectIdentifier IdShake128Len = HashAlgs.Branch("17"); + public static readonly DerObjectIdentifier IdShake256Len = HashAlgs.Branch("18"); + public static readonly DerObjectIdentifier IdKmacWithShake128 = HashAlgs.Branch("19"); + public static readonly DerObjectIdentifier IdKmacWithShake256 = HashAlgs.Branch("20"); public static readonly DerObjectIdentifier Aes = new DerObjectIdentifier(NistAlgorithm + ".1"); diff --git a/crypto/src/asn1/pkcs/AuthenticatedSafe.cs b/crypto/src/asn1/pkcs/AuthenticatedSafe.cs index f3dabb89c..6a112d9df 100644 --- a/crypto/src/asn1/pkcs/AuthenticatedSafe.cs +++ b/crypto/src/asn1/pkcs/AuthenticatedSafe.cs @@ -1,3 +1,5 @@ +using System; + using Org.BouncyCastle.Asn1; namespace Org.BouncyCastle.Asn1.Pkcs @@ -5,33 +7,59 @@ namespace Org.BouncyCastle.Asn1.Pkcs public class AuthenticatedSafe : Asn1Encodable { + private static ContentInfo[] Copy(ContentInfo[] info) + { + return (ContentInfo[])info.Clone(); + } + + public static AuthenticatedSafe GetInstance(object obj) + { + if (obj is AuthenticatedSafe) + return (AuthenticatedSafe)obj; + if (obj == null) + return null; + return new AuthenticatedSafe(Asn1Sequence.GetInstance(obj)); + } + private readonly ContentInfo[] info; + private readonly bool isBer; + [Obsolete("Use 'GetInstance' instead")] public AuthenticatedSafe( Asn1Sequence seq) { info = new ContentInfo[seq.Count]; - for (int i = 0; i != info.Length; i++) + for (int i = 0; i != info.Length; i++) { info[i] = ContentInfo.GetInstance(seq[i]); } + + isBer = seq is BerSequence; } public AuthenticatedSafe( ContentInfo[] info) { - this.info = (ContentInfo[]) info.Clone(); + this.info = Copy(info); + this.isBer = true; } public ContentInfo[] GetContentInfo() { - return (ContentInfo[]) info.Clone(); + return Copy(info); } - public override Asn1Object ToAsn1Object() + public override Asn1Object ToAsn1Object() { - return new BerSequence(info); + if (isBer) + { + return new BerSequence(info); + } + + // TODO bc-java uses DL sequence + //return new DLSequence(info); + return new DerSequence(info); } } } diff --git a/crypto/src/asn1/pkcs/CertBag.cs b/crypto/src/asn1/pkcs/CertBag.cs index e561fb890..61165c087 100644 --- a/crypto/src/asn1/pkcs/CertBag.cs +++ b/crypto/src/asn1/pkcs/CertBag.cs @@ -5,17 +5,25 @@ namespace Org.BouncyCastle.Asn1.Pkcs public class CertBag : Asn1Encodable { -// private readonly Asn1Sequence seq; + public static CertBag GetInstance(object obj) + { + if (obj is CertBag) + return (CertBag)obj; + if (obj == null) + return null; + return new CertBag(Asn1Sequence.GetInstance(obj)); + } + private readonly DerObjectIdentifier certID; private readonly Asn1Object certValue; + [Obsolete("Use 'GetInstance' instead")] public CertBag( Asn1Sequence seq) { if (seq.Count != 2) throw new ArgumentException("Wrong number of elements in sequence", "seq"); -// this.seq = seq; this.certID = DerObjectIdentifier.GetInstance(seq[0]); this.certValue = Asn1TaggedObject.GetInstance(seq[1]).GetObject(); } @@ -28,12 +36,12 @@ namespace Org.BouncyCastle.Asn1.Pkcs this.certValue = certValue; } - public DerObjectIdentifier CertID + public virtual DerObjectIdentifier CertID { get { return certID; } } - public Asn1Object CertValue + public virtual Asn1Object CertValue { get { return certValue; } } diff --git a/crypto/src/asn1/pkcs/Pfx.cs b/crypto/src/asn1/pkcs/Pfx.cs index 4f958a070..3aec8ed0f 100644 --- a/crypto/src/asn1/pkcs/Pfx.cs +++ b/crypto/src/asn1/pkcs/Pfx.cs @@ -11,29 +11,35 @@ namespace Org.BouncyCastle.Asn1.Pkcs public class Pfx : Asn1Encodable { - private ContentInfo contentInfo; - private MacData macData; + public static Pfx GetInstance(object obj) + { + if (obj is Pfx) + return (Pfx)obj; + if (obj == null) + return null; + return new Pfx(Asn1Sequence.GetInstance(obj)); + } + + private readonly ContentInfo contentInfo; + private readonly MacData macData; + [Obsolete("Use 'GetInstance' instead")] public Pfx( Asn1Sequence seq) { - BigInteger version = ((DerInteger) seq[0]).Value; - if (version.IntValue != 3) - { + DerInteger version = DerInteger.GetInstance(seq[0]); + if (version.IntValueExact != 3) throw new ArgumentException("wrong version for PFX PDU"); - } - contentInfo = ContentInfo.GetInstance(seq[1]); + this.contentInfo = ContentInfo.GetInstance(seq[1]); - if (seq.Count == 3) + if (seq.Count == 3) { - macData = MacData.GetInstance(seq[2]); + this.macData = MacData.GetInstance(seq[2]); } } - public Pfx( - ContentInfo contentInfo, - MacData macData) + public Pfx(ContentInfo contentInfo, MacData macData) { this.contentInfo = contentInfo; this.macData = macData; diff --git a/crypto/src/asn1/pkcs/SafeBag.cs b/crypto/src/asn1/pkcs/SafeBag.cs index ea1ce951e..7951d4892 100644 --- a/crypto/src/asn1/pkcs/SafeBag.cs +++ b/crypto/src/asn1/pkcs/SafeBag.cs @@ -1,3 +1,5 @@ +using System; + using Org.BouncyCastle.Asn1; namespace Org.BouncyCastle.Asn1.Pkcs @@ -5,6 +7,15 @@ namespace Org.BouncyCastle.Asn1.Pkcs public class SafeBag : Asn1Encodable { + public static SafeBag GetInstance(object obj) + { + if (obj is SafeBag) + return (SafeBag)obj; + if (obj == null) + return null; + return new SafeBag(Asn1Sequence.GetInstance(obj)); + } + private readonly DerObjectIdentifier bagID; private readonly Asn1Object bagValue; private readonly Asn1Set bagAttributes; @@ -28,14 +39,15 @@ namespace Org.BouncyCastle.Asn1.Pkcs this.bagAttributes = bagAttributes; } + [Obsolete("Use 'GetInstance' instead")] public SafeBag( Asn1Sequence seq) { - this.bagID = (DerObjectIdentifier) seq[0]; - this.bagValue = ((DerTaggedObject) seq[1]).GetObject(); + this.bagID = (DerObjectIdentifier)seq[0]; + this.bagValue = ((DerTaggedObject)seq[1]).GetObject(); if (seq.Count == 3) { - this.bagAttributes = (Asn1Set) seq[2]; + this.bagAttributes = (Asn1Set)seq[2]; } } diff --git a/crypto/src/asn1/x509/AuthorityInformationAccess.cs b/crypto/src/asn1/x509/AuthorityInformationAccess.cs index 9329e2b98..f4b694cf0 100644 --- a/crypto/src/asn1/x509/AuthorityInformationAccess.cs +++ b/crypto/src/asn1/x509/AuthorityInformationAccess.cs @@ -26,7 +26,10 @@ namespace Org.BouncyCastle.Asn1.X509 public class AuthorityInformationAccess : Asn1Encodable { - private readonly AccessDescription[] descriptions; + private static AccessDescription[] Copy(AccessDescription[] descriptions) + { + return (AccessDescription[])descriptions.Clone(); + } public static AuthorityInformationAccess GetInstance(object obj) { @@ -37,6 +40,13 @@ namespace Org.BouncyCastle.Asn1.X509 return new AuthorityInformationAccess(Asn1Sequence.GetInstance(obj)); } + public static AuthorityInformationAccess FromExtensions(X509Extensions extensions) + { + return GetInstance(X509Extensions.GetExtensionParsedValue(extensions, X509Extensions.AuthorityInfoAccess)); + } + + private readonly AccessDescription[] descriptions; + private AuthorityInformationAccess( Asn1Sequence seq) { @@ -57,6 +67,12 @@ namespace Org.BouncyCastle.Asn1.X509 this.descriptions = new AccessDescription[]{ description }; } + public AuthorityInformationAccess( + AccessDescription[] descriptions) + { + this.descriptions = Copy(descriptions); + } + /** * create an AuthorityInformationAccess with the oid and location provided. */ @@ -67,7 +83,7 @@ namespace Org.BouncyCastle.Asn1.X509 public AccessDescription[] GetAccessDescriptions() { - return (AccessDescription[])descriptions.Clone(); + return Copy(descriptions); } public override Asn1Object ToAsn1Object() diff --git a/crypto/src/asn1/x509/AuthorityKeyIdentifier.cs b/crypto/src/asn1/x509/AuthorityKeyIdentifier.cs index aca1dc330..e7f12016a 100644 --- a/crypto/src/asn1/x509/AuthorityKeyIdentifier.cs +++ b/crypto/src/asn1/x509/AuthorityKeyIdentifier.cs @@ -5,6 +5,7 @@ using Org.BouncyCastle.Crypto; using Org.BouncyCastle.Crypto.Digests; using Org.BouncyCastle.Math; using Org.BouncyCastle.Utilities; +using Org.BouncyCastle.Utilities.Encoders; namespace Org.BouncyCastle.Asn1.X509 { @@ -25,56 +26,51 @@ namespace Org.BouncyCastle.Asn1.X509 public class AuthorityKeyIdentifier : Asn1Encodable { - internal readonly Asn1OctetString keyidentifier; - internal readonly GeneralNames certissuer; - internal readonly DerInteger certserno; - - public static AuthorityKeyIdentifier GetInstance( - Asn1TaggedObject obj, - bool explicitly) + public static AuthorityKeyIdentifier GetInstance(Asn1TaggedObject obj, bool explicitly) { return GetInstance(Asn1Sequence.GetInstance(obj, explicitly)); } - public static AuthorityKeyIdentifier GetInstance( - object obj) + public static AuthorityKeyIdentifier GetInstance(object obj) { if (obj is AuthorityKeyIdentifier) - { - return (AuthorityKeyIdentifier) obj; - } - - if (obj is Asn1Sequence) - { - return new AuthorityKeyIdentifier((Asn1Sequence) obj); - } + return (AuthorityKeyIdentifier)obj; + if (obj is X509Extension) + return GetInstance(X509Extension.ConvertValueToObject((X509Extension)obj)); + if (obj == null) + return null; + return new AuthorityKeyIdentifier(Asn1Sequence.GetInstance(obj)); + } - if (obj is X509Extension) - { - return GetInstance(X509Extension.ConvertValueToObject((X509Extension) obj)); - } + public static AuthorityKeyIdentifier FromExtensions(X509Extensions extensions) + { + return GetInstance(X509Extensions.GetExtensionParsedValue(extensions, X509Extensions.AuthorityKeyIdentifier)); + } - throw new ArgumentException("unknown object in factory: " + Platform.GetTypeName(obj), "obj"); - } + private readonly Asn1OctetString keyidentifier; + private readonly GeneralNames certissuer; + private readonly DerInteger certserno; - protected internal AuthorityKeyIdentifier( + protected internal AuthorityKeyIdentifier( Asn1Sequence seq) { - foreach (Asn1TaggedObject o in seq) + foreach (Asn1Encodable element in seq) { - switch (o.TagNo) + Asn1TaggedObject obj = Asn1TaggedObject.GetInstance(element); + + switch (obj.TagNo) { - case 0: - this.keyidentifier = Asn1OctetString.GetInstance(o, false); - break; - case 1: - this.certissuer = GeneralNames.GetInstance(o, false); - break; - case 2: - this.certserno = DerInteger.GetInstance(o, false); - break; - default: - throw new ArgumentException("illegal tag"); + case 0: + this.keyidentifier = Asn1OctetString.GetInstance(obj, false); + break; + case 1: + this.certissuer = GeneralNames.GetInstance(obj, false); + break; + case 2: + this.certserno = DerInteger.GetInstance(obj, false); + break; + default: + throw new ArgumentException("illegal tag"); } } } @@ -94,14 +90,8 @@ namespace Org.BouncyCastle.Asn1.X509 **/ public AuthorityKeyIdentifier( SubjectPublicKeyInfo spki) + : this(spki, null, null) { - IDigest digest = new Sha1Digest(); - byte[] resBuf = new byte[digest.GetDigestSize()]; - - byte[] bytes = spki.PublicKeyData.GetBytes(); - digest.BlockUpdate(bytes, 0, bytes.Length); - digest.DoFinal(resBuf, 0); - this.keyidentifier = new DerOctetString(resBuf); } /** @@ -115,27 +105,24 @@ namespace Org.BouncyCastle.Asn1.X509 { IDigest digest = new Sha1Digest(); byte[] resBuf = new byte[digest.GetDigestSize()]; - byte[] bytes = spki.PublicKeyData.GetBytes(); digest.BlockUpdate(bytes, 0, bytes.Length); digest.DoFinal(resBuf, 0); this.keyidentifier = new DerOctetString(resBuf); this.certissuer = name; - this.certserno = new DerInteger(serialNumber); + this.certserno = serialNumber == null ? null : new DerInteger(serialNumber); } - /** + /** * create an AuthorityKeyIdentifier with the GeneralNames tag and * the serial number provided. */ public AuthorityKeyIdentifier( GeneralNames name, BigInteger serialNumber) + : this((byte[])null, name, serialNumber) { - this.keyidentifier = null; - this.certissuer = GeneralNames.GetInstance(name.ToAsn1Object()); - this.certserno = new DerInteger(serialNumber); } /** @@ -143,13 +130,11 @@ namespace Org.BouncyCastle.Asn1.X509 */ public AuthorityKeyIdentifier( byte[] keyIdentifier) + : this(keyIdentifier, null, null) { - this.keyidentifier = new DerOctetString(keyIdentifier); - this.certissuer = null; - this.certserno = null; } - /** + /** * create an AuthorityKeyIdentifier with a precomupted key identifier * and the GeneralNames tag and the serial number provided as well. */ @@ -158,9 +143,9 @@ namespace Org.BouncyCastle.Asn1.X509 GeneralNames name, BigInteger serialNumber) { - this.keyidentifier = new DerOctetString(keyIdentifier); - this.certissuer = GeneralNames.GetInstance(name.ToAsn1Object()); - this.certserno = new DerInteger(serialNumber); + this.keyidentifier = keyIdentifier == null ? null : new DerOctetString(keyIdentifier); + this.certissuer = name; + this.certserno = serialNumber == null ? null : new DerInteger(serialNumber); } public byte[] GetKeyIdentifier() @@ -178,7 +163,7 @@ namespace Org.BouncyCastle.Asn1.X509 get { return certserno == null ? null : certserno.Value; } } - /** + /** * Produce an object suitable for an Asn1OutputStream. */ public override Asn1Object ToAsn1Object() @@ -192,7 +177,9 @@ namespace Org.BouncyCastle.Asn1.X509 public override string ToString() { - return ("AuthorityKeyIdentifier: KeyID(" + this.keyidentifier.GetOctets() + ")"); + string keyID = (keyidentifier != null) ? Hex.ToHexString(keyidentifier.GetOctets()) : "null"; + + return "AuthorityKeyIdentifier: KeyID(" + keyID + ")"; } } } diff --git a/crypto/src/asn1/x509/BasicConstraints.cs b/crypto/src/asn1/x509/BasicConstraints.cs index 079294d1b..deecae241 100644 --- a/crypto/src/asn1/x509/BasicConstraints.cs +++ b/crypto/src/asn1/x509/BasicConstraints.cs @@ -8,38 +8,31 @@ namespace Org.BouncyCastle.Asn1.X509 public class BasicConstraints : Asn1Encodable { - private readonly DerBoolean cA; - private readonly DerInteger pathLenConstraint; - - public static BasicConstraints GetInstance( - Asn1TaggedObject obj, - bool explicitly) + public static BasicConstraints GetInstance(Asn1TaggedObject obj, bool explicitly) { return GetInstance(Asn1Sequence.GetInstance(obj, explicitly)); } - public static BasicConstraints GetInstance( - object obj) + public static BasicConstraints GetInstance(object obj) { - if (obj == null || obj is BasicConstraints) - { - return (BasicConstraints) obj; - } - - if (obj is Asn1Sequence) - { - return new BasicConstraints((Asn1Sequence) obj); - } + if (obj is BasicConstraints) + return (BasicConstraints)obj; + if (obj is X509Extension) + return GetInstance(X509Extension.ConvertValueToObject((X509Extension)obj)); + if (obj == null) + return null; + return new BasicConstraints(Asn1Sequence.GetInstance(obj)); + } - if (obj is X509Extension) - { - return GetInstance(X509Extension.ConvertValueToObject((X509Extension) obj)); - } + public static BasicConstraints FromExtensions(X509Extensions extensions) + { + return GetInstance(X509Extensions.GetExtensionParsedValue(extensions, X509Extensions.BasicConstraints)); + } - throw new ArgumentException("unknown object in factory: " + Platform.GetTypeName(obj), "obj"); - } + private readonly DerBoolean cA; + private readonly DerInteger pathLenConstraint; - private BasicConstraints( + private BasicConstraints( Asn1Sequence seq) { if (seq.Count > 0) @@ -105,7 +98,7 @@ namespace Org.BouncyCastle.Asn1.X509 */ public override Asn1Object ToAsn1Object() { - Asn1EncodableVector v = new Asn1EncodableVector(); + Asn1EncodableVector v = new Asn1EncodableVector(2); v.AddOptional(cA, pathLenConstraint); // yes some people actually do this when cA is false... return new DerSequence(v); diff --git a/crypto/src/asn1/x509/CRLDistPoint.cs b/crypto/src/asn1/x509/CRLDistPoint.cs index 56ba79ca5..446bb19db 100644 --- a/crypto/src/asn1/x509/CRLDistPoint.cs +++ b/crypto/src/asn1/x509/CRLDistPoint.cs @@ -8,32 +8,28 @@ namespace Org.BouncyCastle.Asn1.X509 public class CrlDistPoint : Asn1Encodable { - internal readonly Asn1Sequence seq; - - public static CrlDistPoint GetInstance( - Asn1TaggedObject obj, - bool explicitly) + public static CrlDistPoint GetInstance(Asn1TaggedObject obj, bool explicitly) { return GetInstance(Asn1Sequence.GetInstance(obj, explicitly)); } - public static CrlDistPoint GetInstance( - object obj) + public static CrlDistPoint GetInstance(object obj) { - if (obj is CrlDistPoint || obj == null) - { - return (CrlDistPoint) obj; - } + if (obj is CrlDistPoint) + return (CrlDistPoint)obj; + if (obj == null) + return null; + return new CrlDistPoint(Asn1Sequence.GetInstance(obj)); + } - if (obj is Asn1Sequence) - { - return new CrlDistPoint((Asn1Sequence) obj); - } + public static CrlDistPoint FromExtensions(X509Extensions extensions) + { + return GetInstance(X509Extensions.GetExtensionParsedValue(extensions, X509Extensions.CrlDistributionPoints)); + } - throw new ArgumentException("unknown object in factory: " + Platform.GetTypeName(obj), "obj"); - } + internal readonly Asn1Sequence seq; - private CrlDistPoint( + private CrlDistPoint( Asn1Sequence seq) { this.seq = seq; diff --git a/crypto/src/asn1/x509/CertificatePolicies.cs b/crypto/src/asn1/x509/CertificatePolicies.cs index a83565bb2..97214bd3f 100644 --- a/crypto/src/asn1/x509/CertificatePolicies.cs +++ b/crypto/src/asn1/x509/CertificatePolicies.cs @@ -6,13 +6,17 @@ namespace Org.BouncyCastle.Asn1.X509 public class CertificatePolicies : Asn1Encodable { - private readonly PolicyInformation[] policyInformation; + private static PolicyInformation[] Copy(PolicyInformation[] policyInfo) + { + return (PolicyInformation[])policyInfo.Clone(); + } public static CertificatePolicies GetInstance(object obj) { - if (obj == null || obj is CertificatePolicies) + if (obj is CertificatePolicies) return (CertificatePolicies)obj; - + if (obj == null) + return null; return new CertificatePolicies(Asn1Sequence.GetInstance(obj)); } @@ -21,6 +25,13 @@ namespace Org.BouncyCastle.Asn1.X509 return GetInstance(Asn1Sequence.GetInstance(obj, isExplicit)); } + public static CertificatePolicies FromExtensions(X509Extensions extensions) + { + return GetInstance(X509Extensions.GetExtensionParsedValue(extensions, X509Extensions.CertificatePolicies)); + } + + private readonly PolicyInformation[] policyInformation; + /** * Construct a CertificatePolicies object containing one PolicyInformation. * @@ -33,7 +44,7 @@ namespace Org.BouncyCastle.Asn1.X509 public CertificatePolicies(PolicyInformation[] policyInformation) { - this.policyInformation = policyInformation; + this.policyInformation = Copy(policyInformation); } private CertificatePolicies(Asn1Sequence seq) @@ -48,7 +59,20 @@ namespace Org.BouncyCastle.Asn1.X509 public virtual PolicyInformation[] GetPolicyInformation() { - return (PolicyInformation[])policyInformation.Clone(); + return Copy(policyInformation); + } + + public virtual PolicyInformation GetPolicyInformation(DerObjectIdentifier policyIdentifier) + { + for (int i = 0; i != policyInformation.Length; i++) + { + if (policyIdentifier.Equals(policyInformation[i].PolicyIdentifier)) + { + return policyInformation[i]; + } + } + + return null; } /** diff --git a/crypto/src/asn1/x509/ExtendedKeyUsage.cs b/crypto/src/asn1/x509/ExtendedKeyUsage.cs index 8f7e6a353..7e8c7a37c 100644 --- a/crypto/src/asn1/x509/ExtendedKeyUsage.cs +++ b/crypto/src/asn1/x509/ExtendedKeyUsage.cs @@ -14,9 +14,6 @@ namespace Org.BouncyCastle.Asn1.X509 public class ExtendedKeyUsage : Asn1Encodable { - internal readonly IDictionary usageTable = Platform.CreateHashtable(); - internal readonly Asn1Sequence seq; - public static ExtendedKeyUsage GetInstance( Asn1TaggedObject obj, bool explicitly) @@ -28,34 +25,32 @@ namespace Org.BouncyCastle.Asn1.X509 object obj) { if (obj is ExtendedKeyUsage) - { - return (ExtendedKeyUsage) obj; - } - - if (obj is Asn1Sequence) - { - return new ExtendedKeyUsage((Asn1Sequence) obj); - } - + return (ExtendedKeyUsage)obj; if (obj is X509Extension) - { - return GetInstance(X509Extension.ConvertValueToObject((X509Extension) obj)); - } + return GetInstance(X509Extension.ConvertValueToObject((X509Extension)obj)); + if (obj == null) + return null; + return new ExtendedKeyUsage(Asn1Sequence.GetInstance(obj)); + } - throw new ArgumentException("Invalid ExtendedKeyUsage: " + Platform.GetTypeName(obj)); + public static ExtendedKeyUsage FromExtensions(X509Extensions extensions) + { + return GetInstance(X509Extensions.GetExtensionParsedValue(extensions, X509Extensions.ExtendedKeyUsage)); } + internal readonly IDictionary usageTable = Platform.CreateHashtable(); + internal readonly Asn1Sequence seq; + private ExtendedKeyUsage( Asn1Sequence seq) { this.seq = seq; - foreach (object o in seq) + foreach (Asn1Encodable element in seq) { - if (!(o is DerObjectIdentifier)) - throw new ArgumentException("Only DerObjectIdentifier instances allowed in ExtendedKeyUsage."); + DerObjectIdentifier oid = DerObjectIdentifier.GetInstance(element); - this.usageTable[o] = o; + this.usageTable[oid] = oid; } } @@ -86,10 +81,10 @@ namespace Org.BouncyCastle.Asn1.X509 foreach (object usage in usages) { - Asn1Encodable o = KeyPurposeID.GetInstance(usage); + DerObjectIdentifier oid = DerObjectIdentifier.GetInstance(usage); - v.Add(o); - this.usageTable[o] = o; + v.Add(oid); + this.usageTable[oid] = oid; } this.seq = new DerSequence(v); diff --git a/crypto/src/asn1/x509/GeneralNames.cs b/crypto/src/asn1/x509/GeneralNames.cs index fcd2ecb24..c105f3b6e 100644 --- a/crypto/src/asn1/x509/GeneralNames.cs +++ b/crypto/src/asn1/x509/GeneralNames.cs @@ -8,32 +8,33 @@ namespace Org.BouncyCastle.Asn1.X509 public class GeneralNames : Asn1Encodable { - private readonly GeneralName[] names; + private static GeneralName[] Copy(GeneralName[] names) + { + return (GeneralName[])names.Clone(); + } - public static GeneralNames GetInstance( - object obj) + public static GeneralNames GetInstance(object obj) { - if (obj == null || obj is GeneralNames) - { - return (GeneralNames) obj; - } - - if (obj is Asn1Sequence) - { - return new GeneralNames((Asn1Sequence) obj); - } - - throw new ArgumentException("unknown object in factory: " + Platform.GetTypeName(obj), "obj"); + if (obj is GeneralNames) + return (GeneralNames)obj; + if (obj == null) + return null; + return new GeneralNames(Asn1Sequence.GetInstance(obj)); } - public static GeneralNames GetInstance( - Asn1TaggedObject obj, - bool explicitly) + public static GeneralNames GetInstance(Asn1TaggedObject obj, bool explicitly) { return GetInstance(Asn1Sequence.GetInstance(obj, explicitly)); } - /// <summary>Construct a GeneralNames object containing one GeneralName.</summary> + public static GeneralNames FromExtensions(X509Extensions extensions, DerObjectIdentifier extOid) + { + return GetInstance(X509Extensions.GetExtensionParsedValue(extensions, extOid)); + } + + private readonly GeneralName[] names; + + /// <summary>Construct a GeneralNames object containing one GeneralName.</summary> /// <param name="name">The name to be contained.</param> public GeneralNames( GeneralName name) @@ -44,7 +45,7 @@ namespace Org.BouncyCastle.Asn1.X509 public GeneralNames( GeneralName[] names) { - this.names = (GeneralName[])names.Clone(); + this.names = Copy(names); } private GeneralNames( @@ -60,7 +61,7 @@ namespace Org.BouncyCastle.Asn1.X509 public GeneralName[] GetNames() { - return (GeneralName[]) names.Clone(); + return Copy(names); } /** diff --git a/crypto/src/asn1/x509/KeyUsage.cs b/crypto/src/asn1/x509/KeyUsage.cs index aeaffb708..b31b54341 100644 --- a/crypto/src/asn1/x509/KeyUsage.cs +++ b/crypto/src/asn1/x509/KeyUsage.cs @@ -30,23 +30,23 @@ namespace Org.BouncyCastle.Asn1.X509 public const int EncipherOnly = (1 << 0); public const int DecipherOnly = (1 << 15); - public static new KeyUsage GetInstance( - object obj) + public static new KeyUsage GetInstance(object obj) { if (obj is KeyUsage) - { return (KeyUsage)obj; - } - - if (obj is X509Extension) - { - return GetInstance(X509Extension.ConvertValueToObject((X509Extension) obj)); - } - + if (obj is X509Extension) + return GetInstance(X509Extension.ConvertValueToObject((X509Extension)obj)); + if (obj == null) + return null; return new KeyUsage(DerBitString.GetInstance(obj)); } - /** + public static KeyUsage FromExtensions(X509Extensions extensions) + { + return GetInstance(X509Extensions.GetExtensionParsedValue(extensions, X509Extensions.KeyUsage)); + } + + /** * Basic constructor. * * @param usage - the bitwise OR of the Key Usage flags giving the diff --git a/crypto/src/asn1/x509/SubjectKeyIdentifier.cs b/crypto/src/asn1/x509/SubjectKeyIdentifier.cs index f2e6cc006..bb694681b 100644 --- a/crypto/src/asn1/x509/SubjectKeyIdentifier.cs +++ b/crypto/src/asn1/x509/SubjectKeyIdentifier.cs @@ -15,54 +15,44 @@ namespace Org.BouncyCastle.Asn1.X509 public class SubjectKeyIdentifier : Asn1Encodable { - private readonly byte[] keyIdentifier; - - public static SubjectKeyIdentifier GetInstance( - Asn1TaggedObject obj, - bool explicitly) + public static SubjectKeyIdentifier GetInstance(Asn1TaggedObject obj, bool explicitly) { return GetInstance(Asn1OctetString.GetInstance(obj, explicitly)); } - public static SubjectKeyIdentifier GetInstance( - object obj) + public static SubjectKeyIdentifier GetInstance(object obj) { if (obj is SubjectKeyIdentifier) - { - return (SubjectKeyIdentifier) obj; - } - - if (obj is SubjectPublicKeyInfo) - { - return new SubjectKeyIdentifier((SubjectPublicKeyInfo) obj); - } - - if (obj is Asn1OctetString) - { - return new SubjectKeyIdentifier((Asn1OctetString) obj); - } - - if (obj is X509Extension) - { - return GetInstance(X509Extension.ConvertValueToObject((X509Extension) obj)); - } - - throw new ArgumentException("Invalid SubjectKeyIdentifier: " + Platform.GetTypeName(obj)); + return (SubjectKeyIdentifier)obj; + if (obj is SubjectPublicKeyInfo) + return new SubjectKeyIdentifier((SubjectPublicKeyInfo)obj); + if (obj is X509Extension) + return GetInstance(X509Extension.ConvertValueToObject((X509Extension)obj)); + if (obj == null) + return null; + return new SubjectKeyIdentifier(Asn1OctetString.GetInstance(obj)); } - public SubjectKeyIdentifier( + public static SubjectKeyIdentifier FromExtensions(X509Extensions extensions) + { + return GetInstance(X509Extensions.GetExtensionParsedValue(extensions, X509Extensions.SubjectKeyIdentifier)); + } + + private readonly byte[] keyIdentifier; + + public SubjectKeyIdentifier( byte[] keyID) { if (keyID == null) throw new ArgumentNullException("keyID"); - this.keyIdentifier = keyID; + this.keyIdentifier = Arrays.Clone(keyID); } public SubjectKeyIdentifier( Asn1OctetString keyID) + : this(keyID.GetOctets()) { - this.keyIdentifier = keyID.GetOctets(); } /** @@ -79,12 +69,12 @@ namespace Org.BouncyCastle.Asn1.X509 public byte[] GetKeyIdentifier() { - return keyIdentifier; + return Arrays.Clone(keyIdentifier); } - public override Asn1Object ToAsn1Object() + public override Asn1Object ToAsn1Object() { - return new DerOctetString(keyIdentifier); + return new DerOctetString(GetKeyIdentifier()); } /** diff --git a/crypto/src/asn1/x509/X509Extensions.cs b/crypto/src/asn1/x509/X509Extensions.cs index d1b9fa39a..42121fa60 100644 --- a/crypto/src/asn1/x509/X509Extensions.cs +++ b/crypto/src/asn1/x509/X509Extensions.cs @@ -172,6 +172,16 @@ namespace Org.BouncyCastle.Asn1.X509 private readonly IDictionary extensions = Platform.CreateHashtable(); private readonly IList ordering; + public static X509Extension GetExtension(X509Extensions extensions, DerObjectIdentifier oid) + { + return null == extensions ? null : extensions.GetExtension(oid); + } + + public static Asn1Encodable GetExtensionParsedValue(X509Extensions extensions, DerObjectIdentifier oid) + { + return null == extensions ? null : extensions.GetExtensionParsedValue(oid); + } + public static X509Extensions GetInstance( Asn1TaggedObject obj, bool explicitly) @@ -368,7 +378,20 @@ namespace Org.BouncyCastle.Asn1.X509 public X509Extension GetExtension( DerObjectIdentifier oid) { - return (X509Extension) extensions[oid]; + return (X509Extension)extensions[oid]; + } + + /** + * return the parsed value of the extension represented by the object identifier + * passed in. + * + * @return the parsed value of the extension if it's present, null otherwise. + */ + public Asn1Encodable GetExtensionParsedValue(DerObjectIdentifier oid) + { + X509Extension ext = GetExtension(oid); + + return ext == null ? null : ext.GetParsedValue(); } /** diff --git a/crypto/src/asn1/x9/X962Parameters.cs b/crypto/src/asn1/x9/X962Parameters.cs index 04a5c9cbe..5bdabc647 100644 --- a/crypto/src/asn1/x9/X962Parameters.cs +++ b/crypto/src/asn1/x9/X962Parameters.cs @@ -49,7 +49,14 @@ namespace Org.BouncyCastle.Asn1.X9 this._params = namedCurve; } - public X962Parameters( + public X962Parameters( + Asn1Null obj) + { + this._params = obj; + } + + [Obsolete("Use 'GetInstance' instead")] + public X962Parameters( Asn1Object obj) { this._params = obj; diff --git a/crypto/src/bcpg/ECPublicBCPGKey.cs b/crypto/src/bcpg/ECPublicBCPGKey.cs index c473139e7..df19caac3 100644 --- a/crypto/src/bcpg/ECPublicBCPGKey.cs +++ b/crypto/src/bcpg/ECPublicBCPGKey.cs @@ -81,10 +81,10 @@ namespace Org.BouncyCastle.Bcpg BcpgInputStream bcpgIn) { int length = bcpgIn.ReadByte(); + if (length < 0) + throw new EndOfStreamException(); if (length == 0 || length == 0xFF) - { - throw new IOException("future extensions not yet implemented."); - } + throw new IOException("future extensions not yet implemented"); byte[] buffer = new byte[length + 2]; bcpgIn.ReadFully(buffer, 2, buffer.Length - 2); diff --git a/crypto/src/bcpg/SignatureSubpacketsReader.cs b/crypto/src/bcpg/SignatureSubpacketsReader.cs index 80bedb07c..45dc96885 100644 --- a/crypto/src/bcpg/SignatureSubpacketsReader.cs +++ b/crypto/src/bcpg/SignatureSubpacketsReader.cs @@ -52,6 +52,9 @@ namespace Org.BouncyCastle.Bcpg if (tag < 0) throw new EndOfStreamException("unexpected EOF reading signature sub packet"); + if (bodyLen <= 0) + throw new EndOfStreamException("out of range data found in signature sub packet"); + byte[] data = new byte[bodyLen - 1]; // diff --git a/crypto/src/cms/CMSSignedData.cs b/crypto/src/cms/CMSSignedData.cs index 979be6535..8634b2b3a 100644 --- a/crypto/src/cms/CMSSignedData.cs +++ b/crypto/src/cms/CMSSignedData.cs @@ -280,6 +280,16 @@ namespace Org.BouncyCastle.Cms return contentInfo.GetEncoded(); } + /** + * return the ASN.1 encoded representation of this object using the specified encoding. + * + * @param encoding the ASN.1 encoding format to use ("BER" or "DER"). + */ + public byte[] GetEncoded(string encoding) + { + return contentInfo.GetEncoded(encoding); + } + /** * Replace the signerinformation store associated with this * CmsSignedData object with the new one passed in. You would diff --git a/crypto/src/crypto.csproj b/crypto/src/crypto.csproj index 43117bb4d..0fc60462d 100644 --- a/crypto/src/crypto.csproj +++ b/crypto/src/crypto.csproj @@ -6,7 +6,7 @@ <AssemblyOriginatorKeyFile>..\..\BouncyCastle.snk</AssemblyOriginatorKeyFile> <SignAssembly>true</SignAssembly> <Product>Bouncy Castle for .NET ($(TargetFramework))</Product> - <Copyright>© 2000-2019 Legion of the Bouncy Castle Inc. </Copyright> + <Copyright>© 2000-2020 Legion of the Bouncy Castle Inc. </Copyright> <Company>The Legion of the Bouncy Castle Inc.</Company> <Authors>Oren Novotny</Authors> <Title>Bouncy Castle Portable</Title> @@ -15,7 +15,7 @@ <DebugType>embedded</DebugType> <PackageLicenseUrl>https://www.bouncycastle.org/csharp/licence.html</PackageLicenseUrl> <PackageProjectUrl>https://www.bouncycastle.org/csharp/</PackageProjectUrl> - <PackageReleaseNotes>https://www.bouncycastle.org/csharp/#RELEASENOTES185</PackageReleaseNotes> + <PackageReleaseNotes>https://www.bouncycastle.org/csharp/#RELEASENOTES186</PackageReleaseNotes> <RepositoryType>git</RepositoryType> <RepositoryUrl>https://github.com/onovotny/bc-csharp</RepositoryUrl> <PackageIconUrl>https://www.bouncycastle.org/images/csharp_logo.gif</PackageIconUrl> @@ -36,7 +36,7 @@ <ItemGroup> <Compile Include="..\bzip2\src\**\*.cs" LinkBase="bzip2" /> <None Include="..\..\BouncyCastle.snk" /> - <PackageReference Include="NerdBank.GitVersioning" Version="3.0.28" PrivateAssets="All" /> + <PackageReference Include="NerdBank.GitVersioning" Version="3.0.50" PrivateAssets="All" /> <PackageReference Include="Microsoft.SourceLink.GitHub" Version="1.0.0" PrivateAssets="All" /> </ItemGroup> diff --git a/crypto/src/crypto/encodings/Pkcs1Encoding.cs b/crypto/src/crypto/encodings/Pkcs1Encoding.cs index b2d60fe4c..ce2f15a38 100644 --- a/crypto/src/crypto/encodings/Pkcs1Encoding.cs +++ b/crypto/src/crypto/encodings/Pkcs1Encoding.cs @@ -41,7 +41,7 @@ namespace Org.BouncyCastle.Crypto.Encodings { string strictProperty = Platform.GetEnvironmentVariable(StrictLengthEnabledProperty); - strictLengthEnabled = new bool[]{ strictProperty == null || strictProperty.Equals("true")}; + strictLengthEnabled = new bool[]{ strictProperty == null || Platform.EqualsIgnoreCase("true", strictProperty) }; } diff --git a/crypto/src/crypto/parameters/Ed25519PrivateKeyParameters.cs b/crypto/src/crypto/parameters/Ed25519PrivateKeyParameters.cs index 8046a0b1b..531bca0e9 100644 --- a/crypto/src/crypto/parameters/Ed25519PrivateKeyParameters.cs +++ b/crypto/src/crypto/parameters/Ed25519PrivateKeyParameters.cs @@ -16,6 +16,8 @@ namespace Org.BouncyCastle.Crypto.Parameters private readonly byte[] data = new byte[KeySize]; + private Ed25519PublicKeyParameters cachedPublicKey; + public Ed25519PrivateKeyParameters(SecureRandom random) : base(true) { @@ -47,23 +49,33 @@ namespace Org.BouncyCastle.Crypto.Parameters public Ed25519PublicKeyParameters GeneratePublicKey() { - byte[] publicKey = new byte[Ed25519.PublicKeySize]; - Ed25519.GeneratePublicKey(data, 0, publicKey, 0); - return new Ed25519PublicKeyParameters(publicKey, 0); + lock (data) + { + if (null == cachedPublicKey) + { + byte[] publicKey = new byte[Ed25519.PublicKeySize]; + Ed25519.GeneratePublicKey(data, 0, publicKey, 0); + cachedPublicKey = new Ed25519PublicKeyParameters(publicKey, 0); + } + + return cachedPublicKey; + } } + [Obsolete("Use overload that doesn't take a public key")] public void Sign(Ed25519.Algorithm algorithm, Ed25519PublicKeyParameters publicKey, byte[] ctx, byte[] msg, int msgOff, int msgLen, byte[] sig, int sigOff) { + Sign(algorithm, ctx, msg, msgOff, msgLen, sig, sigOff); + } + + public void Sign(Ed25519.Algorithm algorithm, byte[] ctx, byte[] msg, int msgOff, int msgLen, + byte[] sig, int sigOff) + { + Ed25519PublicKeyParameters publicKey = GeneratePublicKey(); + byte[] pk = new byte[Ed25519.PublicKeySize]; - if (null == publicKey) - { - Ed25519.GeneratePublicKey(data, 0, pk, 0); - } - else - { - publicKey.Encode(pk, 0); - } + publicKey.Encode(pk, 0); switch (algorithm) { diff --git a/crypto/src/crypto/parameters/Ed448PrivateKeyParameters.cs b/crypto/src/crypto/parameters/Ed448PrivateKeyParameters.cs index f2fc4d533..1b38143fa 100644 --- a/crypto/src/crypto/parameters/Ed448PrivateKeyParameters.cs +++ b/crypto/src/crypto/parameters/Ed448PrivateKeyParameters.cs @@ -16,6 +16,8 @@ namespace Org.BouncyCastle.Crypto.Parameters private readonly byte[] data = new byte[KeySize]; + private Ed448PublicKeyParameters cachedPublicKey; + public Ed448PrivateKeyParameters(SecureRandom random) : base(true) { @@ -47,23 +49,33 @@ namespace Org.BouncyCastle.Crypto.Parameters public Ed448PublicKeyParameters GeneratePublicKey() { - byte[] publicKey = new byte[Ed448.PublicKeySize]; - Ed448.GeneratePublicKey(data, 0, publicKey, 0); - return new Ed448PublicKeyParameters(publicKey, 0); + lock (data) + { + if (null == cachedPublicKey) + { + byte[] publicKey = new byte[Ed448.PublicKeySize]; + Ed448.GeneratePublicKey(data, 0, publicKey, 0); + cachedPublicKey = new Ed448PublicKeyParameters(publicKey, 0); + } + + return cachedPublicKey; + } } + [Obsolete("Use overload that doesn't take a public key")] public void Sign(Ed448.Algorithm algorithm, Ed448PublicKeyParameters publicKey, byte[] ctx, byte[] msg, int msgOff, int msgLen, byte[] sig, int sigOff) { + Sign(algorithm, ctx, msg, msgOff, msgLen, sig, sigOff); + } + + public void Sign(Ed448.Algorithm algorithm, byte[] ctx, byte[] msg, int msgOff, int msgLen, + byte[] sig, int sigOff) + { + Ed448PublicKeyParameters publicKey = GeneratePublicKey(); + byte[] pk = new byte[Ed448.PublicKeySize]; - if (null == publicKey) - { - Ed448.GeneratePublicKey(data, 0, pk, 0); - } - else - { - publicKey.Encode(pk, 0); - } + publicKey.Encode(pk, 0); switch (algorithm) { diff --git a/crypto/src/crypto/signers/Ed25519Signer.cs b/crypto/src/crypto/signers/Ed25519Signer.cs index a916601e6..e58d14ea4 100644 --- a/crypto/src/crypto/signers/Ed25519Signer.cs +++ b/crypto/src/crypto/signers/Ed25519Signer.cs @@ -32,10 +32,8 @@ namespace Org.BouncyCastle.Crypto.Signers if (forSigning) { - // TODO Allow IAsymmetricCipherKeyPair to be an ICipherParameters? - this.privateKey = (Ed25519PrivateKeyParameters)parameters; - this.publicKey = privateKey.GeneratePublicKey(); + this.publicKey = null; } else { @@ -61,7 +59,7 @@ namespace Org.BouncyCastle.Crypto.Signers if (!forSigning || null == privateKey) throw new InvalidOperationException("Ed25519Signer not initialised for signature generation."); - return buffer.GenerateSignature(privateKey, publicKey); + return buffer.GenerateSignature(privateKey); } public virtual bool VerifySignature(byte[] signature) @@ -79,7 +77,7 @@ namespace Org.BouncyCastle.Crypto.Signers private class Buffer : MemoryStream { - internal byte[] GenerateSignature(Ed25519PrivateKeyParameters privateKey, Ed25519PublicKeyParameters publicKey) + internal byte[] GenerateSignature(Ed25519PrivateKeyParameters privateKey) { lock (this) { @@ -91,7 +89,7 @@ namespace Org.BouncyCastle.Crypto.Signers int count = (int)Position; #endif byte[] signature = new byte[Ed25519PrivateKeyParameters.SignatureSize]; - privateKey.Sign(Ed25519.Algorithm.Ed25519, publicKey, null, buf, 0, count, signature, 0); + privateKey.Sign(Ed25519.Algorithm.Ed25519, null, buf, 0, count, signature, 0); Reset(); return signature; } diff --git a/crypto/src/crypto/signers/Ed25519ctxSigner.cs b/crypto/src/crypto/signers/Ed25519ctxSigner.cs index ab7201b62..2b5296e96 100644 --- a/crypto/src/crypto/signers/Ed25519ctxSigner.cs +++ b/crypto/src/crypto/signers/Ed25519ctxSigner.cs @@ -34,10 +34,8 @@ namespace Org.BouncyCastle.Crypto.Signers if (forSigning) { - // TODO Allow IAsymmetricCipherKeyPair to be an ICipherParameters? - this.privateKey = (Ed25519PrivateKeyParameters)parameters; - this.publicKey = privateKey.GeneratePublicKey(); + this.publicKey = null; } else { @@ -63,7 +61,7 @@ namespace Org.BouncyCastle.Crypto.Signers if (!forSigning || null == privateKey) throw new InvalidOperationException("Ed25519ctxSigner not initialised for signature generation."); - return buffer.GenerateSignature(privateKey, publicKey, context); + return buffer.GenerateSignature(privateKey, context); } public virtual bool VerifySignature(byte[] signature) @@ -81,7 +79,7 @@ namespace Org.BouncyCastle.Crypto.Signers private class Buffer : MemoryStream { - internal byte[] GenerateSignature(Ed25519PrivateKeyParameters privateKey, Ed25519PublicKeyParameters publicKey, byte[] ctx) + internal byte[] GenerateSignature(Ed25519PrivateKeyParameters privateKey, byte[] ctx) { lock (this) { @@ -93,7 +91,7 @@ namespace Org.BouncyCastle.Crypto.Signers int count = (int)Position; #endif byte[] signature = new byte[Ed25519PrivateKeyParameters.SignatureSize]; - privateKey.Sign(Ed25519.Algorithm.Ed25519ctx, publicKey, ctx, buf, 0, count, signature, 0); + privateKey.Sign(Ed25519.Algorithm.Ed25519ctx, ctx, buf, 0, count, signature, 0); Reset(); return signature; } diff --git a/crypto/src/crypto/signers/Ed25519phSigner.cs b/crypto/src/crypto/signers/Ed25519phSigner.cs index 2538b16f5..cb3c3080a 100644 --- a/crypto/src/crypto/signers/Ed25519phSigner.cs +++ b/crypto/src/crypto/signers/Ed25519phSigner.cs @@ -33,10 +33,8 @@ namespace Org.BouncyCastle.Crypto.Signers if (forSigning) { - // TODO Allow AsymmetricCipherKeyPair to be a CipherParameters? - this.privateKey = (Ed25519PrivateKeyParameters)parameters; - this.publicKey = privateKey.GeneratePublicKey(); + this.publicKey = null; } else { @@ -67,7 +65,7 @@ namespace Org.BouncyCastle.Crypto.Signers throw new InvalidOperationException("Prehash digest failed"); byte[] signature = new byte[Ed25519PrivateKeyParameters.SignatureSize]; - privateKey.Sign(Ed25519.Algorithm.Ed25519ph, publicKey, context, msg, 0, Ed25519.PrehashSize, signature, 0); + privateKey.Sign(Ed25519.Algorithm.Ed25519ph, context, msg, 0, Ed25519.PrehashSize, signature, 0); return signature; } diff --git a/crypto/src/crypto/signers/Ed448Signer.cs b/crypto/src/crypto/signers/Ed448Signer.cs index b0563d544..9d1495f2e 100644 --- a/crypto/src/crypto/signers/Ed448Signer.cs +++ b/crypto/src/crypto/signers/Ed448Signer.cs @@ -34,10 +34,8 @@ namespace Org.BouncyCastle.Crypto.Signers if (forSigning) { - // TODO Allow IAsymmetricCipherKeyPair to be an ICipherParameters? - this.privateKey = (Ed448PrivateKeyParameters)parameters; - this.publicKey = privateKey.GeneratePublicKey(); + this.publicKey = null; } else { @@ -63,7 +61,7 @@ namespace Org.BouncyCastle.Crypto.Signers if (!forSigning || null == privateKey) throw new InvalidOperationException("Ed448Signer not initialised for signature generation."); - return buffer.GenerateSignature(privateKey, publicKey, context); + return buffer.GenerateSignature(privateKey, context); } public virtual bool VerifySignature(byte[] signature) @@ -81,7 +79,7 @@ namespace Org.BouncyCastle.Crypto.Signers private class Buffer : MemoryStream { - internal byte[] GenerateSignature(Ed448PrivateKeyParameters privateKey, Ed448PublicKeyParameters publicKey, byte[] ctx) + internal byte[] GenerateSignature(Ed448PrivateKeyParameters privateKey, byte[] ctx) { lock (this) { @@ -93,7 +91,7 @@ namespace Org.BouncyCastle.Crypto.Signers int count = (int)Position; #endif byte[] signature = new byte[Ed448PrivateKeyParameters.SignatureSize]; - privateKey.Sign(Ed448.Algorithm.Ed448, publicKey, ctx, buf, 0, count, signature, 0); + privateKey.Sign(Ed448.Algorithm.Ed448, ctx, buf, 0, count, signature, 0); Reset(); return signature; } diff --git a/crypto/src/crypto/signers/Ed448phSigner.cs b/crypto/src/crypto/signers/Ed448phSigner.cs index d656c1392..f01b6bfd4 100644 --- a/crypto/src/crypto/signers/Ed448phSigner.cs +++ b/crypto/src/crypto/signers/Ed448phSigner.cs @@ -33,10 +33,8 @@ namespace Org.BouncyCastle.Crypto.Signers if (forSigning) { - // TODO Allow AsymmetricCipherKeyPair to be a CipherParameters? - this.privateKey = (Ed448PrivateKeyParameters)parameters; - this.publicKey = privateKey.GeneratePublicKey(); + this.publicKey = null; } else { @@ -67,7 +65,7 @@ namespace Org.BouncyCastle.Crypto.Signers throw new InvalidOperationException("Prehash digest failed"); byte[] signature = new byte[Ed448PrivateKeyParameters.SignatureSize]; - privateKey.Sign(Ed448.Algorithm.Ed448ph, publicKey, context, msg, 0, Ed448.PrehashSize, signature, 0); + privateKey.Sign(Ed448.Algorithm.Ed448ph, context, msg, 0, Ed448.PrehashSize, signature, 0); return signature; } diff --git a/crypto/src/crypto/tls/CipherSuite.cs b/crypto/src/crypto/tls/CipherSuite.cs index 679a8be85..5aa556389 100644 --- a/crypto/src/crypto/tls/CipherSuite.cs +++ b/crypto/src/crypto/tls/CipherSuite.cs @@ -346,22 +346,6 @@ namespace Org.BouncyCastle.Crypto.Tls public const int DRAFT_TLS_DHE_PSK_WITH_CHACHA20_POLY1305_SHA256 = 0xCCAD; public const int DRAFT_TLS_RSA_PSK_WITH_CHACHA20_POLY1305_SHA256 = 0xCCAE; - /* - * draft-zauner-tls-aes-ocb-04 (code points TBD) - */ - public const int DRAFT_TLS_DHE_RSA_WITH_AES_128_OCB = 0xFF00; - public const int DRAFT_TLS_DHE_RSA_WITH_AES_256_OCB = 0xFF01; - public const int DRAFT_TLS_ECDHE_RSA_WITH_AES_128_OCB = 0xFF02; - public const int DRAFT_TLS_ECDHE_RSA_WITH_AES_256_OCB = 0xFF03; - public const int DRAFT_TLS_ECDHE_ECDSA_WITH_AES_128_OCB = 0xFF04; - public const int DRAFT_TLS_ECDHE_ECDSA_WITH_AES_256_OCB = 0xFF05; - public const int DRAFT_TLS_PSK_WITH_AES_128_OCB = 0xFF10; - public const int DRAFT_TLS_PSK_WITH_AES_256_OCB = 0xFF11; - public const int DRAFT_TLS_DHE_PSK_WITH_AES_128_OCB = 0xFF12; - public const int DRAFT_TLS_DHE_PSK_WITH_AES_256_OCB = 0xFF13; - public const int DRAFT_TLS_ECDHE_PSK_WITH_AES_128_OCB = 0xFF14; - public const int DRAFT_TLS_ECDHE_PSK_WITH_AES_256_OCB = 0xFF15; - public static bool IsScsv(int cipherSuite) { switch (cipherSuite) diff --git a/crypto/src/crypto/tls/TlsAeadCipher.cs b/crypto/src/crypto/tls/TlsAeadCipher.cs index cc0575cf0..9a65d5ee5 100644 --- a/crypto/src/crypto/tls/TlsAeadCipher.cs +++ b/crypto/src/crypto/tls/TlsAeadCipher.cs @@ -105,7 +105,10 @@ namespace Org.BouncyCastle.Crypto.Tls decryptKey = server_write_key; } + // NOTE: Ensure dummy nonce is not part of the generated sequence(s) byte[] dummyNonce = new byte[fixed_iv_length + record_iv_length]; + dummyNonce[0] = (byte)~encryptImplicitNonce[0]; + dummyNonce[1] = (byte)~decryptImplicitNonce[1]; this.encryptCipher.Init(true, new AeadParameters(encryptKey, 8 * macSize, dummyNonce)); this.decryptCipher.Init(false, new AeadParameters(decryptKey, 8 * macSize, dummyNonce)); diff --git a/crypto/src/crypto/tls/TlsDHUtilities.cs b/crypto/src/crypto/tls/TlsDHUtilities.cs index 59006018e..fb521336e 100644 --- a/crypto/src/crypto/tls/TlsDHUtilities.cs +++ b/crypto/src/crypto/tls/TlsDHUtilities.cs @@ -359,14 +359,6 @@ namespace Org.BouncyCastle.Crypto.Tls case CipherSuite.DRAFT_TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256: /* - * draft-zauner-tls-aes-ocb-04 - */ - case CipherSuite.DRAFT_TLS_DHE_RSA_WITH_AES_128_OCB: - case CipherSuite.DRAFT_TLS_DHE_RSA_WITH_AES_256_OCB: - case CipherSuite.DRAFT_TLS_DHE_PSK_WITH_AES_128_OCB: - case CipherSuite.DRAFT_TLS_DHE_PSK_WITH_AES_256_OCB: - - /* * DH_anon cipher suites are consider ephemeral DH */ case CipherSuite.TLS_DH_anon_WITH_3DES_EDE_CBC_SHA: diff --git a/crypto/src/crypto/tls/TlsEccUtilities.cs b/crypto/src/crypto/tls/TlsEccUtilities.cs index 7b7e89f84..5ef72a74e 100644 --- a/crypto/src/crypto/tls/TlsEccUtilities.cs +++ b/crypto/src/crypto/tls/TlsEccUtilities.cs @@ -247,16 +247,6 @@ namespace Org.BouncyCastle.Crypto.Tls case CipherSuite.DRAFT_TLS_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256: case CipherSuite.DRAFT_TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256: - /* - * draft-zauner-tls-aes-ocb-04 - */ - case CipherSuite.DRAFT_TLS_ECDHE_RSA_WITH_AES_128_OCB: - case CipherSuite.DRAFT_TLS_ECDHE_RSA_WITH_AES_256_OCB: - case CipherSuite.DRAFT_TLS_ECDHE_ECDSA_WITH_AES_128_OCB: - case CipherSuite.DRAFT_TLS_ECDHE_ECDSA_WITH_AES_256_OCB: - case CipherSuite.DRAFT_TLS_ECDHE_PSK_WITH_AES_128_OCB: - case CipherSuite.DRAFT_TLS_ECDHE_PSK_WITH_AES_256_OCB: - return true; default: diff --git a/crypto/src/crypto/tls/TlsProtocol.cs b/crypto/src/crypto/tls/TlsProtocol.cs index cc6ae0259..9e5d5c12e 100644 --- a/crypto/src/crypto/tls/TlsProtocol.cs +++ b/crypto/src/crypto/tls/TlsProtocol.cs @@ -1263,24 +1263,19 @@ namespace Org.BouncyCastle.Crypto.Tls case CipherSuite.TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA256: case CipherSuite.TLS_DHE_PSK_WITH_AES_128_CCM: case CipherSuite.TLS_DHE_PSK_WITH_AES_128_GCM_SHA256: - case CipherSuite.DRAFT_TLS_DHE_PSK_WITH_AES_128_OCB: case CipherSuite.TLS_DHE_PSK_WITH_AES_256_CCM: - case CipherSuite.DRAFT_TLS_DHE_PSK_WITH_AES_256_OCB: case CipherSuite.TLS_DHE_PSK_WITH_CAMELLIA_128_GCM_SHA256: case CipherSuite.DRAFT_TLS_DHE_PSK_WITH_CHACHA20_POLY1305_SHA256: case CipherSuite.TLS_DHE_RSA_WITH_AES_128_CBC_SHA256: case CipherSuite.TLS_DHE_RSA_WITH_AES_128_CCM: case CipherSuite.TLS_DHE_RSA_WITH_AES_128_CCM_8: case CipherSuite.TLS_DHE_RSA_WITH_AES_128_GCM_SHA256: - case CipherSuite.DRAFT_TLS_DHE_RSA_WITH_AES_128_OCB: case CipherSuite.TLS_DHE_RSA_WITH_AES_256_CBC_SHA256: case CipherSuite.TLS_DHE_RSA_WITH_AES_256_CCM: case CipherSuite.TLS_DHE_RSA_WITH_AES_256_CCM_8: - case CipherSuite.DRAFT_TLS_DHE_RSA_WITH_AES_256_OCB: case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256: case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_128_GCM_SHA256: case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256: - case CipherSuite.DRAFT_TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256: case CipherSuite.TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256: case CipherSuite.TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256: case CipherSuite.TLS_ECDH_ECDSA_WITH_CAMELLIA_128_CBC_SHA256: @@ -1293,20 +1288,14 @@ namespace Org.BouncyCastle.Crypto.Tls case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_CCM: case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8: case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256: - case CipherSuite.DRAFT_TLS_ECDHE_ECDSA_WITH_AES_128_OCB: case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_256_CCM: case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8: - case CipherSuite.DRAFT_TLS_ECDHE_ECDSA_WITH_AES_256_OCB: case CipherSuite.TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256: case CipherSuite.TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_GCM_SHA256: case CipherSuite.DRAFT_TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256: - case CipherSuite.DRAFT_TLS_ECDHE_PSK_WITH_AES_128_OCB: - case CipherSuite.DRAFT_TLS_ECDHE_PSK_WITH_AES_256_OCB: case CipherSuite.DRAFT_TLS_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256: case CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256: case CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256: - case CipherSuite.DRAFT_TLS_ECDHE_RSA_WITH_AES_128_OCB: - case CipherSuite.DRAFT_TLS_ECDHE_RSA_WITH_AES_256_OCB: case CipherSuite.TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256: case CipherSuite.TLS_ECDHE_RSA_WITH_CAMELLIA_128_GCM_SHA256: case CipherSuite.DRAFT_TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256: @@ -1315,10 +1304,8 @@ namespace Org.BouncyCastle.Crypto.Tls case CipherSuite.TLS_PSK_WITH_AES_128_CCM: case CipherSuite.TLS_PSK_WITH_AES_128_CCM_8: case CipherSuite.TLS_PSK_WITH_AES_128_GCM_SHA256: - case CipherSuite.DRAFT_TLS_PSK_WITH_AES_128_OCB: case CipherSuite.TLS_PSK_WITH_AES_256_CCM: case CipherSuite.TLS_PSK_WITH_AES_256_CCM_8: - case CipherSuite.DRAFT_TLS_PSK_WITH_AES_256_OCB: case CipherSuite.TLS_PSK_WITH_CAMELLIA_128_GCM_SHA256: case CipherSuite.DRAFT_TLS_PSK_WITH_CHACHA20_POLY1305_SHA256: case CipherSuite.TLS_RSA_PSK_WITH_AES_128_GCM_SHA256: diff --git a/crypto/src/crypto/tls/TlsServerProtocol.cs b/crypto/src/crypto/tls/TlsServerProtocol.cs index 1ba90cfdc..85b450c9e 100644 --- a/crypto/src/crypto/tls/TlsServerProtocol.cs +++ b/crypto/src/crypto/tls/TlsServerProtocol.cs @@ -390,37 +390,31 @@ namespace Org.BouncyCastle.Crypto.Tls protected override void HandleAlertWarningMessage(byte alertDescription) { - 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 + * either the certificate message or a no_certificate alert. + */ + if (AlertDescription.no_certificate == alertDescription && null != mCertificateRequest + && TlsUtilities.IsSsl(mTlsServerContext)) { - /* - * 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) && this.mCertificateRequest != null) + switch (mConnectionState) { - switch (this.mConnectionState) - { - case CS_SERVER_HELLO_DONE: - case CS_CLIENT_SUPPLEMENTAL_DATA: + case CS_SERVER_HELLO_DONE: + case CS_CLIENT_SUPPLEMENTAL_DATA: + { + if (mConnectionState < CS_CLIENT_SUPPLEMENTAL_DATA) { - if (mConnectionState < CS_CLIENT_SUPPLEMENTAL_DATA) - { - mTlsServer.ProcessClientSupplementalData(null); - } - - NotifyClientCertificate(Certificate.EmptyChain); - this.mConnectionState = CS_CLIENT_CERTIFICATE; - return; - } + mTlsServer.ProcessClientSupplementalData(null); } + + NotifyClientCertificate(Certificate.EmptyChain); + this.mConnectionState = CS_CLIENT_CERTIFICATE; + return; + } } - throw new TlsFatalAlert(AlertDescription.unexpected_message); } - } + + base.HandleAlertWarningMessage(alertDescription); } protected virtual void NotifyClientCertificate(Certificate clientCertificate) diff --git a/crypto/src/crypto/tls/TlsUtilities.cs b/crypto/src/crypto/tls/TlsUtilities.cs index 9f4aac651..6ee71021f 100644 --- a/crypto/src/crypto/tls/TlsUtilities.cs +++ b/crypto/src/crypto/tls/TlsUtilities.cs @@ -1391,14 +1391,6 @@ namespace Org.BouncyCastle.Crypto.Tls case CipherSuite.TLS_RSA_WITH_AES_128_GCM_SHA256: return EncryptionAlgorithm.AES_128_GCM; - case CipherSuite.DRAFT_TLS_DHE_PSK_WITH_AES_128_OCB: - case CipherSuite.DRAFT_TLS_DHE_RSA_WITH_AES_128_OCB: - case CipherSuite.DRAFT_TLS_ECDHE_ECDSA_WITH_AES_128_OCB: - case CipherSuite.DRAFT_TLS_ECDHE_PSK_WITH_AES_128_OCB: - case CipherSuite.DRAFT_TLS_ECDHE_RSA_WITH_AES_128_OCB: - case CipherSuite.DRAFT_TLS_PSK_WITH_AES_128_OCB: - return EncryptionAlgorithm.AES_128_OCB_TAGLEN96; - case CipherSuite.TLS_DH_anon_WITH_AES_256_CBC_SHA: case CipherSuite.TLS_DH_anon_WITH_AES_256_CBC_SHA256: case CipherSuite.TLS_DH_DSS_WITH_AES_256_CBC_SHA: @@ -1462,14 +1454,6 @@ namespace Org.BouncyCastle.Crypto.Tls case CipherSuite.TLS_RSA_WITH_AES_256_GCM_SHA384: return EncryptionAlgorithm.AES_256_GCM; - case CipherSuite.DRAFT_TLS_DHE_PSK_WITH_AES_256_OCB: - case CipherSuite.DRAFT_TLS_DHE_RSA_WITH_AES_256_OCB: - case CipherSuite.DRAFT_TLS_ECDHE_ECDSA_WITH_AES_256_OCB: - case CipherSuite.DRAFT_TLS_ECDHE_PSK_WITH_AES_256_OCB: - case CipherSuite.DRAFT_TLS_ECDHE_RSA_WITH_AES_256_OCB: - case CipherSuite.DRAFT_TLS_PSK_WITH_AES_256_OCB: - return EncryptionAlgorithm.AES_256_OCB_TAGLEN96; - case CipherSuite.TLS_DH_anon_WITH_CAMELLIA_128_CBC_SHA: case CipherSuite.TLS_DH_anon_WITH_CAMELLIA_128_CBC_SHA256: case CipherSuite.TLS_DH_DSS_WITH_CAMELLIA_128_CBC_SHA: @@ -1684,12 +1668,10 @@ namespace Org.BouncyCastle.Crypto.Tls case CipherSuite.TLS_DHE_PSK_WITH_AES_128_CBC_SHA256: case CipherSuite.TLS_DHE_PSK_WITH_AES_128_CCM: case CipherSuite.TLS_DHE_PSK_WITH_AES_128_GCM_SHA256: - case CipherSuite.DRAFT_TLS_DHE_PSK_WITH_AES_128_OCB: case CipherSuite.TLS_DHE_PSK_WITH_AES_256_CBC_SHA: case CipherSuite.TLS_DHE_PSK_WITH_AES_256_CBC_SHA384: case CipherSuite.TLS_DHE_PSK_WITH_AES_256_CCM: case CipherSuite.TLS_DHE_PSK_WITH_AES_256_GCM_SHA384: - case CipherSuite.DRAFT_TLS_DHE_PSK_WITH_AES_256_OCB: case CipherSuite.TLS_DHE_PSK_WITH_CAMELLIA_128_CBC_SHA256: case CipherSuite.TLS_DHE_PSK_WITH_CAMELLIA_128_GCM_SHA256: case CipherSuite.TLS_DHE_PSK_WITH_CAMELLIA_256_CBC_SHA384: @@ -1709,13 +1691,11 @@ namespace Org.BouncyCastle.Crypto.Tls case CipherSuite.TLS_DHE_RSA_WITH_AES_128_CCM: case CipherSuite.TLS_DHE_RSA_WITH_AES_128_CCM_8: case CipherSuite.TLS_DHE_RSA_WITH_AES_128_GCM_SHA256: - case CipherSuite.DRAFT_TLS_DHE_RSA_WITH_AES_128_OCB: case CipherSuite.TLS_DHE_RSA_WITH_AES_256_CBC_SHA: case CipherSuite.TLS_DHE_RSA_WITH_AES_256_CBC_SHA256: case CipherSuite.TLS_DHE_RSA_WITH_AES_256_CCM: case CipherSuite.TLS_DHE_RSA_WITH_AES_256_CCM_8: case CipherSuite.TLS_DHE_RSA_WITH_AES_256_GCM_SHA384: - case CipherSuite.DRAFT_TLS_DHE_RSA_WITH_AES_256_OCB: case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA: case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256: case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_128_GCM_SHA256: @@ -1737,11 +1717,9 @@ namespace Org.BouncyCastle.Crypto.Tls case CipherSuite.TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA: case CipherSuite.TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256: case CipherSuite.TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256: - case CipherSuite.DRAFT_TLS_ECDHE_ECDSA_WITH_AES_128_OCB: case CipherSuite.TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA: case CipherSuite.TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384: case CipherSuite.TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384: - case CipherSuite.DRAFT_TLS_ECDHE_ECDSA_WITH_AES_256_OCB: case CipherSuite.TLS_ECDH_ECDSA_WITH_CAMELLIA_128_CBC_SHA256: case CipherSuite.TLS_ECDH_ECDSA_WITH_CAMELLIA_128_GCM_SHA256: case CipherSuite.TLS_ECDH_ECDSA_WITH_CAMELLIA_256_CBC_SHA384: @@ -1788,10 +1766,8 @@ namespace Org.BouncyCastle.Crypto.Tls case CipherSuite.TLS_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA: case CipherSuite.TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA: case CipherSuite.TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256: - case CipherSuite.DRAFT_TLS_ECDHE_PSK_WITH_AES_128_OCB: case CipherSuite.TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA: case CipherSuite.TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384: - case CipherSuite.DRAFT_TLS_ECDHE_PSK_WITH_AES_256_OCB: case CipherSuite.TLS_ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256: case CipherSuite.TLS_ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384: case CipherSuite.DRAFT_TLS_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256: @@ -1805,11 +1781,9 @@ namespace Org.BouncyCastle.Crypto.Tls case CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA: case CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256: case CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256: - case CipherSuite.DRAFT_TLS_ECDHE_RSA_WITH_AES_128_OCB: case CipherSuite.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA: case CipherSuite.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384: case CipherSuite.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384: - case CipherSuite.DRAFT_TLS_ECDHE_RSA_WITH_AES_256_OCB: case CipherSuite.TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256: case CipherSuite.TLS_ECDHE_RSA_WITH_CAMELLIA_128_GCM_SHA256: case CipherSuite.TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384: @@ -1825,13 +1799,11 @@ namespace Org.BouncyCastle.Crypto.Tls case CipherSuite.TLS_PSK_WITH_AES_128_CCM: case CipherSuite.TLS_PSK_WITH_AES_128_CCM_8: case CipherSuite.TLS_PSK_WITH_AES_128_GCM_SHA256: - case CipherSuite.DRAFT_TLS_PSK_WITH_AES_128_OCB: case CipherSuite.TLS_PSK_WITH_AES_256_CBC_SHA: case CipherSuite.TLS_PSK_WITH_AES_256_CBC_SHA384: case CipherSuite.TLS_PSK_WITH_AES_256_CCM: case CipherSuite.TLS_PSK_WITH_AES_256_CCM_8: case CipherSuite.TLS_PSK_WITH_AES_256_GCM_SHA384: - case CipherSuite.DRAFT_TLS_PSK_WITH_AES_256_OCB: case CipherSuite.TLS_PSK_WITH_CAMELLIA_128_CBC_SHA256: case CipherSuite.TLS_PSK_WITH_CAMELLIA_128_GCM_SHA256: case CipherSuite.TLS_PSK_WITH_CAMELLIA_256_CBC_SHA384: @@ -1928,21 +1900,17 @@ namespace Org.BouncyCastle.Crypto.Tls case CipherSuite.TLS_DHE_DSS_WITH_CAMELLIA_256_GCM_SHA384: case CipherSuite.TLS_DHE_PSK_WITH_AES_128_CCM: case CipherSuite.TLS_DHE_PSK_WITH_AES_128_GCM_SHA256: - case CipherSuite.DRAFT_TLS_DHE_PSK_WITH_AES_128_OCB: case CipherSuite.TLS_DHE_PSK_WITH_AES_256_CCM: case CipherSuite.TLS_DHE_PSK_WITH_AES_256_GCM_SHA384: - case CipherSuite.DRAFT_TLS_DHE_PSK_WITH_AES_256_OCB: case CipherSuite.TLS_DHE_PSK_WITH_CAMELLIA_128_GCM_SHA256: case CipherSuite.TLS_DHE_PSK_WITH_CAMELLIA_256_GCM_SHA384: case CipherSuite.DRAFT_TLS_DHE_PSK_WITH_CHACHA20_POLY1305_SHA256: case CipherSuite.TLS_DHE_RSA_WITH_AES_128_CCM: case CipherSuite.TLS_DHE_RSA_WITH_AES_128_CCM_8: case CipherSuite.TLS_DHE_RSA_WITH_AES_128_GCM_SHA256: - case CipherSuite.DRAFT_TLS_DHE_RSA_WITH_AES_128_OCB: case CipherSuite.TLS_DHE_RSA_WITH_AES_256_CCM: case CipherSuite.TLS_DHE_RSA_WITH_AES_256_CCM_8: case CipherSuite.TLS_DHE_RSA_WITH_AES_256_GCM_SHA384: - case CipherSuite.DRAFT_TLS_DHE_RSA_WITH_AES_256_OCB: case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_128_GCM_SHA256: case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_256_GCM_SHA384: case CipherSuite.DRAFT_TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256: @@ -1957,21 +1925,15 @@ namespace Org.BouncyCastle.Crypto.Tls case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_CCM: case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8: case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256: - case CipherSuite.DRAFT_TLS_ECDHE_ECDSA_WITH_AES_128_OCB: case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_256_CCM: case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8: case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384: - case CipherSuite.DRAFT_TLS_ECDHE_ECDSA_WITH_AES_256_OCB: case CipherSuite.TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_GCM_SHA256: case CipherSuite.TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_GCM_SHA384: case CipherSuite.DRAFT_TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256: - case CipherSuite.DRAFT_TLS_ECDHE_PSK_WITH_AES_128_OCB: - case CipherSuite.DRAFT_TLS_ECDHE_PSK_WITH_AES_256_OCB: case CipherSuite.DRAFT_TLS_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256: case CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256: - case CipherSuite.DRAFT_TLS_ECDHE_RSA_WITH_AES_128_OCB: case CipherSuite.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384: - case CipherSuite.DRAFT_TLS_ECDHE_RSA_WITH_AES_256_OCB: case CipherSuite.TLS_ECDHE_RSA_WITH_CAMELLIA_128_GCM_SHA256: case CipherSuite.TLS_ECDHE_RSA_WITH_CAMELLIA_256_GCM_SHA384: case CipherSuite.DRAFT_TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256: @@ -1980,11 +1942,9 @@ namespace Org.BouncyCastle.Crypto.Tls case CipherSuite.TLS_PSK_WITH_AES_128_CCM: case CipherSuite.TLS_PSK_WITH_AES_128_CCM_8: case CipherSuite.TLS_PSK_WITH_AES_128_GCM_SHA256: - case CipherSuite.DRAFT_TLS_PSK_WITH_AES_128_OCB: case CipherSuite.TLS_PSK_WITH_AES_256_CCM: case CipherSuite.TLS_PSK_WITH_AES_256_CCM_8: case CipherSuite.TLS_PSK_WITH_AES_256_GCM_SHA384: - case CipherSuite.DRAFT_TLS_PSK_WITH_AES_256_OCB: case CipherSuite.TLS_PSK_WITH_CAMELLIA_128_GCM_SHA256: case CipherSuite.TLS_PSK_WITH_CAMELLIA_256_GCM_SHA384: case CipherSuite.DRAFT_TLS_PSK_WITH_CHACHA20_POLY1305_SHA256: @@ -2214,10 +2174,8 @@ namespace Org.BouncyCastle.Crypto.Tls case CipherSuite.TLS_DHE_DSS_WITH_CAMELLIA_256_GCM_SHA384: case CipherSuite.TLS_DHE_PSK_WITH_AES_128_CCM: case CipherSuite.TLS_DHE_PSK_WITH_AES_128_GCM_SHA256: - case CipherSuite.DRAFT_TLS_DHE_PSK_WITH_AES_128_OCB: case CipherSuite.TLS_DHE_PSK_WITH_AES_256_CCM: case CipherSuite.TLS_DHE_PSK_WITH_AES_256_GCM_SHA384: - case CipherSuite.DRAFT_TLS_DHE_PSK_WITH_AES_256_OCB: case CipherSuite.TLS_DHE_PSK_WITH_CAMELLIA_128_GCM_SHA256: case CipherSuite.TLS_DHE_PSK_WITH_CAMELLIA_256_GCM_SHA384: case CipherSuite.DRAFT_TLS_DHE_PSK_WITH_CHACHA20_POLY1305_SHA256: @@ -2225,12 +2183,10 @@ namespace Org.BouncyCastle.Crypto.Tls case CipherSuite.TLS_DHE_RSA_WITH_AES_128_CCM: case CipherSuite.TLS_DHE_RSA_WITH_AES_128_CCM_8: case CipherSuite.TLS_DHE_RSA_WITH_AES_128_GCM_SHA256: - case CipherSuite.DRAFT_TLS_DHE_RSA_WITH_AES_128_OCB: case CipherSuite.TLS_DHE_RSA_WITH_AES_256_CBC_SHA256: case CipherSuite.TLS_DHE_RSA_WITH_AES_256_CCM: case CipherSuite.TLS_DHE_RSA_WITH_AES_256_CCM_8: case CipherSuite.TLS_DHE_RSA_WITH_AES_256_GCM_SHA384: - case CipherSuite.DRAFT_TLS_DHE_RSA_WITH_AES_256_OCB: case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256: case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_128_GCM_SHA256: case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256: @@ -2256,26 +2212,20 @@ namespace Org.BouncyCastle.Crypto.Tls case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_CCM: case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8: case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256: - case CipherSuite.DRAFT_TLS_ECDHE_ECDSA_WITH_AES_128_OCB: case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384: case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_256_CCM: case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8: case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384: - case CipherSuite.DRAFT_TLS_ECDHE_ECDSA_WITH_AES_256_OCB: case CipherSuite.TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256: case CipherSuite.TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_GCM_SHA256: case CipherSuite.TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384: case CipherSuite.TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_GCM_SHA384: case CipherSuite.DRAFT_TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256: - case CipherSuite.DRAFT_TLS_ECDHE_PSK_WITH_AES_128_OCB: - case CipherSuite.DRAFT_TLS_ECDHE_PSK_WITH_AES_256_OCB: case CipherSuite.DRAFT_TLS_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256: case CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256: case CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256: - case CipherSuite.DRAFT_TLS_ECDHE_RSA_WITH_AES_128_OCB: case CipherSuite.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384: case CipherSuite.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384: - case CipherSuite.DRAFT_TLS_ECDHE_RSA_WITH_AES_256_OCB: case CipherSuite.TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256: case CipherSuite.TLS_ECDHE_RSA_WITH_CAMELLIA_128_GCM_SHA256: case CipherSuite.TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384: @@ -2286,11 +2236,9 @@ namespace Org.BouncyCastle.Crypto.Tls case CipherSuite.TLS_PSK_WITH_AES_128_CCM: case CipherSuite.TLS_PSK_WITH_AES_128_CCM_8: case CipherSuite.TLS_PSK_WITH_AES_128_GCM_SHA256: - case CipherSuite.DRAFT_TLS_PSK_WITH_AES_128_OCB: case CipherSuite.TLS_PSK_WITH_AES_256_CCM: case CipherSuite.TLS_PSK_WITH_AES_256_CCM_8: case CipherSuite.TLS_PSK_WITH_AES_256_GCM_SHA384: - case CipherSuite.DRAFT_TLS_PSK_WITH_AES_256_OCB: case CipherSuite.TLS_PSK_WITH_CAMELLIA_128_GCM_SHA256: case CipherSuite.TLS_PSK_WITH_CAMELLIA_256_GCM_SHA384: case CipherSuite.DRAFT_TLS_PSK_WITH_CHACHA20_POLY1305_SHA256: diff --git a/crypto/src/math/ec/ECAlgorithms.cs b/crypto/src/math/ec/ECAlgorithms.cs index 4976b73b0..64e68fccc 100644 --- a/crypto/src/math/ec/ECAlgorithms.cs +++ b/crypto/src/math/ec/ECAlgorithms.cs @@ -168,8 +168,9 @@ namespace Org.BouncyCastle.Math.EC } /** - * Simple shift-and-add multiplication. Serves as reference implementation - * to verify (possibly faster) implementations, and for very small scalars. + * Simple shift-and-add multiplication. Serves as reference implementation to verify (possibly + * faster) implementations, and for very small scalars. CAUTION: This implementation is NOT + * constant-time in any way. It is only intended to be used for diagnostics. * * @param p * The point to multiply. diff --git a/crypto/src/math/ec/multiplier/DoubleAddMultiplier.cs b/crypto/src/math/ec/multiplier/DoubleAddMultiplier.cs index 18a72c0a2..6648727f9 100644 --- a/crypto/src/math/ec/multiplier/DoubleAddMultiplier.cs +++ b/crypto/src/math/ec/multiplier/DoubleAddMultiplier.cs @@ -1,5 +1,8 @@ -namespace Org.BouncyCastle.Math.EC.Multiplier +using System; + +namespace Org.BouncyCastle.Math.EC.Multiplier { + [Obsolete("Will be removed")] public class DoubleAddMultiplier : AbstractECMultiplier { diff --git a/crypto/src/math/ec/multiplier/MixedNafR2LMultiplier.cs b/crypto/src/math/ec/multiplier/MixedNafR2LMultiplier.cs index a4c201832..2bed8920c 100644 --- a/crypto/src/math/ec/multiplier/MixedNafR2LMultiplier.cs +++ b/crypto/src/math/ec/multiplier/MixedNafR2LMultiplier.cs @@ -6,6 +6,7 @@ namespace Org.BouncyCastle.Math.EC.Multiplier * Class implementing the NAF (Non-Adjacent Form) multiplication algorithm (right-to-left) using * mixed coordinates. */ + [Obsolete("Will be removed")] public class MixedNafR2LMultiplier : AbstractECMultiplier { diff --git a/crypto/src/math/ec/multiplier/MontgomeryLadderMultiplier.cs b/crypto/src/math/ec/multiplier/MontgomeryLadderMultiplier.cs index e2470a383..45df2fdae 100644 --- a/crypto/src/math/ec/multiplier/MontgomeryLadderMultiplier.cs +++ b/crypto/src/math/ec/multiplier/MontgomeryLadderMultiplier.cs @@ -1,5 +1,8 @@ -namespace Org.BouncyCastle.Math.EC.Multiplier +using System; + +namespace Org.BouncyCastle.Math.EC.Multiplier { + [Obsolete("Will be removed")] public class MontgomeryLadderMultiplier : AbstractECMultiplier { diff --git a/crypto/src/math/ec/multiplier/NafL2RMultiplier.cs b/crypto/src/math/ec/multiplier/NafL2RMultiplier.cs index ac80cf905..d41a0d651 100644 --- a/crypto/src/math/ec/multiplier/NafL2RMultiplier.cs +++ b/crypto/src/math/ec/multiplier/NafL2RMultiplier.cs @@ -1,8 +1,11 @@ +using System; + namespace Org.BouncyCastle.Math.EC.Multiplier { /** * Class implementing the NAF (Non-Adjacent Form) multiplication algorithm (left-to-right). */ + [Obsolete("Will be removed")] public class NafL2RMultiplier : AbstractECMultiplier { diff --git a/crypto/src/math/ec/multiplier/NafR2LMultiplier.cs b/crypto/src/math/ec/multiplier/NafR2LMultiplier.cs index 1fa69fae8..8157cf05e 100644 --- a/crypto/src/math/ec/multiplier/NafR2LMultiplier.cs +++ b/crypto/src/math/ec/multiplier/NafR2LMultiplier.cs @@ -1,8 +1,11 @@ -namespace Org.BouncyCastle.Math.EC.Multiplier +using System; + +namespace Org.BouncyCastle.Math.EC.Multiplier { /** * Class implementing the NAF (Non-Adjacent Form) multiplication algorithm (right-to-left). */ + [Obsolete("Will be removed")] public class NafR2LMultiplier : AbstractECMultiplier { diff --git a/crypto/src/math/ec/multiplier/ReferenceMultiplier.cs b/crypto/src/math/ec/multiplier/ReferenceMultiplier.cs index 4848ada39..40563cdc7 100644 --- a/crypto/src/math/ec/multiplier/ReferenceMultiplier.cs +++ b/crypto/src/math/ec/multiplier/ReferenceMultiplier.cs @@ -1,5 +1,8 @@ +using System; + namespace Org.BouncyCastle.Math.EC.Multiplier { + [Obsolete("Will be removed")] public class ReferenceMultiplier : AbstractECMultiplier { diff --git a/crypto/src/math/ec/multiplier/ZSignedDigitL2RMultiplier.cs b/crypto/src/math/ec/multiplier/ZSignedDigitL2RMultiplier.cs index 554ac61b3..1c7a5d104 100644 --- a/crypto/src/math/ec/multiplier/ZSignedDigitL2RMultiplier.cs +++ b/crypto/src/math/ec/multiplier/ZSignedDigitL2RMultiplier.cs @@ -1,5 +1,8 @@ -namespace Org.BouncyCastle.Math.EC.Multiplier +using System; + +namespace Org.BouncyCastle.Math.EC.Multiplier { + [Obsolete("Will be removed")] public class ZSignedDigitL2RMultiplier : AbstractECMultiplier { diff --git a/crypto/src/math/ec/multiplier/ZSignedDigitR2LMultiplier.cs b/crypto/src/math/ec/multiplier/ZSignedDigitR2LMultiplier.cs index 91c06cbb8..46d234c37 100644 --- a/crypto/src/math/ec/multiplier/ZSignedDigitR2LMultiplier.cs +++ b/crypto/src/math/ec/multiplier/ZSignedDigitR2LMultiplier.cs @@ -1,5 +1,8 @@ -namespace Org.BouncyCastle.Math.EC.Multiplier +using System; + +namespace Org.BouncyCastle.Math.EC.Multiplier { + [Obsolete("Will be removed")] public class ZSignedDigitR2LMultiplier : AbstractECMultiplier { diff --git a/crypto/src/math/ec/rfc7748/X25519Field.cs b/crypto/src/math/ec/rfc7748/X25519Field.cs index 3a06941dd..6843e274a 100644 --- a/crypto/src/math/ec/rfc7748/X25519Field.cs +++ b/crypto/src/math/ec/rfc7748/X25519Field.cs @@ -49,6 +49,11 @@ namespace Org.BouncyCastle.Math.EC.Rfc7748 int z0 = z[0], z1 = z[1], z2 = z[2], z3 = z[3], z4 = z[4]; int z5 = z[5], z6 = z[6], z7 = z[7], z8 = z[8], z9 = z[9]; + z2 += (z1 >> 26); z1 &= M26; + z4 += (z3 >> 26); z3 &= M26; + z7 += (z6 >> 26); z6 &= M26; + z9 += (z8 >> 26); z8 &= M26; + z3 += (z2 >> 25); z2 &= M25; z5 += (z4 >> 25); z4 &= M25; z8 += (z7 >> 25); z7 &= M25; @@ -439,22 +444,22 @@ namespace Org.BouncyCastle.Math.EC.Rfc7748 Mul(t, x, rz); } - private static void Reduce(int[] z, int c) - { - int z9 = z[9], t = z9; - z9 = t & M24; t >>= 24; - t += c; - t *= 19; - t += z[0]; z[0] = t & M26; t >>= 26; - t += z[1]; z[1] = t & M26; t >>= 26; - t += z[2]; z[2] = t & M25; t >>= 25; - t += z[3]; z[3] = t & M26; t >>= 26; - t += z[4]; z[4] = t & M25; t >>= 25; - t += z[5]; z[5] = t & M26; t >>= 26; - t += z[6]; z[6] = t & M26; t >>= 26; - t += z[7]; z[7] = t & M25; t >>= 25; - t += z[8]; z[8] = t & M26; t >>= 26; - t += z9; z[9] = t; + private static void Reduce(int[] z, int x) + { + int t = z[9], z9 = t & M24; + t = (t >> 24) + x; + + long cc = t * 19; + cc += z[0]; z[0] = (int)cc & M26; cc >>= 26; + cc += z[1]; z[1] = (int)cc & M26; cc >>= 26; + cc += z[2]; z[2] = (int)cc & M25; cc >>= 25; + cc += z[3]; z[3] = (int)cc & M26; cc >>= 26; + cc += z[4]; z[4] = (int)cc & M25; cc >>= 25; + cc += z[5]; z[5] = (int)cc & M26; cc >>= 26; + cc += z[6]; z[6] = (int)cc & M26; cc >>= 26; + cc += z[7]; z[7] = (int)cc & M25; cc >>= 25; + cc += z[8]; z[8] = (int)cc & M26; cc >>= 26; + z[9] = z9 + (int)cc; } public static void Sqr(int[] x, int[] z) diff --git a/crypto/src/math/ec/rfc7748/X448Field.cs b/crypto/src/math/ec/rfc7748/X448Field.cs index 14c9b4879..240518cde 100644 --- a/crypto/src/math/ec/rfc7748/X448Field.cs +++ b/crypto/src/math/ec/rfc7748/X448Field.cs @@ -45,6 +45,11 @@ namespace Org.BouncyCastle.Math.EC.Rfc7748 uint z0 = z[0], z1 = z[1], z2 = z[2], z3 = z[3], z4 = z[4], z5 = z[5], z6 = z[6], z7 = z[7]; uint z8 = z[8], z9 = z[9], z10 = z[10], z11 = z[11], z12 = z[12], z13 = z[13], z14 = z[14], z15 = z[15]; + z1 += (z0 >> 28); z0 &= M28; + z5 += (z4 >> 28); z4 &= M28; + z9 += (z8 >> 28); z8 &= M28; + z13 += (z12 >> 28); z12 &= M28; + z2 += (z1 >> 28); z1 &= M28; z6 += (z5 >> 28); z5 &= M28; z10 += (z9 >> 28); z9 &= M28; @@ -647,18 +652,22 @@ namespace Org.BouncyCastle.Math.EC.Rfc7748 Mul(t, x222, z); } - private static void Reduce(uint[] z, int c) + private static void Reduce(uint[] z, int x) { - uint z15 = z[15]; - long t = z15; - z15 &= M28; - t = (t >> 28) + c; - z[8] += (uint)t; - for (int i = 0; i < 15; ++i) + uint u = z[15], z15 = u & M28; + int t = (int)(u >> 28) + x; + + long cc = t; + for (int i = 0; i < 8; ++i) + { + cc += z[i]; z[i] = (uint)cc & M28; cc >>= 28; + } + cc += t; + for (int i = 8; i < 15; ++i) { - t += z[i]; z[i] = (uint)t & M28; t >>= 28; + cc += z[i]; z[i] = (uint)cc & M28; cc >>= 28; } - z[15] = z15 + (uint)t; + z[15] = z15 + (uint)cc; } public static void Sqr(uint[] x, uint[] z) diff --git a/crypto/src/math/ec/rfc8032/Ed25519.cs b/crypto/src/math/ec/rfc8032/Ed25519.cs index 238256cf7..95ba43472 100644 --- a/crypto/src/math/ec/rfc8032/Ed25519.cs +++ b/crypto/src/math/ec/rfc8032/Ed25519.cs @@ -314,7 +314,7 @@ namespace Org.BouncyCastle.Math.EC.Rfc8032 ScalarMultBaseEncoded(s, pk, pkOff); } - private static sbyte[] GetWnaf(uint[] n, int width) + private static sbyte[] GetWnafVar(uint[] n, int width) { Debug.Assert(n[ScalarUints - 1] >> 28 == 0); @@ -1000,8 +1000,8 @@ namespace Org.BouncyCastle.Math.EC.Rfc8032 int width = 5; - sbyte[] ws_b = GetWnaf(nb, WnafWidthBase); - sbyte[] ws_p = GetWnaf(np, width); + sbyte[] ws_b = GetWnafVar(nb, WnafWidthBase); + sbyte[] ws_p = GetWnafVar(np, width); PointExt[] tp = PointPrecompVar(p, 1 << (width - 2)); diff --git a/crypto/src/math/ec/rfc8032/Ed448.cs b/crypto/src/math/ec/rfc8032/Ed448.cs index 925f48eb1..12f24c1ff 100644 --- a/crypto/src/math/ec/rfc8032/Ed448.cs +++ b/crypto/src/math/ec/rfc8032/Ed448.cs @@ -323,7 +323,7 @@ namespace Org.BouncyCastle.Math.EC.Rfc8032 ScalarMultBaseEncoded(s, pk, pkOff); } - private static sbyte[] GetWnaf(uint[] n, int width) + private static sbyte[] GetWnafVar(uint[] n, int width) { Debug.Assert(n[ScalarUints - 1] >> 30 == 0U); @@ -1087,8 +1087,8 @@ namespace Org.BouncyCastle.Math.EC.Rfc8032 int width = 5; - sbyte[] ws_b = GetWnaf(nb, WnafWidthBase); - sbyte[] ws_p = GetWnaf(np, width); + sbyte[] ws_b = GetWnafVar(nb, WnafWidthBase); + sbyte[] ws_p = GetWnafVar(np, width); PointExt[] tp = PointPrecompVar(p, 1 << (width - 2)); diff --git a/crypto/src/openpgp/PGPKeyRing.cs b/crypto/src/openpgp/PGPKeyRing.cs index 6426f3f25..425eaca56 100644 --- a/crypto/src/openpgp/PGPKeyRing.cs +++ b/crypto/src/openpgp/PGPKeyRing.cs @@ -16,7 +16,7 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp BcpgInputStream bcpgInput) { return (bcpgInput.NextPacketTag() == PacketTag.Trust) - ? (TrustPacket) bcpgInput.ReadPacket() + ? (TrustPacket)bcpgInput.ReadPacket() : null; } diff --git a/crypto/src/openpgp/PgpCompressedData.cs b/crypto/src/openpgp/PgpCompressedData.cs index e64a17c9c..c841b7474 100644 --- a/crypto/src/openpgp/PgpCompressedData.cs +++ b/crypto/src/openpgp/PgpCompressedData.cs @@ -14,7 +14,11 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp public PgpCompressedData( BcpgInputStream bcpgInput) { - data = (CompressedDataPacket) bcpgInput.ReadPacket(); + Packet packet = bcpgInput.ReadPacket(); + if (!(packet is CompressedDataPacket)) + throw new IOException("unexpected packet in stream: " + packet); + + this.data = (CompressedDataPacket)packet; } /// <summary>The algorithm used for compression</summary> diff --git a/crypto/src/openpgp/PgpEncryptedDataList.cs b/crypto/src/openpgp/PgpEncryptedDataList.cs index 8dded7c05..1f605dab5 100644 --- a/crypto/src/openpgp/PgpEncryptedDataList.cs +++ b/crypto/src/openpgp/PgpEncryptedDataList.cs @@ -1,5 +1,6 @@ using System; using System.Collections; +using System.IO; using Org.BouncyCastle.Utilities; using Org.BouncyCastle.Utilities.Collections; @@ -10,10 +11,10 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp public class PgpEncryptedDataList : PgpObject { - private IList list = Platform.CreateArrayList(); - private InputStreamPacket data; + private readonly IList list = Platform.CreateArrayList(); + private readonly InputStreamPacket data; - public PgpEncryptedDataList( + public PgpEncryptedDataList( BcpgInputStream bcpgInput) { while (bcpgInput.NextPacketTag() == PacketTag.PublicKeyEncryptedSession @@ -22,9 +23,13 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp list.Add(bcpgInput.ReadPacket()); } - data = (InputStreamPacket)bcpgInput.ReadPacket(); + Packet packet = bcpgInput.ReadPacket(); + if (!(packet is InputStreamPacket)) + throw new IOException("unexpected packet in stream: " + packet); - for (int i = 0; i != list.Count; i++) + this.data = (InputStreamPacket)packet; + + for (int i = 0; i != list.Count; i++) { if (list[i] is SymmetricKeyEncSessionPacket) { diff --git a/crypto/src/openpgp/PgpLiteralData.cs b/crypto/src/openpgp/PgpLiteralData.cs index 79bbc3984..d1b7b4a4d 100644 --- a/crypto/src/openpgp/PgpLiteralData.cs +++ b/crypto/src/openpgp/PgpLiteralData.cs @@ -16,12 +16,16 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp /// <summary>The special name indicating a "for your eyes only" packet.</summary> public const string Console = "_CONSOLE"; - private LiteralDataPacket data; + private readonly LiteralDataPacket data; public PgpLiteralData( BcpgInputStream bcpgInput) { - data = (LiteralDataPacket) bcpgInput.ReadPacket(); + Packet packet = bcpgInput.ReadPacket(); + if (!(packet is LiteralDataPacket)) + throw new IOException("unexpected packet in stream: " + packet); + + this.data = (LiteralDataPacket)packet; } /// <summary>The format of the data stream - Binary or Text</summary> diff --git a/crypto/src/openpgp/PgpMarker.cs b/crypto/src/openpgp/PgpMarker.cs index 733e4e959..7257767ec 100644 --- a/crypto/src/openpgp/PgpMarker.cs +++ b/crypto/src/openpgp/PgpMarker.cs @@ -1,3 +1,6 @@ +using System; +using System.IO; + namespace Org.BouncyCastle.Bcpg.OpenPgp { /// <remarks> @@ -7,12 +10,16 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp public class PgpMarker : PgpObject { - private readonly MarkerPacket p; + private readonly MarkerPacket data; public PgpMarker( - BcpgInputStream bcpgIn) + BcpgInputStream bcpgInput) { - p = (MarkerPacket) bcpgIn.ReadPacket(); + Packet packet = bcpgInput.ReadPacket(); + if (!(packet is MarkerPacket)) + throw new IOException("unexpected packet in stream: " + packet); + + this.data = (MarkerPacket)packet; } } } diff --git a/crypto/src/openpgp/PgpOnePassSignature.cs b/crypto/src/openpgp/PgpOnePassSignature.cs index 68fc5994d..2fab5137e 100644 --- a/crypto/src/openpgp/PgpOnePassSignature.cs +++ b/crypto/src/openpgp/PgpOnePassSignature.cs @@ -9,14 +9,22 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp /// <remarks>A one pass signature object.</remarks> public class PgpOnePassSignature { - private OnePassSignaturePacket sigPack; - private int signatureType; + private static OnePassSignaturePacket Cast(Packet packet) + { + if (!(packet is OnePassSignaturePacket)) + throw new IOException("unexpected packet in stream: " + packet); + + return (OnePassSignaturePacket)packet; + } + + private readonly OnePassSignaturePacket sigPack; + private readonly int signatureType; private ISigner sig; private byte lastb; internal PgpOnePassSignature( BcpgInputStream bcpgInput) - : this((OnePassSignaturePacket) bcpgInput.ReadPacket()) + : this(Cast(bcpgInput.ReadPacket())) { } diff --git a/crypto/src/openpgp/PgpPublicKeyEncryptedData.cs b/crypto/src/openpgp/PgpPublicKeyEncryptedData.cs index c2a351182..04fe3ad37 100644 --- a/crypto/src/openpgp/PgpPublicKeyEncryptedData.cs +++ b/crypto/src/openpgp/PgpPublicKeyEncryptedData.cs @@ -197,12 +197,17 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp byte[] enc = secKeyData[0]; int pLen = ((((enc[0] & 0xff) << 8) + (enc[1] & 0xff)) + 7) / 8; - byte[] pEnc = new byte[pLen]; + if ((2 + pLen + 1) > enc.Length) + throw new PgpException("encoded length out of range"); + byte[] pEnc = new byte[pLen]; Array.Copy(enc, 2, pEnc, 0, pLen); - byte[] keyEnc = new byte[enc[pLen + 2]]; + int keyLen = enc[pLen + 2]; + if ((2 + pLen + 1 + keyLen) > enc.Length) + throw new PgpException("encoded length out of range"); + byte[] keyEnc = new byte[keyLen]; Array.Copy(enc, 2 + pLen + 1, keyEnc, 0, keyEnc.Length); ECPoint publicPoint = x9Params.Curve.DecodePoint(pEnc); diff --git a/crypto/src/openpgp/PgpPublicKeyRing.cs b/crypto/src/openpgp/PgpPublicKeyRing.cs index 92464d64f..c214623b4 100644 --- a/crypto/src/openpgp/PgpPublicKeyRing.cs +++ b/crypto/src/openpgp/PgpPublicKeyRing.cs @@ -45,7 +45,7 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp + "tag 0x" + ((int)initialTag).ToString("X")); } - PublicKeyPacket pubPk = (PublicKeyPacket) bcpgInput.ReadPacket(); + PublicKeyPacket pubPk = ReadPublicKeyPacket(bcpgInput); TrustPacket trustPk = ReadOptionalTrustPacket(bcpgInput); // direct signatures and revocations @@ -186,9 +186,18 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp return found ? new PgpPublicKeyRing(keys) : null; } + internal static PublicKeyPacket ReadPublicKeyPacket(BcpgInputStream bcpgInput) + { + Packet packet = bcpgInput.ReadPacket(); + if (!(packet is PublicKeyPacket)) + throw new IOException("unexpected packet in stream: " + packet); + + return (PublicKeyPacket)packet; + } + internal static PgpPublicKey ReadSubkey(BcpgInputStream bcpgInput) { - PublicKeyPacket pk = (PublicKeyPacket) bcpgInput.ReadPacket(); + PublicKeyPacket pk = ReadPublicKeyPacket(bcpgInput); TrustPacket kTrust = ReadOptionalTrustPacket(bcpgInput); // PGP 8 actually leaves out the signature. diff --git a/crypto/src/openpgp/PgpSecretKey.cs b/crypto/src/openpgp/PgpSecretKey.cs index b3986073d..01cceadbb 100644 --- a/crypto/src/openpgp/PgpSecretKey.cs +++ b/crypto/src/openpgp/PgpSecretKey.cs @@ -536,12 +536,15 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp for (int i = 0; i != 4; i++) { - int encLen = (((encData[pos] << 8) | (encData[pos + 1] & 0xff)) + 7) / 8; + int encLen = ((((encData[pos] & 0xff) << 8) | (encData[pos + 1] & 0xff)) + 7) / 8; data[pos] = encData[pos]; data[pos + 1] = encData[pos + 1]; pos += 2; + if (encLen > (encData.Length - pos)) + throw new PgpException("out of range encLen found in encData"); + byte[] tmp = RecoverKeyData(encAlgorithm, "/CFB/NoPadding", key, iv, encData, pos, encLen); Array.Copy(tmp, 0, data, pos, encLen); pos += encLen; @@ -984,11 +987,14 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp int pos = 0; for (int i = 0; i != 4; i++) { - int encLen = (((rawKeyData[pos] << 8) | (rawKeyData[pos + 1] & 0xff)) + 7) / 8; + int encLen = ((((rawKeyData[pos] & 0xff) << 8) | (rawKeyData[pos + 1] & 0xff)) + 7) / 8; keyData[pos] = rawKeyData[pos]; keyData[pos + 1] = rawKeyData[pos + 1]; + if (encLen > (rawKeyData.Length - (pos + 2))) + throw new PgpException("out of range encLen found in rawKeyData"); + byte[] tmp; if (i == 0) { diff --git a/crypto/src/openpgp/PgpSignature.cs b/crypto/src/openpgp/PgpSignature.cs index c8c541bef..fb6244725 100644 --- a/crypto/src/openpgp/PgpSignature.cs +++ b/crypto/src/openpgp/PgpSignature.cs @@ -12,6 +12,14 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp /// <remarks>A PGP signature object.</remarks> public class PgpSignature { + private static SignaturePacket Cast(Packet packet) + { + if (!(packet is SignaturePacket)) + throw new IOException("unexpected packet in stream: " + packet); + + return (SignaturePacket)packet; + } + public const int BinaryDocument = 0x00; public const int CanonicalTextDocument = 0x01; public const int StandAlone = 0x02; @@ -38,7 +46,7 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp internal PgpSignature( BcpgInputStream bcpgInput) - : this((SignaturePacket)bcpgInput.ReadPacket()) + : this(Cast(bcpgInput.ReadPacket())) { } diff --git a/crypto/src/openpgp/PgpUtilities.cs b/crypto/src/openpgp/PgpUtilities.cs index 039aa5893..43d60908b 100644 --- a/crypto/src/openpgp/PgpUtilities.cs +++ b/crypto/src/openpgp/PgpUtilities.cs @@ -27,17 +27,20 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp try { - Asn1Sequence s = (Asn1Sequence) Asn1Object.FromByteArray(encoding); + Asn1Sequence s = Asn1Sequence.GetInstance(encoding); - i1 = (DerInteger) s[0]; - i2 = (DerInteger) s[1]; + i1 = DerInteger.GetInstance(s[0]); + i2 = DerInteger.GetInstance(s[1]); } - catch (IOException e) + catch (Exception e) { throw new PgpException("exception encoding signature", e); } - return new MPInteger[]{ new MPInteger(i1.Value), new MPInteger(i2.Value) }; + return new MPInteger[]{ + new MPInteger(i1.Value), + new MPInteger(i2.Value) + }; } public static MPInteger[] RsaSigToMpi( diff --git a/crypto/src/pkcs/Pkcs12Store.cs b/crypto/src/pkcs/Pkcs12Store.cs index 7db264232..e8a5c4490 100644 --- a/crypto/src/pkcs/Pkcs12Store.cs +++ b/crypto/src/pkcs/Pkcs12Store.cs @@ -19,6 +19,8 @@ namespace Org.BouncyCastle.Pkcs { public class Pkcs12Store { + public const string IgnoreUselessPasswordProperty = "Org.BouncyCastle.Pkcs12.IgnoreUselessPassword"; + private readonly IgnoresCaseHashtable keys = new IgnoresCaseHashtable(); private readonly IDictionary localIds = Platform.CreateHashtable(); private readonly IgnoresCaseHashtable certs = new IgnoresCaseHashtable(); @@ -198,20 +200,22 @@ namespace Org.BouncyCastle.Pkcs if (input == null) throw new ArgumentNullException("input"); - Asn1Sequence obj = (Asn1Sequence) Asn1Object.FromStream(input); - Pfx bag = new Pfx(obj); + Pfx bag = Pfx.GetInstance(Asn1Object.FromStream(input)); ContentInfo info = bag.AuthSafe; bool wrongPkcs12Zero = false; - if (password != null && bag.MacData != null) // check the mac code - { + if (bag.MacData != null) // check the mac code + { + if (password == null) + throw new ArgumentNullException("password", "no password supplied when one expected"); + MacData mData = bag.MacData; DigestInfo dInfo = mData.Mac; AlgorithmIdentifier algId = dInfo.AlgorithmID; byte[] salt = mData.GetSalt(); int itCount = mData.IterationCount.IntValue; - byte[] data = ((Asn1OctetString) info.Content).GetOctets(); + byte[] data = Asn1OctetString.GetInstance(info.Content).GetOctets(); byte[] mac = CalculatePbeMac(algId.Algorithm, salt, itCount, password, false, data); byte[] dig = dInfo.GetDigest(); @@ -228,8 +232,18 @@ namespace Org.BouncyCastle.Pkcs throw new IOException("PKCS12 key store MAC invalid - wrong password or corrupted file."); wrongPkcs12Zero = true; - } - } + } + } + else if (password != null) + { + string ignoreProperty = Platform.GetEnvironmentVariable(IgnoreUselessPasswordProperty); + bool ignore = ignoreProperty != null && Platform.EqualsIgnoreCase("true", ignoreProperty); + + if (!ignore) + { + throw new IOException("password supplied for keystore that does not require one"); + } + } keys.Clear(); localIds.Clear(); @@ -238,10 +252,9 @@ namespace Org.BouncyCastle.Pkcs IList certBags = Platform.CreateArrayList(); if (info.ContentType.Equals(PkcsObjectIdentifiers.Data)) - { - byte[] octs = ((Asn1OctetString)info.Content).GetOctets(); - AuthenticatedSafe authSafe = new AuthenticatedSafe( - (Asn1Sequence) Asn1OctetString.FromByteArray(octs)); + { + Asn1OctetString content = Asn1OctetString.GetInstance(info.Content); + AuthenticatedSafe authSafe = AuthenticatedSafe.GetInstance(content.GetOctets()); ContentInfo[] cis = authSafe.GetContentInfo(); foreach (ContentInfo ci in cis) @@ -250,8 +263,8 @@ namespace Org.BouncyCastle.Pkcs byte[] octets = null; if (oid.Equals(PkcsObjectIdentifiers.Data)) - { - octets = ((Asn1OctetString)ci.Content).GetOctets(); + { + octets = Asn1OctetString.GetInstance(ci.Content).GetOctets(); } else if (oid.Equals(PkcsObjectIdentifiers.EncryptedData)) { @@ -268,8 +281,8 @@ namespace Org.BouncyCastle.Pkcs } if (octets != null) - { - Asn1Sequence seq = (Asn1Sequence)Asn1Object.FromByteArray(octets); + { + Asn1Sequence seq = Asn1Sequence.GetInstance(octets); foreach (Asn1Sequence subSeq in seq) { @@ -527,15 +540,15 @@ namespace Org.BouncyCastle.Pkcs X509Certificate x509c = c.Certificate; X509CertificateEntry nextC = null; - Asn1OctetString ext = x509c.GetExtensionValue(X509Extensions.AuthorityKeyIdentifier); - if (ext != null) + Asn1OctetString akiValue = x509c.GetExtensionValue(X509Extensions.AuthorityKeyIdentifier); + if (akiValue != null) { - AuthorityKeyIdentifier id = AuthorityKeyIdentifier.GetInstance( - Asn1Object.FromByteArray(ext.GetOctets())); + AuthorityKeyIdentifier aki = AuthorityKeyIdentifier.GetInstance(akiValue.GetOctets()); - if (id.GetKeyIdentifier() != null) + byte[] keyID = aki.GetKeyIdentifier(); + if (keyID != null) { - nextC = (X509CertificateEntry) chainCerts[new CertId(id.GetKeyIdentifier())]; + nextC = (X509CertificateEntry)chainCerts[new CertId(keyID)]; } } @@ -1099,6 +1112,11 @@ namespace Org.BouncyCastle.Pkcs { get { return orig.Values; } } + + public int Count + { + get { return orig.Count; } + } } } } diff --git a/crypto/src/pkix/PkixNameConstraintValidator.cs b/crypto/src/pkix/PkixNameConstraintValidator.cs index 4d5af28ea..fbec6fb72 100644 --- a/crypto/src/pkix/PkixNameConstraintValidator.cs +++ b/crypto/src/pkix/PkixNameConstraintValidator.cs @@ -47,11 +47,24 @@ namespace Org.BouncyCastle.Pkix if (subtree.Count < 1 || subtree.Count > dns.Count) return false; + int start = 0; + Rdn subtreeRdnStart = Rdn.GetInstance(subtree[0]); + for (int j = 0; j < dns.Count; j++) + { + start = j; + Rdn dnsRdn = Rdn.GetInstance(dns[j]); + if (IetfUtilities.RdnAreEqual(subtreeRdnStart, dnsRdn)) + break; + } + + if (subtree.Count > dns.Count - start) + return false; + for (int j = 0; j < subtree.Count; ++j) { // both subtree and dns are a ASN.1 Name and the elements are a RDN Rdn subtreeRdn = Rdn.GetInstance(subtree[j]); - Rdn dnsRdn = Rdn.GetInstance(dns[j]); + Rdn dnsRdn = Rdn.GetInstance(dns[start + j]); // check if types and values of all naming attributes are matching, other types which are not restricted are allowed, see https://tools.ietf.org/html/rfc5280#section-7.1 diff --git a/crypto/src/security/PrivateKeyFactory.cs b/crypto/src/security/PrivateKeyFactory.cs index ddcb88992..b72ece365 100644 --- a/crypto/src/security/PrivateKeyFactory.cs +++ b/crypto/src/security/PrivateKeyFactory.cs @@ -107,7 +107,7 @@ namespace Org.BouncyCastle.Security } else if (algOid.Equals(X9ObjectIdentifiers.IdECPublicKey)) { - X962Parameters para = new X962Parameters(algID.Parameters.ToAsn1Object()); + X962Parameters para = X962Parameters.GetInstance(algID.Parameters.ToAsn1Object()); X9ECParameters x9; if (para.IsNamedCurve) @@ -132,8 +132,8 @@ namespace Org.BouncyCastle.Security } else if (algOid.Equals(CryptoProObjectIdentifiers.GostR3410x2001)) { - Gost3410PublicKeyAlgParameters gostParams = new Gost3410PublicKeyAlgParameters( - Asn1Sequence.GetInstance(algID.Parameters.ToAsn1Object())); + Gost3410PublicKeyAlgParameters gostParams = Gost3410PublicKeyAlgParameters.GetInstance( + algID.Parameters.ToAsn1Object()); ECDomainParameters ecP = ECGost3410NamedCurves.GetByOid(gostParams.PublicKeyParamSet); diff --git a/crypto/src/security/PublicKeyFactory.cs b/crypto/src/security/PublicKeyFactory.cs index 7b19f1c0f..6813452a6 100644 --- a/crypto/src/security/PublicKeyFactory.cs +++ b/crypto/src/security/PublicKeyFactory.cs @@ -133,7 +133,7 @@ namespace Org.BouncyCastle.Security } else if (algOid.Equals(X9ObjectIdentifiers.IdECPublicKey)) { - X962Parameters para = new X962Parameters(algID.Parameters.ToAsn1Object()); + X962Parameters para = X962Parameters.GetInstance(algID.Parameters.ToAsn1Object()); X9ECParameters x9; if (para.IsNamedCurve) diff --git a/crypto/src/tsp/TimeStampToken.cs b/crypto/src/tsp/TimeStampToken.cs index 105208a7d..643813552 100644 --- a/crypto/src/tsp/TimeStampToken.cs +++ b/crypto/src/tsp/TimeStampToken.cs @@ -244,9 +244,18 @@ namespace Org.BouncyCastle.Tsp */ public byte[] GetEncoded() { - return tsToken.GetEncoded(); - } - + return tsToken.GetEncoded(Asn1Encodable.Der); + } + + /** + * return the ASN.1 encoded representation of this object using the specified encoding. + * + * @param encoding the ASN.1 encoding format to use ("BER" or "DER"). + */ + public byte[] GetEncoded(string encoding) + { + return tsToken.GetEncoded(encoding); + } // perhaps this should be done using an interface on the ASN.1 classes... private class CertID diff --git a/crypto/src/util/Arrays.cs b/crypto/src/util/Arrays.cs index 6f2503d2d..7b1766bba 100644 --- a/crypto/src/util/Arrays.cs +++ b/crypto/src/util/Arrays.cs @@ -53,9 +53,7 @@ namespace Org.BouncyCastle.Utilities /// <param name="a">Left side.</param> /// <param name="b">Right side.</param> /// <returns>True if equal.</returns> - public static bool AreEqual( - byte[] a, - byte[] b) + public static bool AreEqual(byte[] a, byte[] b) { if (a == b) return true; @@ -66,6 +64,23 @@ namespace Org.BouncyCastle.Utilities return HaveSameContents(a, b); } + public static bool AreEqual(byte[] a, int aFromIndex, int aToIndex, byte[] b, int bFromIndex, int bToIndex) + { + int aLength = aToIndex - aFromIndex; + int bLength = bToIndex - bFromIndex; + + if (aLength != bLength) + return false; + + for (int i = 0; i < aLength; ++i) + { + if (a[aFromIndex + i] != b[bFromIndex + i]) + return false; + } + + return true; + } + [Obsolete("Use 'AreEqual' method instead")] public static bool AreSame( byte[] a, diff --git a/crypto/src/util/io/pem/PemReader.cs b/crypto/src/util/io/pem/PemReader.cs index bf712b6de..61e132fa7 100644 --- a/crypto/src/util/io/pem/PemReader.cs +++ b/crypto/src/util/io/pem/PemReader.cs @@ -39,11 +39,14 @@ namespace Org.BouncyCastle.Utilities.IO.Pem { line = line.Substring(BeginString.Length); int index = line.IndexOf('-'); - string type = line.Substring(0, index); - if (index > 0) - return LoadObject(type); - } + if (index > 0 && Platform.EndsWith(line, "-----") && (line.Length - index) == 5) + { + string type = line.Substring(0, index); + + return LoadObject(type); + } + } return null; } |