From 5e44d5881ab47dfd07d032bafdba7ad85edb95e2 Mon Sep 17 00:00:00 2001 From: jchx Date: Sat, 13 Jun 2026 02:43:31 +0000 Subject: [PATCH] Reject RSA private key encoding without public exponent Add a check to fail RSA private key encoding when e is missing or zero, and add an SDV test for n+d only keys Cherry-picked from: https://gitcode.com/openHiTLS/openhitls/merge_requests/1603 Signed-off-by: Dongjianwei001 --- crypto/codecskey/src/crypt_codecskey_local.c | 18 +++ .../encode/test_suite_sdv_asn1_certkey.c | 105 ++++++++++++++++++ .../encode/test_suite_sdv_asn1_certkey.data | 3 + 3 files changed, 126 insertions(+) diff --git a/crypto/codecskey/src/crypt_codecskey_local.c b/crypto/codecskey/src/crypt_codecskey_local.c index 21790416..3d3d2619 100644 --- a/crypto/codecskey/src/crypt_codecskey_local.c +++ b/crypto/codecskey/src/crypt_codecskey_local.c @@ -1417,6 +1417,19 @@ static void SetRsaPrv2Arr(const CRYPT_EAL_PkeyPrv *rsaPrv, BSL_ASN1_Buffer *asn1 asn1[CRYPT_RSA_PRV_QINV_IDX].tag = BSL_ASN1_TAG_INTEGER; } +static bool RsaPrvPubExpIsZero(const CRYPT_RsaPrv *rsaPrv) +{ + if (rsaPrv->e == NULL || rsaPrv->eLen == 0) { + return true; + } + for (uint32_t i = 0; i < rsaPrv->eLen; i++) { + if (rsaPrv->e[i] != 0) { + return false; + } + } + return true; +} + int32_t EncodeRsaPrikeyAsn1Buff(CRYPT_EAL_PkeyCtx *ealPriKey, BSL_Buffer *encode) { BSL_ASN1_Buffer asn1[CRYPT_RSA_PRV_OTHER_PRIME_IDX + 1] = {0}; @@ -1433,6 +1446,11 @@ int32_t EncodeRsaPrikeyAsn1Buff(CRYPT_EAL_PkeyCtx *ealPriKey, BSL_Buffer *encode BSL_ERR_PUSH_ERROR(ret); return ret; } + if (RsaPrvPubExpIsZero(&rsaPrv.key.rsaPrv)) { + CRYPT_EAL_DeinitRsaPrv(&rsaPrv); + BSL_ERR_PUSH_ERROR(CRYPT_RSA_ERR_INPUT_VALUE); + return CRYPT_RSA_ERR_INPUT_VALUE; + } SetRsaPrv2Arr(&rsaPrv, asn1); uint8_t version = 0; asn1[CRYPT_RSA_PRV_VERSION_IDX].buff = (uint8_t *)&version; diff --git a/testcode/sdv/testcase/crypto/encode/test_suite_sdv_asn1_certkey.c b/testcode/sdv/testcase/crypto/encode/test_suite_sdv_asn1_certkey.c index 71a4dec6..850c30e1 100644 --- a/testcode/sdv/testcase/crypto/encode/test_suite_sdv_asn1_certkey.c +++ b/testcode/sdv/testcase/crypto/encode/test_suite_sdv_asn1_certkey.c @@ -485,6 +485,68 @@ EXIT: return ret; } +static int32_t GenerateRsaNdOnlyKey(CRYPT_EAL_PkeyCtx **ndKey) +{ + CRYPT_EAL_PkeyCtx *fullKey = NULL; + CRYPT_EAL_PkeyCtx *tmpKey = NULL; + uint8_t *keyBuf = NULL; + uint32_t keyLen = 0; + int32_t ret = CRYPT_SUCCESS; + + CRYPT_EAL_PkeyPara para = {0}; + para.id = CRYPT_PKEY_RSA; + para.para.rsaPara.e = g_rsaNoCrtPubExp; + para.para.rsaPara.eLen = sizeof(g_rsaNoCrtPubExp); + para.para.rsaPara.bits = 1024; + + fullKey = CRYPT_EAL_PkeyNewCtx(CRYPT_PKEY_RSA); + tmpKey = CRYPT_EAL_PkeyNewCtx(CRYPT_PKEY_RSA); + if (fullKey == NULL || tmpKey == NULL) { + ret = CRYPT_MEM_ALLOC_FAIL; + goto EXIT; + } + ret = CRYPT_EAL_PkeySetPara(fullKey, ¶); + if (ret != CRYPT_SUCCESS) { + goto EXIT; + } + ret = CRYPT_EAL_PkeyGen(fullKey); + if (ret != CRYPT_SUCCESS) { + goto EXIT; + } + + keyLen = CRYPT_EAL_PkeyGetKeyLen(fullKey); + keyBuf = BSL_SAL_Malloc(keyLen * 2); // n and d + if (keyBuf == NULL) { + ret = CRYPT_MEM_ALLOC_FAIL; + goto EXIT; + } + + CRYPT_EAL_PkeyPrv prv = {0}; + prv.id = CRYPT_PKEY_RSA; + prv.key.rsaPrv.n = keyBuf; + prv.key.rsaPrv.nLen = keyLen; + prv.key.rsaPrv.d = keyBuf + keyLen; + prv.key.rsaPrv.dLen = keyLen; + ret = CRYPT_EAL_PkeyGetPrv(fullKey, &prv); + if (ret != CRYPT_SUCCESS) { + goto EXIT; + } + + ret = CRYPT_EAL_PkeySetPrv(tmpKey, &prv); + if (ret != CRYPT_SUCCESS) { + goto EXIT; + } + + *ndKey = tmpKey; + tmpKey = NULL; + ret = CRYPT_SUCCESS; +EXIT: + CRYPT_EAL_PkeyFreeCtx(fullKey); + CRYPT_EAL_PkeyFreeCtx(tmpKey); + BSL_SAL_ClearFree(keyBuf, keyBuf == NULL ? 0 : keyLen * 2); + return ret; +} + static void RsaNoCrtEncDec(CRYPT_EAL_PkeyCtx *noCrtKey, int isProvider, int keyType, const char *keyTypeStr, const CRYPT_EncodeParam *encodeParam, uint8_t *pwd, uint32_t pwdLen) { @@ -674,6 +736,49 @@ EXIT: } /* END_CASE */ +/** + * @test SDV_CRYPT_EAL_RSA_ND_PRIKEY_ENCODE_REJECT_TC001 + * @title RSA private key encoding rejects n/d only keys + */ +/* BEGIN_CASE */ +void SDV_CRYPT_EAL_RSA_ND_PRIKEY_ENCODE_REJECT_TC001(void) +{ +#if defined(HITLS_CRYPTO_RSA) && defined(HITLS_CRYPTO_KEY_ENCODE) && defined(HITLS_CRYPTO_KEY_DECODE) + CRYPT_EAL_PkeyCtx *ndKey = NULL; + BSL_Buffer encode = {0}; + uint8_t pwd[] = {0x31, 0x32, 0x33, 0x34}; + CRYPT_Pbkdf2Param param = { + .pbesId = BSL_CID_PBES2, + .pbkdfId = BSL_CID_PBKDF2, + .hmacId = CRYPT_MAC_HMAC_SHA256, + .symId = CRYPT_CIPHER_AES256_CBC, + .saltLen = 16, + .pwd = pwd, + .pwdLen = sizeof(pwd), + .itCnt = 2048 + }; + CRYPT_EncodeParam paramEx = {CRYPT_DERIVE_PBKDF2, ¶m}; + + ASSERT_EQ(TestRandInit(), CRYPT_SUCCESS); + ASSERT_EQ(GenerateRsaNdOnlyKey(&ndKey), CRYPT_SUCCESS); + + ASSERT_EQ(CRYPT_EAL_EncodeBuffKey(ndKey, NULL, BSL_FORMAT_ASN1, CRYPT_PRIKEY_RSA, &encode), + CRYPT_RSA_ERR_INPUT_VALUE); + ASSERT_EQ(CRYPT_EAL_EncodeBuffKey(ndKey, NULL, BSL_FORMAT_ASN1, CRYPT_PRIKEY_PKCS8_UNENCRYPT, &encode), + CRYPT_RSA_ERR_INPUT_VALUE); +#if defined(HITLS_CRYPTO_KEY_EPKI) + ASSERT_EQ(CRYPT_EAL_EncodeBuffKey(ndKey, ¶mEx, BSL_FORMAT_ASN1, CRYPT_PRIKEY_PKCS8_ENCRYPT, &encode), + CRYPT_RSA_ERR_INPUT_VALUE); +#endif +EXIT: + CRYPT_EAL_PkeyFreeCtx(ndKey); + TestRandDeInit(); +#else + SKIP_TEST(); +#endif +} +/* END_CASE */ + /* sign and optional compare in a reusable subroutine */ static int32_t PrikeySign(CRYPT_EAL_PkeyCtx *pkeyCtx, int mdId, int fileType, char *fileTypeStr, Hex *msg, Hex *sign) { diff --git a/testcode/sdv/testcase/crypto/encode/test_suite_sdv_asn1_certkey.data b/testcode/sdv/testcase/crypto/encode/test_suite_sdv_asn1_certkey.data index 6b5b7ed2..bdf4b21b 100644 --- a/testcode/sdv/testcase/crypto/encode/test_suite_sdv_asn1_certkey.data +++ b/testcode/sdv/testcase/crypto/encode/test_suite_sdv_asn1_certkey.data @@ -811,6 +811,9 @@ SDV_CRYPT_EAL_RSA_NO_CRT_PRIKEY_ENCDEC_TC001:0 SDV_CRYPT_EAL_RSA_NO_CRT_PRIKEY_ENCDEC_TC001 provider decoder SDV_CRYPT_EAL_RSA_NO_CRT_PRIKEY_ENCDEC_TC001:1 +SDV_CRYPT_EAL_RSA_ND_PRIKEY_ENCODE_REJECT_TC001 +SDV_CRYPT_EAL_RSA_ND_PRIKEY_ENCODE_REJECT_TC001: + SDV_CRYPT_EAL_PROVIDER_DECODE_BUFF_KEY_ALGID_TC001 Test RSA key with mismatched SM2 algId SDV_CRYPT_EAL_PROVIDER_DECODE_BUFF_KEY_ALGID_TC001:"../testdata/cert/asn1/rsa2048key_pkcs8.der":"ASN1":"PRIKEY_PKCS8_UNENCRYPT":CRYPT_PKEY_SM2:CRYPT_PKEY_RSA