Home | History | Annotate | Line # | Download | only in dist
      1 /*	$NetBSD: libcrux-mlkem-mldsa.c,v 1.2 2026/09/21 23:01:54 christos Exp $	*/
      2 /* $OpenBSD: libcrux-mlkem-mldsa.c,v 1.1 2026/06/14 03:59:34 djm Exp $ */
      3 
      4 /*
      5  * Copyright (c) 2026 Damien Miller <djm (at) mindrot.org>
      6  *
      7  * Permission to use, copy, modify, and distribute this software for any
      8  * purpose with or without fee is hereby granted, provided that the above
      9  * copyright notice and this permission notice appear in all copies.
     10  *
     11  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
     12  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
     13  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
     14  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
     15  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
     16  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
     17  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
     18  */
     19 #include "includes.h"
     20 __RCSID("$NetBSD: libcrux-mlkem-mldsa.c,v 1.2 2026/09/21 23:01:54 christos Exp $");
     21 
     22 #include <sys/types.h>
     23 #include <stdint.h>
     24 #include <stdlib.h>
     25 #include <stdbool.h>
     26 #include <string.h>
     27 
     28 #include "log.h"
     29 #include "crypto_api.h"
     30 #include "libcrux_internal.h"
     31 
     32 /* ML-KEM 768 */
     33 
     34 int
     35 crypto_kem_mlkem768_keypair(uint8_t pk[crypto_kem_mlkem768_PUBLICKEYBYTES],
     36     uint8_t sk[crypto_kem_mlkem768_SECRETKEYBYTES])
     37 {
     38 	uint8_t rnd[crypto_kem_mlkem768_KEYPAIRSEEDBYTES];
     39 	int r;
     40 
     41 	arc4random_buf(rnd, sizeof(rnd));
     42 	r = crypto_kem_mlkem768_keypair_seeded(pk, sk, rnd);
     43 	explicit_bzero(rnd, sizeof(rnd));
     44 	return r;
     45 }
     46 
     47 int
     48 crypto_kem_mlkem768_keypair_seeded(uint8_t pk[crypto_kem_mlkem768_PUBLICKEYBYTES],
     49     uint8_t sk[crypto_kem_mlkem768_SECRETKEYBYTES],
     50     const uint8_t seed[crypto_kem_mlkem768_KEYPAIRSEEDBYTES])
     51 {
     52 	libcrux_mlkem768_keypair keypair;
     53 	libcrux_mlkem768_keypair_rnd rnd;
     54 
     55 	memcpy(rnd.data, seed, sizeof(rnd.data));
     56 	keypair = libcrux_ml_kem_mlkem768_portable_generate_key_pair(rnd);
     57 	memcpy(pk, keypair.pk.data, crypto_kem_mlkem768_PUBLICKEYBYTES);
     58 	memcpy(sk, keypair.sk.data, crypto_kem_mlkem768_SECRETKEYBYTES);
     59 
     60 	explicit_bzero(&keypair, sizeof(keypair));
     61 	explicit_bzero(&rnd, sizeof(rnd));
     62 	return 0;
     63 }
     64 
     65 int
     66 crypto_kem_mlkem768_enc(uint8_t ct[crypto_kem_mlkem768_CIPHERTEXTBYTES],
     67     uint8_t shared_secret[crypto_kem_mlkem768_BYTES],
     68     const uint8_t pk[crypto_kem_mlkem768_PUBLICKEYBYTES])
     69 {
     70 	uint8_t rnd[crypto_kem_mlkem768_ENCSEEDBYTES];
     71 	int r;
     72 
     73 	arc4random_buf(rnd, sizeof(rnd));
     74 	r = crypto_kem_mlkem768_enc_seeded(ct, shared_secret, pk, rnd);
     75 	explicit_bzero(rnd, sizeof(rnd));
     76 	return r;
     77 }
     78 
     79 int
     80 crypto_kem_mlkem768_enc_seeded(uint8_t ct[crypto_kem_mlkem768_CIPHERTEXTBYTES],
     81     uint8_t shared_secret[crypto_kem_mlkem768_BYTES],
     82     const uint8_t pk[crypto_kem_mlkem768_PUBLICKEYBYTES],
     83     const uint8_t seed[crypto_kem_mlkem768_ENCSEEDBYTES])
     84 {
     85 	libcrux_mlkem768_enc_result enc;
     86 	libcrux_mlkem768_pk pk_internal;
     87 	libcrux_mlkem768_enc_rnd rnd;
     88 
     89 	memcpy(pk_internal.data, pk, crypto_kem_mlkem768_PUBLICKEYBYTES);
     90 	if (!libcrux_ml_kem_mlkem768_portable_validate_public_key(&pk_internal))
     91 		return -1;
     92 	memcpy(rnd.data, seed, sizeof(rnd.data));
     93 	enc = libcrux_ml_kem_mlkem768_portable_encapsulate(&pk_internal, rnd);
     94 	memcpy(ct, enc.fst.data, crypto_kem_mlkem768_CIPHERTEXTBYTES);
     95 	memcpy(shared_secret, enc.snd.data, crypto_kem_mlkem768_BYTES);
     96 
     97 	explicit_bzero(&enc, sizeof(enc));
     98 	explicit_bzero(&rnd, sizeof(rnd));
     99 	return 0;
    100 }
    101 
    102 int
    103 crypto_kem_mlkem768_dec(uint8_t shared_secret[crypto_kem_mlkem768_BYTES],
    104     const uint8_t ct[crypto_kem_mlkem768_CIPHERTEXTBYTES],
    105     const uint8_t sk[crypto_kem_mlkem768_SECRETKEYBYTES])
    106 {
    107 	libcrux_mlkem768_sk sk_internal;
    108 	libcrux_mlkem768_ciphertext ct_internal;
    109 	libcrux_mlkem768_dec_result shared_secret_internal;
    110 
    111 	memcpy(sk_internal.data, sk, crypto_kem_mlkem768_SECRETKEYBYTES);
    112 	memcpy(ct_internal.data, ct, crypto_kem_mlkem768_CIPHERTEXTBYTES);
    113 	shared_secret_internal = libcrux_ml_kem_mlkem768_portable_decapsulate(
    114 	    &sk_internal, &ct_internal);
    115 	memcpy(shared_secret, shared_secret_internal.data,
    116 	    crypto_kem_mlkem768_BYTES);
    117 
    118 	explicit_bzero(&sk_internal, sizeof(sk_internal));
    119 	explicit_bzero(&shared_secret_internal, sizeof(shared_secret_internal));
    120 	return 0;
    121 }
    122 
    123 /* ML-DSA 44 */
    124 
    125 int
    126 crypto_sign_mldsa44_keypair(uint8_t pk[MLDSA44_PUBLICKEYBYTES],
    127     uint8_t sk[MLDSA44_SECRETKEYBYTES])
    128 {
    129 	uint8_t rnd[MLDSA44_SEEDBYTES];
    130 	int r;
    131 
    132 	arc4random_buf(rnd, sizeof(rnd));
    133 	r = crypto_sign_mldsa44_keypair_seeded(pk, sk, rnd);
    134 	explicit_bzero(rnd, sizeof(rnd));
    135 	return r;
    136 }
    137 
    138 int
    139 crypto_sign_mldsa44_keypair_seeded(uint8_t pk[MLDSA44_PUBLICKEYBYTES],
    140     uint8_t sk[MLDSA44_SECRETKEYBYTES], const uint8_t seed[MLDSA44_SEEDBYTES])
    141 {
    142 	libcrux_mldsa44_keypair_rnd rnd;
    143 	libcrux_mldsa44_keypair keypair;
    144 
    145 	memcpy(rnd.data, seed, sizeof(rnd.data));
    146 	keypair = libcrux_ml_dsa_ml_dsa_44_portable_generate_key_pair(rnd);
    147 	memcpy(pk, keypair.verification_key.data, MLDSA44_PUBLICKEYBYTES);
    148 	memcpy(sk, keypair.signing_key.data, MLDSA44_SECRETKEYBYTES);
    149 
    150 	explicit_bzero(&keypair, sizeof(keypair));
    151 	explicit_bzero(&rnd, sizeof(rnd));
    152 	return 0;
    153 }
    154 
    155 int
    156 crypto_sign_mldsa44(uint8_t sig[MLDSA44_SIGBYTES],
    157     const uint8_t *msg, size_t msglen,
    158     const uint8_t *ctx, size_t ctxlen,
    159     const uint8_t sk[MLDSA44_SECRETKEYBYTES])
    160 {
    161 	uint8_t rnd[MLDSA44_SEEDBYTES];
    162 	int r;
    163 
    164 	arc4random_buf(rnd, sizeof(rnd));
    165 	r = crypto_sign_mldsa44_seeded(sig, msg, msglen, ctx, ctxlen, sk, rnd);
    166 	explicit_bzero(rnd, sizeof(rnd));
    167 	return r;
    168 }
    169 
    170 int
    171 crypto_sign_mldsa44_seeded(uint8_t sig[MLDSA44_SIGBYTES],
    172     const uint8_t *msg, size_t msglen,
    173     const uint8_t *ctx, size_t ctxlen,
    174     const uint8_t sk[MLDSA44_SECRETKEYBYTES],
    175     const uint8_t seed[MLDSA44_SEEDBYTES])
    176 {
    177 	libcrux_mldsa44_sign_rnd rnd;
    178 	libcrux_mldsa44_sk sk_internal;
    179 	libcrux_mldsa44_message message = { msg, msglen };
    180 	libcrux_mldsa44_message context = { ctx, ctxlen };
    181 	libcrux_mldsa44_sign_result res;
    182 	int r = -1;
    183 
    184 	memcpy(sk_internal.data, sk, MLDSA44_SECRETKEYBYTES);
    185 	memcpy(rnd.data, seed, sizeof(rnd.data));
    186 	res = libcrux_ml_dsa_ml_dsa_44_portable_sign(&sk_internal,
    187 	    message, context, rnd);
    188 	if (res.tag == LIBCRUX_RESULT_OK) {
    189 		memcpy(sig, res.val.case_Ok.data, MLDSA44_SIGBYTES);
    190 		r = 0;
    191 	}
    192 
    193 	explicit_bzero(&sk_internal, sizeof(sk_internal));
    194 	explicit_bzero(&res, sizeof(res));
    195 	explicit_bzero(&rnd, sizeof(rnd));
    196 	return r;
    197 }
    198 
    199 int
    200 crypto_sign_mldsa44_verify(const uint8_t sig[MLDSA44_SIGBYTES],
    201     const uint8_t *msg, size_t msglen,
    202     const uint8_t *ctx, size_t ctxlen,
    203     const uint8_t pk[MLDSA44_PUBLICKEYBYTES])
    204 {
    205 	libcrux_mldsa44_pk pk_internal;
    206 	libcrux_mldsa44_signature sig_internal;
    207 	libcrux_mldsa44_message message = { msg, msglen };
    208 	libcrux_mldsa44_message context = { ctx, ctxlen };
    209 	libcrux_mldsa44_verify_result res;
    210 
    211 	memcpy(pk_internal.data, pk, MLDSA44_PUBLICKEYBYTES);
    212 	memcpy(sig_internal.data, sig, MLDSA44_SIGBYTES);
    213 	res = libcrux_ml_dsa_ml_dsa_44_portable_verify(&pk_internal,
    214 	    message, context, &sig_internal);
    215 
    216 	return (res.tag == LIBCRUX_RESULT_OK) ? 0 : -1;
    217 }
    218 
    219 /* ML-DSA 65 */
    220 
    221 #if 0
    222 int
    223 crypto_sign_mldsa65_keypair(uint8_t pk[MLDSA65_PUBLICKEYBYTES],
    224     uint8_t sk[MLDSA65_SECRETKEYBYTES])
    225 {
    226 	uint8_t rnd[MLDSA65_SEEDBYTES];
    227 	int r;
    228 
    229 	arc4random_buf(rnd, sizeof(rnd));
    230 	r = crypto_sign_mldsa65_keypair_seeded(pk, sk, rnd);
    231 	explicit_bzero(rnd, sizeof(rnd));
    232 	return r;
    233 }
    234 
    235 int
    236 crypto_sign_mldsa65_keypair_seeded(uint8_t pk[MLDSA65_PUBLICKEYBYTES],
    237     uint8_t sk[MLDSA65_SECRETKEYBYTES], const uint8_t seed[MLDSA65_SEEDBYTES])
    238 {
    239 	libcrux_mldsa65_keypair_rnd rnd;
    240 	libcrux_mldsa65_keypair keypair;
    241 
    242 	memcpy(rnd.data, seed, sizeof(rnd.data));
    243 	keypair = libcrux_ml_dsa_ml_dsa_65_portable_generate_key_pair(rnd);
    244 	memcpy(pk, keypair.verification_key.data, MLDSA65_PUBLICKEYBYTES);
    245 	memcpy(sk, keypair.signing_key.data, MLDSA65_SECRETKEYBYTES);
    246 
    247 	explicit_bzero(&keypair, sizeof(keypair));
    248 	explicit_bzero(&rnd, sizeof(rnd));
    249 	return 0;
    250 }
    251 
    252 int
    253 crypto_sign_mldsa65(uint8_t sig[MLDSA65_SIGBYTES],
    254     const uint8_t *msg, size_t msglen,
    255     const uint8_t *ctx, size_t ctxlen,
    256     const uint8_t sk[MLDSA65_SECRETKEYBYTES])
    257 {
    258 	uint8_t rnd[MLDSA65_SEEDBYTES];
    259 	int r;
    260 
    261 	arc4random_buf(rnd, sizeof(rnd));
    262 	r = crypto_sign_mldsa65_seeded(sig, msg, msglen, ctx, ctxlen, sk, rnd);
    263 	explicit_bzero(rnd, sizeof(rnd));
    264 	return r;
    265 }
    266 
    267 int
    268 crypto_sign_mldsa65_seeded(uint8_t sig[MLDSA65_SIGBYTES],
    269     const uint8_t *msg, size_t msglen,
    270     const uint8_t *ctx, size_t ctxlen,
    271     const uint8_t sk[MLDSA65_SECRETKEYBYTES],
    272     const uint8_t seed[MLDSA65_SEEDBYTES])
    273 {
    274 	libcrux_mldsa65_sign_rnd rnd;
    275 	libcrux_mldsa65_sk sk_internal;
    276 	libcrux_mldsa65_message message = { msg, msglen };
    277 	libcrux_mldsa65_message context = { ctx, ctxlen };
    278 	libcrux_mldsa65_sign_result res;
    279 	int r = -1;
    280 
    281 	memcpy(sk_internal.data, sk, MLDSA65_SECRETKEYBYTES);
    282 	memcpy(rnd.data, seed, sizeof(rnd.data));
    283 	res = libcrux_ml_dsa_ml_dsa_65_portable_sign(&sk_internal,
    284 	    message, context, rnd);
    285 	if (res.tag == LIBCRUX_RESULT_OK) {
    286 		memcpy(sig, res.val.case_Ok.data, MLDSA65_SIGBYTES);
    287 		r = 0;
    288 	}
    289 
    290 	explicit_bzero(&sk_internal, sizeof(sk_internal));
    291 	explicit_bzero(&res, sizeof(res));
    292 	explicit_bzero(&rnd, sizeof(rnd));
    293 	return r;
    294 }
    295 
    296 int
    297 crypto_sign_mldsa65_verify(const uint8_t sig[MLDSA65_SIGBYTES],
    298     const uint8_t *msg, size_t msglen,
    299     const uint8_t *ctx, size_t ctxlen,
    300     const uint8_t pk[MLDSA65_PUBLICKEYBYTES])
    301 {
    302 	libcrux_mldsa65_pk pk_internal;
    303 	libcrux_mldsa65_signature sig_internal;
    304 	libcrux_mldsa65_message message = { msg, msglen };
    305 	libcrux_mldsa65_message context = { ctx, ctxlen };
    306 	libcrux_mldsa65_verify_result res;
    307 
    308 	memcpy(pk_internal.data, pk, MLDSA65_PUBLICKEYBYTES);
    309 	memcpy(sig_internal.data, sig, MLDSA65_SIGBYTES);
    310 	res = libcrux_ml_dsa_ml_dsa_65_portable_verify(&pk_internal,
    311 	    message, context, &sig_internal);
    312 
    313 	return (res.tag == LIBCRUX_RESULT_OK) ? 0 : -1;
    314 }
    315 #endif
    316 
    317 /* ML-DSA 87 */
    318 
    319 #if 0
    320 int
    321 crypto_sign_mldsa87_keypair(uint8_t pk[MLDSA87_PUBLICKEYBYTES],
    322     uint8_t sk[MLDSA87_SECRETKEYBYTES])
    323 {
    324 	uint8_t rnd[MLDSA87_SEEDBYTES];
    325 	int r;
    326 
    327 	arc4random_buf(rnd, sizeof(rnd));
    328 	r = crypto_sign_mldsa87_keypair_seeded(pk, sk, rnd);
    329 	explicit_bzero(rnd, sizeof(rnd));
    330 	return r;
    331 }
    332 
    333 int
    334 crypto_sign_mldsa87_keypair_seeded(uint8_t pk[MLDSA87_PUBLICKEYBYTES],
    335     uint8_t sk[MLDSA87_SECRETKEYBYTES], const uint8_t seed[MLDSA87_SEEDBYTES])
    336 {
    337 	libcrux_mldsa87_keypair_rnd rnd;
    338 	libcrux_mldsa87_keypair keypair;
    339 
    340 	memcpy(rnd.data, seed, sizeof(rnd.data));
    341 	keypair = libcrux_ml_dsa_ml_dsa_87_portable_generate_key_pair(rnd);
    342 	memcpy(pk, keypair.verification_key.data, MLDSA87_PUBLICKEYBYTES);
    343 	memcpy(sk, keypair.signing_key.data, MLDSA87_SECRETKEYBYTES);
    344 
    345 	explicit_bzero(&keypair, sizeof(keypair));
    346 	explicit_bzero(&rnd, sizeof(rnd));
    347 	return 0;
    348 }
    349 
    350 int
    351 crypto_sign_mldsa87(uint8_t sig[MLDSA87_SIGBYTES],
    352     const uint8_t *msg, size_t msglen,
    353     const uint8_t *ctx, size_t ctxlen,
    354     const uint8_t sk[MLDSA87_SECRETKEYBYTES])
    355 {
    356 	uint8_t rnd[MLDSA87_SEEDBYTES];
    357 	int r;
    358 
    359 	arc4random_buf(rnd, sizeof(rnd));
    360 	r = crypto_sign_mldsa87_seeded(sig, msg, msglen, ctx, ctxlen, sk, rnd);
    361 	explicit_bzero(rnd, sizeof(rnd));
    362 	return r;
    363 }
    364 
    365 int
    366 crypto_sign_mldsa87_seeded(uint8_t sig[MLDSA87_SIGBYTES],
    367     const uint8_t *msg, size_t msglen,
    368     const uint8_t *ctx, size_t ctxlen,
    369     const uint8_t sk[MLDSA87_SECRETKEYBYTES],
    370     const uint8_t seed[MLDSA87_SEEDBYTES])
    371 {
    372 	libcrux_mldsa87_sign_rnd rnd;
    373 	libcrux_mldsa87_sk sk_internal;
    374 	libcrux_mldsa87_message message = { msg, msglen };
    375 	libcrux_mldsa87_message context = { ctx, ctxlen };
    376 	libcrux_mldsa87_sign_result res;
    377 	int r = -1;
    378 
    379 	memcpy(sk_internal.data, sk, MLDSA87_SECRETKEYBYTES);
    380 	memcpy(rnd.data, seed, sizeof(rnd.data));
    381 	res = libcrux_ml_dsa_ml_dsa_87_portable_sign(&sk_internal,
    382 	    message, context, rnd);
    383 	if (res.tag == LIBCRUX_RESULT_OK) {
    384 		memcpy(sig, res.val.case_Ok.data, MLDSA87_SIGBYTES);
    385 		r = 0;
    386 	}
    387 
    388 	explicit_bzero(&sk_internal, sizeof(sk_internal));
    389 	explicit_bzero(&res, sizeof(res));
    390 	explicit_bzero(&rnd, sizeof(rnd));
    391 	return r;
    392 }
    393 
    394 int
    395 crypto_sign_mldsa87_verify(const uint8_t sig[MLDSA87_SIGBYTES],
    396     const uint8_t *msg, size_t msglen,
    397     const uint8_t *ctx, size_t ctxlen,
    398     const uint8_t pk[MLDSA87_PUBLICKEYBYTES])
    399 {
    400 	libcrux_mldsa87_pk pk_internal;
    401 	libcrux_mldsa87_signature sig_internal;
    402 	libcrux_mldsa87_message message = { msg, msglen };
    403 	libcrux_mldsa87_message context = { ctx, ctxlen };
    404 	libcrux_mldsa87_verify_result res;
    405 
    406 	memcpy(pk_internal.data, pk, MLDSA87_PUBLICKEYBYTES);
    407 	memcpy(sig_internal.data, sig, MLDSA87_SIGBYTES);
    408 	res = libcrux_ml_dsa_ml_dsa_87_portable_verify(&pk_internal,
    409 	    message, context, &sig_internal);
    410 
    411 	return (res.tag == LIBCRUX_RESULT_OK) ? 0 : -1;
    412 }
    413 #endif
    414 
    415 void
    416 sha3_256(uint8_t digest[32], const uint8_t *data, size_t len)
    417 {
    418 	Eurydice_borrow_slice_u8 input = { data, len };
    419 	Eurydice_mut_borrow_slice_u8 output = { digest, 32 };
    420 	libcrux_sha3_portable_sha256(output, input);
    421 }
    422 
    423 void
    424 sha3_512(uint8_t digest[64], const uint8_t *data, size_t len)
    425 {
    426 	Eurydice_borrow_slice_u8 input = { data, len };
    427 	Eurydice_mut_borrow_slice_u8 output = { digest, 64 };
    428 	libcrux_sha3_portable_sha512(output, input);
    429 }
    430