Example #1
0
        public DSIGInfo(string filename)
        {
            fontfile = new OTFile();
            tDSIG    = null;

            Warn_TTCv1            = false;
            Warn_DSIG_in_memFonts = false;
            Warn_MalformedSIG     = false;
            usNumSigs             = 0;

            if (!fontfile.open(filename))
            {
                throw new IOException("Cannot open file " + filename);
            }

            TTCHeader ttc = null;

            if (fontfile.IsCollection())
            {
                ttc = fontfile.GetTTCHeader();
                if (fontfile.GetTableManager().GetUnaliasedTableName(ttc.DsigTag) == "DSIG")
                {
                    MBOBuffer buf = fontfile.ReadPaddedBuffer(ttc.DsigOffset, ttc.DsigLength);
                    tDSIG = (Table_DSIG)fontfile.GetTableManager().CreateTableObject(ttc.DsigTag, buf);
                }
                for (uint i = 0; i < fontfile.GetNumFonts(); i++)
                {
                    OTFont     fn      = fontfile.GetFont(i);
                    Table_DSIG memDSIG = (Table_DSIG)fn.GetTable("DSIG");
                    if (memDSIG != null)
                    {
                        Warn_DSIG_in_memFonts = true;
                        break;
                    }
                }
            }
            else
            {
                OTFont fn = fontfile.GetFont(0);
                tDSIG = (Table_DSIG)fn.GetTable("DSIG");
            }

            HaveDSIG = ((tDSIG == null) ? false : true);

            // Officially we should only warn if HaveDSIG true
            if (fontfile.IsCollection() && ttc.version != 0x00020000)
            {
                Warn_TTCv1 = true;
            }

            if (HaveDSIG)
            {
                FurtherWork();
            }
        }
        private static TTFRef[] LoadCollectionRefs(BigEndianReader reader, string fullPath)
        {
            TTCHeader     ttc;
            List <TTFRef> refs = new List <TTFRef>();

            if (TTCHeader.TryReadHeader(reader, out ttc))
            {
                for (var f = 0; f < ttc.NumFonts; f++)
                {
                    reader.Position = ttc.FontOffsets[f];

                    var tref = DoLoadRef(reader, fullPath);

                    if (null == tref)
                    {
                        continue;
                    }

                    tref.HeadOffset = (int)ttc.FontOffsets[f];
                    refs.Add(tref);
                }
            }
            return(refs.ToArray());
        }
