From cb9c4566827fbd85aca696933386f11d51b59905 Mon Sep 17 00:00:00 2001 From: Frank Morgner Date: Thu, 10 Sep 2026 01:19:56 +0200 Subject: [PATCH 1/4] fixed error handling in CVC_verify_authentication_request_signatures --- src/cv_cert.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/cv_cert.c b/src/cv_cert.c index 0765b19..387c07b 100644 --- a/src/cv_cert.c +++ b/src/cv_cert.c @@ -794,6 +794,8 @@ CVC_verify_authentication_request_signatures(EAC_CTX *ctx, data = BUF_MEM_create( ASN1_STRING_length(authentication->certificate_authority_reference) + (size_t) request_len); + if (!data) + goto err; memcpy(data->data, request, request_len); memcpy(data->data + request_len, ASN1_STRING_get0_data(authentication->certificate_authority_reference), From c981e89fdeec5d568188e5f41f5e1a9705c0310b Mon Sep 17 00:00:00 2001 From: Frank Morgner Date: Thu, 10 Sep 2026 01:20:54 +0200 Subject: [PATCH 2/4] fixed error handling with ftell --- src/read_file.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/read_file.c b/src/read_file.c index d5c2a33..cc89371 100644 --- a/src/read_file.c +++ b/src/read_file.c @@ -53,7 +53,7 @@ int read_file(const char *filename, unsigned char **out, size_t *outlen) { FILE *fp = NULL; int fail = 1; - int filesize; + long filesize; unsigned char *p; fp = fopen(filename, "rb"); @@ -74,19 +74,19 @@ int read_file(const char *filename, unsigned char **out, size_t *outlen) fseek(fp, 0L, SEEK_SET); if (0 != filesize) { - p = (unsigned char*) realloc(*out, filesize); + p = (unsigned char*) realloc(*out, (size_t) filesize); if (!p) { puts("Failed to allocate memory"); goto err; } *out = p; - if (filesize != fread(p, sizeof(unsigned char), filesize, fp)) { + if ((size_t) filesize != fread(p, sizeof(unsigned char), (size_t) filesize, fp)) { perror("Failed to read file"); goto err; } } - *outlen = filesize; + *outlen = (size_t) filesize; fail = 0; From 001489063364b6340d1b84136bfbb2d14a687047 Mon Sep 17 00:00:00 2001 From: Frank Morgner Date: Thu, 10 Sep 2026 01:29:39 +0200 Subject: [PATCH 3/4] fixed thread-safe use of gmtime --- src/ta_lib.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/src/ta_lib.c b/src/ta_lib.c index bfd3795..2b8a25f 100644 --- a/src/ta_lib.c +++ b/src/ta_lib.c @@ -105,16 +105,22 @@ cvc_check_time(const CVC_CERT *cert) || ASN1_STRING_length(cert->body->certificate_effective_date) != 6 || !is_bcd(ASN1_STRING_get0_data(cert->body->certificate_effective_date), ASN1_STRING_length(cert->body->certificate_effective_date)) + || !cert->body->certificate_expiration_date || ASN1_STRING_length(cert->body->certificate_expiration_date) != 6 || !is_bcd(ASN1_STRING_get0_data(cert->body->certificate_expiration_date), ASN1_STRING_length(cert->body->certificate_expiration_date))) return -1; - /* FIXME gmtime is not thread safe */ time(&loc); - utc_tm = gmtime(&loc); - if (!utc_tm) +#ifdef _WIN32 + /* `gmtime_s()` is the `gmtime_r()` variant on Windows; + * note reversed argument order */ + if (gmtime_s(&utc_tm_buf, &loc) != 0) return -1; +#else + if (!gmtime_r(&loc, &utc_tm_buf)) + return -1; +#endif memcpy(&eff_tm, utc_tm, sizeof(struct tm)); eff_tm.tm_sec = 0; /* seconds */ From 933d82a317cb0a8fe5bf3b9bd7559eb0dfe0ac78 Mon Sep 17 00:00:00 2001 From: Frank Morgner Date: Thu, 10 Sep 2026 01:59:36 +0200 Subject: [PATCH 4/4] added more defensive checking --- src/cv_cert.c | 5 ++++- src/cvc_lookup.c | 2 +- src/eac_asn1.c | 5 +++-- src/eac_ca.c | 9 +++++++-- src/eac_kdf.c | 8 +++----- src/eac_util.c | 6 +++--- src/x509_lookup.c | 9 +++++---- 7 files changed, 26 insertions(+), 18 deletions(-) diff --git a/src/cv_cert.c b/src/cv_cert.c index 387c07b..832a612 100644 --- a/src/cv_cert.c +++ b/src/cv_cert.c @@ -1214,10 +1214,13 @@ CVC_check_description(const CVC_CERT *cv, const unsigned char *cert_desc_in, unsigned int ret = -1; + if (!cv || !cv->body) + return -1; + count = sk_num((_STACK*) cv->body->certificate_extensions); for (i = 0; i < count; i++) { p = sk_value((_STACK*) cv->body->certificate_extensions, i); - if (OBJ_obj2nid(p->type) == NID_id_description) { + if (p && OBJ_obj2nid(p->type) == NID_id_description) { hash_check = p->discretionary_data1; break; } diff --git a/src/cvc_lookup.c b/src/cvc_lookup.c index af4a822..7426519 100644 --- a/src/cvc_lookup.c +++ b/src/cvc_lookup.c @@ -116,7 +116,7 @@ static int CVC_find_chr_in_directory(const unsigned char *chr, size_t chr_len, if(strlen(dir)+1+chr_len+5 > sizeof path) goto err; - r = BIO_snprintf(path, sizeof path, "%s/%s", dir, chr); + r = BIO_snprintf(path, sizeof path, "%s/%.*s", dir, (int) chr_len, (const char *) chr); if (r <= 0) goto err; diff --git a/src/eac_asn1.c b/src/eac_asn1.c index 24c4ed1..ef29798 100644 --- a/src/eac_asn1.c +++ b/src/eac_asn1.c @@ -380,11 +380,12 @@ aid2pkey(EVP_PKEY **key, ALGORITHM_IDENTIFIER *aid, BN_CTX *bn_ctx) EC_KEY_free(tmp_ec); } else if (nid == NID_standardizedDomainParameters) { - check(aid->parameters->type == V_ASN1_INTEGER, + check(aid->parameters && aid->parameters->type == V_ASN1_INTEGER + && aid->parameters->value.integer, "Invalid data"); check(EVP_PKEY_set_std_dp(tmp_key, ASN1_INTEGER_get(aid->parameters->value.integer)), - "Could not decode standardized domain parameter") + "Could not decode standardized domain parameter"); } else { OBJ_obj2txt(obj_txt, sizeof obj_txt, aid->algorithm, 0); diff --git a/src/eac_ca.c b/src/eac_ca.c index 69c4653..7c3ebc7 100644 --- a/src/eac_ca.c +++ b/src/eac_ca.c @@ -178,11 +178,16 @@ EAC_CTX_init_ef_cardsecurity(const unsigned char *ef_cardsecurity, check((CA_passive_authentication(ctx, p7) == 1), "Failed to perform passive authentication"); + if (!p7->d.sign || !p7->d.sign->contents) + goto err; signed_data = p7->d.sign->contents; - if (OBJ_obj2nid(signed_data->type) != NID_id_SecurityObject + if (!signed_data->type || !signed_data->d.other + || OBJ_obj2nid(signed_data->type) != NID_id_SecurityObject || ASN1_TYPE_get(signed_data->d.other) != V_ASN1_OCTET_STRING) goto err; os = signed_data->d.other->value.octet_string; + if (!os || !os->data) + goto err; if (!EAC_CTX_init_ef_cardaccess(ASN1_STRING_get0_data(os), ASN1_STRING_length(os), ctx) || !ctx || !ctx->ca_ctx || !ctx->ca_ctx->ka_ctx) @@ -305,7 +310,7 @@ CA_STEP6_derive_keys(EAC_CTX *ctx, const BUF_MEM *nonce, const BUF_MEM *token) check(rv >= 0, "Failed to verify authentication token"); /* PACE, TA and CA were successful. Update the trust anchor! */ - if (rv) { + if (rv && ctx->ta_ctx) { if (ctx->ta_ctx->new_trust_anchor) { CVC_CERT_free(ctx->ta_ctx->trust_anchor); ctx->ta_ctx->trust_anchor = ctx->ta_ctx->new_trust_anchor; diff --git a/src/eac_kdf.c b/src/eac_kdf.c index ad10a6f..8694a25 100644 --- a/src/eac_kdf.c +++ b/src/eac_kdf.c @@ -67,7 +67,7 @@ kdf(const BUF_MEM *key, const BUF_MEM *nonce, const uint32_t counter, size_t inlen, key_len; BUF_MEM *in = NULL, *digest = NULL, *out = NULL; - check((key && ka_ctx->md && ka_ctx->cipher), "Invalid arguments"); + check((key && ka_ctx && ka_ctx->md && ka_ctx->cipher), "Invalid arguments"); key_len = EVP_CIPHER_key_length(ka_ctx->cipher); check(0 < EVP_MD_size(ka_ctx->md) @@ -117,11 +117,9 @@ kdf(const BUF_MEM *key, const BUF_MEM *nonce, const uint32_t counter, BUF_MEM * kdf_pi(const PACE_SEC *pi, const BUF_MEM *nonce, const KA_CTX *ctx, EVP_MD_CTX *md_ctx) { - BUF_MEM * out; + check_return(pi && pi->encoded && ctx, "Invalid arguments"); - out = kdf(pi->encoded, nonce, htonl(KDF_PI_COUNTER), ctx, md_ctx); - - return out; + return kdf(pi->encoded, nonce, htonl(KDF_PI_COUNTER), ctx, md_ctx); } BUF_MEM * diff --git a/src/eac_util.c b/src/eac_util.c index dc9304b..6e72f22 100644 --- a/src/eac_util.c +++ b/src/eac_util.c @@ -406,12 +406,12 @@ BUF_MEM * add_iso_pad(const BUF_MEM * m, int block_size) { BUF_MEM * out = NULL; - int p_len; + size_t p_len; - check(m, "Invalid arguments"); + check(m && block_size > 0, "Invalid arguments"); /* calculate length of padded message */ - p_len = (m->length / block_size) * block_size + block_size; + p_len = (m->length / (size_t) block_size) * (size_t) block_size + (size_t) block_size; out = BUF_MEM_create(p_len); if (!out) diff --git a/src/x509_lookup.c b/src/x509_lookup.c index a5b9222..ce00a5c 100644 --- a/src/x509_lookup.c +++ b/src/x509_lookup.c @@ -71,14 +71,15 @@ static X509_STORE *X509_default_lookup(unsigned long issuer_name_hash) { static X509_STORE *store = NULL; - if (!store) - store = X509_STORE_new(); - check(store, "Failed to create trust store"); + if (!store) { + store = X509_STORE_new(); + check(store, "Failed to create trust store"); - if (!X509_STORE_load_locations(store, NULL, x509_default_dir)) { + if (!X509_STORE_load_locations(store, NULL, x509_default_dir)) { log_err("Failed to load trusted certificates"); X509_STORE_free(store); store = NULL; + } } err: