diff options
| -rw-r--r-- | enc.conf.in | 4 | ||||
| -rw-r--r-- | include/ouroboros/crypt.h | 6 | ||||
| -rw-r--r-- | src/irmd/oap/cli.c | 29 | ||||
| -rw-r--r-- | src/irmd/oap/internal.h | 15 | ||||
| -rw-r--r-- | src/irmd/oap/srv.c | 111 | ||||
| -rw-r--r-- | src/irmd/oap/tests/oap_test.c | 262 | ||||
| -rw-r--r-- | src/lib/crypt.c | 70 | ||||
| -rw-r--r-- | src/lib/crypt/openssl.c | 2 |
8 files changed, 417 insertions, 82 deletions
diff --git a/enc.conf.in b/enc.conf.in index 64502fbb..8f91d717 100644 --- a/enc.conf.in +++ b/enc.conf.in @@ -73,8 +73,8 @@ # sha3-256 SHA3-256 # sha3-384 SHA3-384 # sha3-512 SHA3-512 -# blake2b512 BLAKE2b-512 (requires OpenSSL 1.1.0+) -# blake2s256 BLAKE2s-256 (requires OpenSSL 1.1.0+) +# blake2b512 BLAKE2b-512 +# blake2s256 BLAKE2s-256 # # KEM Mode (kem_mode=): # --------------------- diff --git a/include/ouroboros/crypt.h b/include/ouroboros/crypt.h index 5b39fb5f..1f2640e8 100644 --- a/include/ouroboros/crypt.h +++ b/include/ouroboros/crypt.h @@ -276,6 +276,12 @@ const char * crypt_nid_to_str(uint16_t nid); uint16_t crypt_str_to_nid(const char * cipher); +int crypt_cipher_rank(int nid); + +int crypt_kdf_rank(int nid); + +int crypt_kex_rank(int nid); + int md_validate_nid(int nid); const char * md_nid_to_str(uint16_t nid); 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 |
