Exemple #1
0
        public bool Equals(AdditionalText?x, AdditionalText?y)
        {
            if (object.ReferenceEquals(x, y))
            {
                return(true);
            }

            if (x is null || y is null)
            {
                return(false);
            }

            if (!PathUtilities.Comparer.Equals(x.Path, y.Path))
            {
                return(false);
            }

            var xText = GetTextOrNullIfBinary(x);
            var yText = GetTextOrNullIfBinary(y);

            // If xText and yText are both null, then the additional text is observably not changed
            // and can be treated as equal.
            if (xText is null && yText is null)
            {
                return(true);
            }

            if (xText is null || yText is null || xText.Length != yText.Length)
            {
                return(false);
            }

            return(ByteSequenceComparer.Equals(xText.GetChecksum(), yText.GetChecksum()));
        }
        public bool Equals(AdditionalText?x, AdditionalText?y)
        {
            if (object.ReferenceEquals(x, y))
            {
                return(true);
            }

            if (x is null || y is null)
            {
                return(false);
            }

            if (!PathUtilities.Comparer.Equals(x.Path, y.Path))
            {
                return(false);
            }

            var xText = x.GetText();
            var yText = y.GetText();

            if (xText is null || yText is null || xText.Length != yText.Length)
            {
                return(false);
            }

            return(ByteSequenceComparer.Equals(xText.GetChecksum(), yText.GetChecksum()));
        }
 public void Equals1()
 {
     Assert.True(ByteSequenceComparer.Equals(new byte[] { }, new byte[] { }));
     Assert.True(ByteSequenceComparer.Equals(new byte[] { 1 }, new byte[] { 1 }));
     Assert.False(ByteSequenceComparer.Equals(new byte[] { 1 }, new byte[] { 2 }));
     Assert.True(ByteSequenceComparer.Equals(new byte[] { 1, 2 }, new byte[] { 1, 2 }));
     Assert.False(ByteSequenceComparer.Equals(new byte[] { 1, 2 }, new byte[] { 1, 3 }));
 }
 public void Equals2()
 {
     Assert.True(ByteSequenceComparer.Equals(new byte[] { }, 0, new byte[] { }, 0, 0));
     Assert.True(ByteSequenceComparer.Equals(new byte[] { 1 }, 0, new byte[] { }, 0, 0));
     Assert.True(ByteSequenceComparer.Equals(new byte[] { 1 }, 1, new byte[] { 1 }, 1, 0));
     Assert.True(ByteSequenceComparer.Equals(new byte[] { 1 }, 0, new byte[] { 1 }, 0, 1));
     Assert.False(ByteSequenceComparer.Equals(new byte[] { 1 }, 0, new byte[] { 2 }, 0, 1));
     Assert.True(ByteSequenceComparer.Equals(new byte[] { 1, 2 }, 1, new byte[] { 2 }, 0, 1));
 }
Exemple #5
0
        // From StrongNameInternal.cpp
        // Checks to see if a public key is a valid instance of a PublicKeyBlob as
        // defined in StongName.h
        internal static bool IsValidPublicKey(ImmutableArray <byte> blob)
        {
            // The number of public key bytes must be at least large enough for the header and one byte of data.
            if (blob.IsDefault || blob.Length < s_publicKeyHeaderSize + 1)
            {
                return(false);
            }

            var blobReader = new LittleEndianReader(blob.AsSpan());

            // Signature algorithm ID
            var sigAlgId = blobReader.ReadUInt32();
            // Hash algorithm ID
            var hashAlgId = blobReader.ReadUInt32();
            // Size of public key data in bytes, not including the header
            var publicKeySize = blobReader.ReadUInt32();
            // publicKeySize bytes of public key data
            var publicKey = blobReader.ReadByte();

            // The number of public key bytes must be the same as the size of the header plus the size of the public key data.
            if (blob.Length != s_publicKeyHeaderSize + publicKeySize)
            {
                return(false);
            }

            // Check for the ECMA key, which does not obey the invariants checked below.
            if (ByteSequenceComparer.Equals(blob, s_ecmaKey))
            {
                return(true);
            }

            // The public key must be in the wincrypto PUBLICKEYBLOB format
            if (publicKey != PublicKeyBlobId)
            {
                return(false);
            }

            var signatureAlgorithmId = new AlgorithmId(sigAlgId);

            if (signatureAlgorithmId.IsSet && signatureAlgorithmId.Class != AlgorithmClass.Signature)
            {
                return(false);
            }

            var hashAlgorithmId = new AlgorithmId(hashAlgId);

            if (hashAlgorithmId.IsSet && (hashAlgorithmId.Class != AlgorithmClass.Hash || hashAlgorithmId.SubId < AlgorithmSubId.Sha1Hash))
            {
                return(false);
            }

            return(true);
        }
