Beispiel #1
0
        public void WriteData(BlobBuilder resourceWriter)
        {
            if (_fileReference == null)
            {
                try
                {
                    using (Stream stream = _streamProvider())
                    {
                        if (stream == null)
                        {
                            throw new InvalidOperationException(CodeAnalysisResources.ResourceStreamProviderShouldReturnNonNullStream);
                        }

                        var count = (int)(stream.Length - stream.Position);
                        resourceWriter.WriteInt32(count);

                        int bytesWritten = resourceWriter.TryWriteBytes(stream, count);
                        if (bytesWritten != count)
                        {
                            throw new EndOfStreamException(
                                    string.Format(CultureInfo.CurrentUICulture, CodeAnalysisResources.ResourceStreamEndedUnexpectedly, bytesWritten, count));
                        }
                        resourceWriter.Align(8);
                    }
                }
                catch (Exception e)
                {
                    throw new ResourceException(_name, e);
                }
            }
        }
Beispiel #2
0
        public void ProperStreamRead()
        {
            var sourceArray = new byte[] { 1, 2, 3, 4 };
            var stream      = new ProperStreamRead_TestStream(sourceArray);

            var builder = new BlobBuilder();

            Assert.Equal(sourceArray.Length, builder.TryWriteBytes(stream, sourceArray.Length));
            AssertEx.Equal(sourceArray, builder.ToArray());
        }
Beispiel #3
0
        public void PrematureEndOfStream()
        {
            var sourceArray = new byte[] { 1, 2, 3, 4 };
            var stream      = new MemoryStream(sourceArray);

            var destArray = new byte[6];
            var builder   = new BlobBuilder();

            // Try to write more bytes than exist in the stream
            Assert.Equal(4, builder.TryWriteBytes(stream, 6));

            AssertEx.Equal(sourceArray, builder.ToArray());
        }
        private static bool TestChecksumAndAuthenticodeSignature(Stream peStream, byte[] privateKeyOpt = null)
        {
            var  peHeaders        = new PEHeaders(peStream);
            bool is32bit          = peHeaders.PEHeader.Magic == PEMagic.PE32;
            uint expectedChecksum = peHeaders.PEHeader.CheckSum;
            int  peHeadersSize    = peHeaders.PEHeaderStartOffset + PEHeader.Size(is32bit) + SectionHeader.Size * peHeaders.SectionHeaders.Length;

            peStream.Position = 0;

            if (expectedChecksum == 0)
            {
                // not signed
                return(false);
            }

            int peSize  = (int)peStream.Length;
            var peImage = new BlobBuilder(peSize);

            Assert.Equal(peSize, peImage.TryWriteBytes(peStream, peSize));

            var buffer       = peImage.GetBlobs().Single().Buffer;
            var checksumBlob = new Blob(buffer, peHeaders.PEHeaderStartOffset + PEHeader.OffsetOfChecksum, sizeof(uint));

            uint checksum = PEBuilder.CalculateChecksum(peImage, checksumBlob);

            Assert.Equal(expectedChecksum, checksum);

            // validate signature:
            if (privateKeyOpt != null)
            {
                // signature is calculated with checksum zeroed:
                new BlobWriter(checksumBlob).WriteUInt32(0);

                int snOffset;
                Assert.True(peHeaders.TryGetDirectoryOffset(peHeaders.CorHeader.StrongNameSignatureDirectory, out snOffset));
                var snBlob            = new Blob(buffer, snOffset, peHeaders.CorHeader.StrongNameSignatureDirectory.Size);
                var expectedSignature = snBlob.GetBytes().ToArray();
                var signature         = SigningUtilities.CalculateRsaSignature(PEBuilder.GetContentToSign(peImage, peHeadersSize, peHeaders.PEHeader.FileAlignment, snBlob), privateKeyOpt);
                AssertEx.Equal(expectedSignature, signature);
            }

            return(true);
        }
