244 lines
5.2 KiB
C++
244 lines
5.2 KiB
C++
#include "binaryverifier.h"
|
|
|
|
#include <QFile>
|
|
#include <stdio.h>
|
|
|
|
#include "elf32.h"
|
|
|
|
#include <string.h>
|
|
|
|
//++
|
|
typedef char g_sign_string16_t[16];
|
|
typedef char g_sign_string32_t[32];
|
|
typedef char g_sign_string64_t[64];
|
|
typedef char g_sign_string128_t[128];
|
|
typedef char g_sign_string256_t[256];
|
|
typedef char g_sign_string512_t[256];
|
|
|
|
typedef uint8_t g_sign_id_t[16]; /*exactly 8 chars*/
|
|
|
|
struct g_sign_static_data_t
|
|
{
|
|
g_sign_string16_t nickname;
|
|
g_sign_string16_t vstr;
|
|
g_sign_string32_t pn;
|
|
g_sign_string32_t fullname;
|
|
g_sign_string64_t info;
|
|
};
|
|
|
|
struct g_sign_static_t
|
|
{
|
|
g_sign_id_t marker_begin; /* '<<GS++>>' */
|
|
g_sign_id_t signversion;
|
|
|
|
g_sign_static_data_t data;
|
|
|
|
uint32_t dummy_signversion_align;
|
|
g_sign_id_t marker_end; /* '<<GS-->>' */
|
|
};
|
|
|
|
#define G_SIGN_STATIC_BEGIN(INAME_) const struct g_sign_static_t INAME_={ "<<GS+>>@!#!", "0.0",{
|
|
#define G_SIGN_STATIC_END }, 0, "<<GS->>@!#!"}
|
|
|
|
#define G_SIGN_STR_VER2(vmajor_, vminor_) #vmajor_ "." #vminor_
|
|
#define G_SIGN_STR_VER3(vmajor_, vminor_, vbrach_) #vmajor_ "." #vminor_ "." ##vbrach_
|
|
|
|
|
|
struct g_sign_extern_data_t
|
|
{
|
|
g_sign_string64_t fullname;
|
|
g_sign_string64_t filename;
|
|
|
|
g_sign_string16_t buildid;
|
|
|
|
g_sign_string64_t date;
|
|
|
|
g_sign_string64_t host;
|
|
|
|
g_sign_string64_t md5_hash_str;
|
|
g_sign_string16_t md5_hash_bin;
|
|
|
|
g_sign_string512_t cms_signature; /*from CMS, that is SVN or GIT or what else*/
|
|
|
|
g_sign_string512_t userinfo;
|
|
};
|
|
|
|
struct g_sign_extern_t
|
|
{
|
|
g_sign_id_t marker_begin; /* '((GS++))' */
|
|
g_sign_id_t signversion;
|
|
|
|
g_sign_extern_data_t data;
|
|
|
|
uint32_t dummy_signversion_align;
|
|
g_sign_id_t marker_end; /* '((GS--))' */
|
|
};
|
|
//--
|
|
|
|
class BinaryVerifier::Implementation
|
|
{
|
|
public:
|
|
QString errorString;
|
|
BinaryInfo info;
|
|
|
|
Implementation()
|
|
{
|
|
}
|
|
|
|
};
|
|
|
|
BinaryVerifier::BinaryVerifier():
|
|
p_(*new Implementation)
|
|
{
|
|
|
|
}
|
|
|
|
BinaryVerifier::~BinaryVerifier()
|
|
{
|
|
delete &p_;
|
|
}
|
|
|
|
BinaryInfo BinaryVerifier::info() const
|
|
{
|
|
return p_.info;
|
|
}
|
|
|
|
bool BinaryVerifier::verify(const QString &filename)
|
|
{
|
|
QFile f(filename);
|
|
bool ok=f.open(QIODevice::ReadOnly);
|
|
|
|
if (!ok)
|
|
{
|
|
p_.errorString=f.errorString();
|
|
return false;
|
|
}
|
|
|
|
QByteArray d=f.readAll();
|
|
return verify(d);
|
|
}
|
|
|
|
bool BinaryVerifier::verify(const QByteArray& d)
|
|
{
|
|
Elf32_Ehdr h;
|
|
qint64 r=d.size(); //f.read((char*)&h, sizeof h);
|
|
if (r<sizeof h)
|
|
{
|
|
p_.errorString="Reading header";
|
|
return false;
|
|
}
|
|
|
|
h=*(Elf32_Ehdr*)d.constData();
|
|
|
|
if (!((h.e_ident[0]==ELFMAG0) || (h.e_ident[1]==ELFMAG1) || (h.e_ident[2]==ELFMAG2) || (h.e_ident[3]==ELFMAG3)))
|
|
{
|
|
p_.info.m_ftm=BinaryInfo::Binary;
|
|
p_.info.m_fmtName="Binary";
|
|
//A Xilinx bitstream?
|
|
return true;
|
|
}
|
|
p_.info.m_ftm=BinaryInfo::ELF;
|
|
p_.info.m_fmtName="ELF";
|
|
|
|
if (h.e_ident[EI_DATA]!=ELFDATA2LSB)
|
|
{
|
|
p_.errorString="Big Endian";
|
|
return false;
|
|
}
|
|
if (h.e_ident[EI_CLASS]!=ELFCLASS32)
|
|
{
|
|
p_.errorString="64bits";
|
|
return false;
|
|
}
|
|
|
|
if (h.e_type!=ET_EXEC)
|
|
{
|
|
p_.errorString="not ELF EXEC";
|
|
return false;
|
|
}
|
|
|
|
switch(h.e_machine)
|
|
{
|
|
case EM_TI_C6000:
|
|
p_.info.m_arch=BinaryInfo::C6000;
|
|
p_.info.m_archName="C6000";
|
|
p_.info.m_pn="TMS320C6XXX";
|
|
p_.info.m_partType="XMC-DSP";
|
|
break;
|
|
case EM_ARM:
|
|
p_.info.m_arch=BinaryInfo::ARM;
|
|
p_.info.m_archName="ARM";
|
|
p_.info.m_partType="XMC-ZynQ(?)";
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
|
|
//QByteArray d=f.readAll();
|
|
|
|
p_.info.m_hasInfo=false;
|
|
|
|
{
|
|
int spos=0;
|
|
int epos=0;
|
|
|
|
QString markerBegin("<<GS+>>");
|
|
QString markerEnd("<<GS->>");
|
|
int expected_size=sizeof(g_sign_static_t)-sizeof(g_sign_id_t);
|
|
|
|
do
|
|
{
|
|
spos=d.indexOf(markerBegin, spos+1);
|
|
epos=d.indexOf(markerEnd, spos);
|
|
int size=epos-spos;
|
|
if ((spos>=0) || (epos>spos))
|
|
{
|
|
if (size>=expected_size)
|
|
{
|
|
g_sign_static_t s=*reinterpret_cast<const g_sign_static_t*>(&(d.data()[spos]));
|
|
p_.info.m_hasInfo=true;
|
|
p_.info.m_name=s.data.fullname;
|
|
p_.info.m_usr=s.data.info;
|
|
p_.info.m_ibc=s.data.pn;
|
|
p_.info.m_version=s.data.vstr;
|
|
break;
|
|
}
|
|
}
|
|
} while(spos>=0);
|
|
}
|
|
|
|
{
|
|
int spos=0;
|
|
int epos=0;
|
|
|
|
QString markerBegin("<<GX+>>");
|
|
QString markerEnd("<<GX->>");
|
|
int expected_size=sizeof(g_sign_extern_t)-sizeof(g_sign_id_t);
|
|
|
|
do
|
|
{
|
|
spos=d.indexOf(markerBegin, spos+1);
|
|
epos=d.indexOf(markerEnd, spos);
|
|
int size=epos-spos;
|
|
if ((spos>=0) || (epos>spos))
|
|
{
|
|
if (size>=expected_size)
|
|
{
|
|
g_sign_extern_t s=*reinterpret_cast<const g_sign_extern_t*>(&(d.data()[spos]));
|
|
p_.info.m_hasInfo=true;
|
|
//p_.info.m_name=s.data.fullname;
|
|
p_.info.m_host=s.data.host;
|
|
p_.info.m_bid=s.data.buildid;
|
|
p_.info.m_md5=s.data.md5_hash_str;
|
|
//p_.info.m_usr=s.data.userinfo;
|
|
p_.info.m_date=s.data.date;
|
|
break;
|
|
}
|
|
}
|
|
} while(spos>=0);
|
|
}
|
|
|
|
return true;
|
|
}
|