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);