Embedded SDK
Embedded SDK
Loading...
Searching...
No Matches
cx_mlkem.c
Go to the documentation of this file.
1/*****************************************************************************
2 * (c) 2026 Ledger SAS.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 *****************************************************************************/
24#include <string.h>
25
26#include "cx_mlkem_internal.h"
27#include "cx_mlkem_indcpa.h"
28#include "cx_mlkem_util.h"
29#include "cx_utils.h"
30#include "lcx_rng.h"
31
32cx_err_t MLKEM_crypto_kem_keypair(uint8_t *pk,
33 size_t pk_len,
34 uint8_t *sk,
35 size_t sk_len,
36 MLKEM_param_t param)
37{
38 cx_err_t error = CX_INTERNAL_ERROR;
39 uint8_t coins[2 * MLKEM_SYMBYTES] = {0};
40
41 if ((pk == NULL) || (sk == NULL)) {
42 error = CX_INVALID_PARAMETER;
43 goto end;
44 }
45
46 if (param > MLKEM_1024) {
47 error = CX_INVALID_PARAMETER_VALUE;
48 goto end;
49 }
50
51 cx_rng_no_throw(coins, 2 * MLKEM_SYMBYTES);
52 error = MLKEM_crypto_kem_keypair_derand(pk, pk_len, sk, sk_len, coins, param);
53
54end:
55 explicit_bzero(coins, sizeof(coins));
56 return error;
57}
58
59cx_err_t MLKEM_crypto_kem_enc(uint8_t *ct,
60 size_t ct_len,
61 uint8_t *ss,
62 size_t ss_len,
63 const uint8_t *pk,
64 size_t pk_len,
65 MLKEM_param_t param)
66{
67 cx_err_t error = CX_INTERNAL_ERROR;
68 uint8_t coins[2 * MLKEM_SYMBYTES] = {0};
69
70 if ((ct == NULL) || (ss == NULL) || (pk == NULL)) {
71 error = CX_INVALID_PARAMETER;
72 goto end;
73 }
74
75 if (param > MLKEM_1024) {
76 error = CX_INVALID_PARAMETER_VALUE;
77 goto end;
78 }
79
80 cx_rng_no_throw(coins, 2 * MLKEM_SYMBYTES);
81 error = MLKEM_crypto_kem_enc_derand(ct, ct_len, ss, ss_len, pk, pk_len, coins, param);
82
83end:
84 explicit_bzero(coins, sizeof(coins));
85 return error;
86}
87
88cx_err_t MLKEM_crypto_kem_dec(uint8_t *ss,
89 size_t ss_len,
90 const uint8_t *ct,
91 size_t ct_len,
92 const uint8_t *sk,
93 size_t sk_len,
94 MLKEM_param_t param)
95{
96 cx_err_t error = CX_INTERNAL_ERROR;
97 uint8_t buf[2U * MLKEM_SYMBYTES] = {0};
98 uint8_t kr[2U * MLKEM_SYMBYTES] = {0};
99 // Stack optimization: ct2 and tmp share storage: ct2 is used first,
100 // then tmp overwrites it
101 union {
102 uint8_t ct2[MLKEM1024_CIPHERTEXTBYTES];
104 } u;
105
106 const uint8_t *pk = NULL;
107 uint8_t fail;
108
109 if ((ss == NULL) || (ct == NULL) || (sk == NULL)) {
110 error = CX_INVALID_PARAMETER;
111 goto end;
112 }
113
114 if (param > MLKEM_1024) {
115 error = CX_INVALID_PARAMETER_VALUE;
116 goto end;
117 }
118
119 const MLKEM_param_info_t *p = &MLKEM_PARAM[param];
120
121 if (p == NULL) {
122 error = CX_INVALID_PARAMETER;
123 goto end;
124 }
125
126 if ((sk_len < p->sk_bytes) || (ct_len < p->ct_bytes)) {
127 error = CX_INVALID_PARAMETER_SIZE;
128 goto end;
129 }
130
131 if (ss_len < MLKEM_SYMBYTES) {
132 error = CX_INVALID_PARAMETER_SIZE;
133 goto end;
134 }
135
136 pk = &sk[p->indcpa_sk_bytes];
137
138 // All steps must execute unconditionally for CCA security.
139 (void) MLKEM_INDCPA_dec(buf, sizeof(buf), ct, p->ct_bytes, sk, p->sk_bytes, p);
140
141 memcpy(&buf[MLKEM_SYMBYTES], &sk[p->sk_bytes - (2U * MLKEM_SYMBYTES)], MLKEM_SYMBYTES);
142
143 MLKEM_UTIL_hash_g(kr, buf, 2U * MLKEM_SYMBYTES);
144
145 (void) MLKEM_INDCPA_enc(
146 u.ct2, sizeof(u.ct2), buf, sizeof(buf), pk, p->pk_bytes, &kr[MLKEM_SYMBYTES], p);
147 fail = cx_constant_time_eq(ct, u.ct2, p->ct_bytes);
148
149 // ct2 no longer needed; reuse the union as tmp
150 memcpy(u.tmp, &sk[p->sk_bytes - MLKEM_SYMBYTES], MLKEM_SYMBYTES);
151 memcpy(&u.tmp[MLKEM_SYMBYTES], ct, p->ct_bytes);
153
154 MLKEM_UTIL_ct_cmov(ss, kr, MLKEM_SYMBYTES, (uint8_t) (fail == 0U));
155
156 // Return CX_OK even if MLKEM_INDCPA_dec or MLKEM_INDCPA_enc return an error
157 // Decapsulation should be anyway incoherent
158 error = CX_OK;
159
160end:
161 explicit_bzero(buf, sizeof(buf));
162 explicit_bzero(kr, sizeof(kr));
163 explicit_bzero(&u, sizeof(u));
164 return error;
165}
cx_err_t MLKEM_crypto_kem_enc(uint8_t *ct, size_t ct_len, uint8_t *ss, size_t ss_len, const uint8_t *pk, size_t pk_len, MLKEM_param_t param)
ML-KEM encapsulation.
Definition cx_mlkem.c:59
cx_err_t MLKEM_crypto_kem_keypair(uint8_t *pk, size_t pk_len, uint8_t *sk, size_t sk_len, MLKEM_param_t param)
Generates an ML-KEM key pair.
Definition cx_mlkem.c:32
cx_err_t MLKEM_crypto_kem_dec(uint8_t *ss, size_t ss_len, const uint8_t *ct, size_t ct_len, const uint8_t *sk, size_t sk_len, MLKEM_param_t param)
ML-KEM decapsulation.
Definition cx_mlkem.c:88
cx_err_t MLKEM_INDCPA_enc(uint8_t *c, size_t c_len, const uint8_t *m, size_t m_len, const uint8_t *pk, size_t pk_len, const uint8_t coins[2 *MLKEM_SYMBYTES], const MLKEM_param_info_t *p)
cx_err_t MLKEM_INDCPA_dec(uint8_t *m, size_t m_len, const uint8_t *c, size_t c_len, const uint8_t *sk, size_t sk_len, const MLKEM_param_info_t *p)
cx_err_t MLKEM_crypto_kem_enc_derand(uint8_t *ct, size_t ct_len, uint8_t *ss, size_t ss_len, const uint8_t *pk, size_t pk_len, const uint8_t coins[2 *MLKEM_SYMBYTES], MLKEM_param_t param)
Deterministic ML-KEM encapsulation.
cx_err_t MLKEM_crypto_kem_keypair_derand(uint8_t *pk, size_t pk_len, uint8_t *sk, size_t sk_len, const uint8_t coins[2 *MLKEM_SYMBYTES], MLKEM_param_t param)
Deterministic ML-KEM key pair generation.
Internal ML-KEM deterministic routines (not part of the public API).
void MLKEM_UTIL_hash_j(uint8_t *out, const uint8_t *in, size_t inlen)
void MLKEM_UTIL_ct_cmov(uint8_t *dst, const uint8_t *src, size_t len, uint8_t b)
void MLKEM_UTIL_hash_g(uint8_t *out, const uint8_t *in, size_t in_len)
Computes the G hash function (SHA3-512) as defined in FIPS 203.
uint8_t cx_constant_time_eq(const uint8_t *buf1, uint8_t *buf2, size_t len)
Definition cx_utils.c:181
#define MLKEM1024_CIPHERTEXTBYTES
Definition lcx_mlkem.h:149
#define MLKEM_SYMBYTES
Definition lcx_mlkem.h:38
enum MLKEM_param_e MLKEM_param_t
ML-KEM parameter set selector.
const MLKEM_param_info_t MLKEM_PARAM[MLKEM_NUM_PARAM_SETS]
Lookup table of ML-KEM parameter sets indexed by MLKEM_param_t.
@ MLKEM_1024
Definition lcx_mlkem.h:162
Random Number Generation.
ML-KEM parameter set descriptor holding all derived sizes.
Definition lcx_mlkem.h:168
uint16_t indcpa_sk_bytes
Definition lcx_mlkem.h:178