Example #3
0
        static byte[] get_TTC_digest(OTFile f)
        {
            TTCHeader ttc = f.GetTTCHeader();

            uint back_shift = 12;

            //if ( ttc.version == 0x00020000 )
            back_shift = 0;

            TTCHBuffer ttcb = new TTCHBuffer(12 + ttc.DirectoryCount * 4 + 12 - back_shift);

            // write the TTC header
            ttcb.FillUint32MBO((uint)ttc.TTCTag);
            ttcb.FillUint32MBO(ttc.version);
            ttcb.FillUint32MBO(ttc.DirectoryCount);

            for (int i = 0; i < f.GetNumFonts(); i++)
            {
                ttcb.FillUint32MBO((uint)ttc.DirectoryOffsets[i] - back_shift);
            }
            //if ( ttc.version == 0x00020000 )
            {
                ttcb.FillUint32MBO(0);
                ttcb.FillUint32MBO(0);
                ttcb.FillUint32MBO(0);
            }
            uint Position = (uint)ttcb.buffer.Length;

            hash.TransformBlock(ttcb.buffer, 0, ttcb.buffer.Length, ttcb.buffer, 0);

            // build an array of offset tables
            OffsetTable[] otArr = new OffsetTable[f.GetNumFonts()];
            for (uint iFont = 0; iFont < f.GetNumFonts(); iFont++)
            {
                otArr[iFont] = new OffsetTable(new OTFixed(1, 0), f.GetFont(iFont).GetNumTables());

                for (ushort i = 0; i < f.GetFont(iFont).GetNumTables(); i++)
                {
                    DirectoryEntry old = f.GetFont(iFont).GetDirectoryEntry(i);
                    DirectoryEntry de  = new DirectoryEntry(old);
                    de.offset -= back_shift;
                    otArr[iFont].DirectoryEntries.Add(de);
                }
            }

            if ((uint)ttc.DirectoryOffsets[(int)f.GetNumFonts() - 1] < f.GetFont(0).GetDirectoryEntry(0).offset)
            {
                // assume directory-contiguous
                for (uint iFont = 0; iFont < f.GetNumFonts(); iFont++)
                {
                    // write the offset table
                    hash.TransformBlock(otArr[iFont].m_buf.GetBuffer(), 0, (int)otArr[iFont].m_buf.GetLength(),
                                        otArr[iFont].m_buf.GetBuffer(), 0);
                    Position += otArr[iFont].m_buf.GetLength();

                    // write the directory entries
                    for (int i = 0; i < f.GetFont(iFont).GetNumTables(); i++)
                    {
                        DirectoryEntry de = (DirectoryEntry)otArr[iFont].DirectoryEntries[i];
                        hash.TransformBlock(de.m_buf.GetBuffer(), 0, (int)de.m_buf.GetLength(),
                                            de.m_buf.GetBuffer(), 0);
                        Position += de.m_buf.GetLength();
                    }
                }
            }

            // write out each font
            uint max_offset        = 0;
            uint max_padded_length = 0;
            uint PrevPos           = 0;

            for (uint iFont = 0; iFont < f.GetNumFonts(); iFont++)
            {
                ushort numTables = f.GetFont(iFont).GetNumTables();

                if ((uint)ttc.DirectoryOffsets[(int)f.GetNumFonts() - 1] > f.GetFont(0).GetDirectoryEntry(0).offset)
                {
                    // assume font-contiguous
                    // write the offset table
                    hash.TransformBlock(otArr[iFont].m_buf.GetBuffer(), 0, (int)otArr[iFont].m_buf.GetLength(),
                                        otArr[iFont].m_buf.GetBuffer(), 0);
                    Position += otArr[iFont].m_buf.GetLength();

                    // write the directory entries
                    for (int i = 0; i < numTables; i++)
                    {
                        DirectoryEntry de = (DirectoryEntry)otArr[iFont].DirectoryEntries[i];
                        hash.TransformBlock(de.m_buf.GetBuffer(), 0, (int)de.m_buf.GetLength(),
                                            de.m_buf.GetBuffer(), 0);
                        Position += de.m_buf.GetLength();
                    }
                }

                // write out each table unless a shared version has been written
                for (ushort i = 0; i < numTables; i++)
                {
                    DirectoryEntry de = (DirectoryEntry)otArr[iFont].DirectoryEntries[i];
                    if (de.offset > max_offset)
                    {
                        max_offset        = de.offset;
                        max_padded_length = f.GetFont(iFont).GetTable(de.tag).GetBuffer().GetPaddedLength();
                    }
                    if (PrevPos < de.offset) //crude
                    {
                        OTTable table = f.GetFont(iFont).GetTable(de.tag);
                        hash.TransformBlock(table.m_bufTable.GetBuffer(), 0, (int)table.GetBuffer().GetPaddedLength(),
                                            table.m_bufTable.GetBuffer(), 0);
                        Position += table.GetBuffer().GetPaddedLength();
                        PrevPos   = de.offset;
                    }
                }
            }

            if (max_offset + max_padded_length - Position != 0)
            {
                throw new NotImplementedException("Unusual TTC Directory Layout");
            }
            byte[] usFlag = { 0, 1 };
            hash.TransformFinalBlock(usFlag, 0, 2);
            return(hash.Hash);
        }