Exemple #6
0
        private void TestContentEquals(byte[] left, byte[] right)
        {
            var builder1 = new BlobBuilder(0);

            builder1.WriteBytes(left);

            var builder2 = new BlobBuilder(0);

            builder2.WriteBytes(right);

            bool expected = ByteSequenceComparer.Equals(left, right);

            Assert.Equal(expected, builder1.ContentEquals(builder2));
        }
        private static unsafe bool IsValidPublicKeyUnsafe(ImmutableArray <byte> blob)
        {
            fixed(byte *ptr = blob.DangerousGetUnderlyingArray())
            {
                var blobReader = new BlobReader(ptr, blob.Length);

                // Signature algorithm ID
                var sigAlgId = blobReader.ReadUInt32();
                // Hash algorithm ID
                var hashAlgId = blobReader.ReadUInt32();
                // Size of public key data in bytes, not including the header
                var publicKeySize = blobReader.ReadUInt32();
                // publicKeySize bytes of public key data
                var publicKey = blobReader.ReadByte();

                // The number of public key bytes must be the same as the size of the header plus the size of the public key data.
                if (blob.Length != s_publicKeyHeaderSize + publicKeySize)
                {
                    return(false);
                }

                // Check for the ECMA key, which does not obey the invariants checked below.
                if (ByteSequenceComparer.Equals(blob, s_ecmaKey))
                {
                    return(true);
                }

                // The public key must be in the wincrypto PUBLICKEYBLOB format
                if (publicKey != PublicKeyBlobId)
                {
                    return(false);
                }

                var signatureAlgorithmId = new AlgorithmId(sigAlgId);

                if (signatureAlgorithmId.IsSet && signatureAlgorithmId.Class != AlgorithmClass.Signature)
                {
                    return(false);
                }

                var hashAlgorithmId = new AlgorithmId(hashAlgId);

                if (hashAlgorithmId.IsSet && (hashAlgorithmId.Class != AlgorithmClass.Hash || hashAlgorithmId.SubId < AlgorithmSubId.Sha1Hash))
                {
                    return(false);
                }
            }

            return(true);
        }
        public void Equals3()
        {
            var b = new byte[] { 1, 2, 1 };

            Assert.True(ByteSequenceComparer.Equals(b, b));
            Assert.True(ByteSequenceComparer.Equals(b, 0, b, 0, 1));
            Assert.True(ByteSequenceComparer.Equals(b, 2, b, 2, 1));
            Assert.True(ByteSequenceComparer.Equals(b, 0, b, 2, 1));
            Assert.False(ByteSequenceComparer.Equals(b, 0, b, 1, 1));

            Assert.False(ByteSequenceComparer.Equals(null, b));
            Assert.False(ByteSequenceComparer.Equals(null, new byte[] { }));
            Assert.True(ByteSequenceComparer.Equals(null, null));
        }
Exemple #9
0
        // internal for testing
        /// <exception cref="IOException"/>
        internal static ImmutableArray <byte> GetPublicKey(byte[] keyFileContents)
        {
            try
            {
                var lastSeen = lastSeenKeyPair;
                if (lastSeen != null && ByteSequenceComparer.ValueEquals(lastSeen.Item1, keyFileContents))
                {
                    return(lastSeen.Item2);
                }

                ICLRStrongName strongName = GetStrongNameInterface();

                IntPtr keyBlob;
                int    keyBlobByteCount;

                //EDMAURER use marshal to be safe?
                unsafe
                {
                    fixed(byte *p = keyFileContents)
                    {
                        try
                        {
                            strongName.StrongNameGetPublicKey(null, (IntPtr)p, keyFileContents.Length, out keyBlob, out keyBlobByteCount);
                        }
                        catch (ArgumentException ex)
                        {
                            throw new IOException(ex.Message);
                        }
                    }
                }

                byte[] pubKey = new byte[keyBlobByteCount];
                Marshal.Copy(keyBlob, pubKey, 0, keyBlobByteCount);
                strongName.StrongNameFreeBuffer(keyBlob);

                var result = pubKey.AsImmutableOrNull();
                lastSeenKeyPair = Tuple.Create(keyFileContents, result);

                return(result);
            }
            catch (COMException ex)
            {
                throw new IOException(ex.Message);
            }
        }
