Skip to content

Commit

Permalink
android system CA store is hashed with old(md5) method
Browse files Browse the repository at this point in the history
  • Loading branch information
ekoby committed Dec 23, 2024
1 parent 6b9a68b commit 193cf39
Show file tree
Hide file tree
Showing 2 changed files with 96 additions and 4 deletions.
61 changes: 58 additions & 3 deletions src/openssl/engine.c
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,6 @@ static void tls_set_cert_verify(tls_context *ctx,

static int parse_pkcs7_certs(tlsuv_certificate_t *chain, const char *pkcs7, size_t pkcs7len);

static int write_cert_pem(tlsuv_certificate_t cert, int full_chain, char **pem, size_t *pemlen);
static int load_cert(tlsuv_certificate_t *cert, const char *buf, size_t buflen);

static int generate_csr(tlsuv_private_key_t key, char **pem, size_t *pemlen, ...);
Expand All @@ -121,6 +120,7 @@ static int tls_set_partial_vfy(tls_context *ctx, int allow);

static BIO_METHOD *BIO_s_engine(void);

static X509_LOOKUP_METHOD * old_hash_lookup(void);

#if _WIN32
static X509_STORE *load_system_certs();
Expand Down Expand Up @@ -203,6 +203,10 @@ static X509_STORE * load_certs(const char *buf, size_t buf_len) {
if (!X509_STORE_load_locations(certs, buf, NULL)) {
UM_LOG(ERR, "failed to load certs from [%s]", buf);
}
} if (fstat.st_mode & S_IFDIR) {
X509_STORE_load_path(certs, buf);
X509_LOOKUP *lu = X509_STORE_add_lookup(certs, old_hash_lookup());
X509_LOOKUP_set_method_data(lu, (void*)buf);
} else {
UM_LOG(ERR, "cert bundle[%s] is not a regular file", buf);
}
Expand Down Expand Up @@ -358,6 +362,54 @@ static X509_STORE** process_chains(X509_STORE *store, int *count) {
return stores;
}

static int by_subj_old_hash(X509_LOOKUP *lu, X509_LOOKUP_TYPE t, const X509_NAME *name, X509_OBJECT *obj){
if (t != X509_LU_X509) return 0;

const char *dir = X509_LOOKUP_get_method_data(lu);
if (dir == NULL) return 0;

char path[PATH_MAX];

Check failure on line 371 in src/openssl/engine.c

View workflow job for this annotation

GitHub Actions / x64-windows-static-md-openssl

'PATH_MAX': undeclared identifier [D:\a\tlsuv\tlsuv\build\tlsuv.vcxproj]

Check failure on line 371 in src/openssl/engine.c

View workflow job for this annotation

GitHub Actions / x64-windows-static-md-openssl

expected constant expression [D:\a\tlsuv\tlsuv\build\tlsuv.vcxproj]

Check failure on line 371 in src/openssl/engine.c

View workflow job for this annotation

GitHub Actions / x64-windows-static-md-openssl

cannot allocate an array of constant size 0 [D:\a\tlsuv\tlsuv\build\tlsuv.vcxproj]

Check failure on line 371 in src/openssl/engine.c

View workflow job for this annotation

GitHub Actions / x64-windows-static-md-openssl

'path': unknown size [D:\a\tlsuv\tlsuv\build\tlsuv.vcxproj]
unsigned long h[] = {
X509_NAME_hash_old(name),
X509_NAME_hash(name),
};
int count = 0;
for (int i = 0; i < sizeof(h)/sizeof(h[0]); i++) {
for (int idx = 0; ; idx ++) {
snprintf(path, sizeof(path), "%s/%08lx.%d", dir, h[i], idx);
struct stat s;
if (stat(path, &s) != 0) break;
if ((s.st_mode & S_IFREG) == 0) {
continue;
}

if (X509_load_cert_file(lu, path, X509_FILETYPE_PEM) == 0) break;
count++;
}
}
if (count == 0) return 0;

X509_STORE *store = X509_LOOKUP_get_store(lu);
STACK_OF(X509_OBJECT) *objs = X509_STORE_get1_objects(store);
X509_OBJECT *res = X509_OBJECT_retrieve_by_subject(objs, X509_LU_X509, name);
sk_X509_OBJECT_free(objs);
if (res) {
X509_OBJECT_set1_X509(obj, X509_OBJECT_get0_X509(res));
return 1;
} else {
return 0;
}
}

static X509_LOOKUP_METHOD * old_hash_lookup(void) {
static X509_LOOKUP_METHOD *method = NULL;
if (method == NULL) {
method = X509_LOOKUP_meth_new("old-hash-lookup");
X509_LOOKUP_meth_set_get_by_subject(method, by_subj_old_hash);
}
return method;
}

static void init_ssl_context(struct openssl_ctx *c, const char *cabuf, size_t cabuf_len) {
SSL_library_init();

Expand All @@ -376,17 +428,20 @@ static void init_ssl_context(struct openssl_ctx *c, const char *cabuf, size_t ca
X509_STORE *ca = load_certs(cabuf, cabuf_len);
c->ca_chains = process_chains(ca, &c->ca_chains_count);
SSL_CTX_set0_verify_cert_store(ctx, ca);
SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, verify_peer_cb);
SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, verify_peer_cb);
} else {
// try loading default CA stores
#if _WIN32
X509_STORE *ca = load_system_certs();
SSL_CTX_set0_verify_cert_store(ctx, ca);
#elif defined(ANDROID) || defined(__ANDROID__)
SSL_CTX_load_verify_locations(ctx, NULL, "/system/etc/security/cacerts");
X509_STORE *ca = SSL_CTX_get_cert_store(ctx);
X509_LOOKUP *lu = X509_STORE_add_lookup(ca, old_hash_lookup());
X509_LOOKUP_set_method_data(lu, (void*)"/etc/security/cacerts");
#else
SSL_CTX_set_default_verify_paths(ctx);
#endif
SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, NULL);
}
SSL_CTX_set_min_proto_version(ctx, TLS1_2_VERSION);
SSL_CTX_set_max_proto_version(ctx, TLS1_3_VERSION);
Expand Down
39 changes: 38 additions & 1 deletion tests/http_tests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1223,7 +1223,7 @@ sQIwJonMaAFi54mrfhfoFNZEfuNMSQ6/bIBiNLiyoX46FohQvKeIoJ99cx7sUkFN
tlsuv_http_set_ssl(&clt, tls);

