1 =pod 2 3 =encoding utf-8 4 5 =head1 NAME 6 7 EVP_PKEY-ML-DSA, EVP_KEYMGMT-ML-DSA, 8 EVP_PKEY-ML-DSA-44, EVP_PKEY-ML-DSA-65, EVP_PKEY-ML-DSA-87 9 - EVP_PKEY ML-DSA keytype and algorithm support 10 11 =head1 DESCRIPTION 12 13 ML-DSA implements the algorithms B<ML-DSA-44>, B<ML-DSA-65> and B<ML-DSA-87>. 14 The key types B<EVP_PKEY_ML_DSA_44>, B<EVP_PKEY_ML_DSA_65> and 15 B<EVP_PKEY_ML_DSA_87> are implemented in OpenSSL's default and FIPS providers. 16 These implementations support the associated key, containing the public key I<pub> 17 and the private key I<priv>. 18 19 Each of the different key types has an associated security category. 20 This value is one of 2, 3 or 5 for key types B<ML-DSA-44>, B<ML-DSA-65> 21 and B<ML-DSA-87> respectively, which correspond to security strengths of 22 128, 192 and 256 respectively. 23 24 =head2 Keygen Parameters 25 26 =over 4 27 28 =item "seed" (B<OSSL_PKEY_PARAM_ML_DSA_SEED>) <octet string> 29 30 The seed can be used to generate the private and public key components in a 31 deterministic manner. 32 The length of the value supplied must be 32 bytes. 33 When this value is not supplied the seed is generated randomly using a DRBG. 34 35 Generated keys default to retaining the seed used. 36 The seed is also by default retained when keys are loaded from B<PKCS#8> files 37 in the seed format. 38 When available, the seed parameter is also used during key export and import, 39 with keys (by default) regenerated from the seed even when also provided on import. 40 See L</Provider configuration parameters> below for related controls. 41 42 When the seed is retained, it is also available as a B<gettable> parameter, 43 and private key output to B<PKCS#8> files will by default include the seed. 44 When the seed was not initially known, or was not retained, B<PKCS#8> private 45 key files will contain only the private key in FIPS 204 C<sk> format. 46 47 =item "properties" (B<OSSL_PKEY_PARAM_PROPERTIES>) <UTF8 string> 48 49 Sets properties to be used when fetching algorithm implementations used for 50 ML-DSA hashing operations. 51 52 =back 53 54 Use L<EVP_PKEY_CTX_set_params(3)> after calling L<EVP_PKEY_keygen_init(3)>. 55 56 =head2 Common ML-DSA parameters 57 58 In addition to the common parameters that all keytypes should support (see 59 L<provider-keymgmt(7)/Common Information Parameters>, the implementation of 60 these key types support the parameters listed below. 61 These are gettable using 62 L<EVP_PKEY_get_octet_string_param(3)> or L<EVP_PKEY_get_params(3)>. 63 They can be initialised via L<EVP_PKEY_fromdata(3)>, and are returned by 64 L<EVP_PKEY_todata(3)> given a suitable I<selection>. 65 Once a public or private key is configured, it can no longer be modified, 66 nor can another key component be added. 67 68 =over 4 69 70 =item "pub" (B<OSSL_PKEY_PARAM_PUB_KEY>) <octet string> 71 72 The encoded public key value of size 1312, 1952 or 2592 bytes depending on the 73 respective key type of B<ML-DSA-44>, B<ML-DSA-65> or B<ML-DSA-87>. 74 75 =item "priv" (B<OSSL_PKEY_PARAM_PRIV_KEY>) <octet string> 76 77 The encoded private key value of size 2560, 4032 or 4896 bytes depending on the 78 respective key type of B<ML-DSA-44>, B<ML-DSA-65> or B<ML-DSA-87>. 79 80 =back 81 82 =head2 Provider configuration parameters 83 84 See the description of the B<-provparam> option in L<openssl(1)> to learn 85 how to set provider configuration parameters in the command line tools. 86 See L<OSSL_PROVIDER_add_conf_parameter(3)> to learn how to set provider 87 configuration options programmatically. 88 89 =over 4 90 91 =item C<ml-dsa.retain_seed> (B<OSSL_PKEY_PARAM_ML_DSA_RETAIN_SEED>) <UTF8 string> 92 93 When set to a string representing a false boolean value (see 94 L<OSSL_PROVIDER_conf_get_bool(3)>), the seed will not be retained after key 95 generation or key import from a seed value. 96 If the resulting key is then written to a PKCS#8 object, it will contain 97 only the FIPS 204 C<sk> key. 98 99 =item C<ml-dsa.prefer_seed> (B<OSSL_PKEY_PARAM_ML_DSA_PREFER_SEED>) <UTF8 string> 100 101 When decoding PKCS#8 objects that contain both a seed and the FIPS 204 C<sk> 102 private key, the seed is by default used to regenerate the key, and the 103 companion private key is ignored. 104 When this configuration parameter is set to a string representing a false 105 boolean value (see L<OSSL_PROVIDER_conf_get_bool(3)>), the seed is ignored 106 (neither used to regenerate the key, nor retained), and the companion key is 107 used instead. 108 109 =item C<ml-dsa.input_formats> (B<OSSL_PKEY_PARAM_ML_DSA_INPUT_FORMATS>) <UTF8 string> 110 111 List of enabled private key input formats when parsing PKCS#8 objects. 112 List elements are separated by commas, spaces or tabs. 113 The list of enabled formats can be specified in the configuration file, as seen 114 in the L</EXAMPLES> section below, or the via the B<-provparam> command-line 115 option (see also L<OSSL_PROVIDER_add_conf_parameter(3)>). 116 117 Values specified on the command-line override any configuration file settings. 118 By default all the supported formats are enabled. 119 The supported formats are: 120 121 =over 4 122 123 =item C<seed-priv>: 124 125 This format represents B<PKCS#8> objects in which both the FIPS 204 32-byte 126 B<> seed and the secret key B<sk> are present in the private key as part of 127 the DER encoding of the ASN.1 sequence: 128 129 ML-DSA-PrivateKey ::= CHOICE { 130 seed [0] IMPLICIT OCTET STRING (SIZE (32)), 131 expandedKey OCTET STRING (SIZE (2560 | 4032 | 4896)), 132 both SEQUENCE { 133 seed OCTET STRING (SIZE (32)), 134 expandedKey OCTET STRING (SIZE (2560 | 4032 | 4896)) } } 135 136 If the C<seed-priv> format is not included in the list, this format will not be 137 recognised on input. 138 139 =item C<seed-only>: 140 141 This format represents B<PKCS#8> objects in which only the 32-byte FIPS 204 142 B<> seed is present in the above sequence. 143 If the C<seed-only> format is not included in the list, this format will not be 144 recognised on input. 145 146 =item C<priv-only>: 147 148 This format represents B<PKCS#8> objects in which only the FIPS 204 149 private key B<sk> is present in the above sequence. 150 If the C<priv-only> format is not included in the list, this format will not be 151 recognised on input. 152 153 =item C<oqskeypair>: 154 155 This format represents B<PKCS#8> objects in which the private key is a DER 156 encoding of an octet string containing the concatenaton of the FIPS 204 private 157 key B<sk> and the public key B<pk>. 158 This encoding is used in some builds of the C<oqsprovider>. 159 If the C<oqskeypair> format is not included in the list, this format will not be 160 recognised on input. 161 162 =item C<bare-seed>: 163 164 This format represents B<PKCS#8> objects in which the private key contains 165 the 32-byte FIPS 204 seed B<> without any ASN.1 encapsulation. 166 If the C<bare-seed> format is not included in the list, this format will not be 167 recognised on input. 168 169 =item C<bare-priv>: 170 171 This format represents B<PKCS#8> objects in which the private key contains 172 the FIPS 204 secret key B<sk> without any ASN.1 encapsulation. 173 If the C<bare-priv> format is not included in the list, this format will not be 174 recognised on input. 175 176 =back 177 178 =item C<ml-dsa.output_formats> (B<OSSL_PKEY_PARAM_ML_DSA_OUTPUT_FORMATS>) <UTF8 string> 179 180 Ordered list of enabled private key output formats when writing B<PKCS#8> files. 181 List elements are separated by commas, spaces or tabs. 182 The list of enabled formats can be specified in the configuration file, as seen 183 in the L</EXAMPLES> section below, or the via the B<-provparam> command-line 184 option. 185 186 This supports the same set of formats as described under C<ml-dsa.input_formats> 187 above. 188 The order in which elements are listed is important, the selected format will be 189 the first one that is possible to output. 190 If the key seed is known, the first listed format will be selected. 191 If the key seed is not known, the first format that omits the seed will be selected. 192 The default order is equivalent to C<seed-priv> first and C<priv-only> second, with 193 both seed and key output when the seed is available, and just the 194 key otherwise. 195 If C<seed-only> is listed first, then the seed will be output without the key 196 when available, otherwise the output will have just the key. 197 If C<priv-only> is listed first, then just the key is output regardless of 198 whether the seed is present. 199 The legacy C<oqskeypair>, C<bare-seed> and C<bare-priv> formats can also be 200 output, by listing those first. 201 202 =back 203 204 =head1 CONFORMING TO 205 206 =over 4 207 208 =item FIPS 204 209 210 =back 211 212 =head1 EXAMPLES 213 214 An B<EVP_PKEY> context can be obtained by calling: 215 216 EVP_PKEY_CTX *pctx = 217 EVP_PKEY_CTX_new_from_name(NULL, "ML-DSA-44", NULL); 218 219 An B<ML-DSA-44> key can be generated like this: 220 221 pkey = EVP_PKEY_Q_keygen(NULL, NULL, "ML-DSA-44"); 222 223 The key pair components can be extracted from a key by calling: 224 225 /* Sizes large enough for ML-DSA-87 */ 226 uint8_t pub[2592], priv[4896], seed[32]: 227 size_t priv_len, pub_len, seed_len; 228 229 EVP_PKEY_get_octet_string_param(pkey, OSSL_PKEY_PARAM_ML_DSA_SEED, 230 seed, sizeof(seed), &seed_len); 231 EVP_PKEY_get_octet_string_param(pkey, OSSL_PKEY_PARAM_PRIV_KEY, 232 priv, sizeof(priv), &priv_len); 233 EVP_PKEY_get_octet_string_param(pkey, OSSL_PKEY_PARAM_PUB_KEY, 234 pub, sizeof(pub), &pub_len)); 235 236 An B<ML-DSA> private key in seed format can be converted to a key in the FIPS 237 204 B<sk> format by running: 238 239 $ openssl pkey -provparam ml-dsa.retain_seed=no \ 240 -in seed-only.pem -out priv-only.pem 241 242 To generate an, e.g., B<ML-DSA-65> key, in FIPS 204 B<sk> format, you can run: 243 244 $ openssl genpkey -provparam ml-dsa.retain_seed=no \ 245 -algorithm ml-dsa-65 -out priv-only.pem 246 247 If you have a B<PKCS#8> file with both a seed and a key, and prefer to import the 248 companion key rather than the seed, you can run: 249 250 $ openssl pkey -provparam ml-dsa.prefer_seed=no \ 251 -in seed-priv.pem -out priv-only.pem 252 253 In the B<openssl.cnf> file, this looks like: 254 255 openssl_conf = openssl_init 256 257 [openssl_init] 258 providers = providers_sect 259 260 # Can be referenced in one or more provider sections 261 [ml_dsa_sect] 262 prefer_seed = yes 263 retain_seed = yes 264 # OQS legacy formats disabled 265 input_formats = seed-priv, seed-only, priv-only 266 # Output either the seed alone, or else the key alone 267 output_formats = seed-only, priv-only 268 269 [providers_sect] 270 default = default_sect 271 # Or perhaps just: base = default_sect 272 base = base_sect 273 274 [default_sect] 275 ml-dsa = ml_dsa_sect 276 277 [base_sect] 278 ml-dsa = ml_dsa_sect 279 280 =head1 SEE ALSO 281 282 L<EVP_KEYMGMT(3)>, 283 L<EVP_PKEY(3)>, 284 L<provider-keymgmt(7)>, 285 L<EVP_PKEY_get_raw_private_key(3)>, 286 L<EVP_PKEY_get_raw_public_key(3)>, 287 L<EVP_PKEY_get1_encoded_public_key(3)>, 288 L<OSSL_PROVIDER_add_conf_parameter(3)>, 289 L<provider-keymgmt(7)>, 290 L<EVP_SIGNATURE-ML-DSA(7)> 291 292 =head1 HISTORY 293 294 This functionality was added in OpenSSL 3.5. 295 296 =head1 COPYRIGHT 297 298 Copyright 2025 The OpenSSL Project Authors. All Rights Reserved. 299 300 Licensed under the Apache License 2.0 (the "License"). You may not use 301 this file except in compliance with the License. You can obtain a copy 302 in the file LICENSE in the source distribution or at 303 L<https://www.openssl.org/source/license.html>. 304 305 =cut 306