mirror of
https://github.com/mtrojnar/osslsigncode.git
synced 2025-05-21 02:44:28 -05:00
- improved checks for valid PE file
- initialize OpenSSL before we use it - updated documentation links - fixed bug in MSI merge (missing CAB OBJID set) - reindentation + Emacs settings for it - fixed various warnings
This commit is contained in:
parent
b34b3b67e7
commit
d16acb6019
@ -37,6 +37,14 @@ static const char *rcsid = "$Id: osslsigncode.c,v 1.4 2011/08/12 11:08:12 mfive
|
|||||||
|
|
||||||
http://www.microsoft.com/whdc/system/platform/firmware/PECOFF.mspx
|
http://www.microsoft.com/whdc/system/platform/firmware/PECOFF.mspx
|
||||||
|
|
||||||
|
* MS Windows Authenticode PE Signature Format
|
||||||
|
|
||||||
|
http://msdn.microsoft.com/en-US/windows/hardware/gg463183
|
||||||
|
|
||||||
|
(Although the part of how the actual checksumming is done is not
|
||||||
|
how it is done inside Windows. The end result is however the same
|
||||||
|
on all "normal" PE files.)
|
||||||
|
|
||||||
* tail -c, tcpdump, mimencode & openssl asn1parse :)
|
* tail -c, tcpdump, mimencode & openssl asn1parse :)
|
||||||
|
|
||||||
*/
|
*/
|
||||||
@ -480,6 +488,7 @@ static void usage(const char *argv0)
|
|||||||
|
|
||||||
#define DO_EXIT_0(x) { fputs(x, stderr); goto err_cleanup; }
|
#define DO_EXIT_0(x) { fputs(x, stderr); goto err_cleanup; }
|
||||||
#define DO_EXIT_1(x, y) { fprintf(stderr, x, y); goto err_cleanup; }
|
#define DO_EXIT_1(x, y) { fprintf(stderr, x, y); goto err_cleanup; }
|
||||||
|
#define DO_EXIT_2(x, y, z) { fprintf(stderr, x, y, z); goto err_cleanup; }
|
||||||
|
|
||||||
#define GET_UINT16_LE(p) (((u_char*)(p))[0] | (((u_char*)(p))[1]<<8))
|
#define GET_UINT16_LE(p) (((u_char*)(p))[0] | (((u_char*)(p))[1]<<8))
|
||||||
|
|
||||||
@ -544,6 +553,7 @@ static void get_indirect_data_blob(u_char **blob, int *len, const EVP_MD *md, in
|
|||||||
p = OPENSSL_malloc(l);
|
p = OPENSSL_malloc(l);
|
||||||
i2d_SpcLink(link, &p);
|
i2d_SpcLink(link, &p);
|
||||||
p -= l;
|
p -= l;
|
||||||
|
idc->data->type = OBJ_txt2obj(SPC_CAB_DATA_OBJID, 1);
|
||||||
} else if (type == FILE_TYPE_PE) {
|
} else if (type == FILE_TYPE_PE) {
|
||||||
SpcPeImageData *pid = SpcPeImageData_new();
|
SpcPeImageData *pid = SpcPeImageData_new();
|
||||||
pid->flags = ASN1_BIT_STRING_new();
|
pid->flags = ASN1_BIT_STRING_new();
|
||||||
@ -572,6 +582,7 @@ static void get_indirect_data_blob(u_char **blob, int *len, const EVP_MD *md, in
|
|||||||
p -= l;
|
p -= l;
|
||||||
idc->data->type = OBJ_txt2obj(SPC_SIPINFO_OBJID, 1);
|
idc->data->type = OBJ_txt2obj(SPC_SIPINFO_OBJID, 1);
|
||||||
} else {
|
} else {
|
||||||
|
fprintf(stderr, "Unexpected file type: %d\n", type);
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -703,7 +714,7 @@ int main(int argc, char **argv)
|
|||||||
PKCS7_SIGNER_INFO *si;
|
PKCS7_SIGNER_INFO *si;
|
||||||
ASN1_TYPE dummy;
|
ASN1_TYPE dummy;
|
||||||
ASN1_STRING *astr;
|
ASN1_STRING *astr;
|
||||||
const EVP_MD *md = EVP_sha1();
|
const EVP_MD *md;
|
||||||
|
|
||||||
const char *argv0 = argv[0];
|
const char *argv0 = argv[0];
|
||||||
static char buf[64*1024];
|
static char buf[64*1024];
|
||||||
@ -715,14 +726,9 @@ int main(int argc, char **argv)
|
|||||||
u_char *p;
|
u_char *p;
|
||||||
int i, len = 0, type = 0, jp = -1, fd = -1, pe32plus = 0, comm = 0;
|
int i, len = 0, type = 0, jp = -1, fd = -1, pe32plus = 0, comm = 0;
|
||||||
unsigned int tmp, peheader = 0, padlen;
|
unsigned int tmp, peheader = 0, padlen;
|
||||||
|
off_t fileend;
|
||||||
struct stat st;
|
struct stat st;
|
||||||
|
|
||||||
#ifdef WITH_GSF
|
|
||||||
GsfOutfile *outole;
|
|
||||||
GsfOutput *sink;
|
|
||||||
gsf_init();
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
static u_char spcIndirectDataContext_blob_cab[] = {
|
static u_char spcIndirectDataContext_blob_cab[] = {
|
||||||
0x30, 0x50,
|
0x30, 0x50,
|
||||||
@ -772,6 +778,17 @@ int main(int argc, char **argv)
|
|||||||
0xd0, 0xcf, 0x11, 0xe0, 0xa1, 0xb1, 0x1a, 0xe1
|
0xd0, 0xcf, 0x11, 0xe0, 0xa1, 0xb1, 0x1a, 0xe1
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#ifdef WITH_GSF
|
||||||
|
GsfOutfile *outole = NULL;
|
||||||
|
GsfOutput *sink = NULL;
|
||||||
|
gsf_init();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Set up OpenSSL */
|
||||||
|
ERR_load_crypto_strings();
|
||||||
|
OPENSSL_add_all_algorithms_conf();
|
||||||
|
|
||||||
|
md = EVP_sha1();
|
||||||
spcfile = keyfile = pkcs12file = infile = outfile = desc = url = NULL;
|
spcfile = keyfile = pkcs12file = infile = outfile = desc = url = NULL;
|
||||||
hash = outdata = NULL;
|
hash = outdata = NULL;
|
||||||
|
|
||||||
@ -867,10 +884,6 @@ int main(int argc, char **argv)
|
|||||||
if (!infile || !outfile || !((spcfile && keyfile) || pkcs12file))
|
if (!infile || !outfile || !((spcfile && keyfile) || pkcs12file))
|
||||||
usage(argv0);
|
usage(argv0);
|
||||||
|
|
||||||
/* Set up OpenSSL */
|
|
||||||
ERR_load_crypto_strings();
|
|
||||||
OPENSSL_add_all_algorithms_conf();
|
|
||||||
|
|
||||||
/* Read certificate and key */
|
/* Read certificate and key */
|
||||||
if (pkcs12file != NULL) {
|
if (pkcs12file != NULL) {
|
||||||
if ((btmp = BIO_new_file(pkcs12file, "rb")) == NULL ||
|
if ((btmp = BIO_new_file(pkcs12file, "rb")) == NULL ||
|
||||||
@ -899,6 +912,8 @@ int main(int argc, char **argv)
|
|||||||
if (stat(infile, &st))
|
if (stat(infile, &st))
|
||||||
DO_EXIT_1("Failed to open file: %s\n", infile);
|
DO_EXIT_1("Failed to open file: %s\n", infile);
|
||||||
|
|
||||||
|
fileend = st.st_size;
|
||||||
|
|
||||||
if (st.st_size < 4)
|
if (st.st_size < 4)
|
||||||
DO_EXIT_1("Unrecognized file type - file is too short: %s\n", infile);
|
DO_EXIT_1("Unrecognized file type - file is too short: %s\n", infile);
|
||||||
|
|
||||||
@ -960,7 +975,7 @@ int main(int argc, char **argv)
|
|||||||
|
|
||||||
for (i = 0; i < gsf_infile_num_children(ole); i++) {
|
for (i = 0; i < gsf_infile_num_children(ole); i++) {
|
||||||
GsfInput *child = gsf_infile_child_by_index(ole, i);
|
GsfInput *child = gsf_infile_child_by_index(ole, i);
|
||||||
const guint8 *name = gsf_input_name(child);
|
const guint8 *name = (const guint8*)gsf_input_name(child);
|
||||||
msi_decode(name, decoded);
|
msi_decode(name, decoded);
|
||||||
if (!g_strcmp0(decoded, "\05DigitalSignature"))
|
if (!g_strcmp0(decoded, "\05DigitalSignature"))
|
||||||
continue;
|
continue;
|
||||||
@ -1048,18 +1063,38 @@ int main(int argc, char **argv)
|
|||||||
/* Write what's left */
|
/* Write what's left */
|
||||||
BIO_write(hash, indata+i, st.st_size-i);
|
BIO_write(hash, indata+i, st.st_size-i);
|
||||||
} else if (type == FILE_TYPE_PE) {
|
} else if (type == FILE_TYPE_PE) {
|
||||||
|
unsigned int sigpos, siglen, nrvas;
|
||||||
|
unsigned short magic;
|
||||||
|
|
||||||
if (jp >= 0)
|
if (jp >= 0)
|
||||||
fprintf(stderr, "Warning: -jp option is only valid "
|
fprintf(stderr, "Warning: -jp option is only valid "
|
||||||
"for CAB files.\n");
|
"for CAB files.\n");
|
||||||
|
|
||||||
pe32plus = GET_UINT16_LE(indata + peheader + 24) == 0x20b ? 1 : 0;
|
magic = GET_UINT16_LE(indata + peheader + 24);
|
||||||
|
if (magic == 0x20b) {
|
||||||
|
pe32plus = 1;
|
||||||
|
} else if (magic == 0x10b) {
|
||||||
|
pe32plus = 0;
|
||||||
|
} else {
|
||||||
|
DO_EXIT_2("Corrupt PE file - found unknown magic %x: %s\n", magic, infile);
|
||||||
|
}
|
||||||
|
|
||||||
/* If the file has been signed already, this will let us pretend the file we are signing is
|
nrvas = GET_UINT32_LE(indata + peheader + 116 + pe32plus*16);
|
||||||
* only as big as the portion that exists before the signed data at the end of the file.
|
if (nrvas < 5)
|
||||||
* This prevents adding more and more data to the end of the file with each signing.
|
DO_EXIT_1("Can not sign PE files without certificate table resource: %s\n", infile);
|
||||||
*/
|
|
||||||
i = GET_UINT32_LE(indata + peheader + 152 + pe32plus*16);
|
sigpos = GET_UINT32_LE(indata + peheader + 152 + pe32plus*16);
|
||||||
if( i > 0 ) st.st_size = i;
|
siglen = GET_UINT32_LE(indata + peheader + 152 + pe32plus*16 + 4);
|
||||||
|
|
||||||
|
/* Since fix for MS Bulletin MS12-024 we can really assume
|
||||||
|
that signature should be last part of file */
|
||||||
|
if (sigpos > 0 && sigpos + siglen != st.st_size)
|
||||||
|
DO_EXIT_1("Corrupt PE file - current signature not at end of file: %s\n", infile);
|
||||||
|
|
||||||
|
if (sigpos > 0) {
|
||||||
|
/* Strip current signature */
|
||||||
|
fileend = sigpos;
|
||||||
|
}
|
||||||
|
|
||||||
BIO_write(hash, indata, peheader + 88);
|
BIO_write(hash, indata, peheader + 88);
|
||||||
i = peheader + 88;
|
i = peheader + 88;
|
||||||
@ -1071,14 +1106,14 @@ int main(int argc, char **argv)
|
|||||||
BIO_write(outdata, indata + i, 8);
|
BIO_write(outdata, indata + i, 8);
|
||||||
i += 8;
|
i += 8;
|
||||||
|
|
||||||
BIO_write(hash, indata + i, st.st_size - i);
|
BIO_write(hash, indata + i, fileend - i);
|
||||||
|
|
||||||
/* pad (with 0's) pe file to 8 byte boundary */
|
/* pad (with 0's) pe file to 8 byte boundary */
|
||||||
len = 8 - st.st_size % 8;
|
len = 8 - fileend % 8;
|
||||||
if (len > 0 && len != 8) {
|
if (len > 0 && len != 8) {
|
||||||
memset(buf, 0, len);
|
memset(buf, 0, len);
|
||||||
BIO_write(hash, buf, len);
|
BIO_write(hash, buf, len);
|
||||||
st.st_size += len;
|
fileend += len;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
sig = PKCS7_new();
|
sig = PKCS7_new();
|
||||||
@ -1213,12 +1248,12 @@ int main(int argc, char **argv)
|
|||||||
padlen = (8 - len%8) % 8;
|
padlen = (8 - len%8) % 8;
|
||||||
|
|
||||||
if (type == FILE_TYPE_PE) {
|
if (type == FILE_TYPE_PE) {
|
||||||
static const char magic[] = {
|
static const char cert_rev_and_type[] = {
|
||||||
0x00, 0x02, 0x02, 0x00
|
0x00, 0x02, 0x02, 0x00
|
||||||
};
|
};
|
||||||
PUT_UINT32_LE(len+8+padlen, buf);
|
PUT_UINT32_LE(len+8+padlen, buf);
|
||||||
BIO_write(outdata, buf, 4);
|
BIO_write(outdata, buf, 4);
|
||||||
BIO_write(outdata, magic, sizeof(magic));
|
BIO_write(outdata, cert_rev_and_type, sizeof(cert_rev_and_type));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (type == FILE_TYPE_PE || type == FILE_TYPE_CAB) {
|
if (type == FILE_TYPE_PE || type == FILE_TYPE_CAB) {
|
||||||
@ -1231,10 +1266,7 @@ int main(int argc, char **argv)
|
|||||||
}
|
}
|
||||||
#ifdef WITH_GSF
|
#ifdef WITH_GSF
|
||||||
} else if (type == FILE_TYPE_MSI) {
|
} else if (type == FILE_TYPE_MSI) {
|
||||||
GsfOutput *child;
|
GsfOutput *child = gsf_outfile_new_child(outole, "\05DigitalSignature", FALSE);
|
||||||
GError *error = NULL;
|
|
||||||
|
|
||||||
child = gsf_outfile_new_child(outole, "\05DigitalSignature", FALSE);
|
|
||||||
if (!gsf_output_write(child, len, p))
|
if (!gsf_output_write(child, len, p))
|
||||||
DO_EXIT_1("Failed to write MSI signature to %s", infile);
|
DO_EXIT_1("Failed to write MSI signature to %s", infile);
|
||||||
gsf_output_close(child);
|
gsf_output_close(child);
|
||||||
@ -1245,7 +1277,7 @@ int main(int argc, char **argv)
|
|||||||
|
|
||||||
if (type == FILE_TYPE_PE) {
|
if (type == FILE_TYPE_PE) {
|
||||||
(void)BIO_seek(outdata, peheader+152+pe32plus*16);
|
(void)BIO_seek(outdata, peheader+152+pe32plus*16);
|
||||||
PUT_UINT32_LE(st.st_size, buf);
|
PUT_UINT32_LE(fileend, buf);
|
||||||
BIO_write(outdata, buf, 4);
|
BIO_write(outdata, buf, 4);
|
||||||
PUT_UINT32_LE(len+8+padlen, buf);
|
PUT_UINT32_LE(len+8+padlen, buf);
|
||||||
BIO_write(outdata, buf, 4);
|
BIO_write(outdata, buf, 4);
|
||||||
@ -1271,3 +1303,11 @@ err_cleanup:
|
|||||||
fprintf(stderr, "\nFailed\n");
|
fprintf(stderr, "\nFailed\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Local Variables:
|
||||||
|
c-basic-offset: 4
|
||||||
|
tab-width: 4
|
||||||
|
indent-tabs-mode: t
|
||||||
|
End:
|
||||||
|
*/
|
||||||
|
Loading…
x
Reference in New Issue
Block a user