mirror of
https://github.com/mtrojnar/osslsigncode.git
synced 2025-04-05 09:08:04 -05:00
PE, MSI: implement -require-leaf-hash for CMD_VERIFY.
This commit is contained in:
parent
30ee6536c4
commit
b96f440b03
116
osslsigncode.c
116
osslsigncode.c
@ -736,7 +736,9 @@ static void usage(const char *argv0)
|
||||
"\t\t[ -in ] <infile> [-out ] <outfile>\n\n"
|
||||
"\textract-signature [ -in ] <infile> [ -out ] <outfile>\n\n"
|
||||
"\tremove-signature [ -in ] <infile> [ -out ] <outfile>\n\n"
|
||||
"\tverify [ -in ] <infile>\n\n"
|
||||
"\tverify [ -in ] <infile>\n"
|
||||
"\t\t[ -require-leaf-hash {md5,sha1,sha2(56),sha384,sha512}:XXXXXXXXXXXX... ]\n"
|
||||
"\n"
|
||||
"",
|
||||
argv0);
|
||||
cleanup_lib_state();
|
||||
@ -988,6 +990,84 @@ static void recalc_pe_checksum(BIO *bio, unsigned int peheader)
|
||||
BIO_write(bio, buf, 4);
|
||||
}
|
||||
|
||||
static unsigned char nib2val(unsigned char c) {
|
||||
if (c >= '0' && c <= '9') {
|
||||
return c - '0';
|
||||
} else if (c >= 'a' && c <= 'f') {
|
||||
return c - 'a' + 10;
|
||||
} else if (c >= 'A' && c <= 'F') {
|
||||
return c - 'A' + 10;
|
||||
}
|
||||
}
|
||||
|
||||
static int verify_leaf_hash(X509 *leaf, char *leafhash) {
|
||||
char *orig = leafhash;
|
||||
char *mdid = orig;
|
||||
char *hash = NULL;
|
||||
while (leafhash != NULL && *leafhash != '\0') {
|
||||
if (*leafhash == ':') {
|
||||
*leafhash = '\0';
|
||||
++leafhash;
|
||||
hash = leafhash;
|
||||
break;
|
||||
}
|
||||
++leafhash;
|
||||
}
|
||||
if (hash == NULL) {
|
||||
printf("Unable to parse -require-leaf-hash parameter: %s\n\n", orig);
|
||||
return 1;
|
||||
}
|
||||
|
||||
const EVP_MD *md = EVP_get_digestbyname(mdid);
|
||||
if (md == NULL) {
|
||||
printf("Unable to lookup digest by name '%s'\n", mdid);
|
||||
return 1;
|
||||
}
|
||||
|
||||
unsigned long sz = EVP_MD_size(md);
|
||||
unsigned long actual = strlen(hash);
|
||||
if (actual%2 != 0) {
|
||||
printf("Hash length mismatch: length is uneven.\n");
|
||||
return 1;
|
||||
}
|
||||
actual /= 2;
|
||||
if (actual != sz) {
|
||||
printf("Hash length mismatch: '%s' digest must be %lu bytes long (got %lu bytes)\n", mdid, sz, actual);
|
||||
return 1;
|
||||
}
|
||||
|
||||
unsigned char mdbuf[EVP_MAX_MD_SIZE];
|
||||
unsigned char cmdbuf[EVP_MAX_MD_SIZE];
|
||||
int i = 0, j = 0;
|
||||
while (i < sz*2) {
|
||||
unsigned char x;
|
||||
x = nib2val(hash[i+1]);
|
||||
x |= nib2val(hash[i]) << 4;
|
||||
mdbuf[j] = x;
|
||||
i += 2;
|
||||
j += 1;
|
||||
}
|
||||
|
||||
unsigned long certlen = i2d_X509(leaf, NULL);
|
||||
unsigned char *certbuf = malloc(certlen);
|
||||
unsigned char *tmp = certbuf;
|
||||
i2d_X509(leaf, &tmp);
|
||||
|
||||
EVP_MD_CTX *ctx = EVP_MD_CTX_create();
|
||||
EVP_DigestInit_ex(ctx, md, NULL);
|
||||
EVP_DigestUpdate(ctx, certbuf, certlen);
|
||||
EVP_DigestFinal_ex(ctx, cmdbuf, NULL);
|
||||
EVP_MD_CTX_destroy(ctx);
|
||||
|
||||
free(certbuf);
|
||||
|
||||
if (memcmp(mdbuf, cmdbuf, EVP_MD_size(md))) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef WITH_GSF
|
||||
static gint msi_base64_decode(gint x)
|
||||
{
|
||||
@ -1254,7 +1334,7 @@ static gboolean msi_handle_dir(GsfInfile *infile, GsfOutfile *outole, BIO *hash)
|
||||
/*
|
||||
* msi_verify_file checks whether or not the signature of infile is valid.
|
||||
*/
|
||||
static int msi_verify_file(GsfInfile *infile) {
|
||||
static int msi_verify_file(GsfInfile *infile, char *leafhash) {
|
||||
GsfInput *sig = NULL;
|
||||
GsfInput *exsig = NULL;
|
||||
gchar decoded[0x40];
|
||||
@ -1419,6 +1499,7 @@ static int msi_verify_file(GsfInfile *infile) {
|
||||
ret = 1;
|
||||
}
|
||||
|
||||
int leafok = 0;
|
||||
STACK_OF(X509) *signers = PKCS7_get0_signers(p7, NULL, 0);
|
||||
printf("Number of signers: %d\n", sk_X509_num(signers));
|
||||
for (i=0; i<sk_X509_num(signers); i++) {
|
||||
@ -1428,6 +1509,10 @@ static int msi_verify_file(GsfInfile *infile) {
|
||||
printf("\tSigner #%d:\n\t\tSubject : %s\n\t\tIssuer : %s\n", i, subject, issuer);
|
||||
OPENSSL_free(subject);
|
||||
OPENSSL_free(issuer);
|
||||
|
||||
if (leafhash != NULL && leafok == 0) {
|
||||
leafok = verify_leaf_hash(cert, leafhash) == 0;
|
||||
}
|
||||
}
|
||||
sk_X509_free(signers);
|
||||
|
||||
@ -1443,6 +1528,12 @@ static int msi_verify_file(GsfInfile *infile) {
|
||||
|
||||
printf("\n");
|
||||
|
||||
if (leafhash != NULL) {
|
||||
printf("Leaf hash match: %s\n\n", leafok ? "ok" : "failed");
|
||||
if (!leafok)
|
||||
ret = 1;
|
||||
}
|
||||
|
||||
out:
|
||||
free(indata);
|
||||
free(exdata);
|
||||
@ -1670,7 +1761,7 @@ static unsigned char *calc_page_hash(char *indata, unsigned int peheader, int pe
|
||||
}
|
||||
|
||||
static int verify_pe_file(char *indata, unsigned int peheader, int pe32plus,
|
||||
unsigned int sigpos, unsigned int siglen)
|
||||
unsigned int sigpos, unsigned int siglen, char *leafhash)
|
||||
{
|
||||
int ret = 0;
|
||||
unsigned int pe_checksum = GET_UINT32_LE(indata + peheader + 88);
|
||||
@ -1779,6 +1870,7 @@ static int verify_pe_file(char *indata, unsigned int peheader, int pe32plus,
|
||||
}
|
||||
|
||||
int i;
|
||||
int leafok = 0;
|
||||
STACK_OF(X509) *signers = PKCS7_get0_signers(p7, NULL, 0);
|
||||
printf("Number of signers: %d\n", sk_X509_num(signers));
|
||||
for (i=0; i<sk_X509_num(signers); i++) {
|
||||
@ -1788,6 +1880,10 @@ static int verify_pe_file(char *indata, unsigned int peheader, int pe32plus,
|
||||
printf("\tSigner #%d:\n\t\tSubject: %s\n\t\tIssuer : %s\n", i, subject, issuer);
|
||||
OPENSSL_free(subject);
|
||||
OPENSSL_free(issuer);
|
||||
|
||||
if (leafhash != NULL && leafok == 0) {
|
||||
leafok = verify_leaf_hash(cert, leafhash) == 0;
|
||||
}
|
||||
}
|
||||
sk_X509_free(signers);
|
||||
|
||||
@ -1806,6 +1902,12 @@ static int verify_pe_file(char *indata, unsigned int peheader, int pe32plus,
|
||||
|
||||
printf("\n");
|
||||
|
||||
if (leafhash != NULL) {
|
||||
printf("Leaf hash match: %s\n\n", leafok ? "ok" : "failed");
|
||||
if (!leafok)
|
||||
ret = 1;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -1848,6 +1950,7 @@ int main(int argc, char **argv)
|
||||
static char buf[64*1024];
|
||||
char *xcertfile, *certfile, *keyfile, *pvkfile, *pkcs12file, *infile, *outfile, *desc, *url, *indata;
|
||||
char *pass = "";
|
||||
char *leafhash = NULL;
|
||||
#ifdef ENABLE_CURL
|
||||
char *turl[MAX_TS_SERVERS], *proxy = NULL, *tsurl[MAX_TS_SERVERS];
|
||||
int nturl = 0, ntsurl = 0;
|
||||
@ -1969,6 +2072,9 @@ int main(int argc, char **argv)
|
||||
if (--argc < 1) usage(argv0);
|
||||
proxy = *(++argv);
|
||||
#endif
|
||||
} else if ((cmd == CMD_VERIFY) && !strcmp(*argv, "-require-leaf-hash")) {
|
||||
if (--argc < 1) usage(argv0);
|
||||
leafhash = (*++argv);
|
||||
} else if (!strcmp(*argv, "-v") || !strcmp(*argv, "--version")) {
|
||||
printf(PACKAGE_STRING ", using:\n\t%s\n\t%s\n",
|
||||
SSLeay_version(SSLEAY_VERSION),
|
||||
@ -2166,7 +2272,7 @@ int main(int argc, char **argv)
|
||||
ret = msi_extract_signature(ole, outfile);
|
||||
goto skip_signing;
|
||||
} else if (cmd == CMD_VERIFY) {
|
||||
ret = msi_verify_file(ole);
|
||||
ret = msi_verify_file(ole, leafhash);
|
||||
goto skip_signing;
|
||||
}
|
||||
|
||||
@ -2338,7 +2444,7 @@ int main(int argc, char **argv)
|
||||
}
|
||||
|
||||
if (cmd == CMD_VERIFY) {
|
||||
ret = verify_pe_file(indata, peheader, pe32plus, sigpos ? sigpos : fileend, siglen);
|
||||
ret = verify_pe_file(indata, peheader, pe32plus, sigpos ? sigpos : fileend, siglen, leafhash);
|
||||
goto skip_signing;
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user