3 // Copyright (c) Microsoft Corporation. All rights reserved.
6 // <OWNER>Microsoft</OWNER>
10 // HashMembershipCondition.cs
12 // Implementation of membership condition for hashes of assemblies.
15 namespace System
.Security
.Policy
{
16 using System
.Collections
;
17 using System
.Runtime
.Serialization
;
18 using System
.Security
;
19 using System
.Security
.Cryptography
;
20 using System
.Security
.Util
;
21 using System
.Security
.Permissions
;
22 using System
.Threading
;
23 using System
.Globalization
;
24 using System
.Diagnostics
.Contracts
;
27 [System
.Runtime
.InteropServices
.ComVisible(true)]
28 public sealed class HashMembershipCondition
: ISerializable
, IDeserializationCallback
, IMembershipCondition
, IReportMatchMembershipCondition
{
29 private byte[] m_value
= null;
30 private HashAlgorithm m_hashAlg
= null;
31 private SecurityElement m_element
= null;
33 private object s_InternalSyncObject
= null;
34 private object InternalSyncObject
{
36 if (s_InternalSyncObject
== null) {
37 Object o
= new Object();
38 Interlocked
.CompareExchange(ref s_InternalSyncObject
, o
, null);
40 return s_InternalSyncObject
;
44 internal HashMembershipCondition() {}
45 private HashMembershipCondition (SerializationInfo info
, StreamingContext context
) {
46 m_value
= (byte[]) info
.GetValue("HashValue", typeof(byte[]));
47 string hashAlgorithm
= (string) info
.GetValue("HashAlgorithm", typeof(string));
48 if (hashAlgorithm
!= null)
49 m_hashAlg
= HashAlgorithm
.Create(hashAlgorithm
);
51 m_hashAlg
= new SHA1Managed();
54 public HashMembershipCondition(HashAlgorithm hashAlg
, byte[] value) {
56 throw new ArgumentNullException("value");
58 throw new ArgumentNullException("hashAlg");
59 Contract
.EndContractBlock();
61 m_value
= new byte[value.Length
];
62 Array
.Copy(value, m_value
, value.Length
);
67 [System
.Security
.SecurityCritical
]
68 void ISerializable
.GetObjectData(SerializationInfo info
, StreamingContext context
)
70 info
.AddValue("HashValue", this.HashValue
);
71 info
.AddValue("HashAlgorithm", this.HashAlgorithm
.ToString());
75 void IDeserializationCallback
.OnDeserialization (Object sender
) {}
77 public HashAlgorithm HashAlgorithm
{
80 throw new ArgumentNullException("HashAlgorithm");
81 Contract
.EndContractBlock();
85 if (m_hashAlg
== null && m_element
!= null)
91 public byte[] HashValue
{
94 throw new ArgumentNullException("value");
95 Contract
.EndContractBlock();
96 m_value
= new byte[value.Length
];
97 Array
.Copy(value, m_value
, value.Length
);
100 if (m_value
== null && m_element
!= null)
105 byte[] value = new byte[m_value
.Length
];
106 Array
.Copy(m_value
, value, m_value
.Length
);
111 public bool Check(Evidence evidence
) {
112 object usedEvidence
= null;
113 return (this as IReportMatchMembershipCondition
).Check(evidence
, out usedEvidence
);
116 bool IReportMatchMembershipCondition
.Check(Evidence evidence
, out object usedEvidence
) {
119 if (evidence
== null)
122 Hash hash
= evidence
.GetHostEvidence
<Hash
>();
124 if (m_value
== null && m_element
!= null)
127 if (m_hashAlg
== null && m_element
!= null)
128 ParseHashAlgorithm();
130 byte[] asmHash
= null;
131 lock (InternalSyncObject
) {
132 asmHash
= hash
.GenerateHash(m_hashAlg
);
135 if (asmHash
!= null && CompareArrays(asmHash
, m_value
)) {
144 public IMembershipCondition
Copy() {
145 if (m_value
== null && m_element
!= null)
148 if (m_hashAlg
== null && m_element
!= null)
149 ParseHashAlgorithm();
151 return new HashMembershipCondition(m_hashAlg
, m_value
);
154 public SecurityElement
ToXml() {
158 public void FromXml(SecurityElement e
) {
162 public SecurityElement
ToXml(PolicyLevel level
) {
163 if (m_value
== null && m_element
!= null)
166 if (m_hashAlg
== null && m_element
!= null)
167 ParseHashAlgorithm();
169 SecurityElement root
= new SecurityElement("IMembershipCondition");
170 XMLUtil
.AddClassAttribute(root
, this.GetType(), "System.Security.Policy.HashMembershipCondition");
171 // If you hit this assert then most likely you are trying to change the name of this class.
172 // This is ok as long as you change the hard coded string above and change the assert below.
173 Contract
.Assert(this.GetType().FullName
.Equals("System.Security.Policy.HashMembershipCondition"), "Class name changed!");
175 root
.AddAttribute("version", "1");
177 root
.AddAttribute(s_tagHashValue
, Hex
.EncodeHexString(HashValue
));
178 if (m_hashAlg
!= null)
179 root
.AddAttribute(s_tagHashAlgorithm
, HashAlgorithm
.GetType().FullName
);
183 public void FromXml(SecurityElement e
, PolicyLevel level
) {
185 throw new ArgumentNullException("e");
187 if (!e
.Tag
.Equals("IMembershipCondition"))
188 throw new ArgumentException(Environment
.GetResourceString("Argument_MembershipConditionElement"));
189 Contract
.EndContractBlock();
191 lock (InternalSyncObject
) {
198 public override bool Equals(Object o
) {
199 HashMembershipCondition that
= (o
as HashMembershipCondition
);
201 if (this.m_hashAlg
== null && this.m_element
!= null)
202 this.ParseHashAlgorithm();
203 if (that
.m_hashAlg
== null && that
.m_element
!= null)
204 that
.ParseHashAlgorithm();
206 if (this.m_hashAlg
!= null && that
.m_hashAlg
!= null &&
207 this.m_hashAlg
.GetType() == that
.m_hashAlg
.GetType()) {
208 if (this.m_value
== null && this.m_element
!= null)
209 this.ParseHashValue();
210 if (that
.m_value
== null && that
.m_element
!= null)
211 that
.ParseHashValue();
213 if (this.m_value
.Length
!= that
.m_value
.Length
)
216 for (int i
= 0; i
< m_value
.Length
; i
++) {
217 if (this.m_value
[i
] != that
.m_value
[i
])
226 public override int GetHashCode() {
227 if (this.m_hashAlg
== null && this.m_element
!= null)
228 this.ParseHashAlgorithm();
230 int accumulator
= this.m_hashAlg
!= null ? this.m_hashAlg
.GetType().GetHashCode() : 0;
231 if (this.m_value
== null && this.m_element
!= null)
232 this.ParseHashValue();
234 accumulator
= accumulator ^
GetByteArrayHashCode(this.m_value
);
238 public override string ToString() {
239 if (m_hashAlg
== null)
240 ParseHashAlgorithm();
242 return Environment
.GetResourceString("Hash_ToString", m_hashAlg
.GetType().AssemblyQualifiedName
, Hex
.EncodeHexString(HashValue
));
245 private const string s_tagHashValue
= "HashValue";
246 private const string s_tagHashAlgorithm
= "HashAlgorithm";
248 private void ParseHashValue() {
249 lock (InternalSyncObject
) {
250 if (m_element
== null)
253 string elHash
= m_element
.Attribute(s_tagHashValue
);
255 m_value
= Hex
.DecodeHexString(elHash
);
257 throw new ArgumentException(Environment
.GetResourceString("Argument_InvalidXMLElement", s_tagHashValue
, this.GetType().FullName
));
259 if (m_value
!= null && m_hashAlg
!= null) {
265 private void ParseHashAlgorithm() {
266 lock (InternalSyncObject
) {
267 if (m_element
== null)
270 string elHashAlg
= m_element
.Attribute(s_tagHashAlgorithm
);
271 if (elHashAlg
!= null)
272 m_hashAlg
= HashAlgorithm
.Create(elHashAlg
);
274 m_hashAlg
= new SHA1Managed();
276 if (m_value
!= null && m_hashAlg
!= null)
281 private static bool CompareArrays(byte[] first
, byte[] second
) {
282 if (first
.Length
!= second
.Length
)
285 int count
= first
.Length
;
286 for (int i
= 0; i
< count
; ++i
) {
287 if (first
[i
] != second
[i
])
294 private static int GetByteArrayHashCode(byte[] baData
) {
299 for (int i
= 0; i
< baData
.Length
; ++i
) {
300 accumulator
= (accumulator
<< 8) ^
(int)baData
[i
] ^
(accumulator
>> 24);