Beispiel #5
0
        /// <summary>
        /// Creates the blob to be saved to the PDB.
        /// </summary>
        internal static ImmutableArray <byte> CreateBlob(Stream stream)
        {
            long length2 = stream.Length;

            if (length2 > int.MaxValue)
            {
                throw new IOException("Stream is too long");
            }
            stream.Seek(0L, SeekOrigin.Begin);
            int length = (int)length2;

            if (length < 200)
            {
                BlobBuilder pooledBlobBuilder = new BlobBuilder();
                pooledBlobBuilder.WriteInt32(0);
                int bytesWritten = pooledBlobBuilder.TryWriteBytes(stream, length);
                if (length != bytesWritten)
                {
                    throw new EndOfStreamException();
                }
                return(pooledBlobBuilder.ToImmutableArray());
            }
            using (BlobBuildingStream builder = BlobBuildingStream.GetInstance())
            {
                builder.WriteInt32(length);
                using (CountingDeflateStream deflater = new CountingDeflateStream(builder, CompressionLevel.Optimal, leaveOpen: true))
                {
                    stream.CopyTo(deflater);
                    if (length != deflater.BytesWritten)
                    {
                        throw new EndOfStreamException();
                    }
                }
                return(builder.ToImmutableArray());
            }
        }
Beispiel #6
0
        /// <summary>
        /// Validates that the given stream is marked as signed, the signature matches
        /// the public key, and the header checksum is correct.
        /// </summary>
        public static bool IsStreamFullSigned(Stream moduleContents)
        {
            var savedPosition = moduleContents.Position;

            try
            {
                moduleContents.Position = 0;

                var peHeaders = new PEHeaders(moduleContents);

                moduleContents.Position = 0;

                using (var metadata = ModuleMetadata.CreateFromStream(moduleContents, leaveOpen: true))
                {
                    var metadataReader = metadata.MetadataReader;
                    var peReader       = metadata.Module.PEReaderOpt;
                    var flags          = peHeaders.CorHeader.Flags;

                    if (CorFlags.StrongNameSigned != (flags & CorFlags.StrongNameSigned))
                    {
                        return(false);
                    }

                    var snDirectory = peReader.PEHeaders.CorHeader.StrongNameSignatureDirectory;
                    if (!peHeaders.TryGetDirectoryOffset(snDirectory, out int snOffset))
                    {
                        return(false);
                    }

                    moduleContents.Position = 0;
                    int peSize;
                    try
                    {
                        peSize = checked ((int)moduleContents.Length);
                    }
                    catch
                    {
                        return(false);
                    }

                    var peImage = new BlobBuilder(peSize);
                    if (peSize != peImage.TryWriteBytes(moduleContents, peSize))
                    {
                        return(false);
                    }

                    byte[] buffer = GetBlobBuffer(peImage.GetBlobs().Single());

                    uint expectedChecksum = peHeaders.PEHeader.CheckSum;
                    Blob checksumBlob     = MakeBlob(buffer, peHeaders.PEHeaderStartOffset + ChecksumOffset, sizeof(uint));

                    if (expectedChecksum != PeWriter.CalculateChecksum(peImage, checksumBlob))
                    {
                        return(false);
                    }

                    int    snSize = snDirectory.Size;
                    byte[] hash   = ComputeSigningHash(peImage, peHeaders, checksumBlob, snOffset, snSize);

                    ImmutableArray <byte> publicKeyBlob = metadataReader.GetBlobContent(metadataReader.GetAssemblyDefinition().PublicKey);
                    // RSA parameters start after the public key offset
                    byte[] publicKeyParams = new byte[publicKeyBlob.Length - CryptoBlobParser.s_publicKeyHeaderSize];
                    publicKeyBlob.CopyTo(CryptoBlobParser.s_publicKeyHeaderSize, publicKeyParams, 0, publicKeyParams.Length);
                    var snKey = publicKeyParams.ToRSAParameters(includePrivateParameters: false);

                    using (var rsa = RSA.Create())
                    {
                        rsa.ImportParameters(snKey);
                        var reversedSignature = peReader.GetSectionData(snDirectory.RelativeVirtualAddress).GetContent(0, snSize).ToArray();

                        // Unknown why the signature is reversed, but this matches the behavior of the CLR
                        // signing implementation.
                        Array.Reverse(reversedSignature);

                        if (!rsa.VerifyHash(hash, reversedSignature, HashAlgorithmName.SHA1, RSASignaturePadding.Pkcs1))
                        {
                            return(false);
                        }
                    }

                    return(true);
                }
            }
            finally
            {
                moduleContents.Position = savedPosition;
            }
        }
