mirror of
https://github.com/mtrojnar/osslsigncode.git
synced 2025-04-09 10:38:05 -05:00
improved verify callbacks
This commit is contained in:
parent
b8e690f3bd
commit
e2ab4a152d
175
osslsigncode.c
175
osslsigncode.c
@ -1173,7 +1173,6 @@ static void print_cert(X509 *cert, int i)
|
||||
issuer = X509_NAME_oneline(X509_get_issuer_name(cert), NULL, 0);
|
||||
serialbn = ASN1_INTEGER_to_BN(X509_get_serialNumber(cert), NULL);
|
||||
serial = BN_bn2hex(serialbn);
|
||||
if (i > 0)
|
||||
printf("\t------------------\n");
|
||||
printf("\tSigner #%d:\n\t\tSubject: %s\n\t\tIssuer : %s\n\t\tSerial : %s\n\t\tCertificate expiration date:\n",
|
||||
i, subject, issuer, serial);
|
||||
@ -1181,6 +1180,7 @@ static void print_cert(X509 *cert, int i)
|
||||
print_asn1_time(X509_get0_notBefore(cert));
|
||||
printf("\t\t\tnotAfter : ");
|
||||
print_asn1_time(X509_get0_notAfter(cert));
|
||||
printf("\n");
|
||||
|
||||
OPENSSL_free(subject);
|
||||
OPENSSL_free(issuer);
|
||||
@ -1189,24 +1189,106 @@ static void print_cert(X509 *cert, int i)
|
||||
}
|
||||
|
||||
/*
|
||||
* Print X509 certificate list from p7->d.sign->cert
|
||||
* [in] p7: PKCS#7 signature
|
||||
* [returns] 1 on success
|
||||
* [in] txt, list
|
||||
* [returns] 0 on error or 1 on success
|
||||
*/
|
||||
static int print_certs(PKCS7 *p7)
|
||||
static int on_list(const char *txt, const char *list[])
|
||||
{
|
||||
X509 *cert;
|
||||
int i, count;
|
||||
|
||||
count = sk_X509_num(p7->d.sign->cert);
|
||||
printf("\nNumber of certificates: %d\n", count);
|
||||
for (i=0; i<count; i++) {
|
||||
cert = sk_X509_value(p7->d.sign->cert, i);
|
||||
if (!cert)
|
||||
return 0; /* FAILED */
|
||||
print_cert(cert, i);
|
||||
}
|
||||
while (*list)
|
||||
if (!strcmp(txt, *list++))
|
||||
return 1; /* OK */
|
||||
return 0; /* FAILED */
|
||||
}
|
||||
|
||||
/*
|
||||
* Check Windows certificate whitelist:
|
||||
* https://learn.microsoft.com/en-us/troubleshoot/windows-server/identity/trusted-root-certificates-are-required
|
||||
* For Microsoft Root Authority, serial number: 00C1008B3C3C8811D13EF663ECDF40,
|
||||
* fingerprint: "F3:84:06:E5:40:D7:A9:D9:0C:B4:A9:47:92:99:64:0F:FB:6D:F9:E2:24:EC:C7:A0:1C:0D:95:58:D8:DA:D7:7D"
|
||||
* expiration date: 12/31/2020, intended purposes: All,
|
||||
* ignore X509_V_ERR_INVALID_CA and X509_V_ERR_CERT_HAS_EXPIRED
|
||||
* [in] cert: X509 certificate
|
||||
* [in] error: error code
|
||||
* [returns] 0 on error or 1 on success
|
||||
*/
|
||||
static int trusted_cert(X509 *cert, int error) {
|
||||
const char *fingerprints[] = {
|
||||
"F3:84:06:E5:40:D7:A9:D9:0C:B4:A9:47:92:99:64:0F:FB:6D:F9:E2:24:EC:C7:A0:1C:0D:95:58:D8:DA:D7:7D",
|
||||
NULL
|
||||
};
|
||||
u_char mdbuf[EVP_MAX_MD_SIZE], *p;
|
||||
char *hex = NULL;
|
||||
int len;
|
||||
const EVP_MD *md = EVP_get_digestbynid(NID_sha256);
|
||||
BIO *bhash = BIO_new(BIO_f_md());
|
||||
|
||||
if (!BIO_set_md(bhash, md)) {
|
||||
BIO_free_all(bhash);
|
||||
return 0; /* FAILED */
|
||||
}
|
||||
BIO_push(bhash, BIO_new(BIO_s_null()));
|
||||
len = i2d_X509(cert, NULL);
|
||||
p = OPENSSL_malloc((size_t)len);
|
||||
i2d_X509(cert, &p);
|
||||
p -= len;
|
||||
BIO_write(bhash, p, len);
|
||||
OPENSSL_free(p);
|
||||
BIO_gets(bhash, (char *)mdbuf, EVP_MD_size(md));
|
||||
BIO_free_all(bhash);
|
||||
|
||||
hex = OPENSSL_buf2hexstr(mdbuf, (size_t)EVP_MD_size(md));
|
||||
if (!hex) {
|
||||
return 0; /* FAILED */
|
||||
}
|
||||
if (on_list(hex, fingerprints)) {
|
||||
printf("\tWarning: Ignoring %s error for Windows certificate whitelist\n",
|
||||
X509_verify_cert_error_string(error));
|
||||
OPENSSL_free(hex);
|
||||
return 1; /* trusted */
|
||||
}
|
||||
OPENSSL_free(hex);
|
||||
return 0; /* untrusted */
|
||||
}
|
||||
|
||||
/*
|
||||
* X509_STORE_CTX_verify_cb
|
||||
*/
|
||||
static int verify_ca_callback(int ok, X509_STORE_CTX *ctx)
|
||||
{
|
||||
int error = X509_STORE_CTX_get_error(ctx);
|
||||
int depth = X509_STORE_CTX_get_error_depth(ctx);
|
||||
|
||||
X509 *current_cert = X509_STORE_CTX_get_current_cert(ctx);
|
||||
print_cert(current_cert, depth);
|
||||
if (!ok) {
|
||||
if (trusted_cert(current_cert, error)) {
|
||||
return 1;
|
||||
} else {
|
||||
printf("\tError: %s\n", X509_verify_cert_error_string(error));
|
||||
}
|
||||
}
|
||||
return ok;
|
||||
}
|
||||
|
||||
static int verify_crl_callback(int ok, X509_STORE_CTX *ctx)
|
||||
{
|
||||
int error = X509_STORE_CTX_get_error(ctx);
|
||||
int depth = X509_STORE_CTX_get_error_depth(ctx);
|
||||
|
||||
X509 *current_cert = X509_STORE_CTX_get_current_cert(ctx);
|
||||
print_cert(current_cert, depth);
|
||||
if (!ok) {
|
||||
if (trusted_cert(current_cert, error)) {
|
||||
return 1;
|
||||
} else if (error == X509_V_ERR_CERT_HAS_EXPIRED) {
|
||||
printf("\tWarning: Ignoring %s error for CRL validation\n",
|
||||
X509_verify_cert_error_string(error));
|
||||
return 1;
|
||||
} else {
|
||||
printf("\tError: %s\n", X509_verify_cert_error_string(error));
|
||||
}
|
||||
}
|
||||
return ok;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -1233,30 +1315,11 @@ static int x509_store_load_file(X509_STORE *store, char *cafile)
|
||||
return 0; /* FAILED */
|
||||
if (!X509_STORE_set1_param(store, param))
|
||||
return 0; /* FAILED */
|
||||
X509_STORE_set_verify_cb(store, verify_ca_callback);
|
||||
|
||||
return 1; /* OK */
|
||||
}
|
||||
|
||||
/* X509_STORE_CTX_verify_cb */
|
||||
static int verify_callback(int ok, X509_STORE_CTX *ctx)
|
||||
{
|
||||
int error = X509_STORE_CTX_get_error(ctx);
|
||||
int depth = X509_STORE_CTX_get_error_depth(ctx);
|
||||
|
||||
if (!ok && error == X509_V_ERR_CERT_HAS_EXPIRED) {
|
||||
if (depth == 0) {
|
||||
printf("\nWarning: Ignoring expired signer certificate for CRL validation\n");
|
||||
return 1;
|
||||
} else {
|
||||
X509 *current_cert = X509_STORE_CTX_get_current_cert(ctx);
|
||||
printf("\nError: Expired CA certificate:\n");
|
||||
print_cert(current_cert, 0);
|
||||
printf("\n");
|
||||
}
|
||||
}
|
||||
return ok;
|
||||
}
|
||||
|
||||
/*
|
||||
* [in, out] store: structure for holding information about X.509 certificates and CRLs
|
||||
* [in] cafile: file contains concatenated CA certificates in PEM format
|
||||
@ -1287,7 +1350,7 @@ static int x509_store_load_crlfile(X509_STORE *store, char *cafile, char *crlfil
|
||||
return 0; /* FAILED */
|
||||
if (!X509_STORE_set1_param(store, param))
|
||||
return 0; /* FAILED */
|
||||
X509_STORE_set_verify_cb(store, verify_callback);
|
||||
X509_STORE_set_verify_cb(store, verify_crl_callback);
|
||||
|
||||
return 1; /* OK */
|
||||
}
|
||||
@ -1326,6 +1389,7 @@ static int verify_crl(char *cafile, char *crlfile, STACK_OF(X509_CRL) *crls,
|
||||
if (crls)
|
||||
X509_STORE_CTX_set0_crls(ctx, crls);
|
||||
|
||||
printf("\nCertificate Revocation List verified by:\n");
|
||||
if (X509_verify_cert(ctx) <= 0) {
|
||||
int error = X509_STORE_CTX_get_error(ctx);
|
||||
printf("\nX509_verify_cert: certificate verify error: %s\n",
|
||||
@ -1567,6 +1631,7 @@ static int verify_timestamp(FILE_FORMAT_CTX *ctx, PKCS7 *p7, CMS_ContentInfo *ti
|
||||
}
|
||||
|
||||
/* verify a CMS SignedData structure */
|
||||
printf("\nTimestamp verified by:\n");
|
||||
if (!CMS_verify(timestamp, NULL, store, 0, NULL, 0)) {
|
||||
printf("\nCMS_verify error\n");
|
||||
X509_STORE_free(store);
|
||||
@ -1680,6 +1745,7 @@ static int verify_authenticode(FILE_FORMAT_CTX *ctx, PKCS7 *p7, time_t time, X50
|
||||
bio = BIO_new_mem_buf(p7->d.sign->contents->d.other->value.sequence->data,
|
||||
p7->d.sign->contents->d.other->value.sequence->length);
|
||||
}
|
||||
printf("\nSigning Certificate Chain:\n");
|
||||
if (!PKCS7_verify(p7, NULL, store, bio, NULL, 0)) {
|
||||
printf("\nPKCS7_verify error\n");
|
||||
X509_STORE_free(store);
|
||||
@ -1812,6 +1878,7 @@ static int print_cms_timestamp(CMS_ContentInfo *timestamp, time_t time)
|
||||
{
|
||||
STACK_OF(CMS_SignerInfo) *sinfos;
|
||||
CMS_SignerInfo *si;
|
||||
X509_ATTRIBUTE *attr;
|
||||
int md_nid;
|
||||
ASN1_INTEGER *serialno;
|
||||
char *issuer_name, *serial;
|
||||
@ -1825,19 +1892,28 @@ static int print_cms_timestamp(CMS_ContentInfo *timestamp, time_t time)
|
||||
si = sk_CMS_SignerInfo_value(sinfos, 0);
|
||||
if (si == NULL)
|
||||
return 0; /* FAILED */
|
||||
printf("\nThe signature is timestamped: ");
|
||||
printf("\nCountersignatures:\n\tTimestamp time: ");
|
||||
print_time_t(time);
|
||||
|
||||
/* PKCS#9 signing time - Policy OID: 1.2.840.113549.1.9.5 */
|
||||
attr = CMS_signed_get_attr(si, CMS_signed_get_attr_by_NID(si, NID_pkcs9_signingTime, -1));
|
||||
if (attr == NULL)
|
||||
return 0; /* FAILED */
|
||||
printf("\tSigning time: ");
|
||||
print_time_t(time_t_get_asn1_time(X509_ATTRIBUTE_get0_data(attr, 0, V_ASN1_UTCTIME, NULL)));
|
||||
|
||||
CMS_SignerInfo_get0_algs(si, NULL, NULL, &pdig, NULL);
|
||||
if (pdig == NULL || pdig->algorithm == NULL)
|
||||
return 0; /* FAILED */
|
||||
md_nid = OBJ_obj2nid(pdig->algorithm);
|
||||
printf("Hash Algorithm: %s\n", (md_nid == NID_undef) ? "UNKNOWN" : OBJ_nid2ln(md_nid));
|
||||
printf("\tHash Algorithm: %s\n", (md_nid == NID_undef) ? "UNKNOWN" : OBJ_nid2ln(md_nid));
|
||||
|
||||
if (!CMS_SignerInfo_get0_signer_id(si, NULL, &issuer, &serialno) || !issuer)
|
||||
return 0; /* FAILED */
|
||||
issuer_name = X509_NAME_oneline(issuer, NULL, 0);
|
||||
serialbn = ASN1_INTEGER_to_BN(serialno, NULL);
|
||||
serial = BN_bn2hex(serialbn);
|
||||
printf("Timestamp Verified by:\n\t\tIssuer : %s\n\t\tSerial : %s\n", issuer_name, serial);
|
||||
printf("\tIssuer: %s\n\tSerial: %s\n", issuer_name, serial);
|
||||
OPENSSL_free(issuer_name);
|
||||
BN_free(serialbn);
|
||||
OPENSSL_free(serial);
|
||||
@ -1871,7 +1947,7 @@ static time_t time_t_timestamp_get_attributes(CMS_ContentInfo **timestamp, PKCS7
|
||||
if (!si)
|
||||
return INVALID_TIME; /* FAILED */
|
||||
md_nid = OBJ_obj2nid(si->digest_alg->algorithm);
|
||||
printf("\nMessage digest algorithm: %s\n",
|
||||
printf("Message digest algorithm: %s\n",
|
||||
(md_nid == NID_undef) ? "UNKNOWN" : OBJ_nid2sn(md_nid));
|
||||
printf("\nAuthenticated attributes:\n");
|
||||
auth_attr = PKCS7_get_signed_attributes(si); /* cont[0] */
|
||||
@ -2336,8 +2412,6 @@ static int verify_signature(FILE_FORMAT_CTX *ctx, PKCS7 *p7)
|
||||
printf("Signer's certificate:\n");
|
||||
print_cert(signer, 0);
|
||||
|
||||
if (!print_certs(p7))
|
||||
printf("Print certs error\n");
|
||||
time = time_t_timestamp_get_attributes(×tamp, p7, ctx->options->verbose);
|
||||
if (ctx->options->leafhash != NULL) {
|
||||
leafok = verify_leaf_hash(signer, ctx->options->leafhash);
|
||||
@ -2358,7 +2432,7 @@ static int verify_signature(FILE_FORMAT_CTX *ctx, PKCS7 *p7)
|
||||
printf("TSA's CRL file: %s\n", ctx->options->tsa_crlfile);
|
||||
if (timestamp) {
|
||||
if (ctx->options->ignore_timestamp) {
|
||||
printf("\nTimestamp Server Signature verification is disabled\n\n");
|
||||
printf("\nTimestamp Server Signature verification is disabled\n");
|
||||
time = INVALID_TIME;
|
||||
} else {
|
||||
int timeok = verify_timestamp(ctx, p7, timestamp, time);
|
||||
@ -2620,19 +2694,6 @@ static void free_options(GLOBAL_OPTIONS *options)
|
||||
options->crls = NULL;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* [in] txt, list
|
||||
* [returns] 0 on error or 1 on success
|
||||
*/
|
||||
static int on_list(const char *txt, const char *list[])
|
||||
{
|
||||
while (*list)
|
||||
if (!strcmp(txt, *list++))
|
||||
return 1; /* OK */
|
||||
return 0; /* FAILED */
|
||||
}
|
||||
|
||||
/*
|
||||
* [in] argv0, cmd
|
||||
* [returns] none
|
||||
|
Loading…
x
Reference in New Issue
Block a user