Add a helper to compare two ML-KEM public keys

Two ML-KEM public keys are equal if their hashes are equal.
This will be exposed through EVP_PKEY_cmp.

Bug: 449751916
Change-Id: I6514292c0f62bb9ec1f2cfe6a48996ac6a6a6964
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/91307
Auto-Submit: Lily Chen <chlily@google.com>
Commit-Queue: Adam Langley <agl@google.com>
Reviewed-by: Adam Langley <agl@google.com>
diff --git a/crypto/fipsmodule/bcm_interface.h b/crypto/fipsmodule/bcm_interface.h
index 6acaba1..d4ea95d 100644
--- a/crypto/fipsmodule/bcm_interface.h
+++ b/crypto/fipsmodule/bcm_interface.h
@@ -644,6 +644,11 @@
 OPENSSL_EXPORT bcm_status BCM_mlkem768_marshal_public_key(
     CBB *out, const MLKEM768_public_key *public_key);
 
+// BCM_mlkem768_public_keys_equal returns one if |a| and |b| are equal and zero
+// otherwise.
+int BCM_mlkem768_public_keys_equal(const MLKEM768_public_key *a,
+                                   const MLKEM768_public_key *b);
+
 OPENSSL_EXPORT bcm_status
 BCM_mlkem768_parse_public_key(MLKEM768_public_key *out_public_key, CBS *in);
 
@@ -720,6 +725,11 @@
 OPENSSL_EXPORT bcm_status BCM_mlkem1024_marshal_public_key(
     CBB *out, const MLKEM1024_public_key *public_key);
 
+// BCM_mlkem1024_public_keys_equal returns one if |a| and |b| are equal and zero
+// otherwise.
+int BCM_mlkem1024_public_keys_equal(const MLKEM1024_public_key *a,
+                                    const MLKEM1024_public_key *b);
+
 OPENSSL_EXPORT bcm_status
 BCM_mlkem1024_parse_public_key(MLKEM1024_public_key *out_public_key, CBS *in);
 
diff --git a/crypto/fipsmodule/mlkem/mlkem.cc.inc b/crypto/fipsmodule/mlkem/mlkem.cc.inc
index aab115a..7ad4821 100644
--- a/crypto/fipsmodule/mlkem/mlkem.cc.inc
+++ b/crypto/fipsmodule/mlkem/mlkem.cc.inc
@@ -702,6 +702,12 @@
 }
 
 template <int RANK>
+static bool mlkem_public_keys_equal(const public_key<RANK> *a,
+                                    const public_key<RANK> *b) {
+  return OPENSSL_memcmp(a->public_key_hash, b->public_key_hash, 32) == 0;
+}
+
+template <int RANK>
 void mlkem_generate_key_external_seed_no_self_test(
     uint8_t *out_encoded_public_key, private_key<RANK> *priv,
     const uint8_t seed[MLKEM_SEED_BYTES]) {
@@ -1348,6 +1354,26 @@
       out, mlkem::public_key_1024_from_external(public_key));
 }
 
+int bssl::BCM_mlkem768_public_keys_equal(const MLKEM768_public_key *a,
+                                         const MLKEM768_public_key *b) {
+  const auto *pub_a = mlkem::public_key_768_from_external(a);
+  const auto *pub_b = mlkem::public_key_768_from_external(b);
+  if (mlkem_public_keys_equal(pub_a, pub_b)) {
+    return 1;
+  }
+  return 0;
+}
+
+int bssl::BCM_mlkem1024_public_keys_equal(const MLKEM1024_public_key *a,
+                                          const MLKEM1024_public_key *b) {
+  const auto *pub_a = mlkem::public_key_1024_from_external(a);
+  const auto *pub_b = mlkem::public_key_1024_from_external(b);
+  if (mlkem_public_keys_equal(pub_a, pub_b)) {
+    return 1;
+  }
+  return 0;
+}
+
 bcm_status bssl::BCM_mlkem768_parse_public_key(MLKEM768_public_key *public_key,
                                                CBS *in) {
   mlkem::public_key<RANK768> *pub =