struct result_t {
int code;
int code{0};
std::string msg;
} result;
tlsuv_http_req(&clt, "GET", "/version",
Expand Down Expand Up @@ -1257,4 +1257,41 @@ sQIwJonMaAFi54mrfhfoFNZEfuNMSQ6/bIBiNLiyoX46FohQvKeIoJ99cx7sUkFN

tlsuv_http_close(&clt, nullptr);
uv_run(loop, UV_RUN_DEFAULT);
}

// test for exercising CA store that's
// hashing certs with X509_NAME_hash_old()/MD5
// e.g. on Android
TEST_CASE("old-ca-store", "[http]") {
auto ca_dir = getenv("TLSUV_TEST_OLD_CA_DIR");
if (ca_dir == nullptr) {
SKIP("TLSUV_TEST_OLD_CA_DIR is not set");
return;
}
auto loop = uv_loop_new();
tlsuv_http_t clt{};
tlsuv_http_init(loop, &clt, "https://google.com");
auto tls = default_tls_context(ca_dir, 0);
tlsuv_http_set_ssl(&clt, tls);

struct result_t {
int code{0};
std::string msg;
} result;
tlsuv_http_req(&clt, "GET", "/",
[](tlsuv_http_resp_t *resp, void *res){
auto r = (result_t*)res;
r->code = resp->code;
r->msg = resp->status;
},
&result);
uv_run(loop, UV_RUN_DEFAULT);

// should get HTTP response here
INFO(result.msg);
CHECK(result.code >= 200);

tlsuv_http_close(&clt, nullptr);
uv_run(loop, UV_RUN_DEFAULT);
uv_loop_delete(loop);
}

0 comments on commit 193cf39

Please sign in to comment.