diff options
| author | Dimitri Staessens <dimitri@ouroboros.rocks> | 2026-06-12 19:34:27 +0200 |
|---|---|---|
| committer | Sander Vrijders <sander@ouroboros.rocks> | 2026-06-29 08:32:58 +0200 |
| commit | 977bcac2d56a8793ed93b4aac7016ef36b51a07f (patch) | |
| tree | 7e26553a57cbdc75d9c33b25fe228631dea36142 /src/lib/crypt.c | |
| parent | 67c55d5869d5473e5139614637f31ea37746181d (diff) | |
| download | ouroboros-977bcac2d56a8793ed93b4aac7016ef36b51a07f.tar.gz ouroboros-977bcac2d56a8793ed93b4aac7016ef36b51a07f.zip | |
irmd: Add issuer and digest pinning to OAP
A peer certificate that verifies against the CA store could have
been issued by any trusted CA, and a peer could pick any supported
digest for its signature. Tighten the authentication contract with
two local policies.
cacert= pins the issuing CA: a peer certificate, if presented, must
chain through the pinned CA. Whether a certificate is mandatory at
all remains controlled by auth= alone.
digest= now also pins the signature digest: a classical peer must sign
with the locally configured digest, and may not omit the digest NID to
fall back to the key's default digest. PQC signatures (ML-DSA,
SLH-DSA) have an intrinsic digest and may be NID_undef.
Signed-off-by: Dimitri Staessens <dimitri@ouroboros.rocks>
Signed-off-by: Sander Vrijders <sander@ouroboros.rocks>
Diffstat (limited to 'src/lib/crypt.c')
| -rw-r--r-- | src/lib/crypt.c | 58 |
1 files changed, 56 insertions, 2 deletions
diff --git a/src/lib/crypt.c b/src/lib/crypt.c index 66d07131..73cb0b51 100644 --- a/src/lib/crypt.c +++ b/src/lib/crypt.c @@ -141,7 +141,8 @@ struct crypt_ctx { }; struct auth_ctx { - void * store; + void * store; /* trusted anchors */ + void * chain; /* untrusted build-only interm */ }; static int parse_kex_value(const char * value, @@ -229,6 +230,10 @@ int parse_sec_config(struct sec_config * cfg, } else { return -EINVAL; } + } else if (strcmp(key, "cacert") == 0) { + if (strlen(value) >= sizeof(cfg->cacert)) + return -EINVAL; + strcpy(cfg->cacert, value); } else if (strcmp(key, "encryption") == 0) { if (strcmp(value, "none") != 0) return -EINVAL; @@ -988,9 +993,15 @@ struct auth_ctx * auth_create_ctx(void) ctx->store = openssl_auth_create_store(); if (ctx->store == NULL) goto fail_store; + + ctx->chain = openssl_auth_create_chain(); + if (ctx->chain == NULL) + goto fail_chain; #endif return ctx; #ifdef HAVE_OPENSSL + fail_chain: + openssl_auth_destroy_store(ctx->store); fail_store: free(ctx); #endif @@ -1003,6 +1014,7 @@ void auth_destroy_ctx(struct auth_ctx * ctx) if (ctx == NULL) return; #ifdef HAVE_OPENSSL + openssl_auth_destroy_chain(ctx->chain); openssl_auth_destroy_store(ctx->store); #endif free(ctx); @@ -1024,11 +1036,27 @@ int auth_add_crt_to_store(struct auth_ctx * ctx, #endif } +int auth_add_crt_to_chain(struct auth_ctx * ctx, + void * crt) +{ + assert(ctx != NULL); + assert(crt != NULL); + +#ifdef HAVE_OPENSSL + return openssl_auth_add_crt_to_chain(ctx->chain, crt); +#else + (void) ctx; + (void) crt; + + return 0; +#endif +} + int auth_verify_crt(struct auth_ctx * ctx, void * crt) { #ifdef HAVE_OPENSSL - return openssl_verify_crt(ctx->store, crt); + return openssl_verify_crt(ctx->store, ctx->chain, crt); #else (void) ctx; (void) crt; @@ -1037,6 +1065,32 @@ int auth_verify_crt(struct auth_ctx * ctx, #endif } +int auth_verify_crt_pin(struct auth_ctx * ctx, + void * crt, + void * pin) +{ +#ifdef HAVE_OPENSSL + return openssl_verify_crt_pin(ctx->store, ctx->chain, crt, pin); +#else + (void) ctx; + (void) crt; + (void) pin; + + return 0; +#endif +} + +bool crypt_pk_requires_md(const void * pk) +{ +#ifdef HAVE_OPENSSL + return openssl_pk_requires_md((const EVP_PKEY *) pk); +#else + (void) pk; + + return false; +#endif +} + int auth_sign(void * pkp, int md_nid, buffer_t msg, |
