Skip to content

Commit 49d9bfa

Browse files
authored
Merge pull request #8758 from bigbrett/exportx509pubkey-api
Added new ASN X509 API: `wc_GetSubjectPubKeyInfoDerFromCert`
2 parents 813e36a + 40c9a03 commit 49d9bfa

3 files changed

Lines changed: 228 additions & 1 deletion

File tree

tests/api.c

Lines changed: 146 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22755,6 +22755,151 @@ static int test_wc_GetPubKeyDerFromCert(void)
2275522755
return EXPECT_RESULT();
2275622756
}
2275722757

22758+
static int test_wc_GetSubjectPubKeyInfoDerFromCert(void)
22759+
{
22760+
EXPECT_DECLS;
22761+
#if !defined(NO_RSA) || defined(HAVE_ECC)
22762+
int ret;
22763+
word32 idx = 0;
22764+
byte keyDer[TWOK_BUF]; /* large enough for up to RSA 2048 */
22765+
word32 keyDerSz = (word32)sizeof(keyDer);
22766+
#if !defined(NO_RSA) && defined(WOLFSSL_CERT_REQ) && !defined(NO_FILESYSTEM)
22767+
byte certBuf[6000]; /* for PEM and CSR, client-cert.pem is 5-6kB */
22768+
word32 certBufSz = sizeof(certBuf);
22769+
#endif
22770+
#if ((!defined(USE_CERT_BUFFERS_2048) && !defined(USE_CERT_BUFFERS_1024)) || \
22771+
defined(WOLFSSL_CERT_REQ)) && !defined(NO_RSA) && !defined(NO_FILESYSTEM)
22772+
XFILE fp = XBADFILE;
22773+
#endif
22774+
#ifndef NO_RSA
22775+
RsaKey rsaKey;
22776+
#if defined(USE_CERT_BUFFERS_2048)
22777+
byte* rsaCertDer = (byte*)client_cert_der_2048;
22778+
word32 rsaCertDerSz = sizeof_client_cert_der_2048;
22779+
#elif defined(USE_CERT_BUFFERS_1024)
22780+
byte* rsaCertDer = (byte*)client_cert_der_1024;
22781+
word32 rsaCertDerSz = sizeof_client_cert_der_1024;
22782+
#else
22783+
unsigned char rsaCertDer[TWOK_BUF];
22784+
word32 rsaCertDerSz;
22785+
#endif
22786+
#endif
22787+
#ifdef HAVE_ECC
22788+
ecc_key eccKey;
22789+
#if defined(USE_CERT_BUFFERS_256)
22790+
byte* eccCert = (byte*)cliecc_cert_der_256;
22791+
word32 eccCertSz = sizeof_cliecc_cert_der_256;
22792+
#else
22793+
unsigned char eccCert[ONEK_BUF];
22794+
word32 eccCertSz;
22795+
XFILE fp2 = XBADFILE;
22796+
#endif
22797+
#endif
22798+
22799+
#ifndef NO_RSA
22800+
22801+
#if !defined(USE_CERT_BUFFERS_1024) && !defined(USE_CERT_BUFFERS_2048)
22802+
ExpectTrue((fp = XFOPEN("./certs/1024/client-cert.der", "rb")) != XBADFILE);
22803+
ExpectIntGT(rsaCertDerSz = (word32)XFREAD(rsaCertDer, 1, sizeof(rsaCertDer),
22804+
fp), 0);
22805+
if (fp != XBADFILE) {
22806+
XFCLOSE(fp);
22807+
fp = XBADFILE;
22808+
}
22809+
#endif
22810+
22811+
/* good test case - RSA DER cert */
22812+
ExpectIntEQ(wc_GetSubjectPubKeyInfoDerFromCert(rsaCertDer, rsaCertDerSz,
22813+
keyDer, &keyDerSz), 0);
22814+
ExpectIntGT(keyDerSz, 0);
22815+
22816+
/* sanity check, verify we can import DER public key */
22817+
ret = wc_InitRsaKey(&rsaKey, HEAP_HINT);
22818+
ExpectIntEQ(ret, 0);
22819+
ExpectIntEQ(wc_RsaPublicKeyDecode(keyDer, &idx, &rsaKey, keyDerSz), 0);
22820+
if (ret == 0) {
22821+
wc_FreeRsaKey(&rsaKey);
22822+
}
22823+
22824+
/* bad args: certDer */
22825+
keyDerSz = (word32)sizeof(keyDer);
22826+
ExpectIntEQ(wc_GetSubjectPubKeyInfoDerFromCert(NULL, rsaCertDerSz, keyDer,
22827+
&keyDerSz),
22828+
WC_NO_ERR_TRACE(BAD_FUNC_ARG));
22829+
22830+
/* bad args: 0 sized certSz */
22831+
keyDerSz = (word32)sizeof(keyDer);
22832+
ExpectIntEQ(wc_GetSubjectPubKeyInfoDerFromCert(rsaCertDer, 0, keyDer,
22833+
&keyDerSz),
22834+
WC_NO_ERR_TRACE(BAD_FUNC_ARG));
22835+
22836+
/* bad args: NULL inout size */
22837+
ExpectIntEQ(ret = wc_GetSubjectPubKeyInfoDerFromCert(rsaCertDer,
22838+
rsaCertDerSz, keyDer,
22839+
NULL),
22840+
WC_NO_ERR_TRACE(BAD_FUNC_ARG));
22841+
22842+
/* Certificate Request Tests */
22843+
#if defined(WOLFSSL_CERT_REQ) && !defined(NO_FILESYSTEM)
22844+
{
22845+
XMEMSET(certBuf, 0, sizeof(certBuf));
22846+
ExpectTrue((fp = XFOPEN("./certs/csr.signed.der", "rb")) != XBADFILE);
22847+
ExpectIntGT(certBufSz = (word32)XFREAD(certBuf, 1, certBufSz, fp), 0);
22848+
if (fp != XBADFILE) {
22849+
XFCLOSE(fp);
22850+
}
22851+
22852+
/* good test case - RSA DER certificate request */
22853+
keyDerSz = sizeof(keyDer);
22854+
ExpectIntEQ(ret = wc_GetSubjectPubKeyInfoDerFromCert(rsaCertDer,
22855+
rsaCertDerSz,
22856+
keyDer,
22857+
&keyDerSz), 0);
22858+
ExpectIntGT(keyDerSz, 0);
22859+
22860+
/* sanity check, verify we can import DER public key */
22861+
ret = wc_InitRsaKey(&rsaKey, HEAP_HINT);
22862+
ExpectIntEQ(ret, 0);
22863+
idx = 0;
22864+
ExpectIntEQ(wc_RsaPublicKeyDecode(keyDer, &idx, &rsaKey, keyDerSz), 0);
22865+
if (ret == 0) {
22866+
wc_FreeRsaKey(&rsaKey);
22867+
}
22868+
}
22869+
#endif /* WOLFSSL_CERT_REQ */
22870+
#endif /* NO_RSA */
22871+
22872+
#ifdef HAVE_ECC
22873+
#ifndef USE_CERT_BUFFERS_256
22874+
ExpectTrue((fp2 = XFOPEN("./certs/client-ecc-cert.der", "rb")) !=
22875+
XBADFILE);
22876+
ExpectIntGT(eccCertSz = (word32)XFREAD(eccCert, 1, ONEK_BUF, fp2), 0);
22877+
if (fp2 != XBADFILE) {
22878+
XFCLOSE(fp2);
22879+
}
22880+
#endif
22881+
22882+
/* good test case - ECC */
22883+
XMEMSET(keyDer, 0, sizeof(keyDer));
22884+
keyDerSz = sizeof(keyDer);
22885+
ExpectIntEQ(wc_GetSubjectPubKeyInfoDerFromCert(eccCert, eccCertSz, keyDer,
22886+
&keyDerSz), 0);
22887+
ExpectIntGT(keyDerSz, 0);
22888+
22889+
/* sanity check, verify we can import DER public key */
22890+
ret = wc_ecc_init(&eccKey);
22891+
ExpectIntEQ(ret, 0);
22892+
idx = 0; /* reset idx to 0, used above in RSA case */
22893+
ExpectIntEQ(wc_EccPublicKeyDecode(keyDer, &idx, &eccKey, keyDerSz), 0);
22894+
if (ret == 0) {
22895+
wc_ecc_free(&eccKey);
22896+
}
22897+
22898+
#endif
22899+
#endif /* !NO_RSA || HAVE_ECC */
22900+
return EXPECT_RESULT();
22901+
}
22902+
2275822903
static int test_wc_CheckCertSigPubKey(void)
2275922904
{
2276022905
EXPECT_DECLS;
@@ -66846,6 +66991,7 @@ TEST_CASE testCases[] = {
6684666991
TEST_DECL(test_wc_PubKeyPemToDer),
6684766992
TEST_DECL(test_wc_PemPubKeyToDer),
6684866993
TEST_DECL(test_wc_GetPubKeyDerFromCert),
66994+
TEST_DECL(test_wc_GetSubjectPubKeyInfoDerFromCert),
6684966995
TEST_DECL(test_wc_CheckCertSigPubKey),
6685066996

6685166997
/* wolfCrypt ASN tests */

wolfcrypt/src/asn.c

Lines changed: 78 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23030,7 +23030,8 @@ static int CheckDate(ASNGetData *dataASN, int dateType)
2303023030
* @param [out] badDateRet Bad date return code.
2303123031
* @param [in] stopAtPubKey Stop parsing before subjectPublicKeyInfo.
2303223032
* @param [in] stopAfterPubKey Stop parsing after subjectPublicKeyInfo.
23033-
* @return 0 on success.
23033+
* @return 0 on success if of the stop arguments is not set, otherwise set to
23034+
* the corresponding byte offset at which the parsing stopped.
2303423035
* @return ASN_CRIT_EXT_E when a critical extension was not recognized.
2303523036
* @return ASN_TIME_E when date BER tag is nor UTC or GENERALIZED time.
2303623037
* @return ASN_DATE_SZ_E when time data is not supported.
@@ -24657,6 +24658,82 @@ int wc_CertGetPubKey(const byte* cert, word32 certSz,
2465724658
return ret;
2465824659
}
2465924660
#endif
24661+
24662+
/*
24663+
* @brief Export the SubjectPublicKeyInfo from an X.509 certificate
24664+
*
24665+
* This function extracts the SubjectPublicKeyInfo (SPKI) section from an X.509
24666+
* certificate in DER format. The SPKI contains the public key algorithm and
24667+
* the public key itself.
24668+
*
24669+
* @param certDer [in] Pointer to the DER encoded certificate
24670+
* @param certSz [in] Size of the DER encoded certificate
24671+
* @param pubKeyDer [out] Buffer to hold the extracted SPKI (can be NULL to
24672+
* get size)
24673+
* @param pubKeyDerSz [in,out] On input, size of pubKeyDer buffer
24674+
* On output, actual size of the SPKI
24675+
*
24676+
* @return 0 on success, negative on error
24677+
* @return BAD_FUNC_ARG if certDer is NULL, certSz is 0, or pubKeyDerSz is NULL
24678+
* @return BUFFER_E if the provided buffer is too small
24679+
*/
24680+
WOLFSSL_API int wc_GetSubjectPubKeyInfoDerFromCert(const byte* certDer,
24681+
word32 certDerSz,
24682+
byte* pubKeyDer,
24683+
word32* pubKeyDerSz)
24684+
{
24685+
DecodedCert cert;
24686+
int ret;
24687+
word32 startIdx;
24688+
word32 idx;
24689+
word32 length;
24690+
int badDate;
24691+
24692+
if (certDer == NULL || certDerSz == 0 || pubKeyDerSz == NULL) {
24693+
return BAD_FUNC_ARG;
24694+
}
24695+
24696+
length = 0;
24697+
badDate = 0;
24698+
24699+
wc_InitDecodedCert(&cert, certDer, certDerSz, NULL);
24700+
24701+
/* Parse up to the SubjectPublicKeyInfo */
24702+
ret = wc_GetPubX509(&cert, 0, &badDate);
24703+
if (ret >= 0) {
24704+
/* Save the starting index of SubjectPublicKeyInfo */
24705+
startIdx = cert.srcIdx;
24706+
24707+
/* Get the length of the SubjectPublicKeyInfo sequence */
24708+
idx = startIdx;
24709+
ret = GetSequence(certDer, &idx, (int*)&length, certDerSz);
24710+
if (ret >= 0) {
24711+
/* Calculate total length including sequence header */
24712+
length += (idx - startIdx);
24713+
24714+
/* Copy the SubjectPublicKeyInfo if buffer provided */
24715+
if (pubKeyDer != NULL) {
24716+
if (*pubKeyDerSz < (word32)length) {
24717+
ret = BUFFER_E;
24718+
}
24719+
else {
24720+
XMEMCPY(pubKeyDer, &certDer[startIdx], length);
24721+
}
24722+
}
24723+
}
24724+
}
24725+
24726+
if (ret >= 0) {
24727+
ret = 0;
24728+
}
24729+
24730+
*pubKeyDerSz = length;
24731+
wc_FreeDecodedCert(&cert);
24732+
24733+
return ret;
24734+
}
24735+
24736+
2466024737
#ifdef HAVE_OCSP
2466124738
Signer* findSignerByKeyHash(Signer *list, byte *hash)
2466224739
{

wolfssl/wolfcrypt/asn_public.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -862,6 +862,10 @@ WOLFSSL_API int wc_ParseCert(
862862

863863
WOLFSSL_API int wc_GetPubKeyDerFromCert(struct DecodedCert* cert,
864864
byte* derKey, word32* derKeySz);
865+
WOLFSSL_API int wc_GetSubjectPubKeyInfoDerFromCert(const byte* certDer,
866+
word32 certDerSz,
867+
byte* pubKeyDer,
868+
word32* pubKeyDerSz);
865869

866870
#ifdef WOLFSSL_FPKI
867871
WOLFSSL_API int wc_GetUUIDFromCert(struct DecodedCert* cert,

0 commit comments

Comments
 (0)