// Sebastien Pouliot <sebastien@ximian.com>
//
// (C) 2003 Motus Technologies Inc. (http://www.motus.com)
-// Copyright (C) 2004 Novell, Inc (http://www.novell.com)
+// Copyright (C) 2004, 2006-2007 Novell, Inc (http://www.novell.com)
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
private PKCS7.SignedData pkcs7;
private string description;
private Uri url;
- private byte [] entry;
public AuthenticodeFormatter () : base ()
{
public string Hash {
get {
if (hash == null)
- hash = "MD5";
+ hash = "SHA1";
return hash;
}
set {
else
opus = Attribute (spcSpOpusInfo, Opus (description, url.ToString ()));
pkcs7.SignerInfo.AuthenticatedAttributes.Add (opus);
- pkcs7.SignerInfo.AuthenticatedAttributes.Add (Attribute (spcStatementType, new ASN1 (0x30, ASN1Convert.FromOid (commercialCodeSigning).GetBytes ())));
+// When using the MS Root Agency (test) we can't include this attribute in the signature or it won't validate!
+// pkcs7.SignerInfo.AuthenticatedAttributes.Add (Attribute (spcStatementType, new ASN1 (0x30, ASN1Convert.FromOid (commercialCodeSigning).GetBytes ())));
pkcs7.GetASN1 (); // sign
return pkcs7.SignerInfo.Signature;
}
return wc.UploadData (timestamp.ToString (), tsdata);
}
- private byte[] file;
- private int pe_offset = -1;
- private int sec_offset = -1;
- private int sec_size = -1;
-
- private int PEOffset {
- get {
- if (file == null)
- return -1;
- if (pe_offset == -1) {
- int peOffset = BitConverterLE.ToInt32 (file, 60);
- if (peOffset < file.Length)
- pe_offset = peOffset;
- }
- return pe_offset;
- }
- }
-
- private int SecurityOffset {
- get {
- if (file == null)
- return -1;
- if (sec_offset == -1) {
- sec_offset = BitConverterLE.ToInt32 (file, PEOffset + 152);
- }
- return sec_offset;
- }
- }
-
- private int SecuritySize {
- get {
- if (file == null)
- return -1;
- if (sec_size == -1) {
- sec_size = BitConverterLE.ToInt32 (file, PEOffset + 156);
- }
- return sec_size;
- }
- }
-
- private bool Open (string fileName)
- {
- using (FileStream fs = new FileStream (fileName, FileMode.Open, FileAccess.Read, FileShare.Read)) {
- file = new byte[fs.Length];
- fs.Read (file, 0, file.Length);
- fs.Close ();
- }
-
- // MZ - DOS header
- if (BitConverterLE.ToUInt16 (file, 0) != 0x5A4D)
- return false;
-
- // PE Header
- if (PEOffset == -1)
- return false;
-
- // PE - NT header
- if (BitConverterLE.ToUInt16 (file, PEOffset) != 0x4550)
- return false;
-
- // IMAGE_DIRECTORY_ENTRY_SECURITY
- if (SecuritySize > 8) {
- entry = new byte[SecuritySize - 8];
- Buffer.BlockCopy (file, SecurityOffset + 8, entry, 0, entry.Length);
- } else
- entry = null;
-
- return true;
- }
-
private bool Save (string fileName, byte[] asn)
{
-#if !DEBUG
+#if DEBUG
using (FileStream fs = File.Open (fileName + ".sig", FileMode.Create, FileAccess.Write)) {
fs.Write (asn, 0, asn.Length);
fs.Close ();
// someday I may be sure enough to move this into DEBUG ;-)
File.Copy (fileName, fileName + ".bak", true);
- using (FileStream fs = File.Open (fileName, FileMode.Create, FileAccess.Write)) {
- int filesize = (SecurityOffset == 0) ? file.Length : SecurityOffset;
- // IMAGE_DIRECTORY_ENTRY_SECURITY (offset, size)
- byte[] data = BitConverterLE.GetBytes (filesize);
- file[PEOffset + 152] = data[0];
- file[PEOffset + 153] = data[1];
- file[PEOffset + 154] = data[2];
- file[PEOffset + 155] = data[3];
- int size = asn.Length + 8;
+ using (FileStream fs = File.Open (fileName, FileMode.Open, FileAccess.ReadWrite)) {
+ int filesize;
+ if (SecurityOffset > 0) {
+ // file was already signed, we'll reuse the position for the updated signature
+ filesize = SecurityOffset;
+ } else if (CoffSymbolTableOffset > 0) {
+ // strip (deprecated) COFF symbol table
+ fs.Seek (PEOffset + 12, SeekOrigin.Begin);
+ for (int i = 0; i < 8; i++)
+ fs.WriteByte (0);
+ // we'll put the Authenticode signature at this same place (just after the last section)
+ filesize = CoffSymbolTableOffset;
+ } else {
+ // file was never signed, nor does it contains (deprecated) COFF symbols
+ filesize = (int)fs.Length;
+ }
// must be a multiple of 8 bytes
- int addsize = (size % 8);
+ int addsize = (filesize & 7);
if (addsize > 0)
addsize = 8 - addsize;
- size += addsize;
- data = BitConverterLE.GetBytes (size); // header
- file[PEOffset + 156] = data[0];
- file[PEOffset + 157] = data[1];
- file[PEOffset + 158] = data[2];
- file[PEOffset + 159] = data[3];
- fs.Write (file, 0, filesize);
+
+ // IMAGE_DIRECTORY_ENTRY_SECURITY (offset, size)
+ byte[] data = BitConverterLE.GetBytes (filesize + addsize);
+ fs.Seek (PEOffset + 152, SeekOrigin.Begin);
+ fs.Write (data, 0, 4);
+ int size = asn.Length + 8;
+ int addsize_signature = (size & 7);
+ if (addsize_signature > 0)
+ addsize_signature = 8 - addsize_signature;
+ data = BitConverterLE.GetBytes (size + addsize_signature);
+ fs.Seek (PEOffset + 156, SeekOrigin.Begin);
+ fs.Write (data, 0, 4);
+ fs.Seek (filesize, SeekOrigin.Begin);
+ // align certificate entry to a multiple of 8 bytes
+ if (addsize > 0) {
+ byte[] fillup = new byte[addsize];
+ fs.Write (fillup, 0, fillup.Length);
+ }
fs.Write (data, 0, data.Length); // length (again)
- data = BitConverterLE.GetBytes (0x00020200); // magic
+ data = BitConverterLE.GetBytes (0x00020200); // magic
fs.Write (data, 0, data.Length);
fs.Write (asn, 0, asn.Length);
- // fill up
- byte[] fillup = new byte[addsize];
- fs.Write (fillup, 0, fillup.Length);
+ if (addsize_signature > 0) {
+ byte[] fillup = new byte[addsize_signature];
+ fs.Write (fillup, 0, fillup.Length);
+ }
fs.Close ();
}
return true;
public bool Sign (string fileName)
{
try {
- if (!Open (fileName))
- return false;
+ Open (fileName);
HashAlgorithm hash = HashAlgorithm.Create (Hash);
// 0 to 215 (216) then skip 4 (checksum)
- int pe = PEOffset + 88;
- hash.TransformBlock (file, 0, pe, file, 0);
- pe += 4;
- // 220 to 279 (60) then skip 8 (IMAGE_DIRECTORY_ENTRY_SECURITY)
- hash.TransformBlock (file, pe, 60, file, pe);
- pe += 68;
- // 288 to end of file
- int n = file.Length - pe;
- // minus any authenticode signature (with 8 bytes header)
- if (SecurityOffset != 0)
- n -= (SecuritySize);
- hash.TransformFinalBlock (file, pe, n);
-
- byte[] signature = Header (hash.Hash, Hash);
+
+ byte[] digest = GetHash (hash);
+ byte[] signature = Header (digest, Hash);
if (timestamp != null) {
byte[] ts = Timestamp (signature);
// add timestamp information inside the current pkcs7 SignedData instance
PKCS7.ContentInfo sign = new PKCS7.ContentInfo (signedData);
sign.Content.Add (pkcs7.ASN1);
authenticode = sign.ASN1;
+ Close ();
return Save (fileName, authenticode.GetBytes ());
}
try {
AuthenticodeDeformatter def = new AuthenticodeDeformatter (fileName);
byte[] signature = def.Signature;
- if ((signature != null) && Open (fileName)) {
+ if (signature != null) {
+ Open (fileName);
PKCS7.ContentInfo ci = new PKCS7.ContentInfo (signature);
pkcs7 = new PKCS7.SignedData (ci.Content);