Exemple #10
0
            // From StrongNameInternal.cpp
            public static bool TryDecode(ImmutableArray <byte> bytes)
            {
                // The number of public key bytes must be at least large enough for the header and one byte of data.
                if (bytes.IsDefault || bytes.Length < HeaderSize + 1)
                {
                    return(false);
                }

                // The number of public key bytes must be the same as the size of the header plus the size of the public key data.
                var dataSize = ToUInt32(bytes, PublicKeySizeOffset);

                if (bytes.Length != HeaderSize + dataSize)
                {
                    return(false);
                }

                // Check for the ECMA key, which does not obey the invariants checked below.
                if (ByteSequenceComparer.Equals(bytes, s_ecmaKey))
                {
                    return(true);
                }

                var signatureAlgorithmId = new AlgorithmId(ToUInt32(bytes, 0));

                if (signatureAlgorithmId.IsSet && signatureAlgorithmId.Class != AlgorithmClass.Signature)
                {
                    return(false);
                }

                var hashAlgorithmId = new AlgorithmId(ToUInt32(bytes, 4));

                if (hashAlgorithmId.IsSet && (hashAlgorithmId.Class != AlgorithmClass.Hash || hashAlgorithmId.SubId < AlgorithmSubId.Sha1Hash))
                {
                    return(false);
                }

                if (bytes[PublicKeyDataOffset] != PublicKeyBlob)
                {
                    return(false);
                }

                return(true);
            }
Exemple #11
0
        private static unsafe bool IsValidPublicKeyUnsafe(ImmutableArray <byte> blob)
        {
            var blobArray = blob.DangerousGetUnderlyingArray();

            fixed(byte *blobPtr = blobArray)
            {
                var pkb = (SnPublicKeyBlob *)blobPtr;

                // The number of public key bytes must be the same as the size of the header plus the size of the public key data.
                if (blob.Length != s_publicKeyHeaderSize + pkb->PublicKeySize)
                {
                    return(false);
                }

                // Check for the ECMA key, which does not obey the invariants checked below.
                if (ByteSequenceComparer.Equals(blob, s_ecmaKey))
                {
                    return(true);
                }

                // The public key must be in the wincrypto PUBLICKEYBLOB format
                if (pkb->PublicKey[0] != PublicKeyBlobId)
                {
                    return(false);
                }

                var signatureAlgorithmId = new AlgorithmId(pkb->SigAlgId);

                if (signatureAlgorithmId.IsSet && signatureAlgorithmId.Class != AlgorithmClass.Signature)
                {
                    return(false);
                }

                var hashAlgorithmId = new AlgorithmId(pkb->HashAlgId);

                if (hashAlgorithmId.IsSet && (hashAlgorithmId.Class != AlgorithmClass.Hash || hashAlgorithmId.SubId < AlgorithmSubId.Sha1Hash))
                {
                    return(false);
                }
            }

            return(true);
        }
