summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/irmd/oap/cli.c29
-rw-r--r--src/irmd/oap/internal.h15
-rw-r--r--src/irmd/oap/srv.c111
-rw-r--r--src/irmd/oap/tests/oap_test.c262
-rw-r--r--src/lib/crypt.c70
-rw-r--r--src/lib/crypt/openssl.c2
6 files changed, 409 insertions, 80 deletions
diff --git a/src/irmd/oap/cli.c b/src/irmd/oap/cli.c
index ea2a25d1..9472e331 100644
--- a/src/irmd/oap/cli.c
+++ b/src/irmd/oap/cli.c
@@ -439,10 +439,16 @@ static int do_client_kex_complete(struct oap_cli_ctx * s,
{
struct sec_config * kcfg = &s->kcfg;
uint8_t * id = s->id.data;
+ int cipher_nid;
+ int kdf_nid;
if (!IS_KEX_ALGO_SET(kcfg))
return 0;
+ /* Save client's configured minimums */
+ cipher_nid = kcfg->c.nid;
+ kdf_nid = kcfg->k.nid;
+
/* Accept server's cipher choice */
if (peer_hdr->cipher_str == NULL) {
log_err_id(id, "Server did not provide cipher.");
@@ -456,7 +462,28 @@ static int do_client_kex_complete(struct oap_cli_ctx * s,
return -ENOTSUP;
}
- log_dbg_id(id, "Accepted server cipher %s.", peer_hdr->cipher_str);
+ /* Verify server cipher >= client's minimum */
+ if (crypt_cipher_rank(kcfg->c.nid) < crypt_cipher_rank(cipher_nid)) {
+ log_err_id(id, "Server cipher %s too weak.",
+ peer_hdr->cipher_str);
+ return -ECRYPT;
+ }
+
+ log_dbg_id(id, "Accepted server cipher %s.",
+ peer_hdr->cipher_str);
+
+ /* Accept server's KDF for non-client-encap modes */
+ if (kcfg->x.mode != KEM_MODE_CLIENT_ENCAP
+ && peer_hdr->kdf_nid != NID_undef) {
+ if (crypt_kdf_rank(peer_hdr->kdf_nid)
+ < crypt_kdf_rank(kdf_nid)) {
+ log_err_id(id, "Server KDF too weak.");
+ return -ECRYPT;
+ }
+ SET_KEX_KDF_NID(kcfg, peer_hdr->kdf_nid);
+ log_dbg_id(id, "Accepted server KDF %s.",
+ md_nid_to_str(kcfg->k.nid));
+ }
/* Derive shared secret */
if (IS_KEM_ALGORITHM(kcfg->x.str))
diff --git a/src/irmd/oap/internal.h b/src/irmd/oap/internal.h
index 8363e3a2..f118cc33 100644
--- a/src/irmd/oap/internal.h
+++ b/src/irmd/oap/internal.h
@@ -34,24 +34,15 @@
#include <stdbool.h>
#include <stdint.h>
-/*
- * Authentication functions (auth.c)
- */
int oap_check_hdr(const struct oap_hdr * hdr);
int oap_auth_peer(char * name,
const struct oap_hdr * local_hdr,
const struct oap_hdr * peer_hdr);
-/*
- * Key exchange functions (kex.c)
- */
int oap_negotiate_cipher(const struct oap_hdr * peer_hdr,
struct sec_config * kcfg);
-/*
- * Credential loading (oap.c) - shared between client and server
- */
#ifndef OAP_TEST_MODE
int load_credentials(const char * name,
const struct name_sec_paths * paths,
@@ -63,9 +54,6 @@ int load_kex_config(const char * name,
struct sec_config * cfg);
#endif
-/*
- * Server functions (srv.c)
- */
#ifndef OAP_TEST_MODE
int load_srv_credentials(const struct name_info * info,
void ** pkp,
@@ -94,9 +82,6 @@ int do_server_kex(const struct name_info * info,
buffer_t * kex,
struct crypt_sk * sk);
-/*
- * Client functions (cli.c)
- */
#ifndef OAP_TEST_MODE
int load_cli_credentials(const struct name_info * info,
void ** pkp,
diff --git a/src/irmd/oap/srv.c b/src/irmd/oap/srv.c
index c5a4453f..93270c48 100644
--- a/src/irmd/oap/srv.c
+++ b/src/irmd/oap/srv.c
@@ -134,43 +134,70 @@ static int get_algo_from_peer_key(const struct oap_hdr * peer_hdr,
return 0;
}
-static int negotiate_kex(const struct oap_hdr * peer_hdr,
- struct sec_config * kcfg)
+static int negotiate_cipher(const struct oap_hdr * peer_hdr,
+ struct sec_config * kcfg)
{
uint8_t * id = peer_hdr->id.data;
+ int cli_nid;
+ int cli_rank;
+ int srv_rank;
+
+ /* Cipher: select the strongest of client and server */
+ cli_nid = peer_hdr->cipher_str != NULL
+ ? (int) crypt_str_to_nid(peer_hdr->cipher_str)
+ : NID_undef;
+
+ if (cli_nid != NID_undef
+ && crypt_cipher_rank(cli_nid) < 0) {
+ log_err_id(id, "Unsupported cipher '%s'.",
+ peer_hdr->cipher_str);
+ return -ENOTSUP;
+ }
- if (kcfg->c.nid == NID_undef) {
- if (peer_hdr->cipher_str != NULL) {
- SET_KEX_CIPHER(kcfg, peer_hdr->cipher_str);
- if (kcfg->c.nid == NID_undef) {
- log_err_id(id, "Unsupported cipher '%s'.",
- peer_hdr->cipher_str);
- return -ENOTSUP;
- }
- log_dbg_id(id, "Peer requested cipher %s.",
- peer_hdr->cipher_str);
- } else {
- log_err_id(id, "Encryption requested, no cipher.");
- return -ECRYPT;
- }
+ cli_rank = crypt_cipher_rank(cli_nid);
+ srv_rank = crypt_cipher_rank(kcfg->c.nid);
+
+ if (cli_rank > srv_rank) {
+ SET_KEX_CIPHER_NID(kcfg, cli_nid);
+ log_dbg_id(id, "Selected client cipher %s.",
+ kcfg->c.str);
+ } else if (srv_rank > 0) {
+ log_dbg_id(id, "Selected server cipher %s.",
+ kcfg->c.str);
} else {
- log_dbg_id(id, "Using local cipher %s.", kcfg->c.str);
+ log_err_id(id, "Encryption requested, no cipher.");
+ return -ECRYPT;
}
- /* Negotiate KDF - server overrides client if configured */
- if (kcfg->k.nid != NID_undef) {
- log_dbg_id(id, "Using local KDF %s.",
- md_nid_to_str(kcfg->k.nid));
- } else if (peer_hdr->kdf_nid != NID_undef) {
- if (md_validate_nid(peer_hdr->kdf_nid) == 0) {
- kcfg->k.nid = peer_hdr->kdf_nid;
- log_dbg_id(id, "Using peer KDF %s.",
- md_nid_to_str(peer_hdr->kdf_nid));
- } else {
- log_err_id(id, "Unsupported KDF NID %d.",
- peer_hdr->kdf_nid);
- return -ENOTSUP;
+ /* KDF: select the strongest of client and server */
+ if (peer_hdr->kdf_nid != NID_undef
+ && crypt_kdf_rank(peer_hdr->kdf_nid) < 0) {
+ log_err_id(id, "Unsupported KDF NID %d.",
+ peer_hdr->kdf_nid);
+ return -ENOTSUP;
+ }
+
+ cli_rank = crypt_kdf_rank(peer_hdr->kdf_nid);
+ srv_rank = crypt_kdf_rank(kcfg->k.nid);
+
+ /*
+ * For client-encap KEM, the KDF is baked into
+ * the ciphertext. The server must use the client's
+ * KDF and can only verify the minimum.
+ */
+ if (OAP_KEX_ROLE(peer_hdr) == KEM_MODE_CLIENT_ENCAP) {
+ if (srv_rank > cli_rank) {
+ log_err_id(id, "Client KDF too weak.");
+ return -ECRYPT;
}
+ SET_KEX_KDF_NID(kcfg, peer_hdr->kdf_nid);
+ } else if (cli_rank > srv_rank) {
+ SET_KEX_KDF_NID(kcfg, peer_hdr->kdf_nid);
+ log_dbg_id(id, "Selected client KDF %s.",
+ md_nid_to_str(kcfg->k.nid));
+ } else if (srv_rank > 0) {
+ log_dbg_id(id, "Selected server KDF %s.",
+ md_nid_to_str(kcfg->k.nid));
}
if (IS_KEX_ALGO_SET(kcfg))
@@ -305,6 +332,7 @@ int do_server_kex(const struct name_info * info,
struct crypt_sk * sk)
{
char algo_buf[KEX_ALGO_BUFSZ];
+ int srv_kex_nid;
uint8_t * id;
id = peer_hdr->id.data;
@@ -318,15 +346,26 @@ int do_server_kex(const struct name_info * info,
return 0;
}
- if (negotiate_kex(peer_hdr, kcfg) < 0)
+ if (negotiate_cipher(peer_hdr, kcfg) < 0)
return -ECRYPT;
+ /* Save server's configured KEX before overwriting */
+ srv_kex_nid = kcfg->x.nid;
+
if (OAP_KEX_ROLE(peer_hdr) != KEM_MODE_CLIENT_ENCAP) {
/* Server encapsulation or DHE: extract algo from DER PK */
if (get_algo_from_peer_key(peer_hdr, algo_buf) < 0)
return -ECRYPT;
SET_KEX_ALGO(kcfg, algo_buf);
+
+ /* Reject if client KEX is weaker than server's */
+ if (crypt_kex_rank(kcfg->x.nid)
+ < crypt_kex_rank(srv_kex_nid)) {
+ log_err_id(id, "Client KEX %s too weak.",
+ kcfg->x.str);
+ return -ECRYPT;
+ }
}
/* Dispatch based on algorithm type */
@@ -368,13 +407,11 @@ int oap_srv_process(const struct name_info * info,
log_dbg("Processing OAP request for %s.", info->name);
- /* Load server credentials */
if (load_srv_credentials(info, &pkp, &crt) < 0) {
log_err("Failed to load security keys for %s.", info->name);
goto fail_cred;
}
- /* Load KEX config */
if (load_srv_kex_config(info, &kcfg) < 0) {
log_err("Failed to load KEX config for %s.", info->name);
goto fail_kex;
@@ -392,13 +429,11 @@ int oap_srv_process(const struct name_info * info,
id = peer_hdr.id.data; /* Logging */
- /* Check for replay */
if (oap_check_hdr(&peer_hdr) < 0) {
log_err_id(id, "OAP header failed replay check.");
goto fail_auth;
}
- /* Authenticate client before processing KEX data */
oap_hdr_init(&local_hdr, peer_hdr.id, kex_buf, *data, NID_undef);
if (oap_auth_peer(cli_name, &local_hdr, &peer_hdr) < 0) {
@@ -409,11 +444,15 @@ int oap_srv_process(const struct name_info * info,
if (do_server_kex(info, &peer_hdr, &kcfg, &local_hdr.kex, sk) < 0)
goto fail_kex;
+ /* Update cipher NID after negotiation */
+ sk->nid = kcfg.c.nid;
+
/* Build response header with hash of client request */
local_hdr.nid = sk->nid;
/* Use client's md_nid, defaulting to SHA-384 for PQC */
- req_md_nid = peer_hdr.md_nid != NID_undef ? peer_hdr.md_nid : NID_sha384;
+ req_md_nid = peer_hdr.md_nid != NID_undef ?
+ peer_hdr.md_nid : NID_sha384;
/* Compute request hash using client's md_nid */
hash_ret = md_digest(req_md_nid, req_buf, hash_buf);
diff --git a/src/irmd/oap/tests/oap_test.c b/src/irmd/oap/tests/oap_test.c
index 70f0a248..fc78ed9a 100644
--- a/src/irmd/oap/tests/oap_test.c
+++ b/src/irmd/oap/tests/oap_test.c
@@ -536,7 +536,7 @@ static int test_oap_roundtrip_all(void)
return ret;
}
-/* Cipher negotiation - client should accept server's chosen cipher */
+/* Cipher negotiation - strongest cipher and KDF are selected */
static int test_oap_cipher_mismatch(void)
{
struct oap_test_ctx ctx;
@@ -545,17 +545,17 @@ static int test_oap_cipher_mismatch(void)
memset(&test_cfg, 0, sizeof(test_cfg));
- /* Server: ChaCha20-Poly1305, SHA3-256, SHA-384 */
+ /* Server: AES-128-GCM, SHA-256 */
test_cfg.srv.kex = NID_X25519;
- test_cfg.srv.cipher = NID_chacha20_poly1305;
- test_cfg.srv.kdf = NID_sha3_256;
- test_cfg.srv.md = NID_sha384;
+ test_cfg.srv.cipher = NID_aes_128_gcm;
+ test_cfg.srv.kdf = NID_sha256;
+ test_cfg.srv.md = NID_sha256;
test_cfg.srv.auth = AUTH;
- /* Client: AES-256-GCM, SHA-256, SHA-256 */
+ /* Client: AES-256-GCM, SHA-512 */
test_cfg.cli.kex = NID_X25519;
test_cfg.cli.cipher = NID_aes_256_gcm;
- test_cfg.cli.kdf = NID_sha256;
+ test_cfg.cli.kdf = NID_sha512;
test_cfg.cli.md = NID_sha256;
test_cfg.cli.auth = NO_AUTH;
@@ -577,17 +577,17 @@ static int test_oap_cipher_mismatch(void)
goto fail_cleanup;
}
- /* Verify: both should have the server's chosen cipher and KDF */
- if (ctx.srv.nid != test_cfg.srv.cipher) {
+ /* Verify: both should have the strongest cipher */
+ if (ctx.srv.nid != NID_aes_256_gcm) {
printf("Server cipher mismatch: expected %s, got %s\n",
- crypt_nid_to_str(test_cfg.srv.cipher),
+ crypt_nid_to_str(NID_aes_256_gcm),
crypt_nid_to_str(ctx.srv.nid));
goto fail_cleanup;
}
- if (ctx.cli.nid != test_cfg.srv.cipher) {
+ if (ctx.cli.nid != NID_aes_256_gcm) {
printf("Client cipher mismatch: expected %s, got %s\n",
- crypt_nid_to_str(test_cfg.srv.cipher),
+ crypt_nid_to_str(NID_aes_256_gcm),
crypt_nid_to_str(ctx.cli.nid));
goto fail_cleanup;
}
@@ -598,9 +598,9 @@ static int test_oap_cipher_mismatch(void)
/* KDF NID at offset 26: ID(16) + ts(8) + cipher(2) */
resp_kdf_nid = ntoh16(*(uint16_t *)(ctx.resp_hdr.data + 26));
- if (resp_kdf_nid != test_cfg.srv.kdf) {
+ if (resp_kdf_nid != NID_sha512) {
printf("Response KDF mismatch: expected %s, got %s\n",
- md_nid_to_str(test_cfg.srv.kdf),
+ md_nid_to_str(NID_sha512),
md_nid_to_str(resp_kdf_nid));
goto fail_cleanup;
}
@@ -618,6 +618,228 @@ static int test_oap_cipher_mismatch(void)
return TEST_RC_FAIL;
}
+/* Server encryption, client none: server rejects (no KEX data) */
+static int test_oap_srv_enc_cli_none(void)
+{
+ struct oap_test_ctx ctx;
+
+ TEST_START();
+
+ memset(&test_cfg, 0, sizeof(test_cfg));
+
+ /* Server: encryption configured */
+ test_cfg.srv.kex = NID_X25519;
+ test_cfg.srv.cipher = NID_aes_256_gcm;
+ test_cfg.srv.kdf = NID_sha256;
+ test_cfg.srv.md = NID_sha256;
+ test_cfg.srv.auth = AUTH;
+
+ /* Client: no encryption */
+ test_cfg.cli.md = NID_sha256;
+ test_cfg.cli.auth = NO_AUTH;
+
+ if (oap_test_setup(&ctx, root_ca_crt_ec, im_ca_crt_ec) < 0)
+ goto fail;
+
+ if (oap_cli_prepare_ctx(&ctx) < 0) {
+ printf("Client prepare failed.\n");
+ goto fail_cleanup;
+ }
+
+ /* Server should reject: KEX required but client sent none */
+ if (oap_srv_process_ctx(&ctx) == 0) {
+ printf("Server should have rejected.\n");
+ goto fail_cleanup;
+ }
+
+ oap_test_teardown(&ctx);
+
+ TEST_SUCCESS();
+ return TEST_RC_SUCCESS;
+
+ fail_cleanup:
+ oap_test_teardown(&ctx);
+ fail:
+ TEST_FAIL();
+ return TEST_RC_FAIL;
+}
+
+/* Client encryption, server none: use client settings */
+static int test_oap_cli_enc_srv_none(void)
+{
+ struct oap_test_ctx ctx;
+
+ TEST_START();
+
+ memset(&test_cfg, 0, sizeof(test_cfg));
+
+ /* Server: no encryption configured */
+ test_cfg.srv.md = NID_sha256;
+ test_cfg.srv.auth = AUTH;
+
+ /* Client: encryption configured */
+ test_cfg.cli.kex = NID_X25519;
+ test_cfg.cli.cipher = NID_aes_256_gcm;
+ test_cfg.cli.kdf = NID_sha256;
+ test_cfg.cli.md = NID_sha256;
+ test_cfg.cli.auth = NO_AUTH;
+
+ if (oap_test_setup(&ctx, root_ca_crt_ec, im_ca_crt_ec) < 0)
+ goto fail;
+
+ if (oap_cli_prepare_ctx(&ctx) < 0) {
+ printf("Client prepare failed.\n");
+ goto fail_cleanup;
+ }
+
+ if (oap_srv_process_ctx(&ctx) < 0) {
+ printf("Server process failed.\n");
+ goto fail_cleanup;
+ }
+
+ if (oap_cli_complete_ctx(&ctx) < 0) {
+ printf("Client complete failed.\n");
+ goto fail_cleanup;
+ }
+
+ if (memcmp(ctx.cli.key, ctx.srv.key, SYMMKEYSZ) != 0) {
+ printf("Key mismatch.\n");
+ goto fail_cleanup;
+ }
+
+ if (ctx.cli.nid != NID_aes_256_gcm) {
+ printf("Expected %s, got %s.\n",
+ crypt_nid_to_str(NID_aes_256_gcm),
+ crypt_nid_to_str(ctx.cli.nid));
+ goto fail_cleanup;
+ }
+
+ if (ctx.srv.nid != NID_aes_256_gcm) {
+ printf("Expected %s, got %s.\n",
+ crypt_nid_to_str(NID_aes_256_gcm),
+ crypt_nid_to_str(ctx.srv.nid));
+ goto fail_cleanup;
+ }
+
+ oap_test_teardown(&ctx);
+
+ TEST_SUCCESS();
+ return TEST_RC_SUCCESS;
+
+ fail_cleanup:
+ oap_test_teardown(&ctx);
+ fail:
+ TEST_FAIL();
+ return TEST_RC_FAIL;
+}
+
+/* Client rejects server response with downgraded cipher */
+static int test_oap_cli_rejects_downgrade(void)
+{
+ struct oap_test_ctx ctx;
+ uint16_t weak;
+
+ TEST_START();
+
+ memset(&test_cfg, 0, sizeof(test_cfg));
+
+ test_cfg.srv.kex = NID_X25519;
+ test_cfg.srv.cipher = NID_aes_256_gcm;
+ test_cfg.srv.kdf = NID_sha256;
+ test_cfg.srv.md = NID_sha256;
+ test_cfg.srv.auth = AUTH;
+
+ test_cfg.cli.kex = NID_X25519;
+ test_cfg.cli.cipher = NID_aes_256_gcm;
+ test_cfg.cli.kdf = NID_sha256;
+ test_cfg.cli.md = NID_sha256;
+ test_cfg.cli.auth = NO_AUTH;
+
+ if (oap_test_setup(&ctx, root_ca_crt_ec, im_ca_crt_ec) < 0)
+ goto fail;
+
+ if (oap_cli_prepare_ctx(&ctx) < 0) {
+ printf("Client prepare failed.\n");
+ goto fail_cleanup;
+ }
+
+ if (oap_srv_process_ctx(&ctx) < 0) {
+ printf("Server process failed.\n");
+ goto fail_cleanup;
+ }
+
+ /* Tamper: replace cipher NID with weaker one */
+ weak = hton16(NID_aes_128_ctr);
+ memcpy(ctx.resp_hdr.data + OAP_CIPHER_NID_OFFSET,
+ &weak, sizeof(weak));
+
+ /* Client should reject the downgraded cipher */
+ if (oap_cli_complete_ctx(&ctx) == 0) {
+ printf("Client accepted downgrade.\n");
+ goto fail_cleanup;
+ }
+
+ oap_test_teardown(&ctx);
+
+ TEST_SUCCESS();
+ return TEST_RC_SUCCESS;
+
+ fail_cleanup:
+ oap_test_teardown(&ctx);
+ fail:
+ TEST_FAIL();
+ return TEST_RC_FAIL;
+}
+
+/* Server rejects client with weaker KEX algorithm */
+static int test_oap_srv_rejects_weak_kex(void)
+{
+ struct oap_test_ctx ctx;
+
+ TEST_START();
+
+ memset(&test_cfg, 0, sizeof(test_cfg));
+
+ /* Server: secp521r1 (strong) */
+ test_cfg.srv.kex = NID_secp521r1;
+ test_cfg.srv.cipher = NID_aes_256_gcm;
+ test_cfg.srv.kdf = NID_sha256;
+ test_cfg.srv.md = NID_sha256;
+ test_cfg.srv.auth = AUTH;
+
+ /* Client: ffdhe2048 (weakest) */
+ test_cfg.cli.kex = NID_ffdhe2048;
+ test_cfg.cli.cipher = NID_aes_256_gcm;
+ test_cfg.cli.kdf = NID_sha256;
+ test_cfg.cli.md = NID_sha256;
+ test_cfg.cli.auth = NO_AUTH;
+
+ if (oap_test_setup(&ctx, root_ca_crt_ec, im_ca_crt_ec) < 0)
+ goto fail;
+
+ if (oap_cli_prepare_ctx(&ctx) < 0) {
+ printf("Client prepare failed.\n");
+ goto fail_cleanup;
+ }
+
+ /* Server should reject: client KEX too weak */
+ if (oap_srv_process_ctx(&ctx) == 0) {
+ printf("Server should reject weak KEX.\n");
+ goto fail_cleanup;
+ }
+
+ oap_test_teardown(&ctx);
+
+ TEST_SUCCESS();
+ return TEST_RC_SUCCESS;
+
+ fail_cleanup:
+ oap_test_teardown(&ctx);
+ fail:
+ TEST_FAIL();
+ return TEST_RC_FAIL;
+}
+
/* Test roundtrip with different signature digest algorithms */
static int test_oap_roundtrip_md(int md)
{
@@ -682,8 +904,8 @@ static int test_oap_roundtrip_md_all(void)
int ret = 0;
int i;
- /* Test with default (0) */
- ret |= test_oap_roundtrip_md(0);
+ /* Test with default */
+ ret |= test_oap_roundtrip_md(NID_undef);
/* Test with all supported digest NIDs */
for (i = 0; md_supported_nids[i] != NID_undef; i++)
@@ -919,6 +1141,10 @@ int oap_test(int argc,
ret |= test_oap_unsupported_nid();
ret |= test_oap_cipher_mismatch();
+ ret |= test_oap_srv_enc_cli_none();
+ ret |= test_oap_cli_enc_srv_none();
+ ret |= test_oap_cli_rejects_downgrade();
+ ret |= test_oap_srv_rejects_weak_kex();
ret |= test_oap_outdated_packet();
ret |= test_oap_future_packet();
@@ -940,6 +1166,10 @@ int oap_test(int argc,
(void) test_oap_nid_without_kex;
(void) test_oap_unsupported_nid;
(void) test_oap_cipher_mismatch;
+ (void) test_oap_srv_enc_cli_none;
+ (void) test_oap_cli_enc_srv_none;
+ (void) test_oap_cli_rejects_downgrade;
+ (void) test_oap_srv_rejects_weak_kex;
(void) test_oap_outdated_packet;
(void) test_oap_future_packet;
(void) test_oap_replay_packet;
diff --git a/src/lib/crypt.c b/src/lib/crypt.c
index 8c29cbb3..92da803d 100644
--- a/src/lib/crypt.c
+++ b/src/lib/crypt.c
@@ -56,15 +56,16 @@ static const struct nid_map cipher_nid_map[] = {
{NID_undef, NULL}
};
+/* Ordered in strength preference, lowest first */
const uint16_t crypt_supported_nids[] = {
#ifdef HAVE_OPENSSL
+ NID_aes_128_ctr,
+ NID_aes_192_ctr,
+ NID_aes_256_ctr,
NID_aes_128_gcm,
NID_aes_192_gcm,
NID_aes_256_gcm,
NID_chacha20_poly1305,
- NID_aes_128_ctr,
- NID_aes_192_ctr,
- NID_aes_256_ctr,
#endif
NID_undef
};
@@ -86,16 +87,17 @@ static const struct nid_map kex_nid_map[] = {
{NID_undef, NULL}
};
+/* Ordered in strength preference, lowest first */
const uint16_t kex_supported_nids[] = {
#ifdef HAVE_OPENSSL
+ NID_ffdhe2048,
NID_X9_62_prime256v1,
- NID_secp384r1,
- NID_secp521r1,
NID_X25519,
- NID_X448,
- NID_ffdhe2048,
NID_ffdhe3072,
+ NID_secp384r1,
NID_ffdhe4096,
+ NID_X448,
+ NID_secp521r1,
#ifdef HAVE_OPENSSL_PQC
NID_MLKEM512,
NID_MLKEM768,
@@ -119,16 +121,17 @@ static const struct nid_map md_nid_map[] = {
{NID_undef, NULL}
};
+/* Ordered in strength preference, lowest first */
const uint16_t md_supported_nids[] = {
#ifdef HAVE_OPENSSL
+ NID_blake2s256,
NID_sha256,
- NID_sha384,
- NID_sha512,
NID_sha3_256,
+ NID_sha384,
NID_sha3_384,
- NID_sha3_512,
NID_blake2b512,
- NID_blake2s256,
+ NID_sha512,
+ NID_sha3_512,
#endif
NID_undef
};
@@ -544,6 +547,51 @@ int md_validate_nid(int nid)
return -ENOTSUP;
}
+int crypt_cipher_rank(int nid)
+{
+ int i;
+
+ if (nid == NID_undef)
+ return 0;
+
+ for (i = 0; crypt_supported_nids[i] != NID_undef; i++) {
+ if ((int) crypt_supported_nids[i] == nid)
+ return i + 1;
+ }
+
+ return -1;
+}
+
+int crypt_kdf_rank(int nid)
+{
+ int i;
+
+ if (nid == NID_undef)
+ return 0;
+
+ for (i = 0; md_supported_nids[i] != NID_undef; i++) {
+ if ((int) md_supported_nids[i] == nid)
+ return i + 1;
+ }
+
+ return -1;
+}
+
+int crypt_kex_rank(int nid)
+{
+ int i;
+
+ if (nid == NID_undef)
+ return 0;
+
+ for (i = 0; kex_supported_nids[i] != NID_undef; i++) {
+ if ((int) kex_supported_nids[i] == nid)
+ return i + 1;
+ }
+
+ return -1;
+}
+
/* Hash length now returned by md_digest() */
int crypt_encrypt(struct crypt_ctx * ctx,
diff --git a/src/lib/crypt/openssl.c b/src/lib/crypt/openssl.c
index 232aa6c9..5d95f408 100644
--- a/src/lib/crypt/openssl.c
+++ b/src/lib/crypt/openssl.c
@@ -974,7 +974,7 @@ int openssl_encrypt(struct ossl_crypt_ctx * ctx,
if (random_buffer(iv, ctx->ivsz) < 0)
goto fail_encrypt;
- /* Set IV bit 7 to current key phase (bit KEY_ROTATION_BIT of counter) */
+ /* Set IV bit 7 to current key phase (KEY_ROTATION_BIT of counter) */
if (ctx->rot.cntr & ctx->rot.mask)
iv[0] |= 0x80;
else