From 0719ed46d29b0e57cb9128f5396ff894b7456766 Mon Sep 17 00:00:00 2001 From: Dimitri Staessens Date: Sat, 29 Aug 2026 12:08:29 +0200 Subject: lib: Improve hybrid KEX support The algorithm was inferred from the key length. That will not always work as SecP256r1MLKEM768 private key is 2432 bytes, exactly like an X25519MLKEM768 one. Raw OAP kex payloads now lead with the algorithm NID in network byte order, so a peer reads the algorithm from the wire instead of guessing it from the payload length. Test if the KEX is hybrid KEM with kex_nid_is_hybrid() based on the NID range. The configured algorithm is passed to the raw key loaders. The public key loader imports the key to validate it, so a corrupt or mismatched file is reported at load time. Signed-off-by: Dimitri Staessens Signed-off-by: Sander Vrijders --- src/irmd/oap/hdr.c | 52 +++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 51 insertions(+), 1 deletion(-) (limited to 'src/irmd/oap/hdr.c') diff --git a/src/irmd/oap/hdr.c b/src/irmd/oap/hdr.c index 0cff345c..d037d7b8 100644 --- a/src/irmd/oap/hdr.c +++ b/src/irmd/oap/hdr.c @@ -211,6 +211,56 @@ void oap_hdr_fini(struct oap_hdr * oap_hdr) memset(oap_hdr, 0, sizeof(*oap_hdr)); } +uint16_t oap_kex_nid(buffer_t kex) +{ + uint16_t nid; + + if (kex.len <= OAP_KEX_NIDSZ) + return NID_undef; + + memcpy(&nid, kex.data, sizeof(nid)); + + return ntoh16(nid); +} + +void oap_kex_set_nid(uint8_t * buf, + uint16_t nid) +{ + uint16_t v; + + assert(buf != NULL); + + v = hton16(nid); + + memcpy(buf, &v, sizeof(v)); +} + +int oap_kex_strip_nid(buffer_t * kex, + uint16_t nid) +{ + assert(kex != NULL); + + if (oap_kex_nid(*kex) != nid) + return -1; + + kex->data += OAP_KEX_NIDSZ; + kex->len -= OAP_KEX_NIDSZ; + + return 0; +} + +ssize_t oap_kex_tag_nid(uint8_t * buf, + uint16_t nid, + ssize_t len) +{ + if (len < 0) + return len; + + oap_kex_set_nid(buf, nid); + + return len + OAP_KEX_NIDSZ; +} + int oap_hdr_copy_data(const struct oap_hdr * hdr, buffer_t * out) { @@ -286,7 +336,7 @@ static void write_oap_fixed(uint8_t * buf, kex_len = (uint16_t) hdr->kex.len; if (hdr->kex.len > 0 && IS_KEM_ALGORITHM(scfg->x.str)) { - if (IS_HYBRID_KEM(scfg->x.str)) + if (IS_HYBRID_KEM_NID(scfg->x.nid)) kex_len |= OAP_KEX_FMT_BIT; if (scfg->x.mode == KEM_MODE_CLIENT_ENCAP) kex_len |= OAP_KEX_ROLE_BIT; -- cgit v1.2.3