Exemple #12
0
        /// <summary>
        /// Compares the current content of this writer with another one.
        /// </summary>
        /// <exception cref="InvalidOperationException">Content is not available, the builder has been linked with another one.</exception>
        public bool ContentEquals(BlobBuilder other)
        {
            if (!IsHead)
            {
                Throw.InvalidOperationBuilderAlreadyLinked();
            }

            if (ReferenceEquals(this, other))
            {
                return(true);
            }

            if (other == null)
            {
                return(false);
            }

            if (!other.IsHead)
            {
                Throw.InvalidOperationBuilderAlreadyLinked();
            }

            if (Count != other.Count)
            {
                return(false);
            }

            var leftEnumerator  = GetChunks();
            var rightEnumerator = other.GetChunks();
            int leftStart       = 0;
            int rightStart      = 0;

            bool leftContinues  = leftEnumerator.MoveNext();
            bool rightContinues = rightEnumerator.MoveNext();

            while (leftContinues && rightContinues)
            {
                Debug.Assert(leftStart == 0 || rightStart == 0);

                var left  = leftEnumerator.Current;
                var right = rightEnumerator.Current;

                int minLength = Math.Min(left.Length - leftStart, right.Length - rightStart);
                if (!ByteSequenceComparer.Equals(left._buffer, leftStart, right._buffer, rightStart, minLength))
                {
                    return(false);
                }

                leftStart  += minLength;
                rightStart += minLength;

                // nothing remains in left chunk to compare:
                if (leftStart == left.Length)
                {
                    leftContinues = leftEnumerator.MoveNext();
                    leftStart     = 0;
                }

                // nothing remains in left chunk to compare:
                if (rightStart == right.Length)
                {
                    rightContinues = rightEnumerator.MoveNext();
                    rightStart     = 0;
                }
            }

            return(leftContinues == rightContinues);
        }
Exemple #13
0
 public int GetHashCode(AdditionalText obj)
 {
     return(Hash.Combine(PathUtilities.Comparer.GetHashCode(obj.Path),
                         ByteSequenceComparer.GetHashCode(GetTextOrNullIfBinary(obj)?.GetChecksum() ?? ImmutableArray <byte> .Empty)));
 }
Exemple #14
0
 /// <summary>
 /// Compares the current content of this writer with another one.
 /// </summary>
 public bool ContentEquals(BlobBuilder other)
 {
     return(other != null && Length == other.Length && ByteSequenceComparer.Equals(_buffer, 0, other._buffer, 0, Length));
 }
