* This file is part of the openHiTLS project.
*
* openHiTLS is licensed under the Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
*
* http://license.coscl.org.cn/MulanPSL2
*
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
#include "bsl_sal.h"
#include "bsl_err.h"
#include "crypt_errno.h"
#include "crypt_eal_pkey.h"
#include "crypt_util_rand.h"
#include "eal_pkey_local.h"
#include "crypt_eal_codecs.h"
* @test SDV_CRYPTO_COMPOSITE_API_TC001
* @spec -
* @title Test Composite ML-DSA API: context, key generation, and key I/O.
* @precon nan
* @brief
* 1.Create two contexts (ctxA, ctxB).
* 2.Set parameters by ID, including error test.
* 3.Generate keys for ctxA.
* 4.Export keys from ctxA (GetPub/GetPrv).
* 5.Import keys into ctxB (SetPub/SetPrv).
* @expect
* 1.Contexts and key operations succeed.
* 2.Key I/O is successful.
* @prior nan
* @auto FALSE
@ */
void SDV_CRYPTO_COMPOSITE_API_TC001(int type)
{
TestMemInit();
TestRandInit();
CRYPT_EAL_PkeyCtx *ctxA = CRYPT_EAL_PkeyNewCtx(CRYPT_PKEY_COMPOSITE);
CRYPT_EAL_PkeyCtx *ctxB = CRYPT_EAL_PkeyNewCtx(CRYPT_PKEY_COMPOSITE);
int32_t val = CRYPT_PKEY_PARAID_MAX;
ASSERT_TRUE(ctxA != NULL);
ASSERT_TRUE(ctxB != NULL);
ASSERT_EQ(CRYPT_EAL_PkeySetParaById(ctxA, val), CRYPT_INVALID_ARG);
val = (int32_t)type;
ASSERT_EQ(CRYPT_EAL_PkeySetParaById(ctxA, val), CRYPT_SUCCESS);
ASSERT_EQ(CRYPT_EAL_PkeySetParaById(ctxB, val), CRYPT_SUCCESS);
ASSERT_EQ(CRYPT_EAL_PkeyGen(ctxA), CRYPT_SUCCESS);
uint32_t pubKeyLen = 0;
uint32_t prvKeyLen = 0;
ASSERT_EQ(CRYPT_EAL_PkeyCtrl(ctxA, CRYPT_CTRL_GET_PUBKEY_LEN, &pubKeyLen, sizeof(pubKeyLen)),
CRYPT_SUCCESS);
ASSERT_EQ(CRYPT_EAL_PkeyCtrl(ctxA, CRYPT_CTRL_GET_PRVKEY_LEN, &prvKeyLen, sizeof(prvKeyLen)),
CRYPT_SUCCESS);
CRYPT_EAL_PkeyPub pk = { 0 };
pk.id = CRYPT_PKEY_COMPOSITE;
pk.key.compositePub.len = pubKeyLen;
pk.key.compositePub.data = BSL_SAL_Malloc(pubKeyLen);
ASSERT_TRUE(pk.key.compositePub.data != NULL);
CRYPT_EAL_PkeyPrv sk = { 0 };
sk.id = CRYPT_PKEY_COMPOSITE;
sk.key.compositePrv.len = prvKeyLen;
sk.key.compositePrv.data = BSL_SAL_Malloc(prvKeyLen);
ASSERT_TRUE(sk.key.compositePrv.data != NULL);
ASSERT_EQ(CRYPT_EAL_PkeyGetPub(ctxA, &pk), CRYPT_SUCCESS);
ASSERT_EQ(CRYPT_EAL_PkeyGetPrv(ctxA, &sk), CRYPT_SUCCESS);
ASSERT_EQ(CRYPT_EAL_PkeySetPub(ctxB, &pk), CRYPT_SUCCESS);
ASSERT_EQ(CRYPT_EAL_PkeySetPrv(ctxB, &sk), CRYPT_SUCCESS);
EXIT:
BSL_SAL_Free(pk.key.compositePub.data);
BSL_SAL_Free(sk.key.compositePrv.data);
CRYPT_EAL_PkeyFreeCtx(ctxA);
CRYPT_EAL_PkeyFreeCtx(ctxB);
TestRandDeInit();
return;
}
* @test SDV_CRYPTO_COMPOSITE_SIGN_TC001
* @spec -
* @title Test Composite ML-DSA signature and verification.
* @precon Private and public key data is available.
* @brief
* 1.Create context and set parameters.
* 2.Set the private key.
* 3.Call the signature interface.
* 4.Set the public key.
* 5.Call the verification interface.
* @expect
* 1.Signature operation succeeds.
* 2.Verification operation succeeds.
* @prior nan
* @auto FALSE
@ */
void SDV_CRYPTO_COMPOSITE_SIGN_TC001(int type, Hex *ctxText, Hex *testPrvKey, Hex *testPubKey, Hex *msg)
{
TestMemInit();
TestRandInit();
CRYPT_EAL_PkeyCtx *ctx = CRYPT_EAL_PkeyNewCtx(CRYPT_PKEY_COMPOSITE);
ASSERT_TRUE(ctx != NULL);
uint32_t val = (uint32_t)type;
int32_t ret = CRYPT_EAL_PkeySetParaById(ctx, val);
ASSERT_EQ(ret, CRYPT_SUCCESS);
CRYPT_EAL_PkeyPrv prvKey = { 0 };
prvKey.id = CRYPT_PKEY_COMPOSITE;
prvKey.key.compositePrv.data = testPrvKey->x;
prvKey.key.compositePrv.len = testPrvKey->len;
ret = CRYPT_EAL_PkeySetPrv(ctx, &prvKey);
ASSERT_EQ(ret, CRYPT_SUCCESS);
uint32_t outLen = CRYPT_EAL_PkeyGetSignLen(ctx);
uint8_t *out = BSL_SAL_Malloc(outLen);
ASSERT_TRUE(out != NULL);
ret = CRYPT_EAL_PkeySign(ctx, CRYPT_MD_MAX, msg->x, msg->len, out, &outLen);
ASSERT_EQ(ret, CRYPT_SUCCESS);
CRYPT_EAL_PkeyPub pubKey = { 0 };
pubKey.id = CRYPT_PKEY_COMPOSITE;
pubKey.key.compositePub.data = testPubKey->x;
pubKey.key.compositePub.len = testPubKey->len;
ret = CRYPT_EAL_PkeySetPub(ctx, &pubKey);
ASSERT_EQ(ret, CRYPT_SUCCESS);
ret = CRYPT_EAL_PkeyVerify(ctx, CRYPT_MD_MAX, msg->x, msg->len, out, outLen);
ASSERT_EQ(ret, CRYPT_SUCCESS);
uint32_t outLenWithCtx = CRYPT_EAL_PkeyGetSignLen(ctx);
uint8_t *outWithCtx = BSL_SAL_Malloc(outLenWithCtx);
ASSERT_TRUE(outWithCtx != NULL);
ret = CRYPT_EAL_PkeyCtrl(ctx, CRYPT_CTRL_SET_CTX_INFO, ctxText->x, ctxText->len);
ASSERT_EQ(ret, CRYPT_SUCCESS);
ret = CRYPT_EAL_PkeySign(ctx, CRYPT_MD_MAX, msg->x, msg->len, outWithCtx, &outLenWithCtx);
ASSERT_EQ(ret, CRYPT_SUCCESS);
ret = CRYPT_EAL_PkeyVerify(ctx, CRYPT_MD_MAX, msg->x, msg->len, outWithCtx, outLenWithCtx);
ASSERT_EQ(ret, CRYPT_SUCCESS);
EXIT:
CRYPT_EAL_PkeyFreeCtx(ctx);
BSL_SAL_Free(out);
BSL_SAL_Free(outWithCtx);
TestRandDeInit();
}
* @test SDV_CRYPTO_COMPOSITE_VERIFY_TC001
* @spec -
* @title Test Composite ML-DSA signature verification with pre-generated signature.
* @precon Public key, message, and signature data is available.
* @brief
* 1.Create context and set parameters.
* 2.Set the public key.
* 3.Call the verification interface with message and signature.
* @expect
* 1.Verification operation succeeds.
* @prior nan
* @auto FALSE
@ */
void SDV_CRYPTO_COMPOSITE_VERIFY_TC001(int type, Hex *ctxText, Hex *testPubKey, Hex *msg, Hex *sign, Hex *signWithCtx)
{
TestMemInit();
CRYPT_EAL_PkeyCtx *ctx = CRYPT_EAL_PkeyNewCtx(CRYPT_PKEY_COMPOSITE);
ASSERT_TRUE(ctx != NULL);
uint32_t val = (uint32_t)type;
int32_t ret = CRYPT_EAL_PkeySetParaById(ctx, val);
ASSERT_EQ(ret, CRYPT_SUCCESS);
CRYPT_EAL_PkeyPub pubKey = { 0 };
pubKey.id = CRYPT_PKEY_COMPOSITE;
pubKey.key.compositePub.data = testPubKey->x;
pubKey.key.compositePub.len = testPubKey->len;
ret = CRYPT_EAL_PkeySetPub(ctx, &pubKey);
ASSERT_EQ(ret, CRYPT_SUCCESS);
ret = CRYPT_EAL_PkeyVerify(ctx, CRYPT_MD_MAX, msg->x, msg->len, sign->x, sign->len);
ASSERT_EQ(ret, CRYPT_SUCCESS);
ret = CRYPT_EAL_PkeyCtrl(ctx, CRYPT_CTRL_SET_CTX_INFO, ctxText->x, ctxText->len);
ASSERT_EQ(ret, CRYPT_SUCCESS);
ret = CRYPT_EAL_PkeyVerify(ctx, CRYPT_MD_MAX, msg->x, msg->len, signWithCtx->x, signWithCtx->len);
ASSERT_EQ(ret, CRYPT_SUCCESS);
EXIT:
CRYPT_EAL_PkeyFreeCtx(ctx);
return;
}
* @test SDV_CRYPTO_COMPOSITE_CHECK_KEYPAIR_TC001
* @spec -
* @title Test Composite ML-DSA keypair check API.
* @precon ML-DSA Keypair check is enabled (HITLS_CRYPTO_COMPOSITE_CHECK defined).
* @brief
* 1. Create contexts (ctx, pubCtx, prvCtx) and set parameters.
* 2. Test keypair check before key generation (expect failure).
* 3. Generate a keypair in ctx.
* 4. Test keypair check on the generated keypair (expect success).
* 5. Extract public key (pk) and private key (sk) from ctx.
* 6. Set private key in prvCtx and public key in pubCtx.
* 7. Test keypair check with mismatched public/private contexts (expect failure).
* 8. Test keypair check with a public key context as the private key context (expect failure, no private key).
* 9. Test keypair check with public key context as the public key context and private key context as the private
* key context (expect success).
* @expect
* 1. Keypair check succeeds only when both public and private keys are present and match.
* @prior nan
* @auto FALSE
@ */
void SDV_CRYPTO_COMPOSITE_CHECK_KEYPAIR_TC001(int type)
{
#if !defined(HITLS_CRYPTO_COMPOSITE_CHECK)
(void)type;
SKIP_TEST();
#else
TestMemInit();
TestRandInit();
CRYPT_EAL_PkeyCtx *ctx = NULL;
CRYPT_EAL_PkeyCtx *pubCtx = NULL;
CRYPT_EAL_PkeyCtx *prvCtx = NULL;
#ifdef HITLS_CRYPTO_PROVIDER
ctx =
CRYPT_EAL_ProviderPkeyNewCtx(NULL, CRYPT_PKEY_COMPOSITE, CRYPT_EAL_PKEY_SIGN_OPERATE, "provider=default");
pubCtx =
CRYPT_EAL_ProviderPkeyNewCtx(NULL, CRYPT_PKEY_COMPOSITE, CRYPT_EAL_PKEY_SIGN_OPERATE, "provider=default");
prvCtx =
CRYPT_EAL_ProviderPkeyNewCtx(NULL, CRYPT_PKEY_COMPOSITE, CRYPT_EAL_PKEY_SIGN_OPERATE, "provider=default");
#else
ctx = CRYPT_EAL_PkeyNewCtx(CRYPT_PKEY_COMPOSITE);
pubCtx = CRYPT_EAL_PkeyNewCtx(CRYPT_PKEY_COMPOSITE);
prvCtx = CRYPT_EAL_PkeyNewCtx(CRYPT_PKEY_COMPOSITE);
#endif
ASSERT_TRUE(ctx != NULL);
ASSERT_TRUE(pubCtx != NULL);
ASSERT_TRUE(prvCtx != NULL);
ASSERT_EQ(CRYPT_EAL_PkeyPairCheck(ctx, ctx), CRYPT_COMPOSITE_KEYINFO_NOT_SET);
ASSERT_EQ(CRYPT_EAL_PkeySetParaById(ctx, type), CRYPT_SUCCESS);
ASSERT_EQ(CRYPT_EAL_PkeySetParaById(pubCtx, type), CRYPT_SUCCESS);
ASSERT_EQ(CRYPT_EAL_PkeySetParaById(prvCtx, type), CRYPT_SUCCESS);
ASSERT_EQ(CRYPT_EAL_PkeyGen(ctx), CRYPT_SUCCESS);
ASSERT_EQ(CRYPT_EAL_PkeyPairCheck(ctx, ctx), CRYPT_SUCCESS);
uint32_t pubKeyLen = 0;
uint32_t prvKeyLen = 0;
ASSERT_EQ(CRYPT_EAL_PkeyCtrl(ctx, CRYPT_CTRL_GET_PUBKEY_LEN, &pubKeyLen, sizeof(pubKeyLen)),
CRYPT_SUCCESS);
ASSERT_EQ(CRYPT_EAL_PkeyCtrl(ctx, CRYPT_CTRL_GET_PRVKEY_LEN, &prvKeyLen, sizeof(prvKeyLen)),
CRYPT_SUCCESS);
CRYPT_EAL_PkeyPub pk = { 0 };
pk.id = CRYPT_PKEY_COMPOSITE;
pk.key.compositePub.len = pubKeyLen;
pk.key.compositePub.data = BSL_SAL_Malloc(pubKeyLen);
ASSERT_TRUE(pk.key.compositePub.data != NULL);
CRYPT_EAL_PkeyPrv sk = { 0 };
sk.id = CRYPT_PKEY_COMPOSITE;
sk.key.compositePrv.len = prvKeyLen;
sk.key.compositePrv.data = BSL_SAL_Malloc(prvKeyLen);
ASSERT_TRUE(sk.key.compositePrv.data != NULL);
ASSERT_EQ(CRYPT_EAL_PkeyGetPrv(ctx, &sk), CRYPT_SUCCESS);
ASSERT_EQ(CRYPT_EAL_PkeyGetPub(ctx, &pk), CRYPT_SUCCESS);
ASSERT_EQ(CRYPT_EAL_PkeySetPrv(prvCtx, &sk), CRYPT_SUCCESS);
ASSERT_EQ(CRYPT_EAL_PkeySetPub(pubCtx, &pk), CRYPT_SUCCESS);
ASSERT_EQ(CRYPT_EAL_PkeyPairCheck(prvCtx, pubCtx), CRYPT_MLDSA_INVALID_PRVKEY);
ASSERT_EQ(CRYPT_EAL_PkeyPairCheck(pubCtx, pubCtx), CRYPT_MLDSA_INVALID_PRVKEY);
ASSERT_EQ(CRYPT_EAL_PkeyPairCheck(pubCtx, prvCtx), CRYPT_SUCCESS);
EXIT:
CRYPT_EAL_PkeyFreeCtx(ctx);
CRYPT_EAL_PkeyFreeCtx(pubCtx);
CRYPT_EAL_PkeyFreeCtx(prvCtx);
BSL_SAL_Free(sk.key.compositePrv.data);
BSL_SAL_Free(pk.key.compositePub.data);
TestRandDeInit();
#endif
}