Example #4
0
        static int Main(string[] args)
        {
            if (args.Length == 0)
            {
                Console.WriteLine("DSIGInfo [-v] [-v] [-v] fontfile");
                return(0);
            }

            OTFile     f        = new OTFile();
            Table_DSIG tDSIG    = null;
            string     filename = null;

            verbose = 0;

            for (int i = 0; i < args.Length; i++)
            {
                if ("-v" == args[i])
                {
                    verbose++;
                }
                else
                {
                    filename = args[i];
                }
            }

            if (!f.open(filename))
            {
                Console.WriteLine("Error: Cannot open {0} as font file", filename);
                return(0);
            }

            TTCHeader ttc = null;

            if (f.IsCollection())
            {
                ttc = f.GetTTCHeader();
                if (f.GetTableManager().GetUnaliasedTableName(ttc.DsigTag) == "DSIG")
                {
                    MBOBuffer buf = f.ReadPaddedBuffer(ttc.DsigOffset, ttc.DsigLength);
                    tDSIG = (Table_DSIG)f.GetTableManager().CreateTableObject(ttc.DsigTag, buf);
                }
                for (uint i = 0; i < f.GetNumFonts(); i++)
                {
                    OTFont     fn      = f.GetFont(i);
                    Table_DSIG memDSIG = (Table_DSIG)fn.GetTable("DSIG");
                    if (memDSIG != null)
                    {
                        Console.WriteLine("Warning: DSIG in member font");
                        break;
                    }
                }
            }
            else
            {
                OTFont fn = f.GetFont(0);
                tDSIG = (Table_DSIG)fn.GetTable("DSIG");
            }

            Console.WriteLine("{0} DSIG table: {1}", filename,
                              (tDSIG == null) ? "Absent" : "Present");
            if (tDSIG == null)
            {
                return(0);
            }
            if (f.IsCollection() && ttc.version != 0x00020000)
            {
                Console.WriteLine("Warning: TTC has DSIG but header version is 0x{0}, != 0x00020000", ttc.version.ToString("X8"));
            }

            if (tDSIG.usNumSigs != 1)
            {
                Console.WriteLine("NumSigs = {0}", tDSIG.usNumSigs);
            }
            for (uint v = 0; v < tDSIG.usNumSigs; v++)
            {
                Table_DSIG.SignatureBlock sgb;
                try {
                    sgb = tDSIG.GetSignatureBlock(v);
                } catch (IndexOutOfRangeException)
                {
                    Console.WriteLine("Error: Out of Range SignatureBlock {0}", v);
                    break;
                }

                SignedCms cms = new SignedCms();
                try
                {
                    cms.Decode(sgb.bSignature);
                }
                catch (Exception e)
                {
                    if (e is NullReferenceException || /* Mono */
                        e is CryptographicException /* .Net2 */)
                    {
                        Console.WriteLine("Error: Malformed Signature");
                        break;
                    }
                    Console.WriteLine("Error: Malformed Signature (Unexpected Case 1)");
                    throw;
                }

                if (cms.SignerInfos.Count > 1)
                {
                    Console.WriteLine("#SignerInfos: {0}", cms.SignerInfos.Count);
                }
                foreach (var si in cms.SignerInfos)
                {
                    Console.WriteLine(si.Certificate);
                    if (Type.GetType("Mono.Runtime") == null)
                    {
                        foreach (var ua in si.UnsignedAttributes)
                        {
                            foreach (var asnd in ua.Values)
                            {
                                try
                                {
                                    ASN1 vv = new ASN1(asnd.RawData);
                                    ASN1 t  = new ASN1(vv[3][1][1].Value);
                                    Console.WriteLine("Decoded Signing Time: {0}", ASN1Convert.ToDateTime(t));
                                }
                                catch (Exception)
                                { /* Nothing to do */ }
                            }
                        }
                    }
                }
                Console.WriteLine("#Certificates: {0}", cms.Certificates.Count);
#if HAVE_MONO_X509
                certs = new Mono.Security.X509.X509CertificateCollection();
                //Mono.Security.X509.X509Chain signerChain = new Mono.Security.X509.X509Chain ();
#endif
                foreach (var x509 in cms.Certificates)
                {
#if HAVE_MONO_X509
                    certs.Add(new Mono.Security.X509.X509Certificate(x509.RawData));
#endif
                    if (verbose > 0)
                    {
                        Console.WriteLine(x509);
                    }
                    else
                    {
                        Console.WriteLine(x509.Subject);
                    }
                }
                ;
#if HAVE_MONO_X509
                Mono.Security.X509.X509Certificate x      = new Mono.Security.X509.X509Certificate(cms.SignerInfos[0].Certificate.RawData);
                Mono.Security.X509.X509Certificate parent = x;
                while (x != null) // Self-signed is fine - the font bundled CA is self-signed.
                {
                    parent = x;   // last valid
                    x      = FindCertificateParent(x);
                    if (x != null && x.Equals(parent))
                    {
                        break;
                    }
                }
#endif
                // Windows 10/.net 4.6.x throws here
                ASN1 spc;
                try
                {
                    spc = new ASN1(cms.ContentInfo.Content);
                }
                catch (Exception e)
                {
                    if (e is IndexOutOfRangeException)
                    {
                        Console.WriteLine("Error: Malformed Signature (Win10/.net 4.6.x)");
                        break;
                    }
                    Console.WriteLine("Error: Malformed Signature (Unexpected Case 2)");
                    throw;
                }

                ASN1 playload_oid = null;
                ASN1 oid          = null;
                ASN1 digest       = null;
                ASN1 obsolete     = null;
                if (Type.GetType("Mono.Runtime") == null)
                {
                    // DotNet is much saner!
                    playload_oid = spc[0][0];
                    obsolete     = spc[0][1][0];
                    oid          = spc[1][0][0];
                    digest       = spc[1][1];
                }
                else
                {
                    playload_oid = spc[0];
                    obsolete     = spc[1][0];
                    oid          = spc[2][0][0];
                    digest       = spc[2][1];
                }
                string algo     = ASN1Convert.ToOid(oid);
                string algoname = (new Oid(algo)).FriendlyName;
                Console.WriteLine("Digest Algorithm: {0}", algoname);
                byte[]        Value       = digest.Value;
                StringBuilder hexLine_sig = new StringBuilder();
                for (int i = 0; i < Value.Length; i++)
                {
                    hexLine_sig.AppendFormat("{0} ", Value [i].ToString("X2"));
                }
                hexLine_sig.AppendFormat(Environment.NewLine);

                switch (algoname)
                {
                case "md5":
                    hash = HashAlgorithm.Create("MD5");
                    break;

                case "sha1":
                    hash = HashAlgorithm.Create("SHA1");
                    break;

                default:
                    throw new NotImplementedException("Unknown HashAlgorithm: " + algoname);
                }

                byte[] cdigest;
                if (f.IsCollection())
                {
                    cdigest = get_TTC_digest(f);
                }
                else
                {
                    cdigest = get_TTF_digest(f);
                }
                StringBuilder hexLine = new StringBuilder();
                for (int i = 0; i < cdigest.Length; i++)
                {
                    hexLine.AppendFormat("{0} ", cdigest [i].ToString("X2"));
                }
                hexLine.AppendFormat(Environment.NewLine);
                Console.WriteLine("{0} Signed Digest:\t{1}", algoname.ToUpper(), hexLine_sig);
                Console.WriteLine("Calculated Digest:\t{0}", hexLine);
                string root_thumb = "";
#if HAVE_MONO_X509
                root_thumb =
                    (new System.Security.Cryptography.X509Certificates.X509Certificate2(parent.RawData)).Thumbprint;
                Console.WriteLine("ChainEnd Name: {0}", parent.SubjectName);
                Console.WriteLine("ChainEnd Self-Signed: {0}", parent.IsSelfSigned);
#endif
                Console.WriteLine("ChainEnd: {0}", root_thumb);
                bool trusted = false;
                try
                {
                    string root_id = trusted_roots[root_thumb];
                    Console.WriteLine("RootID: {0}", root_id);
                    trusted = true;
                }
                catch (KeyNotFoundException)
                {}
                Console.WriteLine("Trusted: {0}", trusted);
            }

            return(0);
        }