Merge pull request #8947 from SparkiDev/mldsa_openssl_der

ML-DSA/Dilithium: support OpenSSL format
This commit is contained in:
David Garske
2025-07-03 16:10:55 -07:00
committed by GitHub
2 changed files with 74 additions and 4 deletions

View File

@ -36869,7 +36869,8 @@ static const ASNItem edKeyASN[] = {
/* privateKey */
/* PKEY */ { 1, ASN_OCTET_STRING, 0, 1, 0 },
/* CurvePrivateKey */
/* PKEY_CURVEPKEY */ { 2, ASN_OCTET_STRING, 0, 0, 0 },
/* PKEY_CURVEPKEY */ { 2, ASN_OCTET_STRING, 0, 0, 2 },
/* PKEY_MLDSASEQ */ { 2, ASN_SEQUENCE, 1, 0, 2 },
/* attributes */
/* ATTRS */ { 1, ASN_CONTEXT_SPECIFIC | ASN_ASYMKEY_ATTRS, 1, 1, 1 },
/* publicKey */
@ -36882,6 +36883,7 @@ enum {
EDKEYASN_IDX_PKEYALGO_OID,
EDKEYASN_IDX_PKEY,
EDKEYASN_IDX_PKEY_CURVEPKEY,
EDKEYASN_IDX_PKEY_MLDSASEQ,
EDKEYASN_IDX_ATTRS,
EDKEYASN_IDX_PUBKEY
};
@ -36947,8 +36949,15 @@ int DecodeAsymKey_Assign(const byte* input, word32* inOutIdx, word32 inSz,
if (GetOctetString(input, inOutIdx, &length, inSz) < 0)
return ASN_PARSE_E;
if (GetOctetString(input, inOutIdx, &privSz, inSz) < 0)
return ASN_PARSE_E;
if (GetOctetString(input, inOutIdx, &privSz, inSz) < 0) {
if (oid != ML_DSA_LEVEL2k && oid != ML_DSA_LEVEL3k &&
oid != ML_DSA_LEVEL5k) {
return ASN_PARSE_E;
}
if (GetSequence(input, inOutIdx, &privSz, inSz) < 0) {
return ASN_PARSE_E;
}
}
priv = input + *inOutIdx;
*inOutIdx += (word32)privSz;
@ -37026,11 +37035,24 @@ int DecodeAsymKey_Assign(const byte* input, word32* inOutIdx, word32 inSz,
(int)dataASN[EDKEYASN_IDX_PKEYALGO_OID].data.oid.sum;
}
}
if (ret == 0) {
if (ret == 0 && dataASN[EDKEYASN_IDX_PKEY_CURVEPKEY].data.ref.length != 0) {
/* Import private value. */
*privKeyLen = dataASN[EDKEYASN_IDX_PKEY_CURVEPKEY].data.ref.length;
*privKey = dataASN[EDKEYASN_IDX_PKEY_CURVEPKEY].data.ref.data;
}
else if (ret == 0 &&
dataASN[EDKEYASN_IDX_PKEY_MLDSASEQ].data.ref.length != 0) {
if (*inOutKeyType != ML_DSA_LEVEL2k &&
*inOutKeyType != ML_DSA_LEVEL3k &&
*inOutKeyType != ML_DSA_LEVEL5k) {
ret = ASN_PARSE_E;
}
else {
/* Import private value. */
*privKeyLen = dataASN[EDKEYASN_IDX_PKEY_MLDSASEQ].data.ref.length;
*privKey = dataASN[EDKEYASN_IDX_PKEY_MLDSASEQ].data.ref.data;
}
}
if ((ret == 0) && dataASN[EDKEYASN_IDX_PUBKEY].tag == 0) {
/* Set public length to 0 as not seen. */
if (pubKeyLen != NULL)
@ -37454,6 +37476,8 @@ int SetAsymKeyDer(const byte* privKey, word32 privKeyLen,
SetASN_Buffer(&dataASN[EDKEYASN_IDX_PKEY_CURVEPKEY], NULL, privKeyLen);
/* Don't write out attributes. */
dataASN[EDKEYASN_IDX_ATTRS].noOut = 1;
/* Don't write sequence. */
dataASN[EDKEYASN_IDX_PKEY_MLDSASEQ].noOut = 1;
if (pubKey) {
/* Leave space for public key. */
SetASN_Buffer(&dataASN[EDKEYASN_IDX_PUBKEY], NULL, pubKeyLen);

View File

@ -9660,6 +9660,31 @@ int dilithium_get_oid_sum(dilithium_key* key, int* keyFormat) {
#if defined(WOLFSSL_DILITHIUM_PRIVATE_KEY)
/* OCT <seed of 32 bytes> OCT <private key data of more than 256 bytes> */
#define ALT_PRIV_DER_PREFIX (2 + 32 + 4)
/* SEQ [ OCT <seed of 32 bytes> OCT <private key data> ] */
#define ALT_PRIV_DER_PREFIX_SEQ (4 + 2 + 32 + 4)
/* Get the private only key size for the ML-DSA level/parameter id.
*
* @param [in] level Level of the ML-DSA key.
* @return Private key only encoding size for key level on success.
* @return 0 on failure.
*/
static word32 dilithium_get_priv_size(int level)
{
switch (level) {
case WC_ML_DSA_44:
return ML_DSA_LEVEL2_KEY_SIZE;
case WC_ML_DSA_65:
return ML_DSA_LEVEL3_KEY_SIZE;
case WC_ML_DSA_87:
return ML_DSA_LEVEL5_KEY_SIZE;
default:
return 0;
}
}
/* Decode the DER encoded Dilithium key.
*
* @param [in] input Array holding DER encoded data.
@ -9746,6 +9771,19 @@ int wc_Dilithium_PrivateKeyDecode(const byte* input, word32* inOutIdx,
ret = wc_dilithium_set_level(key, (byte)ret);
}
}
/* If it failed to decode try alternative DER encoding. */
else if (ret != 0) {
word32 levelSize = dilithium_get_priv_size(key->level);
privKey = input + *inOutIdx;
privKeyLen = inSz - *inOutIdx;
/* Check for an alternative DER encoding. */
if (privKeyLen == ALT_PRIV_DER_PREFIX_SEQ + levelSize) {
privKey += ALT_PRIV_DER_PREFIX_SEQ;
privKeyLen -= ALT_PRIV_DER_PREFIX_SEQ;
ret = 0;
}
}
}
if ((ret == 0) && (pubKey == NULL) && (pubKeyLen == 0)) {
/* Check if the public key is included in the private key. */
@ -9791,6 +9829,14 @@ int wc_Dilithium_PrivateKeyDecode(const byte* input, word32* inOutIdx,
pubKeyLen = ML_DSA_LEVEL5_PUB_KEY_SIZE;
privKeyLen -= ML_DSA_LEVEL5_PUB_KEY_SIZE;
}
else {
word32 levelSize = dilithium_get_priv_size(key->level);
if (privKeyLen == ALT_PRIV_DER_PREFIX + levelSize) {
privKey += ALT_PRIV_DER_PREFIX;
privKeyLen -= ALT_PRIV_DER_PREFIX;
}
}
}
if (ret == 0) {