diff options
author | Peter Dettman <peter.dettman@bouncycastle.org> | 2015-10-12 15:49:54 +0700 |
---|---|---|
committer | Peter Dettman <peter.dettman@bouncycastle.org> | 2015-10-12 15:49:54 +0700 |
commit | 06ba713c9b19102310675a6c58e07c68d8efb3c7 (patch) | |
tree | 2d4e747d988f74abca2a5513713e4ff0e8ed8e69 /crypto/src/bcpg/SignatureSubpacketsReader.cs | |
parent | Add new file entries (diff) | |
download | BouncyCastle.NET-ed25519-06ba713c9b19102310675a6c58e07c68d8efb3c7.tar.xz |
Port of latest PGP tests and supporting code changes
Diffstat (limited to 'crypto/src/bcpg/SignatureSubpacketsReader.cs')
-rw-r--r-- | crypto/src/bcpg/SignatureSubpacketsReader.cs | 84 |
1 files changed, 62 insertions, 22 deletions
diff --git a/crypto/src/bcpg/SignatureSubpacketsReader.cs b/crypto/src/bcpg/SignatureSubpacketsReader.cs index 8dd1af332..80bedb07c 100644 --- a/crypto/src/bcpg/SignatureSubpacketsReader.cs +++ b/crypto/src/bcpg/SignatureSubpacketsReader.cs @@ -1,6 +1,8 @@ using System; using System.IO; + using Org.BouncyCastle.Bcpg.Sig; +using Org.BouncyCastle.Utilities; using Org.BouncyCastle.Utilities.IO; namespace Org.BouncyCastle.Bcpg @@ -25,7 +27,9 @@ namespace Org.BouncyCastle.Bcpg return null; int bodyLen = 0; - if (l < 192) + bool isLongLength = false; + + if (l < 192) { bodyLen = l; } @@ -35,54 +39,90 @@ namespace Org.BouncyCastle.Bcpg } else if (l == 255) { + isLongLength = true; bodyLen = (input.ReadByte() << 24) | (input.ReadByte() << 16) | (input.ReadByte() << 8) | input.ReadByte(); } else { - // TODO Error? + throw new IOException("unexpected length header"); } - int tag = input.ReadByte(); + int tag = input.ReadByte(); if (tag < 0) throw new EndOfStreamException("unexpected EOF reading signature sub packet"); - byte[] data = new byte[bodyLen - 1]; - if (Streams.ReadFully(input, data) < data.Length) - throw new EndOfStreamException(); + byte[] data = new byte[bodyLen - 1]; + + // + // this may seem a bit strange but it turns out some applications miscode the length + // in fixed length fields, so we check the length we do get, only throwing an exception if + // we really cannot continue + // + int bytesRead = Streams.ReadFully(input, data); + + bool isCritical = ((tag & 0x80) != 0); + SignatureSubpacketTag type = (SignatureSubpacketTag)(tag & 0x7f); - bool isCritical = ((tag & 0x80) != 0); - SignatureSubpacketTag type = (SignatureSubpacketTag)(tag & 0x7f); - switch (type) + if (bytesRead != data.Length) + { + switch (type) + { + case SignatureSubpacketTag.CreationTime: + data = CheckData(data, 4, bytesRead, "Signature Creation Time"); + break; + case SignatureSubpacketTag.IssuerKeyId: + data = CheckData(data, 8, bytesRead, "Issuer"); + break; + case SignatureSubpacketTag.KeyExpireTime: + data = CheckData(data, 4, bytesRead, "Signature Key Expiration Time"); + break; + case SignatureSubpacketTag.ExpireTime: + data = CheckData(data, 4, bytesRead, "Signature Expiration Time"); + break; + default: + throw new EndOfStreamException("truncated subpacket data."); + } + } + + switch (type) { case SignatureSubpacketTag.CreationTime: - return new SignatureCreationTime(isCritical, data); + return new SignatureCreationTime(isCritical, isLongLength, data); case SignatureSubpacketTag.KeyExpireTime: - return new KeyExpirationTime(isCritical, data); + return new KeyExpirationTime(isCritical, isLongLength, data); case SignatureSubpacketTag.ExpireTime: - return new SignatureExpirationTime(isCritical, data); + return new SignatureExpirationTime(isCritical, isLongLength, data); case SignatureSubpacketTag.Revocable: - return new Revocable(isCritical, data); + return new Revocable(isCritical, isLongLength, data); case SignatureSubpacketTag.Exportable: - return new Exportable(isCritical, data); + return new Exportable(isCritical, isLongLength, data); case SignatureSubpacketTag.IssuerKeyId: - return new IssuerKeyId(isCritical, data); + return new IssuerKeyId(isCritical, isLongLength, data); case SignatureSubpacketTag.TrustSig: - return new TrustSignature(isCritical, data); + return new TrustSignature(isCritical, isLongLength, data); case SignatureSubpacketTag.PreferredCompressionAlgorithms: case SignatureSubpacketTag.PreferredHashAlgorithms: case SignatureSubpacketTag.PreferredSymmetricAlgorithms: - return new PreferredAlgorithms(type, isCritical, data); + return new PreferredAlgorithms(type, isCritical, isLongLength, data); case SignatureSubpacketTag.KeyFlags: - return new KeyFlags(isCritical, data); + return new KeyFlags(isCritical, isLongLength, data); case SignatureSubpacketTag.PrimaryUserId: - return new PrimaryUserId(isCritical, data); + return new PrimaryUserId(isCritical, isLongLength, data); case SignatureSubpacketTag.SignerUserId: - return new SignerUserId(isCritical, data); + return new SignerUserId(isCritical, isLongLength, data); case SignatureSubpacketTag.NotationData: - return new NotationData(isCritical, data); + return new NotationData(isCritical, isLongLength, data); } - return new SignatureSubpacket(type, isCritical, data); + return new SignatureSubpacket(type, isCritical, isLongLength, data); } + + private byte[] CheckData(byte[] data, int expected, int bytesRead, string name) + { + if (bytesRead != expected) + throw new EndOfStreamException("truncated " + name + " subpacket data."); + + return Arrays.CopyOfRange(data, 0, expected); + } } } |