.\" Automatically generated by Pod::Man 4.14 (Pod::Simple 3.42)
.\"
.\" Standard preamble:
.\" ========================================================================
.de Sp \" Vertical space (when we can't use .PP)
.if t .sp .5v
.if n .sp
..
.de Vb \" Begin verbatim text
.ft CW
.nf
.ne \\$1
..
.de Ve \" End verbatim text
.ft R
.fi
..
.\" Set up some character translations and predefined strings.  \*(-- will
.\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left
.\" double quote, and \*(R" will give a right double quote.  \*(C+ will
.\" give a nicer C++.  Capital omega is used to do unbreakable dashes and
.\" therefore won't be available.  \*(C` and \*(C' expand to `' in nroff,
.\" nothing in troff, for use with C<>.
.tr \(*W-
.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p'
.ie n \{\
.    ds -- \(*W-
.    ds PI pi
.    if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch
.    if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\"  diablo 12 pitch
.    ds L" ""
.    ds R" ""
.    ds C` ""
.    ds C' ""
'br\}
.el\{\
.    ds -- \|\(em\|
.    ds PI \(*p
.    ds L" ``
.    ds R" ''
.    ds C`
.    ds C'
'br\}
.\"
.\" Escape single quotes in literal strings from groff's Unicode transform.
.ie \n(.g .ds Aq \(aq
.el       .ds Aq '
.\"
.\" If the F register is >0, we'll generate index entries on stderr for
.\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index
.\" entries marked with X<> in POD.  Of course, you'll have to process the
.\" output yourself in some meaningful fashion.
.\"
.\" Avoid warning from groff about undefined register 'F'.
.de IX
..
.nr rF 0
.if \n(.g .if rF .nr rF 1
.if (\n(rF:(\n(.g==0)) \{\
.    if \nF \{\
.        de IX
.        tm Index:\\$1\t\\n%\t"\\$2"
..
.        if !\nF==2 \{\
.            nr % 0
.            nr F 2
.        \}
.    \}
.\}
.rr rF
.\"
.\" Accent mark definitions (@(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2).
.\" Fear.  Run.  Save yourself.  No user-serviceable parts.
.    \" fudge factors for nroff and troff
.if n \{\
.    ds #H 0
.    ds #V .8m
.    ds #F .3m
.    ds #[ \f1
.    ds #] \fP
.\}
.if t \{\
.    ds #H ((1u-(\\\\n(.fu%2u))*.13m)
.    ds #V .6m
.    ds #F 0
.    ds #[ \&
.    ds #] \&
.\}
.    \" simple accents for nroff and troff
.if n \{\
.    ds ' \&
.    ds ` \&
.    ds ^ \&
.    ds , \&
.    ds ~ ~
.    ds /
.\}
.if t \{\
.    ds ' \\k:\h'-(\\n(.wu*8/10-\*(#H)'\'\h"|\\n:u"
.    ds ` \\k:\h'-(\\n(.wu*8/10-\*(#H)'\`\h'|\\n:u'
.    ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'^\h'|\\n:u'
.    ds , \\k:\h'-(\\n(.wu*8/10)',\h'|\\n:u'
.    ds ~ \\k:\h'-(\\n(.wu-\*(#H-.1m)'~\h'|\\n:u'
.    ds / \\k:\h'-(\\n(.wu*8/10-\*(#H)'\z\(sl\h'|\\n:u'
.\}
.    \" troff and (daisy-wheel) nroff accents
.ds : \\k:\h'-(\\n(.wu*8/10-\*(#H+.1m+\*(#F)'\v'-\*(#V'\z.\h'.2m+\*(#F'.\h'|\\n:u'\v'\*(#V'
.ds 8 \h'\*(#H'\(*b\h'-\*(#H'
.ds o \\k:\h'-(\\n(.wu+\w'\(de'u-\*(#H)/2u'\v'-.3n'\*(#[\z\(de\v'.3n'\h'|\\n:u'\*(#]
.ds d- \h'\*(#H'\(pd\h'-\w'~'u'\v'-.25m'\f2\(hy\fP\v'.25m'\h'-\*(#H'
.ds D- D\\k:\h'-\w'D'u'\v'-.11m'\z\(hy\v'.11m'\h'|\\n:u'
.ds th \*(#[\v'.3m'\s+1I\s-1\v'-.3m'\h'-(\w'I'u*2/3)'\s-1o\s+1\*(#]
.ds Th \*(#[\s+2I\s-2\h'-\w'I'u*3/5'\v'-.3m'o\v'.3m'\*(#]
.ds ae a\h'-(\w'a'u*4/10)'e
.ds Ae A\h'-(\w'A'u*4/10)'E
.    \" corrections for vroff
.if v .ds ~ \\k:\h'-(\\n(.wu*9/10-\*(#H)'\s-2\u~\d\s+2\h'|\\n:u'
.if v .ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'\v'-.4m'^\v'.4m'\h'|\\n:u'
.    \" for low resolution devices (crt and lpr)
.if \n(.H>23 .if \n(.V>19 \
\{\
.    ds : e
.    ds 8 ss
.    ds o a
.    ds d- d\h'-1'\(ga
.    ds D- D\h'-1'\(hy
.    ds th \o'bp'
.    ds Th \o'LP'
.    ds ae ae
.    ds Ae AE
.\}
.rm #[ #] #H #V #F C
.\" ========================================================================
.\"
.IX Title "EVP_SIGNATURE-ML-DSA 7ossl"
.TH EVP_SIGNATURE-ML-DSA 7ossl "2026-01-16" "3.5.1" "OpenSSL"
.\" For nroff, turn off justification.  Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
.nh
.SH "NAME"
EVP_SIGNATURE\-ML\-DSA,
EVP_SIGNATURE\-ML\-DSA\-44, EVP_SIGNATURE\-ML\-DSA\-65, EVP_SIGNATURE\-ML\-DSA\-87,
\&\- EVP_SIGNATURE ML\-DSA support
.SH "DESCRIPTION"
.IX Header "DESCRIPTION"
The \fB\s-1ML\-DSA\-44\s0\fR, \fB\s-1ML\-DSA\-65\s0\fR and \fB\s-1ML\-DSA\-87\s0\fR \s-1EVP_PKEY\s0 implementations
support key generation, and one-shot sign and verify using the ML-DSA
signature schemes described in \s-1FIPS 204\s0 <https://csrc.nist.gov/pubs/fips/204/final>.
.PP
The different algorithms names correspond to the parameter sets defined in
\&\s-1FIPS 204\s0 <https://csrc.nist.gov/pubs/fips/204/final> Section 4 Table 1.
(The signatures range in size from ~2.5K to ~4.5K depending on the type chosen).
There are 3 different security categories also depending on the type.
.PP
\&\fBEVP_SIGNATURE_fetch\fR\|(3) can be used to explicitely fetch one of the 3
algorithms which can then be used with \fBEVP_PKEY_sign_message_init\fR\|(3),
\&\fBEVP_PKEY_sign\fR\|(3), \fBEVP_PKEY_verify_message_init\fR\|(3), and
\&\fBEVP_PKEY_verify\fR\|(3) to perform one-shot message signing or signature verification.
.PP
The normal signing process (called Pure ML-DSA Signature Generation)
encodes the message internally as 0x00 || len(ctx) || ctx || message.
where \fBctx\fR is some optional value of size 0x00..0xFF.  This process is
defined in \s-1FIPS 204\s0 <https://csrc.nist.gov/pubs/fips/204/final> Algorithm 2
step 10 and Algorithm 3 step 5.
OpenSSL also allows the message to not be encoded which is required for
testing. OpenSSL does not support Pre Hash ML-DSA Signature Generation, but this
may be done by the user by doing Pre hash encoding externally and then choosing
the option to not encode the message.
.SS "ML-DSA Signature Parameters"
.IX Subsection "ML-DSA Signature Parameters"
The following parameter can be used for both signing and verification.
it may be set by passing an \s-1OSSL_PARAM\s0 array to \fBEVP_PKEY_sign_message_init\fR\|(3)
or \fBEVP_PKEY_verify_message_init\fR\|(3)
.ie n .IP """context-string"" (\fB\s-1OSSL_SIGNATURE_PARAM_CONTEXT_STRING\s0\fR) <octet string>" 4
.el .IP "``context-string'' (\fB\s-1OSSL_SIGNATURE_PARAM_CONTEXT_STRING\s0\fR) <octet string>" 4
.IX Item "context-string (OSSL_SIGNATURE_PARAM_CONTEXT_STRING) <octet string>"
A string of octets with length at most 255. By default it is the empty string.
.PP
The following parameters can be used when signing:
They can be set by passing an \s-1OSSL_PARAM\s0 array to \fBEVP_PKEY_sign_init_ex2\fR\|(3).
.ie n .IP """message-encoding"" (\fB\s-1OSSL_SIGNATURE_PARAM_MESSAGE_ENCODING\s0\fR) <integer>" 4
.el .IP "``message-encoding'' (\fB\s-1OSSL_SIGNATURE_PARAM_MESSAGE_ENCODING\s0\fR) <integer>" 4
.IX Item "message-encoding (OSSL_SIGNATURE_PARAM_MESSAGE_ENCODING) <integer>"
The default value of 1 uses 'Pure ML-DSA Signature Generation' as described
above. Setting it to 0 does not encode the message, which is used for testing.
The message encoding steps are defined in
\&\s-1FIPS 204\s0 <https://csrc.nist.gov/pubs/fips/204/final> Algorithm 2 step 10 and
Algorithm 3 step 5.
.ie n .IP """test-entropy"" (\fB\s-1OSSL_SIGNATURE_PARAM_TEST_ENTROPY\s0\fR) <octet string>" 4
.el .IP "``test-entropy'' (\fB\s-1OSSL_SIGNATURE_PARAM_TEST_ENTROPY\s0\fR) <octet string>" 4
.IX Item "test-entropy (OSSL_SIGNATURE_PARAM_TEST_ENTROPY) <octet string>"
Used for testing to pass an optional deterministic per message random value.
If set the size must be 32 bytes.
.ie n .IP """deterministic"" (\fB\s-1OSSL_SIGNATURE_PARAM_DETERMINISTIC\s0\fR) <integer>" 4
.el .IP "``deterministic'' (\fB\s-1OSSL_SIGNATURE_PARAM_DETERMINISTIC\s0\fR) <integer>" 4
.IX Item "deterministic (OSSL_SIGNATURE_PARAM_DETERMINISTIC) <integer>"
The default value of 0 causes the per message randomness to be randomly
generated using a \s-1DRBG.\s0 Setting this to 1 causes the per message randomness
to be set to 32 bytes of zeros. This value is ignored if \*(L"test-entropy\*(R" is set.
.ie n .IP """mu"" (\fB\s-1OSSL_SIGNATURE_PARAM_MU\s0\fR) <integer>" 4
.el .IP "``mu'' (\fB\s-1OSSL_SIGNATURE_PARAM_MU\s0\fR) <integer>" 4
.IX Item "mu (OSSL_SIGNATURE_PARAM_MU) <integer>"
The default value of 0 causes sign and verify operations to process a raw message.
Setting this to 1 causes those operations to assume the input is the \f(CW\*(C`mu\*(C'\fR value
from \s-1FIPS 204\s0 <https://csrc.nist.gov/pubs/fips/204/final> Algorithm 7 step 6 and
Algorithm 8 step 7.
.Sp
Note that the message encoding steps from
\&\s-1FIPS 204\s0 <https://csrc.nist.gov/pubs/fips/204/final> Algorithm 2 step 10 and
Algorithm 3 step 5 are omitted when this setting is 1.
.PP
See \s-1\fBEVP_PKEY\-ML\-DSA\s0\fR\|(7) for information related to \fBML-DSA\fR keys.
.SH "NOTES"
.IX Header "NOTES"
For backwards compatability reasons \fBEVP_DigestSignInit_ex()\fR, \fBEVP_DigestSign()\fR,
\&\fBEVP_DigestVerifyInit_ex()\fR and \fBEVP_DigestVerify()\fR may also be used, but the digest
passed in \fImdname\fR must be \s-1NULL.\s0
.SH "EXAMPLES"
.IX Header "EXAMPLES"
To sign a message using an ML-DSA \s-1EVP_PKEY\s0 structure:
.PP
.Vb 10
\&    void do_sign(EVP_PKEY *key, unsigned char *msg, size_t msg_len)
\&    {
\&        size_t sig_len;
\&        unsigned char *sig = NULL;
\&        const OSSL_PARAM params[] = {
\&            OSSL_PARAM_octet_string("context\-string", (unsigned char *)"A context string", 16),
\&            OSSL_PARAM_END
\&        };
\&        EVP_PKEY_CTX *sctx = EVP_PKEY_CTX_new_from_pkey(NULL, pkey, NULL);
\&        EVP_SIGNATURE *sig_alg = EVP_SIGNATURE_fetch(NULL, "ML\-DSA\-65", NULL);
\&
\&        EVP_PKEY_sign_message_init(sctx, sig_alg, params);
\&        /* Calculate the required size for the signature by passing a NULL buffer. */
\&        EVP_PKEY_sign(sctx, NULL, &sig_len, msg, msg_len);
\&        sig = OPENSSL_zalloc(sig_len);
\&        EVP_PKEY_sign(sctx, sig, &sig_len, msg, msg_len);
\&        ...
\&        OPENSSL_free(sig);
\&        EVP_SIGNATURE(sig_alg);
\&        EVP_PKEY_CTX_free(sctx);
\&    }
.Ve
.SH "SEE ALSO"
.IX Header "SEE ALSO"
\&\s-1\fBEVP_PKEY\-ML\-DSA\s0\fR\|(7)
\&\fBprovider\-signature\fR\|(7),
\&\fBEVP_PKEY_sign\fR\|(3),
\&\fBEVP_PKEY_verify\fR\|(3),
\&\s-1FIPS 204\s0 <https://csrc.nist.gov/pubs/fips/204/final>
.SH "HISTORY"
.IX Header "HISTORY"
This functionality was added in OpenSSL 3.5.
.SH "COPYRIGHT"
.IX Header "COPYRIGHT"
Copyright 2025 The OpenSSL Project Authors. All Rights Reserved.
.PP
Licensed under the Apache License 2.0 (the \*(L"License\*(R").  You may not use
this file except in compliance with the License.  You can obtain a copy
in the file \s-1LICENSE\s0 in the source distribution or at
<https://www.openssl.org/source/license.html>.
