2004-04-08 Bernie Solomon <bernard@ugsolutions.com>
[mono.git] / mcs / class / corlib / Mono.Security.Authenticode / AuthenticodeBase.cs
1 //
2 // AuthenticodeBase.cs: Authenticode signature base class
3 //
4 // Author:
5 //      Sebastien Pouliot (spouliot@motus.com)
6 //
7 // (C) 2003 Motus Technologies Inc. (http://www.motus.com)
8 //
9
10 using System;
11 using System.IO;
12 using System.Security.Cryptography;
13
14 namespace Mono.Security.Authenticode {
15
16         // References:
17         // a.   http://www.cs.auckland.ac.nz/~pgut001/pubs/authenticode.txt
18
19 #if INSIDE_CORLIB
20         internal
21 #else
22         public
23 #endif
24         enum AuthenticodeAuthority {
25                 Individual,
26                 Commercial,
27                 Maximum
28         }
29
30 #if INSIDE_CORLIB
31         internal
32 #else
33         public
34 #endif
35         class AuthenticodeBase {
36
37                 public const string spcIndirectDataContext = "1.3.6.1.4.1.311.2.1.4";
38
39                 protected byte[] rawData;
40
41                 public AuthenticodeBase ()
42                 {
43                 }
44
45                 protected byte[] HashFile (string fileName, string hashName) 
46                 {
47                         FileStream fs = new FileStream (fileName, FileMode.Open, FileAccess.Read, FileShare.Read);
48                         byte[] file = new byte [fs.Length];
49                         fs.Read (file, 0, file.Length);
50                         fs.Close ();
51
52                         // MZ - DOS header
53                         if (BitConverterLE.ToUInt16 (file, 0) != 0x5A4D)
54                                 return null;
55
56                         // find offset of PE header
57                         int peOffset = BitConverterLE.ToInt32 (file, 60);
58                         if (peOffset > file.Length)
59                                 return null;
60
61                         // PE - NT header
62                         if (BitConverterLE.ToUInt16 (file, peOffset) != 0x4550)
63                                 return null;
64
65                         // IMAGE_DIRECTORY_ENTRY_SECURITY
66                         int dirSecurityOffset = BitConverterLE.ToInt32 (file, peOffset + 152);
67                         int dirSecuritySize = BitConverterLE.ToInt32 (file, peOffset + 156);
68
69                         if (dirSecuritySize > 8) {
70                                 rawData = new byte [dirSecuritySize - 8];
71                                 Array.Copy (file, dirSecurityOffset + 8, rawData, 0, rawData.Length);
72 /* DEBUG 
73                         FileStream debug = new FileStream (fileName + ".sig", FileMode.Create, FileAccess.Write);
74                         debug.Write (rawData, 0, rawData.Length);
75                         debug.Close ();*/
76                         }
77                         else
78                                 rawData = null;
79
80                         HashAlgorithm hash = HashAlgorithm.Create (hashName);
81                         // 0 to 215 (216) then skip 4 (checksum)
82                         int pe = peOffset + 88;
83                         hash.TransformBlock (file, 0, pe, file, 0);
84                         pe += 4;
85                         // 220 to 279 (60) then skip 8 (IMAGE_DIRECTORY_ENTRY_SECURITY)
86                         hash.TransformBlock (file, pe, 60, file, pe);
87                         pe += 68;
88                         // 288 to end of file
89                         int n = file.Length - pe;
90                         // minus any authenticode signature (with 8 bytes header)
91                         if (dirSecurityOffset != 0)
92                                 n -= (dirSecuritySize);
93                         hash.TransformFinalBlock (file, pe, n);
94
95                         return hash.Hash;
96                 }
97         }
98 }