Beispiel #7
0
        public unsafe void Write_Errors()
        {
            var builder = new BlobBuilder(16);
            Assert.Throws<ArgumentNullException>(() => builder.WriteUTF16((char[])null));
            Assert.Throws<ArgumentNullException>(() => builder.WriteUTF16((string)null));
            Assert.Throws<ArgumentNullException>(() => builder.WriteUTF8(null, allowUnpairedSurrogates: true));
            Assert.Throws<ArgumentNullException>(() => builder.WriteUTF8(null, allowUnpairedSurrogates: true));
            Assert.Throws<ArgumentNullException>(() => builder.TryWriteBytes((Stream)null, 0));
            Assert.Throws<ArgumentNullException>(() => builder.WriteBytes(null));
            Assert.Throws<ArgumentNullException>(() => builder.WriteBytes(null, 0, 0));
            Assert.Throws<ArgumentNullException>(() => builder.WriteBytes((byte*)null, 0));
            Assert.Throws<ArgumentNullException>(() => builder.WriteBytes(default(ImmutableArray<byte>)));
            Assert.Throws<ArgumentNullException>(() => builder.WriteBytes(default(ImmutableArray<byte>), 0, 0));

            var bw = default(BlobWriter);
            Assert.Throws<ArgumentNullException>(() => builder.WriteContentTo(ref bw));
            Assert.Throws<ArgumentNullException>(() => builder.WriteContentTo((Stream)null));
            Assert.Throws<ArgumentNullException>(() => builder.WriteContentTo((BlobBuilder)null));

            Assert.Throws<ArgumentOutOfRangeException>(() => builder.TryWriteBytes(new MemoryStream(), -1));
            Assert.Throws<ArgumentOutOfRangeException>(() => builder.WriteBytes(0, -1));
            Assert.Throws<ArgumentOutOfRangeException>(() => builder.WriteBytes(new byte[] { }, 1, 0));
            Assert.Throws<ArgumentOutOfRangeException>(() => builder.WriteBytes(new byte[] { }, 0, 1));
            Assert.Throws<ArgumentOutOfRangeException>(() => builder.WriteBytes(new byte[] { }, 0, -1));
            Assert.Throws<ArgumentOutOfRangeException>(() => builder.WriteBytes(ImmutableArray<byte>.Empty, 1, 0));
            Assert.Throws<ArgumentOutOfRangeException>(() => builder.WriteBytes(ImmutableArray<byte>.Empty, 0, 1));
            Assert.Throws<ArgumentOutOfRangeException>(() => builder.WriteBytes(ImmutableArray<byte>.Empty, 1, -1));
        }
Beispiel #8
0
        public void PrematureEndOfStream()
        {
            var sourceArray = new byte[] { 1, 2, 3, 4 };
            var stream = new MemoryStream(sourceArray);

            var destArray = new byte[6];
            var builder = new BlobBuilder();

            // Try to write more bytes than exist in the stream
            Assert.Equal(4, builder.TryWriteBytes(stream, 6));

            AssertEx.Equal(sourceArray, builder.ToArray());
        }
Beispiel #9
0
        public void ProperStreamRead()
        {
            var sourceArray = new byte[] { 1, 2, 3, 4 };
            var stream = new ProperStreamRead_TestStream(sourceArray);

            var builder = new BlobBuilder();
            Assert.Equal(sourceArray.Length, builder.TryWriteBytes(stream, sourceArray.Length));
            AssertEx.Equal(sourceArray, builder.ToArray());
        }