mirror of
https://github.com/tianocore/edk2
synced 2026-08-27 00:23:19 -04:00
Created ML-DSA API functions to configure public and private keys for ML-DSA algorithm. This will allow users to sign and verify with ML-DSA. Unit tests were add to confirm operation of the API. Signed-off-by: Michael G.A. Holland <michael.holland@intel.com>
291 lines
9.7 KiB
C
291 lines
9.7 KiB
C
/** @file
|
|
ML-DSA API implementation based on OpenSSL
|
|
|
|
Copyright (c) 2026, Intel Corporation. All rights reserved.
|
|
SPDX-License-Identifier: BSD-2-Clause-Patent
|
|
|
|
**/
|
|
|
|
#include <Library/BaseCryptLib.h>
|
|
#include <Library/DebugLib.h>
|
|
|
|
/**
|
|
Creates a new ML-DSA context by Crypto NID.
|
|
|
|
This function allocates and initializes a new ML-DSA context for the specified
|
|
ML-DSA variant. The context is created with no key material; the EVP_PKEY
|
|
structure is set to NULL. The caller must call MlDsaFree() to release the
|
|
context when done.
|
|
|
|
Before keys can be used for signing or verification, they must be set using
|
|
MlDsaSetPrivKey() or MlDsaSetPubKey().
|
|
|
|
If Nid is not a supported ML-DSA variant, then return NULL.
|
|
If memory allocation fails, then return NULL.
|
|
|
|
@param[in] Nid Crypto NID of the ML-DSA variant (e.g., CRYPTO_NID_ML_DSA_87).
|
|
|
|
@retval Pointer to new ML-DSA context if successful.
|
|
@retval NULL if Nid is unsupported or allocation failed.
|
|
|
|
**/
|
|
VOID *
|
|
EFIAPI
|
|
MlDsaNewByNid (
|
|
IN UINTN Nid
|
|
)
|
|
{
|
|
ASSERT (FALSE);
|
|
return NULL;
|
|
}
|
|
|
|
/**
|
|
Frees an ML-DSA context and all associated resources.
|
|
|
|
This function releases all memory associated with the ML-DSA context, including
|
|
the EVP_PKEY structure. After calling this function, the MlDsaContext pointer
|
|
should not be used.
|
|
|
|
If MlDsaContext is NULL, then this function returns immediately without action.
|
|
|
|
@param[in] MlDsaContext Pointer to the ML-DSA context to be released.
|
|
|
|
**/
|
|
VOID
|
|
EFIAPI
|
|
MlDsaFree (
|
|
IN VOID *MlDsaContext
|
|
)
|
|
{
|
|
ASSERT (FALSE);
|
|
}
|
|
|
|
/**
|
|
Retrieves the ML-DSA public key from the ML-DSA context.
|
|
|
|
This function extracts the public key from the ML-DSA context and copies it to
|
|
the provided buffer. The public key is returned in raw binary format.
|
|
|
|
The context must have a key set (either via MlDsaSetPrivKey() or MlDsaSetPubKey())
|
|
before calling this function.
|
|
|
|
If MlDsaContext is NULL, then return FALSE.
|
|
If PublicKeySize is NULL, then return FALSE.
|
|
If the context does not contain a valid key, then return FALSE.
|
|
If PublicKey buffer is too small, PublicKeySize is updated with required size and return FALSE.
|
|
|
|
@param[in] MlDsaContext Pointer to ML-DSA context containing the key.
|
|
@param[out] PublicKey Pointer to buffer to receive the public key.
|
|
@param[in,out] PublicKeySize On input, size of PublicKey buffer in bytes.
|
|
On output, actual size of public key written.
|
|
|
|
@retval TRUE ML-DSA public key retrieved successfully.
|
|
@retval FALSE Invalid parameters or buffer too small.
|
|
|
|
**/
|
|
BOOLEAN
|
|
EFIAPI
|
|
MlDsaGetPubKey (
|
|
IN VOID *MlDsaContext,
|
|
OUT UINT8 *PublicKey,
|
|
IN OUT UINTN *PublicKeySize
|
|
)
|
|
{
|
|
ASSERT (FALSE);
|
|
return FALSE;
|
|
}
|
|
|
|
/**
|
|
Sets the ML-DSA public key in the ML-DSA context.
|
|
|
|
This function imports a raw public key into the ML-DSA context. The public key
|
|
must be in raw binary format (not PEM or DER encoded). The key size must match
|
|
the expected size for the ML-DSA variant (2592 bytes for ML-DSA-87).
|
|
|
|
After setting the public key, the context can be used for signature verification
|
|
but not for signing (which requires the private key).
|
|
|
|
If MlDsaContext is NULL, then return FALSE.
|
|
If PublicKey is NULL, then return FALSE.
|
|
If PublicKeySize does not match the expected size for the variant, then return FALSE.
|
|
|
|
@param[in] MlDsaContext Pointer to ML-DSA context created by MlDsaNewByNid().
|
|
@param[in] PublicKey Pointer to raw public key bytes.
|
|
@param[in] PublicKeySize Size of the public key in bytes.
|
|
|
|
@retval TRUE ML-DSA public key was set successfully.
|
|
@retval FALSE Invalid parameters or key size mismatch.
|
|
|
|
**/
|
|
BOOLEAN
|
|
EFIAPI
|
|
MlDsaSetPubKey (
|
|
IN VOID *MlDsaContext,
|
|
IN UINT8 *PublicKey,
|
|
IN UINTN PublicKeySize
|
|
)
|
|
{
|
|
ASSERT (FALSE);
|
|
return FALSE;
|
|
}
|
|
|
|
/**
|
|
Sets the ML-DSA private key in the ML-DSA context.
|
|
|
|
This function imports a raw private key into the ML-DSA context. The private key
|
|
must be in raw binary format (not PEM or DER encoded). The key size must match
|
|
the expected size for the ML-DSA variant (4896 bytes for ML-DSA-87).
|
|
|
|
OpenSSL automatically derives the public key from the private key, so after
|
|
calling this function, both signing and verification operations are possible.
|
|
|
|
If MlDsaContext is NULL, then return FALSE.
|
|
If PrivateKey is NULL, then return FALSE.
|
|
If PrivateKeySize does not match the expected size for the variant, then return FALSE.
|
|
|
|
@param[in] MlDsaContext Pointer to ML-DSA context created by MlDsaNewByNid().
|
|
@param[in] PrivateKey Pointer to raw private key bytes.
|
|
@param[in] PrivateKeySize Size of the private key in bytes.
|
|
|
|
@retval TRUE ML-DSA private key was set successfully.
|
|
@retval FALSE Invalid parameters or key size mismatch.
|
|
|
|
**/
|
|
BOOLEAN
|
|
EFIAPI
|
|
MlDsaSetPrivKey (
|
|
IN VOID *MlDsaContext,
|
|
IN UINT8 *PrivateKey,
|
|
IN UINTN PrivateKeySize
|
|
)
|
|
{
|
|
ASSERT (FALSE);
|
|
return FALSE;
|
|
}
|
|
|
|
/**
|
|
Generates and retrieves the public key from a private key context.
|
|
|
|
This function extracts the public key from an ML-DSA context that contains
|
|
a private key. It is equivalent to calling MlDsaGetPubKey() but is provided
|
|
for API consistency with other cryptographic implementations.
|
|
|
|
The context must contain a private key (set via MlDsaSetPrivKey()) before
|
|
calling this function.
|
|
|
|
If MlDsaContext is NULL, then return FALSE.
|
|
If PublicKey is NULL, then return FALSE.
|
|
If PublicKeySize does not match the expected size for the variant, then return FALSE.
|
|
|
|
@param[in] MlDsaContext Pointer to ML-DSA context containing the private key.
|
|
@param[out] PublicKey Pointer to buffer to receive the public key.
|
|
@param[in] PublicKeySize Size of the PublicKey buffer in bytes.
|
|
|
|
@retval TRUE Public key generated and retrieved successfully.
|
|
@retval FALSE Invalid parameters or public key extraction failed.
|
|
|
|
**/
|
|
BOOLEAN
|
|
EFIAPI
|
|
MlDsaGeneratePubKey (
|
|
IN VOID *MlDsaContext,
|
|
OUT UINT8 *PublicKey,
|
|
IN UINTN PublicKeySize
|
|
)
|
|
{
|
|
ASSERT (FALSE);
|
|
return FALSE;
|
|
}
|
|
|
|
/**
|
|
Generates an ML-DSA signature for a given message.
|
|
|
|
This function creates an ML-DSA signature using the private key stored in the
|
|
ML-DSA context. ML-DSA signatures can include an optional context string for
|
|
domain separation, allowing the same key to be used in different contexts
|
|
without creating security vulnerabilities.
|
|
|
|
The context must contain a private key (set via MlDsaSetPrivKey()) before
|
|
calling this function.
|
|
|
|
If MlDsaContext is NULL, then return FALSE.
|
|
If Message is NULL, then return FALSE.
|
|
If Signature is NULL, then return FALSE.
|
|
If SigSize is NULL, then return FALSE.
|
|
If SigSize buffer is too small, SigSize is updated with required size and return FALSE.
|
|
Context may be NULL if no context string is used (ContextSize must be 0).
|
|
|
|
@param[in] MlDsaContext Pointer to ML-DSA context containing the private key.
|
|
@param[in] Context Optional context string for domain separation.
|
|
May be NULL for default context.
|
|
@param[in] ContextSize Size of context string in bytes. Set to 0 if Context is NULL.
|
|
@param[in] Message Pointer to message data to be signed.
|
|
@param[in] MessageSize Size of message in bytes.
|
|
@param[out] Signature Pointer to buffer to receive the signature.
|
|
@param[in,out] SigSize On input, size of Signature buffer.
|
|
On output, actual size of signature (4627 bytes for ML-DSA-87).
|
|
|
|
@retval TRUE ML-DSA signature generated successfully.
|
|
@retval FALSE Invalid parameters or signature generation failed.
|
|
|
|
**/
|
|
BOOLEAN
|
|
EFIAPI
|
|
MlDsaSign (
|
|
IN VOID *MlDsaContext,
|
|
IN UINT8 *Context,
|
|
IN UINTN ContextSize,
|
|
IN CONST UINT8 *Message,
|
|
IN UINTN MessageSize,
|
|
OUT UINT8 *Signature,
|
|
IN OUT UINTN *SigSize
|
|
)
|
|
{
|
|
ASSERT (FALSE);
|
|
return FALSE;
|
|
}
|
|
|
|
/**
|
|
Verifies the ML-DSA signature for a given message.
|
|
|
|
This function verifies an ML-DSA signature against a message using the public key
|
|
contained in the ML-DSA context. An optional context string can be provided which
|
|
must match the context used during signing.
|
|
|
|
The context must contain a key (either public or private) set via MlDsaSetPrivKey()
|
|
or MlDsaSetPubKey() before calling this function.
|
|
|
|
If MlDsaContext is NULL, then return FALSE.
|
|
If Message is NULL, then return FALSE.
|
|
If Signature is NULL, then return FALSE.
|
|
If SigSize is 0 or exceeds INT_MAX, then return FALSE.
|
|
Context may be NULL if no context string is used.
|
|
|
|
@param[in] MlDsaContext Pointer to ML-DSA context containing the public key.
|
|
@param[in] Context Optional context string for domain separation.
|
|
May be NULL for default context.
|
|
@param[in] ContextSize Size of context string in bytes. Set to 0 if Context is NULL.
|
|
@param[in] Message Pointer to the message data to verify.
|
|
@param[in] MessageSize Size of the message in bytes.
|
|
@param[in] Signature Pointer to the ML-DSA signature to verify.
|
|
@param[in] SigSize Size of the signature in bytes.
|
|
|
|
@retval TRUE ML-DSA signature verification succeeded.
|
|
@retval FALSE ML-DSA signature verification failed or invalid parameters.
|
|
|
|
**/
|
|
BOOLEAN
|
|
EFIAPI
|
|
MlDsaVerify (
|
|
IN VOID *MlDsaContext,
|
|
IN UINT8 *Context,
|
|
IN UINTN ContextSize,
|
|
IN CONST UINT8 *Message,
|
|
IN UINTN MessageSize,
|
|
IN UINT8 *Signature,
|
|
IN UINTN SigSize
|
|
)
|
|
{
|
|
ASSERT (FALSE);
|
|
return FALSE;
|
|
}
|