diff options
author | Peter Dettman <peter.dettman@bouncycastle.org> | 2019-08-10 00:18:03 +0700 |
---|---|---|
committer | Peter Dettman <peter.dettman@bouncycastle.org> | 2019-08-10 00:18:03 +0700 |
commit | 9c6880706476c6066b9aa2ce82c159d64c8766c6 (patch) | |
tree | 092fb747c1e8d483d4e611e08a1e648f9d864620 /crypto/src/asn1 | |
parent | Use utility method (diff) | |
download | BouncyCastle.NET-ed25519-9c6880706476c6066b9aa2ce82c159d64c8766c6.tar.xz |
Add and use IntValueExact properties
Diffstat (limited to 'crypto/src/asn1')
20 files changed, 179 insertions, 101 deletions
diff --git a/crypto/src/asn1/DerEnumerated.cs b/crypto/src/asn1/DerEnumerated.cs index 1344926bd..8654a3bfd 100644 --- a/crypto/src/asn1/DerEnumerated.cs +++ b/crypto/src/asn1/DerEnumerated.cs @@ -9,6 +9,7 @@ namespace Org.BouncyCastle.Asn1 : Asn1Object { private readonly byte[] bytes; + private readonly int start; /** * return an integer from the passed in object @@ -54,7 +55,17 @@ namespace Org.BouncyCastle.Asn1 if (val < 0) throw new ArgumentException("enumerated must be non-negative", "val"); - bytes = BigInteger.ValueOf(val).ToByteArray(); + this.bytes = BigInteger.ValueOf(val).ToByteArray(); + this.start = 0; + } + + public DerEnumerated(long val) + { + if (val < 0L) + throw new ArgumentException("enumerated must be non-negative", "val"); + + this.bytes = BigInteger.ValueOf(val).ToByteArray(); + this.start = 0; } public DerEnumerated(BigInteger val) @@ -62,7 +73,8 @@ namespace Org.BouncyCastle.Asn1 if (val.SignValue < 0) throw new ArgumentException("enumerated must be non-negative", "val"); - bytes = val.ToByteArray(); + this.bytes = val.ToByteArray(); + this.start = 0; } public DerEnumerated(byte[] bytes) @@ -73,6 +85,7 @@ namespace Org.BouncyCastle.Asn1 throw new ArgumentException("enumerated must be non-negative", "bytes"); this.bytes = Arrays.Clone(bytes); + this.start = DerInteger.SignBytesToSkip(bytes); } public BigInteger Value @@ -80,17 +93,34 @@ namespace Org.BouncyCastle.Asn1 get { return new BigInteger(bytes); } } - internal override void Encode( - DerOutputStream derOut) + public bool HasValue(BigInteger x) + { + return null != x + // Fast check to avoid allocation + && DerInteger.IntValue(bytes, start, DerInteger.SignExtSigned) == x.IntValue + && Value.Equals(x); + } + + public int IntValueExact + { + get + { + int count = bytes.Length - start; + if (count > 4) + throw new ArithmeticException("ASN.1 Enumerated out of int range"); + + return DerInteger.IntValue(bytes, start, DerInteger.SignExtSigned); + } + } + + internal override void Encode(DerOutputStream derOut) { derOut.WriteEncoded(Asn1Tags.Enumerated, bytes); } - protected override bool Asn1Equals( - Asn1Object asn1Object) + protected override bool Asn1Equals(Asn1Object asn1Object) { DerEnumerated other = asn1Object as DerEnumerated; - if (other == null) return false; @@ -106,27 +136,21 @@ namespace Org.BouncyCastle.Asn1 internal static DerEnumerated FromOctetString(byte[] enc) { + if (enc.Length > 1) + return new DerEnumerated(enc); if (enc.Length == 0) - { throw new ArgumentException("ENUMERATED has zero length", "enc"); - } - if (enc.Length == 1) + int value = enc[0]; + if (value >= cache.Length) + return new DerEnumerated(enc); + + DerEnumerated possibleMatch = cache[value]; + if (possibleMatch == null) { - int value = enc[0]; - if (value < cache.Length) - { - DerEnumerated cached = cache[value]; - if (cached != null) - { - return cached; - } - - return cache[value] = new DerEnumerated(Arrays.Clone(enc)); - } + cache[value] = possibleMatch = new DerEnumerated(enc); } - - return new DerEnumerated(Arrays.Clone(enc)); + return possibleMatch; } } } diff --git a/crypto/src/asn1/DerInteger.cs b/crypto/src/asn1/DerInteger.cs index fec7b9420..3e19a07b6 100644 --- a/crypto/src/asn1/DerInteger.cs +++ b/crypto/src/asn1/DerInteger.cs @@ -16,7 +16,11 @@ namespace Org.BouncyCastle.Asn1 return allowUnsafeValue != null && Platform.EqualsIgnoreCase("true", allowUnsafeValue); } + internal const int SignExtSigned = -1; + internal const int SignExtUnsigned = 0xFF; + private readonly byte[] bytes; + private readonly int start; /** * return an integer from the passed in object @@ -62,7 +66,14 @@ namespace Org.BouncyCastle.Asn1 public DerInteger(int value) { - bytes = BigInteger.ValueOf(value).ToByteArray(); + this.bytes = BigInteger.ValueOf(value).ToByteArray(); + this.start = 0; + } + + public DerInteger(long value) + { + this.bytes = BigInteger.ValueOf(value).ToByteArray(); + this.start = 0; } public DerInteger(BigInteger value) @@ -70,7 +81,8 @@ namespace Org.BouncyCastle.Asn1 if (value == null) throw new ArgumentNullException("value"); - bytes = value.ToByteArray(); + this.bytes = value.ToByteArray(); + this.start = 0; } public DerInteger(byte[] bytes) @@ -84,6 +96,7 @@ namespace Org.BouncyCastle.Asn1 throw new ArgumentException("malformed integer", "bytes"); this.bytes = clone ? Arrays.Clone(bytes) : bytes; + this.start = SignBytesToSkip(bytes); } /** @@ -100,8 +113,39 @@ namespace Org.BouncyCastle.Asn1 get { return new BigInteger(bytes); } } - internal override void Encode( - DerOutputStream derOut) + public bool HasValue(BigInteger x) + { + return null != x + // Fast check to avoid allocation + && IntValue(bytes, start, SignExtSigned) == x.IntValue + && Value.Equals(x); + } + + public int IntPositiveValueExact + { + get + { + int count = bytes.Length - start; + if (count > 4 || (count == 4 && 0 != (bytes[start] & 0x80))) + throw new ArithmeticException("ASN.1 Integer out of positive int range"); + + return IntValue(bytes, start, SignExtUnsigned); + } + } + + public int IntValueExact + { + get + { + int count = bytes.Length - start; + if (count > 4) + throw new ArithmeticException("ASN.1 Integer out of int range"); + + return IntValue(bytes, start, SignExtSigned); + } + } + + internal override void Encode(DerOutputStream derOut) { derOut.WriteEncoded(Asn1Tags.Integer, bytes); } @@ -111,15 +155,13 @@ namespace Org.BouncyCastle.Asn1 return Arrays.GetHashCode(bytes); } - protected override bool Asn1Equals( - Asn1Object asn1Object) + protected override bool Asn1Equals(Asn1Object asn1Object) { DerInteger other = asn1Object as DerInteger; - if (other == null) return false; - return Arrays.AreEqual(this.bytes, other.bytes); + return Arrays.AreEqual(this.bytes, other.bytes); } public override string ToString() @@ -127,6 +169,19 @@ namespace Org.BouncyCastle.Asn1 return Value.ToString(); } + internal static int IntValue(byte[] bytes, int start, int signExt) + { + int length = bytes.Length; + int pos = System.Math.Max(start, length - 4); + + int 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. * @@ -145,5 +200,16 @@ namespace Org.BouncyCastle.Asn1 return (sbyte)bytes[0] == ((sbyte)bytes[1] >> 7) && !AllowUnsafe(); } } + + internal static int SignBytesToSkip(byte[] bytes) + { + int pos = 0, last = bytes.Length - 1; + while (pos < last + && (sbyte)bytes[pos] == ((sbyte)bytes[pos + 1] >> 7)) + { + ++pos; + } + return pos; + } } } diff --git a/crypto/src/asn1/cms/EnvelopedData.cs b/crypto/src/asn1/cms/EnvelopedData.cs index 41dae548f..fbde00b28 100644 --- a/crypto/src/asn1/cms/EnvelopedData.cs +++ b/crypto/src/asn1/cms/EnvelopedData.cs @@ -154,7 +154,7 @@ namespace Org.BouncyCastle.Asn1.Cms { RecipientInfo ri = RecipientInfo.GetInstance(o); - if (ri.Version.Value.IntValue != 0) + if (ri.Version.IntValueExact != 0) { return 2; } diff --git a/crypto/src/asn1/cms/SignedData.cs b/crypto/src/asn1/cms/SignedData.cs index 957b81cd8..dfc1e2829 100644 --- a/crypto/src/asn1/cms/SignedData.cs +++ b/crypto/src/asn1/cms/SignedData.cs @@ -150,7 +150,7 @@ namespace Org.BouncyCastle.Asn1.Cms { SignerInfo s = SignerInfo.GetInstance(obj); - if (s.Version.Value.IntValue == 3) + if (s.Version.IntValueExact == 3) { return true; } diff --git a/crypto/src/asn1/crmf/CertTemplate.cs b/crypto/src/asn1/crmf/CertTemplate.cs index 3de9f1d5a..f731ac12e 100644 --- a/crypto/src/asn1/crmf/CertTemplate.cs +++ b/crypto/src/asn1/crmf/CertTemplate.cs @@ -77,7 +77,7 @@ namespace Org.BouncyCastle.Asn1.Crmf public virtual int Version { - get { return version.Value.IntValue; } + get { return version.IntValueExact; } } public virtual DerInteger SerialNumber diff --git a/crypto/src/asn1/crmf/PopoPrivKey.cs b/crypto/src/asn1/crmf/PopoPrivKey.cs index 0cedc5127..2b38cb109 100644 --- a/crypto/src/asn1/crmf/PopoPrivKey.cs +++ b/crypto/src/asn1/crmf/PopoPrivKey.cs @@ -26,7 +26,7 @@ namespace Org.BouncyCastle.Asn1.Crmf this.obj = DerBitString.GetInstance(obj, false); break; case subsequentMessage: - this.obj = SubsequentMessage.ValueOf(DerInteger.GetInstance(obj, false).Value.IntValue); + this.obj = SubsequentMessage.ValueOf(DerInteger.GetInstance(obj, false).IntValueExact); break; case dhMAC: this.obj = DerBitString.GetInstance(obj, false); diff --git a/crypto/src/asn1/cryptopro/GOST3410ParamSetParameters.cs b/crypto/src/asn1/cryptopro/GOST3410ParamSetParameters.cs index b347f8dbd..ee6ed8c99 100644 --- a/crypto/src/asn1/cryptopro/GOST3410ParamSetParameters.cs +++ b/crypto/src/asn1/cryptopro/GOST3410ParamSetParameters.cs @@ -53,7 +53,7 @@ namespace Org.BouncyCastle.Asn1.CryptoPro if (seq.Count != 4) throw new ArgumentException("Wrong number of elements in sequence", "seq"); - this.keySize = DerInteger.GetInstance(seq[0]).Value.IntValue; + this.keySize = DerInteger.GetInstance(seq[0]).IntValueExact; this.p = DerInteger.GetInstance(seq[1]); this.q = DerInteger.GetInstance(seq[2]); this.a = DerInteger.GetInstance(seq[3]); diff --git a/crypto/src/asn1/icao/CscaMasterList.cs b/crypto/src/asn1/icao/CscaMasterList.cs index 6890d8a2e..d03b3adb4 100644 --- a/crypto/src/asn1/icao/CscaMasterList.cs +++ b/crypto/src/asn1/icao/CscaMasterList.cs @@ -62,7 +62,7 @@ namespace Org.BouncyCastle.Asn1.Icao public virtual int Version { - get { return version.Value.IntValue; } + get { return version.IntValueExact; } } public X509CertificateStructure[] GetCertStructs() diff --git a/crypto/src/asn1/icao/DataGroupHash.cs b/crypto/src/asn1/icao/DataGroupHash.cs index e0d7eee7b..bf83718f3 100644 --- a/crypto/src/asn1/icao/DataGroupHash.cs +++ b/crypto/src/asn1/icao/DataGroupHash.cs @@ -70,7 +70,7 @@ namespace Org.BouncyCastle.Asn1.Icao public int DataGroupNumber { - get { return dataGroupNumber.Value.IntValue; } + get { return dataGroupNumber.IntValueExact; } } public Asn1OctetString DataGroupHashValue diff --git a/crypto/src/asn1/isismtt/x509/DeclarationOfMajority.cs b/crypto/src/asn1/isismtt/x509/DeclarationOfMajority.cs index c4ebb2b72..b82c9373d 100644 --- a/crypto/src/asn1/isismtt/x509/DeclarationOfMajority.cs +++ b/crypto/src/asn1/isismtt/x509/DeclarationOfMajority.cs @@ -134,7 +134,7 @@ namespace Org.BouncyCastle.Asn1.IsisMtt.X509 switch ((Choice) declaration.TagNo) { case Choice.NotYoungerThan: - return DerInteger.GetInstance(declaration, false).Value.IntValue; + return DerInteger.GetInstance(declaration, false).IntValueExact; default: return -1; } diff --git a/crypto/src/asn1/misc/CAST5CBCParameters.cs b/crypto/src/asn1/misc/CAST5CBCParameters.cs index 51fd6607a..7bd9f1ec6 100644 --- a/crypto/src/asn1/misc/CAST5CBCParameters.cs +++ b/crypto/src/asn1/misc/CAST5CBCParameters.cs @@ -52,7 +52,7 @@ namespace Org.BouncyCastle.Asn1.Misc public int KeyLength { - get { return keyLength.Value.IntValue; } + get { return keyLength.IntValueExact; } } /** diff --git a/crypto/src/asn1/ocsp/OCSPResponseStatus.cs b/crypto/src/asn1/ocsp/OCSPResponseStatus.cs index 653317e33..cf52c73e4 100644 --- a/crypto/src/asn1/ocsp/OCSPResponseStatus.cs +++ b/crypto/src/asn1/ocsp/OCSPResponseStatus.cs @@ -34,7 +34,7 @@ namespace Org.BouncyCastle.Asn1.Ocsp } public OcspResponseStatus(DerEnumerated value) - : base(value.Value.IntValue) + : base(value.IntValueExact) { } } diff --git a/crypto/src/asn1/pkcs/EncryptedData.cs b/crypto/src/asn1/pkcs/EncryptedData.cs index 7e95eb586..6a4c04f25 100644 --- a/crypto/src/asn1/pkcs/EncryptedData.cs +++ b/crypto/src/asn1/pkcs/EncryptedData.cs @@ -52,7 +52,7 @@ namespace Org.BouncyCastle.Asn1.Pkcs if (seq.Count != 2) throw new ArgumentException("Wrong number of elements in sequence", "seq"); - int version = ((DerInteger) seq[0]).Value.IntValue; + int version = ((DerInteger)seq[0]).IntValueExact; if (version != 0) { throw new ArgumentException("sequence not version 0"); diff --git a/crypto/src/asn1/tsp/Accuracy.cs b/crypto/src/asn1/tsp/Accuracy.cs index 9da8f1d68..31289db99 100644 --- a/crypto/src/asn1/tsp/Accuracy.cs +++ b/crypto/src/asn1/tsp/Accuracy.cs @@ -22,26 +22,22 @@ namespace Org.BouncyCastle.Asn1.Tsp DerInteger millis, DerInteger micros) { - //Verifications - if (millis != null - && (millis.Value.IntValue < MinMillis - || millis.Value.IntValue > MaxMillis)) - { - throw new ArgumentException( - "Invalid millis field : not in (1..999)"); - } - - if (micros != null - && (micros.Value.IntValue < MinMicros - || micros.Value.IntValue > MaxMicros)) - { - throw new ArgumentException( - "Invalid micros field : not in (1..999)"); - } + if (null != millis) + { + int millisValue = millis.IntValueExact; + if (millisValue < MinMillis || millisValue > MaxMillis) + throw new ArgumentException("Invalid millis field : not in (1..999)"); + } + if (null != micros) + { + int microsValue = micros.IntValueExact; + if (microsValue < MinMicros || microsValue > MaxMicros) + throw new ArgumentException("Invalid micros field : not in (1..999)"); + } - this.seconds = seconds; - this.millis = millis; - this.micros = micros; + this.seconds = seconds; + this.millis = millis; + this.micros = micros; } private Accuracy( @@ -58,29 +54,23 @@ namespace Org.BouncyCastle.Asn1.Tsp { Asn1TaggedObject extra = (Asn1TaggedObject)seq[i]; - switch (extra.TagNo) - { - case 0: - millis = DerInteger.GetInstance(extra, false); - if (millis.Value.IntValue < MinMillis - || millis.Value.IntValue > MaxMillis) - { - throw new ArgumentException( - "Invalid millis field : not in (1..999)."); - } - break; - case 1: - micros = DerInteger.GetInstance(extra, false); - if (micros.Value.IntValue < MinMicros - || micros.Value.IntValue > MaxMicros) - { - throw new ArgumentException( - "Invalid micros field : not in (1..999)."); - } - break; - default: - throw new ArgumentException("Invalig tag number"); - } + switch (extra.TagNo) + { + case 0: + millis = DerInteger.GetInstance(extra, false); + int millisValue = millis.IntValueExact; + if (millisValue < MinMillis || millisValue > MaxMillis) + throw new ArgumentException("Invalid millis field : not in (1..999)"); + break; + case 1: + micros = DerInteger.GetInstance(extra, false); + int microsValue = micros.IntValueExact; + if (microsValue < MinMicros || microsValue > MaxMicros) + throw new ArgumentException("Invalid micros field : not in (1..999)"); + break; + default: + throw new ArgumentException("Invalid tag number"); + } } } } diff --git a/crypto/src/asn1/x509/CRLReason.cs b/crypto/src/asn1/x509/CRLReason.cs index e8eb53a59..050ceb3bd 100644 --- a/crypto/src/asn1/x509/CRLReason.cs +++ b/crypto/src/asn1/x509/CRLReason.cs @@ -45,15 +45,14 @@ namespace Org.BouncyCastle.Asn1.X509 { } - public CrlReason( - DerEnumerated reason) - : base(reason.Value.IntValue) + public CrlReason(DerEnumerated reason) + : base(reason.IntValueExact) { } public override string ToString() { - int reason = Value.IntValue; + int reason = IntValueExact; string str = (reason < 0 || reason > 10) ? "Invalid" : ReasonString[reason]; return "CrlReason: " + str; } diff --git a/crypto/src/asn1/x509/TBSCertList.cs b/crypto/src/asn1/x509/TBSCertList.cs index 2b3646052..a427ba2ba 100644 --- a/crypto/src/asn1/x509/TBSCertList.cs +++ b/crypto/src/asn1/x509/TBSCertList.cs @@ -207,7 +207,7 @@ namespace Org.BouncyCastle.Asn1.X509 public int Version { - get { return version.Value.IntValue + 1; } + get { return version.IntValueExact + 1; } } public DerInteger VersionNumber diff --git a/crypto/src/asn1/x509/TBSCertificateStructure.cs b/crypto/src/asn1/x509/TBSCertificateStructure.cs index 8f091087e..4e3c789e2 100644 --- a/crypto/src/asn1/x509/TBSCertificateStructure.cs +++ b/crypto/src/asn1/x509/TBSCertificateStructure.cs @@ -153,7 +153,7 @@ namespace Org.BouncyCastle.Asn1.X509 public int Version { - get { return version.Value.IntValue + 1; } + get { return version.IntValueExact + 1; } } public DerInteger VersionNumber diff --git a/crypto/src/asn1/x509/qualified/Iso4217CurrencyCode.cs b/crypto/src/asn1/x509/qualified/Iso4217CurrencyCode.cs index 9ec88f5ed..a90a33ae2 100644 --- a/crypto/src/asn1/x509/qualified/Iso4217CurrencyCode.cs +++ b/crypto/src/asn1/x509/qualified/Iso4217CurrencyCode.cs @@ -35,7 +35,7 @@ namespace Org.BouncyCastle.Asn1.X509.Qualified if (obj is DerInteger) { DerInteger numericobj = DerInteger.GetInstance(obj); - int numeric = numericobj.Value.IntValue; + int numeric = numericobj.IntValueExact; return new Iso4217CurrencyCode(numeric); } @@ -74,7 +74,7 @@ namespace Org.BouncyCastle.Asn1.X509.Qualified public string Alphabetic { get { return ((DerPrintableString) obj).GetString(); } } - public int Numeric { get { return ((DerInteger)obj).Value.IntValue; } } + public int Numeric { get { return ((DerInteger)obj).IntValueExact; } } public override Asn1Object ToAsn1Object() { diff --git a/crypto/src/asn1/x509/qualified/TypeOfBiometricData.cs b/crypto/src/asn1/x509/qualified/TypeOfBiometricData.cs index 17b7841c3..a4e2e4555 100644 --- a/crypto/src/asn1/x509/qualified/TypeOfBiometricData.cs +++ b/crypto/src/asn1/x509/qualified/TypeOfBiometricData.cs @@ -35,7 +35,7 @@ namespace Org.BouncyCastle.Asn1.X509.Qualified if (obj is DerInteger) { DerInteger predefinedBiometricTypeObj = DerInteger.GetInstance(obj); - int predefinedBiometricType = predefinedBiometricTypeObj.Value.IntValue; + int predefinedBiometricType = predefinedBiometricTypeObj.IntValueExact; return new TypeOfBiometricData(predefinedBiometricType); } @@ -75,7 +75,7 @@ namespace Org.BouncyCastle.Asn1.X509.Qualified public int PredefinedBiometricType { - get { return ((DerInteger) obj).Value.IntValue; } + get { return ((DerInteger)obj).IntValueExact; } } public DerObjectIdentifier BiometricDataOid diff --git a/crypto/src/asn1/x9/X9Curve.cs b/crypto/src/asn1/x9/X9Curve.cs index eab94def8..0be9bf935 100644 --- a/crypto/src/asn1/x9/X9Curve.cs +++ b/crypto/src/asn1/x9/X9Curve.cs @@ -79,9 +79,8 @@ namespace Org.BouncyCastle.Asn1.X9 { // Characteristic two field DerSequence parameters = (DerSequence)fieldID.Parameters; - int m = ((DerInteger)parameters[0]).Value.IntValue; - DerObjectIdentifier representation - = (DerObjectIdentifier)parameters[1]; + int m = ((DerInteger)parameters[0]).IntValueExact; + DerObjectIdentifier representation = (DerObjectIdentifier)parameters[1]; int k1 = 0; int k2 = 0; @@ -89,15 +88,15 @@ namespace Org.BouncyCastle.Asn1.X9 if (representation.Equals(X9ObjectIdentifiers.TPBasis)) { // Trinomial basis representation - k1 = ((DerInteger)parameters[2]).Value.IntValue; + k1 = ((DerInteger)parameters[2]).IntValueExact; } else { // Pentanomial basis representation DerSequence pentanomial = (DerSequence) parameters[2]; - k1 = ((DerInteger) pentanomial[0]).Value.IntValue; - k2 = ((DerInteger) pentanomial[1]).Value.IntValue; - k3 = ((DerInteger) pentanomial[2]).Value.IntValue; + k1 = ((DerInteger)pentanomial[0]).IntValueExact; + k2 = ((DerInteger)pentanomial[1]).IntValueExact; + k3 = ((DerInteger)pentanomial[2]).IntValueExact; } BigInteger A = new BigInteger(1, Asn1OctetString.GetInstance(seq[0]).GetOctets()); BigInteger B = new BigInteger(1, Asn1OctetString.GetInstance(seq[1]).GetOctets()); |