diff options
Diffstat (limited to 'crypto')
90 files changed, 1149 insertions, 716 deletions
diff --git a/crypto/License.html b/crypto/License.html index 482f20a0f..f091a2934 100644 --- a/crypto/License.html +++ b/crypto/License.html @@ -9,7 +9,7 @@ <h2>The Bouncy Castle Cryptographic C#® API</h2> <h3>License:</h3> The Bouncy Castle License<br> -Copyright (c) 2000-2019 The Legion of the Bouncy Castle Inc. +Copyright (c) 2000-2020 The Legion of the Bouncy Castle Inc. (https://www.bouncycastle.org)<br> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the diff --git a/crypto/Readme.html b/crypto/Readme.html index fc00814ad..30f0337e0 100644 --- a/crypto/Readme.html +++ b/crypto/Readme.html @@ -305,10 +305,15 @@ We state, where EC MQV has not otherwise been disabled or removed: <h5>Defects Fixed</h5> <ul> <li>EdDSA verifiers now reject overly long signatures.</li> + <li>Fixed field reduction for custom secp128r1 curve.</li> + <li>ASN.1: Enforce no leading zeroes in OID branches (longer than 1 character).</li> </ul> <h5>Additional Features and Functionality</h5> <ul> <li>TLS: BasicTlsPskIdentity now reusable (returns cloned array from GetPsk).</li> + <li>Improved performance for multiple ECDSA verifications using same public key.</li> + <li>Support has been added for ChaCha20-Poly1305 AEAD mode from RFC 7539.</li> + <li>PKCS12: Improved support for certificate-only key stores without password.</li> </ul> <h4><a class="mozTocH4" name="mozTocId85319"></a>Release 1.8.5, Thursday January 31, 2019</h4> 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; } diff --git a/crypto/test/src/asn1/test/InputStreamTest.cs b/crypto/test/src/asn1/test/InputStreamTest.cs index 1d92759e0..4cfb304d1 100644 --- a/crypto/test/src/asn1/test/InputStreamTest.cs +++ b/crypto/test/src/asn1/test/InputStreamTest.cs @@ -3,6 +3,7 @@ using System.IO; using NUnit.Framework; +using Org.BouncyCastle.Utilities.Encoders; using Org.BouncyCastle.Utilities.Test; namespace Org.BouncyCastle.Asn1.Tests @@ -11,9 +12,15 @@ namespace Org.BouncyCastle.Asn1.Tests public class InputStreamTest : SimpleTest { - private static readonly byte[] outOfBoundsLength = new byte[] { (byte)0x30, (byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff }; - private static readonly byte[] negativeLength = new byte[] { (byte)0x30, (byte)0x84, (byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff }; - private static readonly byte[] outsideLimitLength = new byte[] { (byte)0x30, (byte)0x83, (byte)0x0f, (byte)0xff, (byte)0xff }; + private static readonly byte[] outOfBoundsLength = new byte[] { (byte)0x30, (byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff }; + private static readonly byte[] negativeLength = new byte[] { (byte)0x30, (byte)0x84, (byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff }; + private static readonly byte[] outsideLimitLength = new byte[] { (byte)0x30, (byte)0x83, (byte)0x0f, (byte)0xff, (byte)0xff }; + + private static readonly byte[] classCast1 = Base64.Decode("p1AkHmYAvfOEIrL4ESfrNg=="); + private static readonly byte[] classCast2 = Base64.Decode("JICNbaBUTTq7uxj5mg=="); + private static readonly byte[] classCast3 = Base64.Decode("JAKzADNCxhrrBSVS"); + private static readonly byte[] memoryError1 = Base64.Decode("vm66gOiEe+FV/NvujMwSkUp5Lffw5caQlaRU5sdMPC70IGWmyK2/"); + private static readonly byte[] memoryError2 = Base64.Decode("vm4ogOSEfVGsS3w+KTzb2A0ALYR8VBOQqQeuRwnsPC4AAGWEDLjd"); public override string Name { @@ -46,7 +53,7 @@ namespace Org.BouncyCastle.Asn1.Tests } catch (IOException e) { - if (!e.Message.Equals("Corrupted stream - negative length found")) + if (!e.Message.Equals("corrupted stream - negative length found")) { Fail("wrong exception: " + e.Message); } @@ -61,12 +68,54 @@ namespace Org.BouncyCastle.Asn1.Tests } catch (IOException e) { - if (!e.Message.Equals("Corrupted stream - out of bounds length found")) - { + if (!e.Message.Equals("corrupted stream - out of bounds length found: 1048575 >= 5")) + { Fail("wrong exception: " + e.Message); } } - } + + DoTestWithByteArray(classCast1, "unknown object encountered: Org.BouncyCastle.Asn1.DerApplicationSpecific"); + DoTestWithByteArray(classCast2, "unknown object encountered: Org.BouncyCastle.Asn1.BerTaggedObjectParser"); + DoTestWithByteArray(classCast3, "unknown object encountered in constructed OCTET STRING: Org.BouncyCastle.Asn1.DerTaggedObject"); + + DoTestWithByteArray(memoryError1, "corrupted stream - out of bounds length found: 2078365180 >= 39"); + DoTestWithByteArray(memoryError2, "corrupted stream - out of bounds length found: 2102504523 >= 39"); + } + + private void DoTestWithByteArray(byte[] data, string message) + { + try + { + Asn1InputStream input = new Asn1InputStream(data); + + IAsn1Convertible p; + while ((p = input.ReadObject()) != null) + { + Asn1Sequence asn1 = Asn1Sequence.GetInstance(p); + for (int i = 0; i < asn1.Count; i++) + { + IAsn1Convertible c = asn1[i]; + } + } + } + catch (IOException e) + { + IsEquals(e.Message, message, e.Message); + } + // TODO Without InMemoryRepresentable, the IOException may be swapped/wrapped with an Asn1ParsingException + catch (Asn1ParsingException e) + { + Exception messageException = e; + + IOException ioe = e.InnerException as IOException; + if (ioe != null) + { + messageException = ioe; + } + + IsEquals(messageException.Message, message, messageException.Message); + } + } public static void Main( string[] args) diff --git a/crypto/test/src/asn1/test/PKCS12Test.cs b/crypto/test/src/asn1/test/PKCS12Test.cs index c20fa8cc6..5e4748728 100644 --- a/crypto/test/src/asn1/test/PKCS12Test.cs +++ b/crypto/test/src/asn1/test/PKCS12Test.cs @@ -114,9 +114,7 @@ namespace Org.BouncyCastle.Asn1.Tests public override void PerformTest() { - Asn1Sequence obj = (Asn1Sequence) Asn1Object.FromByteArray(pkcs12); - - Pfx bag = new Pfx(obj); + Pfx bag = Pfx.GetInstance(pkcs12); ContentInfo info = bag.AuthSafe; MacData mData = bag.MacData; DigestInfo dInfo = mData.Mac; @@ -124,9 +122,8 @@ namespace Org.BouncyCastle.Asn1.Tests byte[] salt = mData.GetSalt(); int itCount = mData.IterationCount.IntValue; - byte[] octets = ((Asn1OctetString) info.Content).GetOctets(); - AuthenticatedSafe authSafe = new AuthenticatedSafe( - (Asn1Sequence) Asn1Object.FromByteArray(octets)); + Asn1OctetString content = Asn1OctetString.GetInstance(info.Content); + AuthenticatedSafe authSafe = AuthenticatedSafe.GetInstance(content.GetOctets()); ContentInfo[] c = authSafe.GetContentInfo(); // @@ -137,10 +134,10 @@ namespace Org.BouncyCastle.Asn1.Tests Fail("Failed comparison data test"); } - octets = ((Asn1OctetString)c[0].Content).GetOctets(); - Asn1Sequence seq = (Asn1Sequence) Asn1Object.FromByteArray(octets); + Asn1OctetString authSafeContent = Asn1OctetString.GetInstance(c[0].Content); + Asn1Sequence seq = Asn1Sequence.GetInstance(authSafeContent.GetOctets()); - SafeBag b = new SafeBag((Asn1Sequence)seq[0]); + SafeBag b = SafeBag.GetInstance(seq[0]); if (!b.BagID.Equals(PkcsObjectIdentifiers.Pkcs8ShroudedKeyBag)) { Fail("Failed comparison shroudedKeyBag test"); @@ -152,9 +149,9 @@ namespace Org.BouncyCastle.Asn1.Tests b = new SafeBag(PkcsObjectIdentifiers.Pkcs8ShroudedKeyBag, encInfo.ToAsn1Object(), b.BagAttributes); - byte[] encodedBytes = new DerSequence(b).GetEncoded(); + byte[] contentOctets = new DerSequence(b).GetEncoded(); - c[0] = new ContentInfo(PkcsObjectIdentifiers.Data, new BerOctetString(encodedBytes)); + c[0] = new ContentInfo(PkcsObjectIdentifiers.Data, new BerOctetString(contentOctets)); // // certificates @@ -173,16 +170,19 @@ namespace Org.BouncyCastle.Asn1.Tests // authSafe = new AuthenticatedSafe(c); - info = new ContentInfo(PkcsObjectIdentifiers.Data, new BerOctetString(authSafe.GetEncoded())); + contentOctets = authSafe.GetEncoded(); + + info = new ContentInfo(PkcsObjectIdentifiers.Data, new BerOctetString(contentOctets)); - mData = new MacData(new DigestInfo(algId, dInfo.GetDigest()), salt, itCount); + mData = new MacData(new DigestInfo(algId, dInfo.GetDigest()), salt, itCount); bag = new Pfx(info, mData); // // comparison test // - if (!Arrays.AreEqual(bag.GetEncoded(), pkcs12)) + byte[] pfxEncoding = bag.GetEncoded(); + if (!Arrays.AreEqual(pfxEncoding, pkcs12)) { Fail("Failed comparison test"); } diff --git a/crypto/test/src/crypto/test/ChaCha20Poly1305Test.cs b/crypto/test/src/crypto/test/ChaCha20Poly1305Test.cs index 3f74669dc..9fade9a5e 100644 --- a/crypto/test/src/crypto/test/ChaCha20Poly1305Test.cs +++ b/crypto/test/src/crypto/test/ChaCha20Poly1305Test.cs @@ -193,7 +193,7 @@ namespace Org.BouncyCastle.Crypto.Tests SecureRandom random = new SecureRandom(); random.SetSeed(DateTimeUtilities.CurrentUnixMs()); - for (int i = 0; i < 10; ++i) + for (int i = 0; i < 100; ++i) { RandomTest(random); } @@ -205,8 +205,10 @@ namespace Org.BouncyCastle.Crypto.Tests byte[] K = new byte[kLength]; random.NextBytes(K); + int pHead = random.Next(256); int pLength = random.Next(65536); - byte[] P = new byte[pLength]; + int pTail = random.Next(256); + byte[] P = new byte[pHead + pLength + pTail]; random.NextBytes(P); int aLength = random.Next(256); @@ -223,28 +225,31 @@ namespace Org.BouncyCastle.Crypto.Tests AeadParameters parameters = new AeadParameters(new KeyParameter(K), 16 * 8, nonce, A); ChaCha20Poly1305 cipher = InitCipher(true, parameters); - byte[] C = new byte[cipher.GetOutputSize(P.Length)]; - int predicted = cipher.GetUpdateOutputSize(P.Length); - int split = NextInt(random, SA.Length + 1); - cipher.ProcessAadBytes(SA, 0, split); - cipher.ProcessAadBytes(SA, split, SA.Length - split); + int ctLength = cipher.GetOutputSize(pLength); + byte[] C = new byte[saLength + ctLength]; + Array.Copy(SA, 0, C, 0, saLength); - int len = cipher.ProcessBytes(P, 0, P.Length, C, 0); + int split = NextInt(random, saLength + 1); + cipher.ProcessAadBytes(C, 0, split); + cipher.ProcessAadBytes(C, split, saLength - split); + + int predicted = cipher.GetUpdateOutputSize(pLength); + int len = cipher.ProcessBytes(P, pHead, pLength, C, saLength); if (predicted != len) { Fail("encryption reported incorrect update length in randomised test"); } - len += cipher.DoFinal(C, len); - if (C.Length != len) + len += cipher.DoFinal(C, saLength + len); + if (ctLength != len) { Fail("encryption reported incorrect length in randomised test"); } byte[] encT = cipher.GetMac(); - byte[] tail = new byte[C.Length - P.Length]; - Array.Copy(C, P.Length, tail, 0, tail.Length); + byte[] tail = new byte[ctLength - pLength]; + Array.Copy(C, saLength + pLength, tail, 0, tail.Length); if (!AreEqual(encT, tail)) { @@ -252,22 +257,26 @@ namespace Org.BouncyCastle.Crypto.Tests } cipher.Init(false, parameters); - byte[] decP = new byte[cipher.GetOutputSize(C.Length)]; - predicted = cipher.GetUpdateOutputSize(C.Length); - split = NextInt(random, SA.Length + 1); - cipher.ProcessAadBytes(SA, 0, split); - cipher.ProcessAadBytes(SA, split, SA.Length - split); + int decPHead = random.Next(256); + int decPLength = cipher.GetOutputSize(ctLength); + int decPTail = random.Next(256); + byte[] decP = new byte[decPHead + decPLength + decPTail]; + + split = NextInt(random, saLength + 1); + cipher.ProcessAadBytes(C, 0, split); + cipher.ProcessAadBytes(C, split, saLength - split); - len = cipher.ProcessBytes(C, 0, C.Length, decP, 0); + predicted = cipher.GetUpdateOutputSize(ctLength); + len = cipher.ProcessBytes(C, saLength, ctLength, decP, decPHead); if (predicted != len) { Fail("decryption reported incorrect update length in randomised test"); } - len += cipher.DoFinal(decP, len); + len += cipher.DoFinal(decP, decPHead + len); - if (!AreEqual(P, decP)) + if (!AreEqual(P, pHead, pHead + pLength, decP, decPHead, decPHead + decPLength)) { Fail("incorrect decrypt in randomised test"); } @@ -282,16 +291,20 @@ namespace Org.BouncyCastle.Crypto.Tests // key reuse test // cipher.Init(false, AeadTestUtilities.ReuseKey(parameters)); - decP = new byte[cipher.GetOutputSize(C.Length)]; - split = NextInt(random, SA.Length + 1); - cipher.ProcessAadBytes(SA, 0, split); - cipher.ProcessAadBytes(SA, split, SA.Length - split); + decPHead = random.Next(256); + decPLength = cipher.GetOutputSize(ctLength); + decPTail = random.Next(256); + decP = new byte[decPHead + decPLength + decPTail]; + + split = NextInt(random, saLength + 1); + cipher.ProcessAadBytes(C, 0, split); + cipher.ProcessAadBytes(C, split, saLength - split); - len = cipher.ProcessBytes(C, 0, C.Length, decP, 0); - len += cipher.DoFinal(decP, len); + len = cipher.ProcessBytes(C, saLength, ctLength, decP, decPHead); + len += cipher.DoFinal(decP, decPHead + len); - if (!AreEqual(P, decP)) + if (!AreEqual(P, pHead, pHead + pLength, decP, decPHead, decPHead + decPLength)) { Fail("incorrect decrypt in randomised test"); } diff --git a/crypto/test/src/openssl/test/ReaderTest.cs b/crypto/test/src/openssl/test/ReaderTest.cs index a7efb6004..2e270ddc1 100644 --- a/crypto/test/src/openssl/test/ReaderTest.cs +++ b/crypto/test/src/openssl/test/ReaderTest.cs @@ -185,8 +185,8 @@ namespace Org.BouncyCastle.OpenSsl.Tests doOpenSslDsaTest("rc2_64_cbc"); doOpenSslRsaTest("rc2_64_cbc"); - doDudPasswordTest("7fd98", 0, "Corrupted stream - out of bounds length found"); - doDudPasswordTest("ef677", 1, "Corrupted stream - out of bounds length found"); + doDudPasswordTest("7fd98", 0, "corrupted stream - out of bounds length found: 599005160 >= 447"); + doDudPasswordTest("ef677", 1, "corrupted stream - out of bounds length found: 2087569732 >= 447"); doDudPasswordTest("800ce", 2, "unknown tag 26 encountered"); doDudPasswordTest("b6cd8", 3, "DEF length 81 object truncated by 56"); doDudPasswordTest("28ce09", 4, "DEF length 110 object truncated by 28"); @@ -202,7 +202,7 @@ namespace Org.BouncyCastle.OpenSsl.Tests doDudPasswordTest("5a3d16", 14, "corrupted stream detected"); doDudPasswordTest("8d0c97", 15, "corrupted stream detected"); doDudPasswordTest("bc0daf", 16, "corrupted stream detected"); - doDudPasswordTest("aaf9c4d",17, "Corrupted stream - out of bounds length found"); + doDudPasswordTest("aaf9c4d", 17, "corrupted stream - out of bounds length found: 1580418590 >= 447"); // encrypted private key test pGet = new Password("password".ToCharArray()); diff --git a/crypto/test/src/pkcs/test/PKCS12StoreTest.cs b/crypto/test/src/pkcs/test/PKCS12StoreTest.cs index cd9dfcfad..9db1a6651 100644 --- a/crypto/test/src/pkcs/test/PKCS12StoreTest.cs +++ b/crypto/test/src/pkcs/test/PKCS12StoreTest.cs @@ -398,6 +398,26 @@ namespace Org.BouncyCastle.Pkcs.Tests + "AHoAeQB0AGsAbwB3AG4AaQBrAGEwMTAhMAkGBSsOAwIaBQAEFKJpUOIj0OtI" + "j2CPp38YIFBEqvjsBAi8G+yhJe3A/wICCAA="); + private static readonly byte[] certsOnly = Base64.Decode( + "MIICnwIBAzCCApgGCSqGSIb3DQEHAaCCAokEggKFMIICgTCCAn0GCSqGSIb3" + + "DQEHAaCCAm4EggJqMIICZjCCAmIGCyqGSIb3DQEMCgEDoIICHDCCAhgGCiq" + + "GSIb3DQEJFgGgggIIBIICBDCCAgAwggFpoAMCAQICBHcheqIwDQYJKoZIhv" + + "cNAQELBQAwMjENMAsGA1UEChMERGVtbzENMAsGA1UECxMERGVtbzESMBAGA" + + "1UEAxMJRGVtbyBjZXJ0MCAXDTE5MDgzMTEzMDgzNloYDzIxMDkwNTE5MTMw" + + "ODM2WjAyMQ0wCwYDVQQKEwREZW1vMQ0wCwYDVQQLEwREZW1vMRIwEAYDVQQ" + + "DEwlEZW1vIGNlcnQwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAKOVC4" + + "Qeg0KPAPRB9WcZdvXitiJ+E6rd3czQGNzEFC6FesAllH3PHSWuUZ2YjhiVM" + + "YJyzwVP1II04iCRaIc65R45oVrHZ2ybWAOda2hBtySjQ2pIQQpoKE7nvL3j" + + "JcHoCIBJVf3c3xpfh7RucCOGiZDjU9CYPG8yznsazb5+fPF/AgMBAAGjITA" + + "fMB0GA1UdDgQWBBR/7wUDwa7T0vNzNgjOKdjz2Up9RzANBgkqhkiG9w0BAQ" + + "sFAAOBgQADzPFsaLhVYD/k9qMueYKi8Ftwijr37niF98cgAHEtq6TGsh3Se" + + "8gEK3dNJL18vm7NXgGsl8jUWsE9hCF9ar+/cDZ+KrZlZ5PLfifXJJKFqVAh" + + "sOORef0NRIVcTCoyQTW4pNpNZP9Ul5LJ3iIDjafgJMyEkRbavqdyfSqVTvY" + + "NpjEzMBkGCSqGSIb3DQEJFDEMHgoAYQBsAGkAYQBzMBYGDGCGSAGG+Watyn" + + "sBATEGBgRVHSUA"); + + private readonly SecureRandom Random = new SecureRandom(); + /** * we generate a self signed certificate for the sake of testing - RSA */ @@ -451,7 +471,43 @@ namespace Org.BouncyCastle.Pkcs.Tests return new X509CertificateEntry(certGen.Generate(privKey)); } - public void doTestPkcs12Store() + private void DoTestCertsOnly() + { + Pkcs12Store pkcs12 = new Pkcs12StoreBuilder().Build(); + + pkcs12.Load(new MemoryStream(certsOnly, false), null); + + IsTrue(pkcs12.ContainsAlias("alias")); + + MemoryStream bOut = new MemoryStream(); + + pkcs12.Save(bOut, null, Random); + + pkcs12 = new Pkcs12StoreBuilder().Build(); + + pkcs12.Load(new MemoryStream(bOut.ToArray(), false), null); + + IsTrue(pkcs12.ContainsAlias("alias")); + + try + { + pkcs12.Load(new MemoryStream(certsOnly, false), "1".ToCharArray()); + Fail("no exception"); + } + catch (IOException e) + { + IsEquals("password supplied for keystore that does not require one", e.Message); + } + + // TODO Modify environment variables in tests? + //System.setProperty(Pkcs12Store.IgnoreUselessPasswordProperty, "true"); + + //pkcs12.Load(new MemoryStream(certsOnly, false), "1".ToCharArray()); + + //System.setProperty(Pkcs12Store.IgnoreUselessPasswordProperty, "false"); + } + + private void DoTestPkcs12Store() { BigInteger mod = new BigInteger("bb1be8074e4787a8d77967f1575ef72dd7582f9b3347724413c021beafad8f32dba5168e280cbf284df722283dad2fd4abc750e3d6487c2942064e2d8d80641aa5866d1f6f1f83eec26b9b46fecb3b1c9856a303148a5cc899c642fb16f3d9d72f52526c751dc81622c420c82e2cfda70fe8d13f16cc7d6a613a5b2a2b5894d1", 16); @@ -502,7 +558,7 @@ namespace Org.BouncyCastle.Pkcs.Tests // save test // MemoryStream bOut = new MemoryStream(); - store.Save(bOut, passwd, new SecureRandom()); + store.Save(bOut, passwd, Random); stream = new MemoryStream(bOut.ToArray(), false); store.Load(stream, passwd); @@ -589,8 +645,8 @@ namespace Org.BouncyCastle.Pkcs.Tests } MemoryStream store1Stream = new MemoryStream(); - store.Save(store1Stream, passwd, new SecureRandom()); - testNoExtraLocalKeyID(store1Stream.ToArray()); + store.Save(store1Stream, passwd, Random); + DoTestNoExtraLocalKeyID(store1Stream.ToArray()); // // no friendly name test @@ -655,7 +711,7 @@ namespace Org.BouncyCastle.Pkcs.Tests Fail("Certificate chain wrong length"); } - store.Save(new MemoryStream(), storagePassword, new SecureRandom()); + store.Save(new MemoryStream(), storagePassword, Random); // // basic certificate check @@ -741,7 +797,7 @@ namespace Org.BouncyCastle.Pkcs.Tests store.Load(stream, "".ToCharArray()); } - private void testSupportedTypes(AsymmetricKeyEntry privKey, X509CertificateEntry[] chain) + private void DoTestSupportedTypes(AsymmetricKeyEntry privKey, X509CertificateEntry[] chain) { basicStoreTest(privKey, chain, PkcsObjectIdentifiers.PbeWithShaAnd3KeyTripleDesCbc, @@ -763,7 +819,7 @@ namespace Org.BouncyCastle.Pkcs.Tests MemoryStream bOut = new MemoryStream(); - store.Save(bOut, passwd, new SecureRandom()); + store.Save(bOut, passwd, Random); store.Load(new MemoryStream(bOut.ToArray(), false), passwd); @@ -851,11 +907,11 @@ namespace Org.BouncyCastle.Pkcs.Tests } } - private void testNoExtraLocalKeyID(byte[] store1data) + private void DoTestNoExtraLocalKeyID(byte[] store1data) { IAsymmetricCipherKeyPairGenerator kpg = GeneratorUtilities.GetKeyPairGenerator("RSA"); kpg.Init(new RsaKeyGenerationParameters( - BigInteger.ValueOf(0x10001), new SecureRandom(), 512, 25)); + BigInteger.ValueOf(0x10001), Random, 512, 25)); AsymmetricCipherKeyPair newPair = kpg.GenerateKeyPair(); @@ -882,7 +938,7 @@ namespace Org.BouncyCastle.Pkcs.Tests MemoryStream bOut = new MemoryStream(); - store2.Save(bOut, passwd, new SecureRandom()); + store2.Save(bOut, passwd, Random); store2.Load(new MemoryStream(bOut.ToArray(), false), passwd); @@ -901,7 +957,8 @@ namespace Org.BouncyCastle.Pkcs.Tests public override void PerformTest() { - doTestPkcs12Store(); + DoTestCertsOnly(); + DoTestPkcs12Store(); } public static void Main( diff --git a/crypto/test/src/tsp/test/TimeStampTokenInfoTest.cs b/crypto/test/src/tsp/test/TimeStampTokenInfoTest.cs index 5a26f5ef6..ea7f2c4dc 100644 --- a/crypto/test/src/tsp/test/TimeStampTokenInfoTest.cs +++ b/crypto/test/src/tsp/test/TimeStampTokenInfoTest.cs @@ -28,7 +28,7 @@ namespace Org.BouncyCastle.Tsp.Tests private static readonly byte[] tstInfoDudDate = Hex.Decode( "303e02010106022a033021300906052b0e03021a050004140000000000000000000000000000000000000000" - + "020118180f32303056313130313038313732315a"); + + "020118180f32303030563130313038313732315a"); [Test] public void TestTstInfo1() diff --git a/crypto/test/src/util/io/pem/test/AllTests.cs b/crypto/test/src/util/io/pem/test/AllTests.cs index 921c40cb8..c0ca667f5 100644 --- a/crypto/test/src/util/io/pem/test/AllTests.cs +++ b/crypto/test/src/util/io/pem/test/AllTests.cs @@ -63,6 +63,14 @@ namespace Org.BouncyCastle.Utilities.IO.Pem.Tests lengthTest("RSA PRIVATE KEY", headers, new byte[103]); } + [Test] + public void TestMalformed() + { + PemReader rd = new PemReader(new StringReader("-----BEGIN \n")); + + Assert.IsNull(rd.ReadPemObject()); + } + private void lengthTest(string type, IList headers, byte[] data) { StringWriter sw = new StringWriter(); diff --git a/crypto/test/src/util/test/SimpleTest.cs b/crypto/test/src/util/test/SimpleTest.cs index 2e24964e2..89df289c6 100644 --- a/crypto/test/src/util/test/SimpleTest.cs +++ b/crypto/test/src/util/test/SimpleTest.cs @@ -91,12 +91,15 @@ namespace Org.BouncyCastle.Utilities.Test throw new TestFailedException(SimpleTestResult.Failed(this, message)); } - internal bool AreEqual( - byte[] a, - byte[] b) + internal bool AreEqual(byte[] a, byte[] b) { - return Arrays.AreEqual(a, b); - } + return Arrays.AreEqual(a, b); + } + + internal bool AreEqual(byte[] a, int aFromIndex, int aToIndex, byte[] b, int bFromIndex, int bToIndex) + { + return Arrays.AreEqual(a, aFromIndex, aToIndex, b, bFromIndex, bToIndex); + } public virtual ITestResult Perform() { |