forked from wolfSSL/wolfssl
add wc_GetPubKeyDerFromCert(), get pub key DER from DecodedCert
This commit is contained in:
@@ -1249,6 +1249,29 @@ WOLFSSL_API int wc_KeyPemToDer(const unsigned char*, int,
|
||||
WOLFSSL_API int wc_CertPemToDer(const unsigned char*, int,
|
||||
unsigned char*, int, int);
|
||||
|
||||
/*!
|
||||
\ingroup CertsKeys
|
||||
|
||||
\brief This function gets the public key in DER format from a populated
|
||||
DecodedCert struct. Users must call wc_InitDecodedCert() and wc_ParseCert()
|
||||
before calling this API. wc_InitDecodedCert() accepts a DER/ASN.1 encoded
|
||||
certificate. To convert a PEM cert to DER, first use wc_CertPemToDer()
|
||||
before calling wc_InitDecodedCert().
|
||||
|
||||
\return 0 on success, negative on error. LENGTH_ONLY_E if derKey is NULL
|
||||
and returning length only.
|
||||
|
||||
\param cert populated DecodedCert struct holding X.509 certificate
|
||||
\param derKey output buffer to place DER encoded public key
|
||||
\param derKeySz [IN/OUT] size of derKey buffer on input, size of public key
|
||||
on return. If derKey is passed in as NULL, derKeySz will be set to required
|
||||
buffer size for public key and LENGTH_ONLY_E will be returned from function.
|
||||
|
||||
\sa wc_GetPubKeyDerFromCert
|
||||
*/
|
||||
WOLFSSL_API int wc_GetPubKeyDerFromCert(struct DecodedCert* cert,
|
||||
byte* derKey, word32* derKeySz);
|
||||
|
||||
/*!
|
||||
\ingroup ASN
|
||||
|
||||
|
168
tests/api.c
168
tests/api.c
@@ -30094,6 +30094,8 @@ static void test_wc_CertPemToDer(void)
|
||||
free(cert_der);
|
||||
if (cert_buf)
|
||||
free(cert_buf);
|
||||
|
||||
printf(resultFmt, passed);
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -30129,6 +30131,8 @@ static void test_wc_PubKeyPemToDer(void)
|
||||
free(cert_der);
|
||||
if (cert_buf)
|
||||
free(cert_buf);
|
||||
|
||||
printf(resultFmt, passed);
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
@@ -30152,9 +30156,172 @@ static void test_wc_PemPubKeyToDer(void)
|
||||
|
||||
free(cert_der);
|
||||
}
|
||||
|
||||
printf(resultFmt, passed);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void test_wc_GetPubKeyDerFromCert(void)
|
||||
{
|
||||
#if !defined(NO_RSA) || defined(HAVE_ECC)
|
||||
int ret;
|
||||
word32 idx = 0;
|
||||
byte keyDer[TWOK_BUF]; /* large enough for up to RSA 2048 */
|
||||
word32 keyDerSz = (word32)sizeof(keyDer);
|
||||
DecodedCert decoded;
|
||||
#if !defined(NO_RSA) && defined(WOLFSSL_CERT_REQ)
|
||||
byte certBuf[6000]; /* for PEM and CSR, client-cert.pem is 5-6kB */
|
||||
word32 certBufSz = sizeof(certBuf);
|
||||
#endif
|
||||
#if (!defined(USE_CERT_BUFFERS_2048) && !defined(USE_CERT_BUFFERS_1024)) || \
|
||||
defined(WOLFSSL_CERT_REQ)
|
||||
XFILE fp;
|
||||
#endif
|
||||
#ifndef NO_RSA
|
||||
RsaKey rsaKey;
|
||||
#if defined(USE_CERT_BUFFERS_2048)
|
||||
byte* rsaCertDer = (byte*)client_cert_der_2048;
|
||||
word32 rsaCertDerSz = sizeof_client_cert_der_2048;
|
||||
#elif defined(USE_CERT_BUFFERS_1024)
|
||||
byte* rsaCertDer = (byte*)client_cert_der_1024;
|
||||
word32 rsaCertDerSz = sizeof_client_cert_der_1024;
|
||||
#else
|
||||
unsigned char rsaCertDer[TWOK_BUF];
|
||||
word32 rsaCertDerSz;
|
||||
#endif
|
||||
#endif
|
||||
#ifdef HAVE_ECC
|
||||
ecc_key eccKey;
|
||||
#if defined(USE_CERT_BUFFERS_256)
|
||||
byte* eccCert = (byte*)cliecc_cert_der_256;
|
||||
word32 eccCertSz = sizeof_cliecc_cert_der_256;
|
||||
#else
|
||||
unsigned char eccCert[ONEK_BUF];
|
||||
word32 eccCertSz;
|
||||
XFILE fp2;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
printf(testingFmt, "wc_GetPubKeyDerFromCert()");
|
||||
|
||||
#ifndef NO_RSA
|
||||
|
||||
#if !defined(USE_CERT_BUFFERS_1024) && !defined(USE_CERT_BUFFERS_2048)
|
||||
fp = XFOPEN("./certs/1024/client-cert.der", "rb");
|
||||
AssertTrue((fp != XBADFILE));
|
||||
rsaCertDerSz = (word32)XFREAD(rsaCertDer, 1, sizeof(rsaCertDer), fp);
|
||||
XFCLOSE(fp);
|
||||
#endif
|
||||
|
||||
/* good test case - RSA DER cert */
|
||||
wc_InitDecodedCert(&decoded, rsaCertDer, rsaCertDerSz, NULL);
|
||||
ret = wc_ParseCert(&decoded, CERT_TYPE, NO_VERIFY, NULL);
|
||||
AssertIntEQ(ret, 0);
|
||||
|
||||
ret = wc_GetPubKeyDerFromCert(&decoded, keyDer, &keyDerSz);
|
||||
AssertIntEQ(ret, 0);
|
||||
AssertIntGT(keyDerSz, 0);
|
||||
|
||||
/* sanity check, verify we can import DER public key */
|
||||
ret = wc_InitRsaKey(&rsaKey, NULL);
|
||||
AssertIntEQ(ret, 0);
|
||||
ret = wc_RsaPublicKeyDecode(keyDer, &idx, &rsaKey, keyDerSz);
|
||||
AssertIntEQ(ret, 0);
|
||||
wc_FreeRsaKey(&rsaKey);
|
||||
|
||||
/* test LENGTH_ONLY_E case */
|
||||
keyDerSz = 0;
|
||||
ret = wc_GetPubKeyDerFromCert(&decoded, NULL, &keyDerSz);
|
||||
AssertIntEQ(ret, LENGTH_ONLY_E);
|
||||
AssertIntGT(keyDerSz, 0);
|
||||
|
||||
/* bad args: DecodedCert NULL */
|
||||
ret = wc_GetPubKeyDerFromCert(NULL, keyDer, &keyDerSz);
|
||||
AssertIntEQ(ret, BAD_FUNC_ARG);
|
||||
|
||||
/* bad args: output key buff size */
|
||||
ret = wc_GetPubKeyDerFromCert(&decoded, keyDer, NULL);
|
||||
AssertIntEQ(ret, BAD_FUNC_ARG);
|
||||
|
||||
/* bad args: zero size output key buffer */
|
||||
keyDerSz = 0;
|
||||
ret = wc_GetPubKeyDerFromCert(&decoded, keyDer, &keyDerSz);
|
||||
AssertIntEQ(ret, BAD_FUNC_ARG);
|
||||
|
||||
wc_FreeDecodedCert(&decoded);
|
||||
|
||||
/* Certificate Request Tests */
|
||||
#ifdef WOLFSSL_CERT_REQ
|
||||
{
|
||||
XMEMSET(certBuf, 0, sizeof(certBuf));
|
||||
fp = XFOPEN("./certs/csr.signed.der", "rb");
|
||||
AssertTrue((fp != XBADFILE));
|
||||
certBufSz = (word32)XFREAD(certBuf, 1, certBufSz, fp);
|
||||
XFCLOSE(fp);
|
||||
|
||||
wc_InitDecodedCert(&decoded, certBuf, certBufSz, NULL);
|
||||
ret = wc_ParseCert(&decoded, CERTREQ_TYPE, NO_VERIFY, NULL);
|
||||
AssertIntEQ(ret, 0);
|
||||
|
||||
/* good test case - RSA DER certificate request */
|
||||
keyDerSz = sizeof(keyDer);
|
||||
ret = wc_GetPubKeyDerFromCert(&decoded, keyDer, &keyDerSz);
|
||||
AssertIntEQ(ret, 0);
|
||||
AssertIntGT(keyDerSz, 0);
|
||||
|
||||
/* sanity check, verify we can import DER public key */
|
||||
ret = wc_InitRsaKey(&rsaKey, NULL);
|
||||
AssertIntEQ(ret, 0);
|
||||
idx = 0;
|
||||
ret = wc_RsaPublicKeyDecode(keyDer, &idx, &rsaKey, keyDerSz);
|
||||
AssertIntEQ(ret, 0);
|
||||
wc_FreeRsaKey(&rsaKey);
|
||||
|
||||
wc_FreeDecodedCert(&decoded);
|
||||
}
|
||||
#endif /* WOLFSSL_CERT_REQ */
|
||||
#endif /* NO_RSA */
|
||||
|
||||
#ifdef HAVE_ECC
|
||||
#ifndef USE_CERT_BUFFERS_256
|
||||
fp2 = XFOPEN("./certs/client-ecc-cert.der", "rb");
|
||||
AssertTrue((fp2 != XBADFILE));
|
||||
eccCertSz = (word32)XFREAD(eccCert, 1, ONEK_BUF, fp2);
|
||||
XFCLOSE(fp2);
|
||||
#endif
|
||||
|
||||
wc_InitDecodedCert(&decoded, eccCert, eccCertSz, NULL);
|
||||
ret = wc_ParseCert(&decoded, CERT_TYPE, NO_VERIFY, NULL);
|
||||
AssertIntEQ(ret, 0);
|
||||
|
||||
/* good test case - ECC */
|
||||
XMEMSET(keyDer, 0, sizeof(keyDer));
|
||||
keyDerSz = sizeof(keyDer);
|
||||
ret = wc_GetPubKeyDerFromCert(&decoded, keyDer, &keyDerSz);
|
||||
AssertIntEQ(ret, 0);
|
||||
AssertIntGT(keyDerSz, 0);
|
||||
|
||||
/* sanity check, verify we can import DER public key */
|
||||
ret = wc_ecc_init(&eccKey);
|
||||
AssertIntEQ(ret, 0);
|
||||
idx = 0; /* reset idx to 0, used above in RSA case */
|
||||
ret = wc_EccPublicKeyDecode(keyDer, &idx, &eccKey, keyDerSz);
|
||||
AssertIntEQ(ret, 0);
|
||||
wc_ecc_free(&eccKey);
|
||||
|
||||
/* test LENGTH_ONLY_E case */
|
||||
keyDerSz = 0;
|
||||
ret = wc_GetPubKeyDerFromCert(&decoded, NULL, &keyDerSz);
|
||||
AssertIntEQ(ret, LENGTH_ONLY_E);
|
||||
AssertIntGT(keyDerSz, 0);
|
||||
|
||||
wc_FreeDecodedCert(&decoded);
|
||||
#endif
|
||||
|
||||
printf(resultFmt, passed);
|
||||
|
||||
#endif /* !NO_RSA || HAVE_ECC */
|
||||
}
|
||||
|
||||
static void test_wolfSSL_certs(void)
|
||||
{
|
||||
@@ -51933,6 +52100,7 @@ void ApiTest(void)
|
||||
test_wc_CertPemToDer();
|
||||
test_wc_PubKeyPemToDer();
|
||||
test_wc_PemPubKeyToDer();
|
||||
test_wc_GetPubKeyDerFromCert();
|
||||
|
||||
/*OCSP Stapling. */
|
||||
AssertIntEQ(test_wolfSSL_UseOCSPStapling(), WOLFSSL_SUCCESS);
|
||||
|
@@ -17245,12 +17245,16 @@ static int DecodeCertReq(DecodedCert* cert, int* criticalExt)
|
||||
int ParseCert(DecodedCert* cert, int type, int verify, void* cm)
|
||||
{
|
||||
int ret;
|
||||
#ifndef WOLFSSL_NO_MALLOC
|
||||
char* ptr;
|
||||
#endif
|
||||
|
||||
ret = ParseCertRelative(cert, type, verify, cm);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
#ifndef WOLFSSL_NO_MALLOC
|
||||
/* cert->subjectCN not stored as copy of WOLFSSL_NO_MALLOC defind */
|
||||
if (cert->subjectCNLen > 0) {
|
||||
ptr = (char*) XMALLOC(cert->subjectCNLen + 1, cert->heap,
|
||||
DYNAMIC_TYPE_SUBJECT_CN);
|
||||
@@ -17261,7 +17265,10 @@ int ParseCert(DecodedCert* cert, int type, int verify, void* cm)
|
||||
cert->subjectCN = ptr;
|
||||
cert->subjectCNStored = 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef WOLFSSL_NO_MALLOC
|
||||
/* cert->publicKey not stored as copy if WOLFSSL_NO_MALLOC defined */
|
||||
if (cert->keyOID == RSAk &&
|
||||
cert->publicKey != NULL && cert->pubKeySize > 0) {
|
||||
ptr = (char*) XMALLOC(cert->pubKeySize, cert->heap,
|
||||
@@ -17272,6 +17279,7 @@ int ParseCert(DecodedCert* cert, int type, int verify, void* cm)
|
||||
cert->publicKey = (byte *)ptr;
|
||||
cert->pubKeyStored = 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
return ret;
|
||||
}
|
||||
@@ -19950,6 +19958,57 @@ int wc_PemPubKeyToDer(const char* fileName,
|
||||
|
||||
#endif /* !NO_FILESYSTEM && WOLFSSL_PEM_TO_DER */
|
||||
|
||||
/* Get public key in DER format from a populated DecodedCert struct.
|
||||
*
|
||||
* Users must call wc_InitDecodedCert() and wc_ParseCert() before calling
|
||||
* this API. wc_InitDecodedCert() accepts a DER/ASN.1 encoded certificate.
|
||||
* To convert a PEM cert to DER first use wc_CertPemToDer() before calling
|
||||
* wc_InitDecodedCert().
|
||||
*
|
||||
* cert - populated DecodedCert struct holding X.509 certificate
|
||||
* derKey - output buffer to place DER/ASN.1 encoded public key
|
||||
* derKeySz [IN/OUT] - size of derKey buffer on input, size of public key
|
||||
* on return. If derKey is passed in as NULL, derKeySz
|
||||
* will be set to required buffer size for public key
|
||||
* and LENGTH_ONLY_E will be returned from function.
|
||||
* Returns 0 on success, or negative error code on failure. LENGTH_ONLY_E
|
||||
* if derKey is NULL and returning length only.
|
||||
*/
|
||||
int wc_GetPubKeyDerFromCert(struct DecodedCert* cert,
|
||||
byte* derKey, word32* derKeySz)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
/* derKey may be NULL to return length only */
|
||||
if (cert == NULL || derKeySz == NULL ||
|
||||
(derKey != NULL && *derKeySz == 0)) {
|
||||
return BAD_FUNC_ARG;
|
||||
}
|
||||
|
||||
if (cert->publicKey == NULL) {
|
||||
WOLFSSL_MSG("DecodedCert does not contain public key\n");
|
||||
return BAD_FUNC_ARG;
|
||||
}
|
||||
|
||||
/* if derKey is NULL, return required output buffer size in derKeySz */
|
||||
if (derKey == NULL) {
|
||||
*derKeySz = cert->pubKeySize;
|
||||
ret = LENGTH_ONLY_E;
|
||||
}
|
||||
|
||||
if (ret == 0) {
|
||||
if (cert->pubKeySize > *derKeySz) {
|
||||
WOLFSSL_MSG("Output buffer not large enough for public key DER");
|
||||
ret = BAD_FUNC_ARG;
|
||||
}
|
||||
else {
|
||||
XMEMCPY(derKey, cert->publicKey, cert->pubKeySize);
|
||||
*derKeySz = cert->pubKeySize;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
#if !defined(NO_RSA) && (defined(WOLFSSL_CERT_GEN) || \
|
||||
defined(WOLFSSL_KCAPI_RSA) || \
|
||||
|
@@ -12238,11 +12238,11 @@ WOLFSSL_TEST_SUBROUTINE int memory_test(void)
|
||||
#ifdef WOLFSSL_CERT_GEN
|
||||
static const char* otherCertPemFile = CERT_WRITE_TEMP_DIR "othercert.pem";
|
||||
static const char* certPemFile = CERT_WRITE_TEMP_DIR "cert.pem";
|
||||
#endif
|
||||
#ifdef WOLFSSL_CERT_REQ
|
||||
static const char* certReqDerFile = CERT_WRITE_TEMP_DIR "certreq.der";
|
||||
static const char* certReqPemFile = CERT_WRITE_TEMP_DIR "certreq.pem";
|
||||
#endif
|
||||
#endif
|
||||
#endif /* !NO_RSA */
|
||||
|
||||
#if !defined(NO_RSA) || !defined(NO_DSA)
|
||||
|
@@ -2327,9 +2327,9 @@ enum { /* ssl Constants */
|
||||
WOLFSSL_UNKNOWN = -2,
|
||||
WOLFSSL_FATAL_ERROR = -1,
|
||||
|
||||
WOLFSSL_FILETYPE_ASN1 = 2,
|
||||
WOLFSSL_FILETYPE_PEM = 1,
|
||||
WOLFSSL_FILETYPE_DEFAULT = 2, /* ASN1 */
|
||||
WOLFSSL_FILETYPE_ASN1 = CTC_FILETYPE_ASN1,
|
||||
WOLFSSL_FILETYPE_PEM = CTC_FILETYPE_PEM,
|
||||
WOLFSSL_FILETYPE_DEFAULT = CTC_FILETYPE_ASN1, /* ASN1 */
|
||||
|
||||
WOLFSSL_VERIFY_NONE = 0,
|
||||
WOLFSSL_VERIFY_PEER = 1 << 0,
|
||||
|
@@ -200,6 +200,9 @@ enum Ctc_Misc {
|
||||
CTC_MAX_ALT_SIZE = WC_CTC_MAX_ALT_SIZE, /* may be huge, default: 16384 */
|
||||
CTC_SERIAL_SIZE = 20,
|
||||
CTC_GEN_SERIAL_SZ = 16,
|
||||
CTC_FILETYPE_ASN1 = 2,
|
||||
CTC_FILETYPE_PEM = 1,
|
||||
CTC_FILETYPE_DEFAULT = 2,
|
||||
#ifdef WOLFSSL_CERT_EXT
|
||||
/* AKID could contains: hash + (Option) AuthCertIssuer,AuthCertSerialNum
|
||||
* We support only hash */
|
||||
@@ -766,6 +769,9 @@ WOLFSSL_API void wc_InitDecodedCert(struct DecodedCert*, const byte*, word32, vo
|
||||
WOLFSSL_API void wc_FreeDecodedCert(struct DecodedCert*);
|
||||
WOLFSSL_API int wc_ParseCert(struct DecodedCert*, int, int, void*);
|
||||
|
||||
WOLFSSL_API int wc_GetPubKeyDerFromCert(struct DecodedCert* cert,
|
||||
byte* derKey, word32* derKeySz);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
Reference in New Issue
Block a user