Exemple #15
0
        protected IVTConclusion PerformIVTCheck(ImmutableArray <byte> key, AssemblyIdentity otherIdentity)
        {
            // This gets a bit complicated. Let's break it down.
            //
            // First off, let's assume that the "other" assembly is Smith.DLL, that the "this"
            // assembly is "Jones.DLL", and that Smith has named Jones as a friend. Whether we
            // allow Jones to see internals of Smith depends on these four factors:
            //
            // q1) Is Smith strong-named?
            // q2) Did Smith name Jones as a friend via a strong name?
            // q3) Is Jones strong-named?
            // q4) Does Smith give a strong-name for Jones that matches our strong name?
            //
            // Before we dive into the details, we should mention two additional facts:
            //
            // * If the answer to q1 is "yes", and Smith was compiled by the C# compiler, then q2 must be "yes" also.
            //   Strong-named Smith must only be friends with strong-named Jones. See the blog article
            //   http://blogs.msdn.com/b/ericlippert/archive/2009/06/04/alas-smith-and-jones.aspx
            //   for an explanation of why this feature is desirable.
            //
            //   Now, just because the compiler enforces this rule does not mean that we will never run into
            //   a scenario where Smith is strong-named and names Jones via a weak name. Not all assemblies
            //   were compiled with the C# compiler. We still need to deal sensibly with this situation.
            //   We do so by ignoring the problem; if strong-named Smith extends friendship to weak-named
            //   Jones then we're done; any assembly named Jones is a friend of Smith.
            //
            //   Incidentally, the compiler produces error CS1726, ERR_FriendAssemblySNReq, when compiling
            //   a strong-named Smith that names a weak-named Jones as its friend.
            //
            // * If the answer to q1 is "no" and the answer to q3 is "yes" then we are in a situation where
            //   strong-named Jones is referencing weak-named Smith, which is illegal. In the dev 10 compiler
            //   we do not give an error about this until emit time. In Roslyn we have a new error, CS7029,
            //   which we give before emit time when we detect that weak-named Smith has given friend access
            //   to strong-named Jones, which then references Smith. However, we still want to give friend
            //   access to Jones for the purposes of semantic analysis.
            //
            // TODO: Roslyn does not yet give an error in other circumstances whereby a strong-named assembly
            // TODO: references a weak-named assembly.
            //
            // Let's make a chart that illustrates all the possible answers to these four questions, and
            // what the resulting accessibility should be:
            //
            // case q1  q2  q3  q4  Result                 Explanation
            // 1    YES YES YES YES SUCCESS          Smith has named this strong-named Jones as a friend.
            // 2    YES YES YES NO  NO MATCH         Smith has named a different strong-named Jones as a friend.
            // 3    YES YES NO  NO  NO MATCH         Smith has named a strong-named Jones as a friend, but this Jones is weak-named.
            // 4    YES NO  YES NO  SUCCESS          Smith has improperly (*) named any Jones as its friend. But we honor its offer of friendship.
            // 5    YES NO  NO  NO  SUCCESS          Smith has improperly (*) named any Jones as its friend. But we honor its offer of friendship.
            // 6    NO  YES YES YES SUCCESS, BAD REF Smith has named this strong-named Jones as a friend, but Jones should not be referring to a weak-named Smith.
            // 7    NO  YES YES NO  NO MATCH         Smith has named a different strong-named Jones as a friend.
            // 8    NO  YES NO  NO  NO MATCH         Smith has named a strong-named Jones as a friend, but this Jones is weak-named.
            // 9    NO  NO  YES NO  SUCCESS, BAD REF Smith has named any Jones as a friend, but Jones should not be referring to a weak-named Smith.
            // 10   NO  NO  NO  NO  SUCCESS          Smith has named any Jones as its friend.
            //
            // (*) Smith was not built with C#, which would have prevented this.
            //
            // This method never returns NoRelationshipClaimed because if control got here, then we know that
            // Smith named Jones as a friend somehow.
            //
            // All that said, we also have an easy out here. Suppose Smith names Jones as a friend, and Jones is
            // being compiled as a module, not as an assembly. You can only strong-name an assembly. So if this module
            // is named Jones, and Smith is extending friend access to Jones, then we are going to optimistically
            // assume that Jones is going to be compiled into an assembly with a matching strong name, if necessary.

            CSharpCompilation compilation = this.DeclaringCompilation;

            if (compilation != null && compilation.Options.OutputKind.IsNetModule())
            {
                return(IVTConclusion.Match);
            }

            bool q1 = otherIdentity.IsStrongName;
            bool q2 = !key.IsDefaultOrEmpty;
            bool q3 = !this.PublicKey.IsDefaultOrEmpty;
            bool q4 = (q2 & q3) && ByteSequenceComparer.Equals(key, this.PublicKey);

            // Cases 2, 3, 7 and 8:
            if (q2 && !q4)
            {
                return(IVTConclusion.PublicKeyDoesntMatch);
            }

            // Cases 6 and 9:
            if (!q1 && q3)
            {
                return(IVTConclusion.OneSignedOneNot);
            }

            // Cases 1, 4, 5 and 10:
            return(IVTConclusion.Match);
        }
        internal static IVTConclusion PerformIVTCheck(
            this AssemblyIdentity assemblyGrantingAccessIdentity,
            ImmutableArray <byte> assemblyWantingAccessKey,
            ImmutableArray <byte> grantedToPublicKey
            )
        {
            // This gets a bit complicated. Let's break it down.
            //
            // First off, let's assume that the "other" assembly is GrantingAssembly.DLL, that the "this"
            // assembly is "WantingAssembly.DLL", and that GrantingAssembly has named WantingAssembly as a friend (that is a precondition
            // to calling this method). Whether we allow WantingAssembly to see internals of GrantingAssembly depends on these four factors:
            //
            // q1) Is GrantingAssembly strong-named?
            // q2) Did GrantingAssembly name WantingAssembly as a friend via a strong name?
            // q3) Is WantingAssembly strong-named?
            // q4) Does GrantingAssembly give a strong-name for WantingAssembly that matches our strong name?
            //
            // Before we dive into the details, we should mention two additional facts:
            //
            // * If the answer to q1 is "yes", and GrantingAssembly was compiled by a Roslyn compiler, then q2 must be "yes" also.
            //   Strong-named GrantingAssembly must only be friends with strong-named WantingAssembly. See the blog article
            //   http://blogs.msdn.com/b/ericlippert/archive/2009/06/04/alas-smith-and-jones.aspx
            //   for an explanation of why this feature is desirable.
            //
            //   Now, just because the compiler enforces this rule does not mean that we will never run into
            //   a scenario where GrantingAssembly is strong-named and names WantingAssembly via a weak name. Not all assemblies
            //   were compiled with a Roslyn compiler. We still need to deal sensibly with this situation.
            //   We do so by ignoring the problem; if strong-named GrantingAssembly extends friendship to weak-named
            //   WantingAssembly then we're done; any assembly named WantingAssembly is a friend of GrantingAssembly.
            //
            //   Incidentally, the C# compiler produces error CS1726, ERR_FriendAssemblySNReq, and VB produces
            //   the error VB31535, ERR_FriendAssemblyStrongNameRequired, when compiling
            //   a strong-named GrantingAssembly that names a weak-named WantingAssembly as its friend.
            //
            // * If the answer to q1 is "no" and the answer to q3 is "yes" then we are in a situation where
            //   strong-named WantingAssembly is referencing weak-named GrantingAssembly, which is illegal. In the dev10 compiler
            //   we do not give an error about this until emit time. In Roslyn we have a new error, CS7029,
            //   which we give before emit time when we detect that weak-named GrantingAssembly has given friend access
            //   to strong-named WantingAssembly, which then references GrantingAssembly. However, we still want to give friend
            //   access to WantingAssembly for the purposes of semantic analysis.
            //
            // Roslyn C# does not yet give an error in other circumstances whereby a strong-named assembly
            // references a weak-named assembly. See https://github.com/dotnet/roslyn/issues/26722
            //
            // Let's make a chart that illustrates all the possible answers to these four questions, and
            // what the resulting accessibility should be:
            //
            // case q1  q2  q3  q4  Result                 Explanation
            // 1    YES YES YES YES SUCCESS          GrantingAssembly has named this strong-named WantingAssembly as a friend.
            // 2    YES YES YES NO  NO MATCH         GrantingAssembly has named a different strong-named WantingAssembly as a friend.
            // 3    YES YES NO  NO  NO MATCH         GrantingAssembly has named a strong-named WantingAssembly as a friend, but this WantingAssembly is weak-named.
            // 4    YES NO  YES NO  SUCCESS          GrantingAssembly has improperly (*) named any WantingAssembly as its friend. But we honor its offer of friendship.
            // 5    YES NO  NO  NO  SUCCESS          GrantingAssembly has improperly (*) named any WantingAssembly as its friend. But we honor its offer of friendship.
            // 6    NO  YES YES YES SUCCESS, BAD REF GrantingAssembly has named this strong-named WantingAssembly as a friend, but WantingAssembly should not be referring to a weak-named GrantingAssembly.
            // 7    NO  YES YES NO  NO MATCH         GrantingAssembly has named a different strong-named WantingAssembly as a friend.
            // 8    NO  YES NO  NO  NO MATCH         GrantingAssembly has named a strong-named WantingAssembly as a friend, but this WantingAssembly is weak-named.
            // 9    NO  NO  YES NO  SUCCESS, BAD REF GrantingAssembly has named any WantingAssembly as a friend, but WantingAssembly should not be referring to a weak-named GrantingAssembly.
            // 10   NO  NO  NO  NO  SUCCESS          GrantingAssembly has named any WantingAssembly as its friend.
            //
            // (*) GrantingAssembly was not built with a Roslyn compiler, which would have prevented this.
            //
            // This method never returns NoRelationshipClaimed because if control got here, then we assume
            // (as a precondition) that GrantingAssembly named WantingAssembly as a friend somehow.

            bool q1 = assemblyGrantingAccessIdentity.IsStrongName;
            bool q2 = !grantedToPublicKey.IsDefaultOrEmpty;
            bool q3 = !assemblyWantingAccessKey.IsDefaultOrEmpty;
            bool q4 =
                (q2 & q3) &&
                ByteSequenceComparer.Equals(grantedToPublicKey, assemblyWantingAccessKey);

            // Cases 2, 3, 7 and 8:
            if (q2 && !q4)
            {
                return(IVTConclusion.PublicKeyDoesntMatch);
            }

            // Cases 6 and 9:
            if (!q1 && q3)
            {
                return(IVTConclusion.OneSignedOneNot);
            }

            // Cases 1, 4, 5 and 10:
            return(IVTConclusion.Match);
        }
Exemple #17
0
 /// <summary>
 /// Compares the current content of this writer with another one.
 /// </summary>
 public bool ContentEquals(BlobWriter other)
 {
     return Length == other.Length && ByteSequenceComparer.Equals(_buffer, _start, other._buffer, other._start, Length);
 }