summaryrefslogtreecommitdiff
path: root/src/lib/libcrypto/mlkem
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/libcrypto/mlkem')
-rw-r--r--src/lib/libcrypto/mlkem/mlkem.h26
-rw-r--r--src/lib/libcrypto/mlkem/mlkem1024.c173
-rw-r--r--src/lib/libcrypto/mlkem/mlkem768.c178
-rw-r--r--src/lib/libcrypto/mlkem/mlkem_internal.h15
4 files changed, 248 insertions, 144 deletions
diff --git a/src/lib/libcrypto/mlkem/mlkem.h b/src/lib/libcrypto/mlkem/mlkem.h
index a5645facc6..a2c5d7fed0 100644
--- a/src/lib/libcrypto/mlkem/mlkem.h
+++ b/src/lib/libcrypto/mlkem/mlkem.h
@@ -1,4 +1,4 @@
1/* $OpenBSD: mlkem.h,v 1.4 2024/12/19 23:52:26 tb Exp $ */ 1/* $OpenBSD: mlkem.h,v 1.6 2025/05/19 06:47:40 beck Exp $ */
2/* 2/*
3 * Copyright (c) 2024, Google Inc. 3 * Copyright (c) 2024, Google Inc.
4 * 4 *
@@ -25,10 +25,6 @@
25extern "C" { 25extern "C" {
26#endif 26#endif
27 27
28/* Hack for now */
29struct cbs_st;
30struct cbb_st;
31
32/* 28/*
33 * ML-KEM-768 29 * ML-KEM-768
34 * 30 *
@@ -78,10 +74,10 @@ struct MLKEM768_private_key {
78/* 74/*
79 * MLKEM_generate_key generates a random public/private key pair, writes the 75 * MLKEM_generate_key generates a random public/private key pair, writes the
80 * encoded public key to |out_encoded_public_key| and sets |out_private_key| to 76 * encoded public key to |out_encoded_public_key| and sets |out_private_key| to
81 * the private key. If |optional_out_seed| us not NULL then te seed used to 77 * the private key. If |optional_out_seed| is not NULL then the seed used to
82 * generate te private key is written to it. 78 * generate the private key is written to it.
83 */ 79 */
84void MLKEM768_generate_key( 80int MLKEM768_generate_key(
85 uint8_t out_encoded_public_key[MLKEM768_PUBLIC_KEY_BYTES], 81 uint8_t out_encoded_public_key[MLKEM768_PUBLIC_KEY_BYTES],
86 uint8_t optional_out_seed[MLKEM_SEED_BYTES], 82 uint8_t optional_out_seed[MLKEM_SEED_BYTES],
87 struct MLKEM768_private_key *out_private_key); 83 struct MLKEM768_private_key *out_private_key);
@@ -137,7 +133,7 @@ int MLKEM768_decap(uint8_t out_shared_secret[MLKEM_SHARED_SECRET_BYTES],
137 * format for ML-KEM public keys. It returns one on success or zero on allocation 133 * format for ML-KEM public keys. It returns one on success or zero on allocation
138 * error. 134 * error.
139 */ 135 */
140int MLKEM768_marshal_public_key(struct cbb_st *out, 136int MLKEM768_marshal_public_key(uint8_t **output, size_t *output_len,
141 const struct MLKEM768_public_key *public_key); 137 const struct MLKEM768_public_key *public_key);
142 138
143/* 139/*
@@ -147,7 +143,7 @@ int MLKEM768_marshal_public_key(struct cbb_st *out,
147 * there are trailing bytes in |in|. 143 * there are trailing bytes in |in|.
148 */ 144 */
149int MLKEM768_parse_public_key(struct MLKEM768_public_key *out_public_key, 145int MLKEM768_parse_public_key(struct MLKEM768_public_key *out_public_key,
150 struct cbs_st *in); 146 const uint8_t *input, size_t input_len);
151 147
152/* 148/*
153 * MLKEM_parse_private_key parses a private key, in the format generated by 149 * MLKEM_parse_private_key parses a private key, in the format generated by
@@ -157,7 +153,7 @@ int MLKEM768_parse_public_key(struct MLKEM768_public_key *out_public_key,
157 * Private keys should be stored as seeds and parsed using |MLKEM768_private_key_from_seed|. 153 * Private keys should be stored as seeds and parsed using |MLKEM768_private_key_from_seed|.
158 */ 154 */
159int MLKEM768_parse_private_key(struct MLKEM768_private_key *out_private_key, 155int MLKEM768_parse_private_key(struct MLKEM768_private_key *out_private_key,
160 struct cbs_st *in); 156 const uint8_t *input, size_t input_len);
161 157
162/* 158/*
163 * ML-KEM-1024 159 * ML-KEM-1024
@@ -200,7 +196,7 @@ struct MLKEM1024_private_key {
200 * the private key. If |optional_out_seed| is not NULL then the seed used to 196 * the private key. If |optional_out_seed| is not NULL then the seed used to
201 * generate the private key is written to it. 197 * generate the private key is written to it.
202 */ 198 */
203void MLKEM1024_generate_key( 199int MLKEM1024_generate_key(
204 uint8_t out_encoded_public_key[MLKEM1024_PUBLIC_KEY_BYTES], 200 uint8_t out_encoded_public_key[MLKEM1024_PUBLIC_KEY_BYTES],
205 uint8_t optional_out_seed[MLKEM_SEED_BYTES], 201 uint8_t optional_out_seed[MLKEM_SEED_BYTES],
206 struct MLKEM1024_private_key *out_private_key); 202 struct MLKEM1024_private_key *out_private_key);
@@ -256,7 +252,7 @@ int MLKEM1024_decap(uint8_t out_shared_secret[MLKEM_SHARED_SECRET_BYTES],
256 * format for ML-KEM-1024 public keys. It returns one on success or zero on 252 * format for ML-KEM-1024 public keys. It returns one on success or zero on
257 * allocation error. 253 * allocation error.
258 */ 254 */
259int MLKEM1024_marshal_public_key(struct cbb_st *out, 255int MLKEM1024_marshal_public_key(uint8_t **output, size_t *output_len,
260 const struct MLKEM1024_public_key *public_key); 256 const struct MLKEM1024_public_key *public_key);
261 257
262/* 258/*
@@ -266,7 +262,7 @@ int MLKEM1024_marshal_public_key(struct cbb_st *out,
266 * there are trailing bytes in |in|. 262 * there are trailing bytes in |in|.
267 */ 263 */
268int MLKEM1024_parse_public_key(struct MLKEM1024_public_key *out_public_key, 264int MLKEM1024_parse_public_key(struct MLKEM1024_public_key *out_public_key,
269 struct cbs_st *in); 265 const uint8_t *input, size_t input_len);
270 266
271/* 267/*
272 * MLKEM1024_parse_private_key parses a private key, in NIST's format for 268 * MLKEM1024_parse_private_key parses a private key, in NIST's format for
@@ -276,7 +272,7 @@ int MLKEM1024_parse_public_key(struct MLKEM1024_public_key *out_public_key,
276 * stored as seeds and parsed using |MLKEM1024_private_key_from_seed|. 272 * stored as seeds and parsed using |MLKEM1024_private_key_from_seed|.
277 */ 273 */
278int MLKEM1024_parse_private_key(struct MLKEM1024_private_key *out_private_key, 274int MLKEM1024_parse_private_key(struct MLKEM1024_private_key *out_private_key,
279 struct cbs_st *in); 275 const uint8_t *input, size_t input_len);
280 276
281#if defined(__cplusplus) 277#if defined(__cplusplus)
282} 278}
diff --git a/src/lib/libcrypto/mlkem/mlkem1024.c b/src/lib/libcrypto/mlkem/mlkem1024.c
index f6fccdf6a8..26c4716539 100644
--- a/src/lib/libcrypto/mlkem/mlkem1024.c
+++ b/src/lib/libcrypto/mlkem/mlkem1024.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: mlkem1024.c,v 1.6 2025/01/03 08:19:24 tb Exp $ */ 1/* $OpenBSD: mlkem1024.c,v 1.11 2025/05/21 02:18:11 kenjiro Exp $ */
2/* 2/*
3 * Copyright (c) 2024, Google Inc. 3 * Copyright (c) 2024, Google Inc.
4 * Copyright (c) 2024, Bob Beck <beck@obtuse.com> 4 * Copyright (c) 2024, Bob Beck <beck@obtuse.com>
@@ -612,6 +612,19 @@ vector_encode(uint8_t *out, const vector *a, int bits)
612 } 612 }
613} 613}
614 614
615/* Encodes an entire vector as above, but adding it to a CBB */
616static int
617vector_encode_cbb(CBB *cbb, const vector *a, int bits)
618{
619 uint8_t *encoded_vector;
620
621 if (!CBB_add_space(cbb, &encoded_vector, kEncodedVectorSize))
622 return 0;
623 vector_encode(encoded_vector, a, bits);
624
625 return 1;
626}
627
615/* 628/*
616 * scalar_decode parses |DEGREE * bits| bits from |in| into |DEGREE| values in 629 * scalar_decode parses |DEGREE * bits| bits from |in| into |DEGREE| values in
617 * |out|. It returns one on success and zero if any parsed value is >= 630 * |out|. It returns one on success and zero if any parsed value is >=
@@ -793,6 +806,8 @@ struct public_key {
793 matrix m; 806 matrix m;
794}; 807};
795 808
809CTASSERT(sizeof(struct MLKEM1024_public_key) == sizeof(struct public_key));
810
796static struct public_key * 811static struct public_key *
797public_key_1024_from_external(const struct MLKEM1024_public_key *external) 812public_key_1024_from_external(const struct MLKEM1024_public_key *external)
798{ 813{
@@ -805,6 +820,8 @@ struct private_key {
805 uint8_t fo_failure_secret[32]; 820 uint8_t fo_failure_secret[32];
806}; 821};
807 822
823CTASSERT(sizeof(struct MLKEM1024_private_key) == sizeof(struct private_key));
824
808static struct private_key * 825static struct private_key *
809private_key_1024_from_external(const struct MLKEM1024_private_key *external) 826private_key_1024_from_external(const struct MLKEM1024_private_key *external)
810{ 827{
@@ -815,7 +832,7 @@ private_key_1024_from_external(const struct MLKEM1024_private_key *external)
815 * Calls |MLKEM1024_generate_key_external_entropy| with random bytes from 832 * Calls |MLKEM1024_generate_key_external_entropy| with random bytes from
816 * |RAND_bytes|. 833 * |RAND_bytes|.
817 */ 834 */
818void 835int
819MLKEM1024_generate_key(uint8_t out_encoded_public_key[MLKEM1024_PUBLIC_KEY_BYTES], 836MLKEM1024_generate_key(uint8_t out_encoded_public_key[MLKEM1024_PUBLIC_KEY_BYTES],
820 uint8_t optional_out_seed[MLKEM_SEED_BYTES], 837 uint8_t optional_out_seed[MLKEM_SEED_BYTES],
821 struct MLKEM1024_private_key *out_private_key) 838 struct MLKEM1024_private_key *out_private_key)
@@ -825,7 +842,7 @@ MLKEM1024_generate_key(uint8_t out_encoded_public_key[MLKEM1024_PUBLIC_KEY_BYTES
825 entropy_buf; 842 entropy_buf;
826 843
827 arc4random_buf(entropy, MLKEM_SEED_BYTES); 844 arc4random_buf(entropy, MLKEM_SEED_BYTES);
828 MLKEM1024_generate_key_external_entropy(out_encoded_public_key, 845 return MLKEM1024_generate_key_external_entropy(out_encoded_public_key,
829 out_private_key, entropy); 846 out_private_key, entropy);
830} 847}
831LCRYPTO_ALIAS(MLKEM1024_generate_key); 848LCRYPTO_ALIAS(MLKEM1024_generate_key);
@@ -839,29 +856,20 @@ MLKEM1024_private_key_from_seed(struct MLKEM1024_private_key *out_private_key,
839 if (seed_len != MLKEM_SEED_BYTES) { 856 if (seed_len != MLKEM_SEED_BYTES) {
840 return 0; 857 return 0;
841 } 858 }
842 MLKEM1024_generate_key_external_entropy(public_key_bytes, 859 return MLKEM1024_generate_key_external_entropy(public_key_bytes,
843 out_private_key, seed); 860 out_private_key, seed);
844
845 return 1;
846} 861}
847LCRYPTO_ALIAS(MLKEM1024_private_key_from_seed); 862LCRYPTO_ALIAS(MLKEM1024_private_key_from_seed);
848 863
849static int 864static int
850mlkem_marshal_public_key(CBB *out, const struct public_key *pub) 865mlkem_marshal_public_key(CBB *out, const struct public_key *pub)
851{ 866{
852 uint8_t *vector_output; 867 if (!vector_encode_cbb(out, &pub->t, kLog2Prime))
853
854 if (!CBB_add_space(out, &vector_output, kEncodedVectorSize)) {
855 return 0; 868 return 0;
856 } 869 return CBB_add_bytes(out, pub->rho, sizeof(pub->rho));
857 vector_encode(vector_output, &pub->t, kLog2Prime);
858 if (!CBB_add_bytes(out, pub->rho, sizeof(pub->rho))) {
859 return 0;
860 }
861 return 1;
862} 870}
863 871
864void 872int
865MLKEM1024_generate_key_external_entropy( 873MLKEM1024_generate_key_external_entropy(
866 uint8_t out_encoded_public_key[MLKEM1024_PUBLIC_KEY_BYTES], 874 uint8_t out_encoded_public_key[MLKEM1024_PUBLIC_KEY_BYTES],
867 struct MLKEM1024_private_key *out_private_key, 875 struct MLKEM1024_private_key *out_private_key,
@@ -875,7 +883,9 @@ MLKEM1024_generate_key_external_entropy(
875 uint8_t hashed[64]; 883 uint8_t hashed[64];
876 vector error; 884 vector error;
877 CBB cbb; 885 CBB cbb;
886 int ret = 0;
878 887
888 memset(&cbb, 0, sizeof(CBB));
879 memcpy(augmented_seed, entropy, 32); 889 memcpy(augmented_seed, entropy, 32);
880 augmented_seed[32] = RANK1024; 890 augmented_seed[32] = RANK1024;
881 hash_g(hashed, augmented_seed, 33); 891 hash_g(hashed, augmented_seed, 33);
@@ -890,16 +900,23 @@ MLKEM1024_generate_key_external_entropy(
890 matrix_mult_transpose(&priv->pub.t, &priv->pub.m, &priv->s); 900 matrix_mult_transpose(&priv->pub.t, &priv->pub.m, &priv->s);
891 vector_add(&priv->pub.t, &error); 901 vector_add(&priv->pub.t, &error);
892 902
893 /* XXX - error checking. */ 903 if (!CBB_init_fixed(&cbb, out_encoded_public_key,
894 CBB_init_fixed(&cbb, out_encoded_public_key, MLKEM1024_PUBLIC_KEY_BYTES); 904 MLKEM1024_PUBLIC_KEY_BYTES))
895 if (!mlkem_marshal_public_key(&cbb, &priv->pub)) { 905 goto err;
896 abort(); 906
897 } 907 if (!mlkem_marshal_public_key(&cbb, &priv->pub))
898 CBB_cleanup(&cbb); 908 goto err;
899 909
900 hash_h(priv->pub.public_key_hash, out_encoded_public_key, 910 hash_h(priv->pub.public_key_hash, out_encoded_public_key,
901 MLKEM1024_PUBLIC_KEY_BYTES); 911 MLKEM1024_PUBLIC_KEY_BYTES);
902 memcpy(priv->fo_failure_secret, entropy + 32, 32); 912 memcpy(priv->fo_failure_secret, entropy + 32, 32);
913
914 ret = 1;
915
916 err:
917 CBB_cleanup(&cbb);
918
919 return ret;
903} 920}
904 921
905void 922void
@@ -1045,11 +1062,26 @@ MLKEM1024_decap(uint8_t out_shared_secret[MLKEM_SHARED_SECRET_BYTES],
1045LCRYPTO_ALIAS(MLKEM1024_decap); 1062LCRYPTO_ALIAS(MLKEM1024_decap);
1046 1063
1047int 1064int
1048MLKEM1024_marshal_public_key(CBB *out, 1065MLKEM1024_marshal_public_key(uint8_t **output, size_t *output_len,
1049 const struct MLKEM1024_public_key *public_key) 1066 const struct MLKEM1024_public_key *public_key)
1050{ 1067{
1051 return mlkem_marshal_public_key(out, 1068 int ret = 0;
1052 public_key_1024_from_external(public_key)); 1069 CBB cbb;
1070
1071 if (!CBB_init(&cbb, MLKEM1024_PUBLIC_KEY_BYTES))
1072 goto err;
1073 if (!mlkem_marshal_public_key(&cbb,
1074 public_key_1024_from_external(public_key)))
1075 goto err;
1076 if (!CBB_finish(&cbb, output, output_len))
1077 goto err;
1078
1079 ret = 1;
1080
1081 err:
1082 CBB_cleanup(&cbb);
1083
1084 return ret;
1053} 1085}
1054LCRYPTO_ALIAS(MLKEM1024_marshal_public_key); 1086LCRYPTO_ALIAS(MLKEM1024_marshal_public_key);
1055 1087
@@ -1062,10 +1094,11 @@ mlkem_parse_public_key_no_hash(struct public_key *pub, CBS *in)
1062{ 1094{
1063 CBS t_bytes; 1095 CBS t_bytes;
1064 1096
1065 if (!CBS_get_bytes(in, &t_bytes, kEncodedVectorSize) || 1097 if (!CBS_get_bytes(in, &t_bytes, kEncodedVectorSize))
1066 !vector_decode(&pub->t, CBS_data(&t_bytes), kLog2Prime)) {
1067 return 0; 1098 return 0;
1068 } 1099 if (!vector_decode(&pub->t, CBS_data(&t_bytes), kLog2Prime))
1100 return 0;
1101
1069 memcpy(pub->rho, CBS_data(in), sizeof(pub->rho)); 1102 memcpy(pub->rho, CBS_data(in), sizeof(pub->rho));
1070 if (!CBS_skip(in, sizeof(pub->rho))) 1103 if (!CBS_skip(in, sizeof(pub->rho)))
1071 return 0; 1104 return 0;
@@ -1074,64 +1107,84 @@ mlkem_parse_public_key_no_hash(struct public_key *pub, CBS *in)
1074} 1107}
1075 1108
1076int 1109int
1077MLKEM1024_parse_public_key(struct MLKEM1024_public_key *public_key, CBS *in) 1110MLKEM1024_parse_public_key(struct MLKEM1024_public_key *public_key,
1111 const uint8_t *input, size_t input_len)
1078{ 1112{
1079 struct public_key *pub = public_key_1024_from_external(public_key); 1113 struct public_key *pub = public_key_1024_from_external(public_key);
1080 CBS orig_in = *in; 1114 CBS cbs;
1081 1115
1082 if (!mlkem_parse_public_key_no_hash(pub, in) || 1116 CBS_init(&cbs, input, input_len);
1083 CBS_len(in) != 0) { 1117 if (!mlkem_parse_public_key_no_hash(pub, &cbs))
1084 return 0; 1118 return 0;
1085 } 1119 if (CBS_len(&cbs) != 0)
1086 hash_h(pub->public_key_hash, CBS_data(&orig_in), CBS_len(&orig_in)); 1120 return 0;
1121
1122 hash_h(pub->public_key_hash, input, input_len);
1123
1087 return 1; 1124 return 1;
1088} 1125}
1089LCRYPTO_ALIAS(MLKEM1024_parse_public_key); 1126LCRYPTO_ALIAS(MLKEM1024_parse_public_key);
1090 1127
1091int 1128int
1092MLKEM1024_marshal_private_key(CBB *out, 1129MLKEM1024_marshal_private_key(const struct MLKEM1024_private_key *private_key,
1093 const struct MLKEM1024_private_key *private_key) 1130 uint8_t **out_private_key, size_t *out_private_key_len)
1094{ 1131{
1095 const struct private_key *const priv = private_key_1024_from_external( 1132 const struct private_key *const priv = private_key_1024_from_external(
1096 private_key); 1133 private_key);
1097 uint8_t *s_output; 1134 CBB cbb;
1135 int ret = 0;
1098 1136
1099 if (!CBB_add_space(out, &s_output, kEncodedVectorSize)) { 1137 if (!CBB_init(&cbb, MLKEM1024_PRIVATE_KEY_BYTES))
1100 return 0; 1138 goto err;
1101 } 1139
1102 vector_encode(s_output, &priv->s, kLog2Prime); 1140 if (!vector_encode_cbb(&cbb, &priv->s, kLog2Prime))
1103 if (!mlkem_marshal_public_key(out, &priv->pub) || 1141 goto err;
1104 !CBB_add_bytes(out, priv->pub.public_key_hash, 1142 if (!mlkem_marshal_public_key(&cbb, &priv->pub))
1105 sizeof(priv->pub.public_key_hash)) || 1143 goto err;
1106 !CBB_add_bytes(out, priv->fo_failure_secret, 1144 if (!CBB_add_bytes(&cbb, priv->pub.public_key_hash,
1107 sizeof(priv->fo_failure_secret))) { 1145 sizeof(priv->pub.public_key_hash)))
1108 return 0; 1146 goto err;
1109 } 1147 if (!CBB_add_bytes(&cbb, priv->fo_failure_secret,
1110 return 1; 1148 sizeof(priv->fo_failure_secret)))
1149 goto err;
1150
1151 if (!CBB_finish(&cbb, out_private_key, out_private_key_len))
1152 goto err;
1153
1154 ret = 1;
1155
1156 err:
1157 CBB_cleanup(&cbb);
1158
1159 return ret;
1111} 1160}
1112 1161
1113int 1162int
1114MLKEM1024_parse_private_key(struct MLKEM1024_private_key *out_private_key, 1163MLKEM1024_parse_private_key(struct MLKEM1024_private_key *out_private_key,
1115 CBS *in) 1164 const uint8_t *input, size_t input_len)
1116{ 1165{
1117 struct private_key *const priv = private_key_1024_from_external( 1166 struct private_key *const priv = private_key_1024_from_external(
1118 out_private_key); 1167 out_private_key);
1119 CBS s_bytes; 1168 CBS cbs, s_bytes;
1120 1169
1121 if (!CBS_get_bytes(in, &s_bytes, kEncodedVectorSize) || 1170 CBS_init(&cbs, input, input_len);
1122 !vector_decode(&priv->s, CBS_data(&s_bytes), kLog2Prime) || 1171
1123 !mlkem_parse_public_key_no_hash(&priv->pub, in)) { 1172 if (!CBS_get_bytes(&cbs, &s_bytes, kEncodedVectorSize))
1124 return 0; 1173 return 0;
1125 } 1174 if (!vector_decode(&priv->s, CBS_data(&s_bytes), kLog2Prime))
1126 memcpy(priv->pub.public_key_hash, CBS_data(in), 1175 return 0;
1176 if (!mlkem_parse_public_key_no_hash(&priv->pub, &cbs))
1177 return 0;
1178
1179 memcpy(priv->pub.public_key_hash, CBS_data(&cbs),
1127 sizeof(priv->pub.public_key_hash)); 1180 sizeof(priv->pub.public_key_hash));
1128 if (!CBS_skip(in, sizeof(priv->pub.public_key_hash))) 1181 if (!CBS_skip(&cbs, sizeof(priv->pub.public_key_hash)))
1129 return 0; 1182 return 0;
1130 memcpy(priv->fo_failure_secret, CBS_data(in), 1183 memcpy(priv->fo_failure_secret, CBS_data(&cbs),
1131 sizeof(priv->fo_failure_secret)); 1184 sizeof(priv->fo_failure_secret));
1132 if (!CBS_skip(in, sizeof(priv->fo_failure_secret))) 1185 if (!CBS_skip(&cbs, sizeof(priv->fo_failure_secret)))
1133 return 0; 1186 return 0;
1134 if (CBS_len(in) != 0) 1187 if (CBS_len(&cbs) != 0)
1135 return 0; 1188 return 0;
1136 1189
1137 return 1; 1190 return 1;
diff --git a/src/lib/libcrypto/mlkem/mlkem768.c b/src/lib/libcrypto/mlkem/mlkem768.c
index bacde0c0b7..653b92d8d8 100644
--- a/src/lib/libcrypto/mlkem/mlkem768.c
+++ b/src/lib/libcrypto/mlkem/mlkem768.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: mlkem768.c,v 1.7 2025/01/03 08:19:24 tb Exp $ */ 1/* $OpenBSD: mlkem768.c,v 1.12 2025/05/20 00:30:38 beck Exp $ */
2/* 2/*
3 * Copyright (c) 2024, Google Inc. 3 * Copyright (c) 2024, Google Inc.
4 * Copyright (c) 2024, Bob Beck <beck@obtuse.com> 4 * Copyright (c) 2024, Bob Beck <beck@obtuse.com>
@@ -89,6 +89,7 @@ static const int kLog2Prime = 12;
89static const uint16_t kHalfPrime = (/*kPrime=*/3329 - 1) / 2; 89static const uint16_t kHalfPrime = (/*kPrime=*/3329 - 1) / 2;
90static const int kDU768 = 10; 90static const int kDU768 = 10;
91static const int kDV768 = 4; 91static const int kDV768 = 4;
92
92/* 93/*
93 * kInverseDegree is 128^-1 mod 3329; 128 because kPrime does not have a 512th 94 * kInverseDegree is 128^-1 mod 3329; 128 because kPrime does not have a 512th
94 * root of unity. 95 * root of unity.
@@ -611,6 +612,19 @@ vector_encode(uint8_t *out, const vector *a, int bits)
611 } 612 }
612} 613}
613 614
615/* Encodes an entire vector as above, but adding it to a CBB */
616static int
617vector_encode_cbb(CBB *cbb, const vector *a, int bits)
618{
619 uint8_t *encoded_vector;
620
621 if (!CBB_add_space(cbb, &encoded_vector, kEncodedVectorSize))
622 return 0;
623 vector_encode(encoded_vector, a, bits);
624
625 return 1;
626}
627
614/* 628/*
615 * scalar_decode parses |DEGREE * bits| bits from |in| into |DEGREE| values in 629 * scalar_decode parses |DEGREE * bits| bits from |in| into |DEGREE| values in
616 * |out|. It returns one on success and zero if any parsed value is >= 630 * |out|. It returns one on success and zero if any parsed value is >=
@@ -792,6 +806,8 @@ struct public_key {
792 matrix m; 806 matrix m;
793}; 807};
794 808
809CTASSERT(sizeof(struct MLKEM768_public_key) == sizeof(struct public_key));
810
795static struct public_key * 811static struct public_key *
796public_key_768_from_external(const struct MLKEM768_public_key *external) 812public_key_768_from_external(const struct MLKEM768_public_key *external)
797{ 813{
@@ -804,6 +820,8 @@ struct private_key {
804 uint8_t fo_failure_secret[32]; 820 uint8_t fo_failure_secret[32];
805}; 821};
806 822
823CTASSERT(sizeof(struct MLKEM768_private_key) == sizeof(struct private_key));
824
807static struct private_key * 825static struct private_key *
808private_key_768_from_external(const struct MLKEM768_private_key *external) 826private_key_768_from_external(const struct MLKEM768_private_key *external)
809{ 827{
@@ -814,7 +832,7 @@ private_key_768_from_external(const struct MLKEM768_private_key *external)
814 * Calls |MLKEM768_generate_key_external_entropy| with random bytes from 832 * Calls |MLKEM768_generate_key_external_entropy| with random bytes from
815 * |RAND_bytes|. 833 * |RAND_bytes|.
816 */ 834 */
817void 835int
818MLKEM768_generate_key(uint8_t out_encoded_public_key[MLKEM768_PUBLIC_KEY_BYTES], 836MLKEM768_generate_key(uint8_t out_encoded_public_key[MLKEM768_PUBLIC_KEY_BYTES],
819 uint8_t optional_out_seed[MLKEM_SEED_BYTES], 837 uint8_t optional_out_seed[MLKEM_SEED_BYTES],
820 struct MLKEM768_private_key *out_private_key) 838 struct MLKEM768_private_key *out_private_key)
@@ -824,7 +842,7 @@ MLKEM768_generate_key(uint8_t out_encoded_public_key[MLKEM768_PUBLIC_KEY_BYTES],
824 entropy_buf; 842 entropy_buf;
825 843
826 arc4random_buf(entropy, MLKEM_SEED_BYTES); 844 arc4random_buf(entropy, MLKEM_SEED_BYTES);
827 MLKEM768_generate_key_external_entropy(out_encoded_public_key, 845 return MLKEM768_generate_key_external_entropy(out_encoded_public_key,
828 out_private_key, entropy); 846 out_private_key, entropy);
829} 847}
830LCRYPTO_ALIAS(MLKEM768_generate_key); 848LCRYPTO_ALIAS(MLKEM768_generate_key);
@@ -838,29 +856,20 @@ MLKEM768_private_key_from_seed(struct MLKEM768_private_key *out_private_key,
838 if (seed_len != MLKEM_SEED_BYTES) { 856 if (seed_len != MLKEM_SEED_BYTES) {
839 return 0; 857 return 0;
840 } 858 }
841 MLKEM768_generate_key_external_entropy(public_key_bytes, 859 return MLKEM768_generate_key_external_entropy(public_key_bytes,
842 out_private_key, seed); 860 out_private_key, seed);
843
844 return 1;
845} 861}
846LCRYPTO_ALIAS(MLKEM768_private_key_from_seed); 862LCRYPTO_ALIAS(MLKEM768_private_key_from_seed);
847 863
848static int 864static int
849mlkem_marshal_public_key(CBB *out, const struct public_key *pub) 865mlkem_marshal_public_key(CBB *out, const struct public_key *pub)
850{ 866{
851 uint8_t *vector_output; 867 if (!vector_encode_cbb(out, &pub->t, kLog2Prime))
852
853 if (!CBB_add_space(out, &vector_output, kEncodedVectorSize)) {
854 return 0;
855 }
856 vector_encode(vector_output, &pub->t, kLog2Prime);
857 if (!CBB_add_bytes(out, pub->rho, sizeof(pub->rho))) {
858 return 0; 868 return 0;
859 } 869 return CBB_add_bytes(out, pub->rho, sizeof(pub->rho));
860 return 1;
861} 870}
862 871
863void 872int
864MLKEM768_generate_key_external_entropy( 873MLKEM768_generate_key_external_entropy(
865 uint8_t out_encoded_public_key[MLKEM768_PUBLIC_KEY_BYTES], 874 uint8_t out_encoded_public_key[MLKEM768_PUBLIC_KEY_BYTES],
866 struct MLKEM768_private_key *out_private_key, 875 struct MLKEM768_private_key *out_private_key,
@@ -874,7 +883,9 @@ MLKEM768_generate_key_external_entropy(
874 uint8_t hashed[64]; 883 uint8_t hashed[64];
875 vector error; 884 vector error;
876 CBB cbb; 885 CBB cbb;
886 int ret = 0;
877 887
888 memset(&cbb, 0, sizeof(CBB));
878 memcpy(augmented_seed, entropy, 32); 889 memcpy(augmented_seed, entropy, 32);
879 augmented_seed[32] = RANK768; 890 augmented_seed[32] = RANK768;
880 hash_g(hashed, augmented_seed, 33); 891 hash_g(hashed, augmented_seed, 33);
@@ -889,16 +900,23 @@ MLKEM768_generate_key_external_entropy(
889 matrix_mult_transpose(&priv->pub.t, &priv->pub.m, &priv->s); 900 matrix_mult_transpose(&priv->pub.t, &priv->pub.m, &priv->s);
890 vector_add(&priv->pub.t, &error); 901 vector_add(&priv->pub.t, &error);
891 902
892 /* XXX - error checking */ 903 if (!CBB_init_fixed(&cbb, out_encoded_public_key,
893 CBB_init_fixed(&cbb, out_encoded_public_key, MLKEM768_PUBLIC_KEY_BYTES); 904 MLKEM768_PUBLIC_KEY_BYTES))
894 if (!mlkem_marshal_public_key(&cbb, &priv->pub)) { 905 goto err;
895 abort(); 906
896 } 907 if (!mlkem_marshal_public_key(&cbb, &priv->pub))
897 CBB_cleanup(&cbb); 908 goto err;
898 909
899 hash_h(priv->pub.public_key_hash, out_encoded_public_key, 910 hash_h(priv->pub.public_key_hash, out_encoded_public_key,
900 MLKEM768_PUBLIC_KEY_BYTES); 911 MLKEM768_PUBLIC_KEY_BYTES);
901 memcpy(priv->fo_failure_secret, entropy + 32, 32); 912 memcpy(priv->fo_failure_secret, entropy + 32, 32);
913
914 ret = 1;
915
916 err:
917 CBB_cleanup(&cbb);
918
919 return ret;
902} 920}
903 921
904void 922void
@@ -961,8 +979,8 @@ MLKEM768_encap(uint8_t out_ciphertext[MLKEM768_CIPHERTEXT_BYTES],
961 uint8_t entropy[MLKEM_ENCAP_ENTROPY]; 979 uint8_t entropy[MLKEM_ENCAP_ENTROPY];
962 980
963 arc4random_buf(entropy, MLKEM_ENCAP_ENTROPY); 981 arc4random_buf(entropy, MLKEM_ENCAP_ENTROPY);
964 MLKEM768_encap_external_entropy(out_ciphertext, out_shared_secret, 982 MLKEM768_encap_external_entropy(out_ciphertext,
965 public_key, entropy); 983 out_shared_secret, public_key, entropy);
966} 984}
967LCRYPTO_ALIAS(MLKEM768_encap); 985LCRYPTO_ALIAS(MLKEM768_encap);
968 986
@@ -1044,11 +1062,26 @@ MLKEM768_decap(uint8_t out_shared_secret[MLKEM_SHARED_SECRET_BYTES],
1044LCRYPTO_ALIAS(MLKEM768_decap); 1062LCRYPTO_ALIAS(MLKEM768_decap);
1045 1063
1046int 1064int
1047MLKEM768_marshal_public_key(CBB *out, 1065MLKEM768_marshal_public_key(uint8_t **output, size_t *output_len,
1048 const struct MLKEM768_public_key *public_key) 1066 const struct MLKEM768_public_key *public_key)
1049{ 1067{
1050 return mlkem_marshal_public_key(out, 1068 int ret = 0;
1051 public_key_768_from_external(public_key)); 1069 CBB cbb;
1070
1071 if (!CBB_init(&cbb, MLKEM768_PUBLIC_KEY_BYTES))
1072 goto err;
1073 if (!mlkem_marshal_public_key(&cbb,
1074 public_key_768_from_external(public_key)))
1075 goto err;
1076 if (!CBB_finish(&cbb, output, output_len))
1077 goto err;
1078
1079 ret = 1;
1080
1081 err:
1082 CBB_cleanup(&cbb);
1083
1084 return ret;
1052} 1085}
1053LCRYPTO_ALIAS(MLKEM768_marshal_public_key); 1086LCRYPTO_ALIAS(MLKEM768_marshal_public_key);
1054 1087
@@ -1061,10 +1094,11 @@ mlkem_parse_public_key_no_hash(struct public_key *pub, CBS *in)
1061{ 1094{
1062 CBS t_bytes; 1095 CBS t_bytes;
1063 1096
1064 if (!CBS_get_bytes(in, &t_bytes, kEncodedVectorSize) || 1097 if (!CBS_get_bytes(in, &t_bytes, kEncodedVectorSize))
1065 !vector_decode(&pub->t, CBS_data(&t_bytes), kLog2Prime)) {
1066 return 0; 1098 return 0;
1067 } 1099 if (!vector_decode(&pub->t, CBS_data(&t_bytes), kLog2Prime))
1100 return 0;
1101
1068 memcpy(pub->rho, CBS_data(in), sizeof(pub->rho)); 1102 memcpy(pub->rho, CBS_data(in), sizeof(pub->rho));
1069 if (!CBS_skip(in, sizeof(pub->rho))) 1103 if (!CBS_skip(in, sizeof(pub->rho)))
1070 return 0; 1104 return 0;
@@ -1073,64 +1107,84 @@ mlkem_parse_public_key_no_hash(struct public_key *pub, CBS *in)
1073} 1107}
1074 1108
1075int 1109int
1076MLKEM768_parse_public_key(struct MLKEM768_public_key *public_key, CBS *in) 1110MLKEM768_parse_public_key(struct MLKEM768_public_key *public_key,
1111 const uint8_t *input, size_t input_len)
1077{ 1112{
1078 struct public_key *pub = public_key_768_from_external(public_key); 1113 struct public_key *pub = public_key_768_from_external(public_key);
1079 CBS orig_in = *in; 1114 CBS cbs;
1080 1115
1081 if (!mlkem_parse_public_key_no_hash(pub, in) || 1116 CBS_init(&cbs, input, input_len);
1082 CBS_len(in) != 0) { 1117 if (!mlkem_parse_public_key_no_hash(pub, &cbs))
1083 return 0; 1118 return 0;
1084 } 1119 if (CBS_len(&cbs) != 0)
1085 hash_h(pub->public_key_hash, CBS_data(&orig_in), CBS_len(&orig_in)); 1120 return 0;
1121
1122 hash_h(pub->public_key_hash, input, input_len);
1123
1086 return 1; 1124 return 1;
1087} 1125}
1088LCRYPTO_ALIAS(MLKEM768_parse_public_key); 1126LCRYPTO_ALIAS(MLKEM768_parse_public_key);
1089 1127
1090int 1128int
1091MLKEM768_marshal_private_key(CBB *out, 1129MLKEM768_marshal_private_key(const struct MLKEM768_private_key *private_key,
1092 const struct MLKEM768_private_key *private_key) 1130 uint8_t **out_private_key, size_t *out_private_key_len)
1093{ 1131{
1094 const struct private_key *const priv = private_key_768_from_external( 1132 const struct private_key *const priv = private_key_768_from_external(
1095 private_key); 1133 private_key);
1096 uint8_t *s_output; 1134 CBB cbb;
1135 int ret = 0;
1097 1136
1098 if (!CBB_add_space(out, &s_output, kEncodedVectorSize)) { 1137 if (!CBB_init(&cbb, MLKEM768_PRIVATE_KEY_BYTES))
1099 return 0; 1138 goto err;
1100 } 1139
1101 vector_encode(s_output, &priv->s, kLog2Prime); 1140 if (!vector_encode_cbb(&cbb, &priv->s, kLog2Prime))
1102 if (!mlkem_marshal_public_key(out, &priv->pub) || 1141 goto err;
1103 !CBB_add_bytes(out, priv->pub.public_key_hash, 1142 if (!mlkem_marshal_public_key(&cbb, &priv->pub))
1104 sizeof(priv->pub.public_key_hash)) || 1143 goto err;
1105 !CBB_add_bytes(out, priv->fo_failure_secret, 1144 if (!CBB_add_bytes(&cbb, priv->pub.public_key_hash,
1106 sizeof(priv->fo_failure_secret))) { 1145 sizeof(priv->pub.public_key_hash)))
1107 return 0; 1146 goto err;
1108 } 1147 if (!CBB_add_bytes(&cbb, priv->fo_failure_secret,
1109 return 1; 1148 sizeof(priv->fo_failure_secret)))
1149 goto err;
1150
1151 if (!CBB_finish(&cbb, out_private_key, out_private_key_len))
1152 goto err;
1153
1154 ret = 1;
1155
1156 err:
1157 CBB_cleanup(&cbb);
1158
1159 return ret;
1110} 1160}
1111 1161
1112int 1162int
1113MLKEM768_parse_private_key(struct MLKEM768_private_key *out_private_key, 1163MLKEM768_parse_private_key(struct MLKEM768_private_key *out_private_key,
1114 CBS *in) 1164 const uint8_t *input, size_t input_len)
1115{ 1165{
1116 struct private_key *const priv = private_key_768_from_external( 1166 struct private_key *const priv = private_key_768_from_external(
1117 out_private_key); 1167 out_private_key);
1118 CBS s_bytes; 1168 CBS cbs, s_bytes;
1119 1169
1120 if (!CBS_get_bytes(in, &s_bytes, kEncodedVectorSize) || 1170 CBS_init(&cbs, input, input_len);
1121 !vector_decode(&priv->s, CBS_data(&s_bytes), kLog2Prime) || 1171
1122 !mlkem_parse_public_key_no_hash(&priv->pub, in)) { 1172 if (!CBS_get_bytes(&cbs, &s_bytes, kEncodedVectorSize))
1123 return 0; 1173 return 0;
1124 } 1174 if (!vector_decode(&priv->s, CBS_data(&s_bytes), kLog2Prime))
1125 memcpy(priv->pub.public_key_hash, CBS_data(in), 1175 return 0;
1176 if (!mlkem_parse_public_key_no_hash(&priv->pub, &cbs))
1177 return 0;
1178
1179 memcpy(priv->pub.public_key_hash, CBS_data(&cbs),
1126 sizeof(priv->pub.public_key_hash)); 1180 sizeof(priv->pub.public_key_hash));
1127 if (!CBS_skip(in, sizeof(priv->pub.public_key_hash))) 1181 if (!CBS_skip(&cbs, sizeof(priv->pub.public_key_hash)))
1128 return 0; 1182 return 0;
1129 memcpy(priv->fo_failure_secret, CBS_data(in), 1183 memcpy(priv->fo_failure_secret, CBS_data(&cbs),
1130 sizeof(priv->fo_failure_secret)); 1184 sizeof(priv->fo_failure_secret));
1131 if (!CBS_skip(in, sizeof(priv->fo_failure_secret))) 1185 if (!CBS_skip(&cbs, sizeof(priv->fo_failure_secret)))
1132 return 0; 1186 return 0;
1133 if (CBS_len(in) != 0) 1187 if (CBS_len(&cbs) != 0)
1134 return 0; 1188 return 0;
1135 1189
1136 return 1; 1190 return 1;
diff --git a/src/lib/libcrypto/mlkem/mlkem_internal.h b/src/lib/libcrypto/mlkem/mlkem_internal.h
index d3f325932f..1e051970a8 100644
--- a/src/lib/libcrypto/mlkem/mlkem_internal.h
+++ b/src/lib/libcrypto/mlkem/mlkem_internal.h
@@ -1,4 +1,4 @@
1/* $OpenBSD: mlkem_internal.h,v 1.4 2024/12/19 23:52:26 tb Exp $ */ 1/* $OpenBSD: mlkem_internal.h,v 1.7 2025/05/20 00:33:40 beck Exp $ */
2/* 2/*
3 * Copyright (c) 2023, Google Inc. 3 * Copyright (c) 2023, Google Inc.
4 * 4 *
@@ -41,7 +41,7 @@ __BEGIN_HIDDEN_DECLS
41 * regular callers should use the non-deterministic |MLKEM_generate_key| 41 * regular callers should use the non-deterministic |MLKEM_generate_key|
42 * directly. 42 * directly.
43 */ 43 */
44void MLKEM768_generate_key_external_entropy( 44int MLKEM768_generate_key_external_entropy(
45 uint8_t out_encoded_public_key[MLKEM768_PUBLIC_KEY_BYTES], 45 uint8_t out_encoded_public_key[MLKEM768_PUBLIC_KEY_BYTES],
46 struct MLKEM768_private_key *out_private_key, 46 struct MLKEM768_private_key *out_private_key,
47 const uint8_t entropy[MLKEM_SEED_BYTES]); 47 const uint8_t entropy[MLKEM_SEED_BYTES]);
@@ -57,8 +57,8 @@ void MLKEM768_generate_key_external_entropy(
57 * format for ML-KEM private keys. It returns one on success or zero on 57 * format for ML-KEM private keys. It returns one on success or zero on
58 * allocation error. 58 * allocation error.
59 */ 59 */
60int MLKEM768_marshal_private_key(CBB *out, 60int MLKEM768_marshal_private_key(const struct MLKEM768_private_key *private_key,
61 const struct MLKEM768_private_key *private_key); 61 uint8_t **out_private_key, size_t *out_private_key_len);
62 62
63/* 63/*
64 * MLKEM_encap_external_entropy behaves like |MLKEM_encap|, but uses 64 * MLKEM_encap_external_entropy behaves like |MLKEM_encap|, but uses
@@ -80,7 +80,7 @@ void MLKEM768_encap_external_entropy(
80 * regular callers should use the non-deterministic |MLKEM_generate_key| 80 * regular callers should use the non-deterministic |MLKEM_generate_key|
81 * directly. 81 * directly.
82 */ 82 */
83void MLKEM1024_generate_key_external_entropy( 83int MLKEM1024_generate_key_external_entropy(
84 uint8_t out_encoded_public_key[MLKEM1024_PUBLIC_KEY_BYTES], 84 uint8_t out_encoded_public_key[MLKEM1024_PUBLIC_KEY_BYTES],
85 struct MLKEM1024_private_key *out_private_key, 85 struct MLKEM1024_private_key *out_private_key,
86 const uint8_t entropy[MLKEM_SEED_BYTES]); 86 const uint8_t entropy[MLKEM_SEED_BYTES]);
@@ -96,8 +96,9 @@ void MLKEM1024_generate_key_external_entropy(
96 * standard format for ML-KEM private keys. It returns one on success or zero on 96 * standard format for ML-KEM private keys. It returns one on success or zero on
97 * allocation error. 97 * allocation error.
98 */ 98 */
99int MLKEM1024_marshal_private_key(CBB *out, 99int MLKEM1024_marshal_private_key(
100 const struct MLKEM1024_private_key *private_key); 100 const struct MLKEM1024_private_key *private_key, uint8_t **out_private_key,
101 size_t *out_private_key_len);
101 102
102/* 103/*
103 * MLKEM_encap_external_entropy behaves like |MLKEM_encap|, but uses 104 * MLKEM_encap_external_entropy behaves like |MLKEM_encap|, but uses