summaryrefslogtreecommitdiff
path: root/src/lib/libcrypto/mlkem/mlkem768.c
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/lib/libcrypto/mlkem/mlkem768.c178
1 files changed, 116 insertions, 62 deletions
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;