Merge pull request #10821 from wolfSSL/feature/x509-no-malloc-verify

Add true zero-allocation X.509 certificate verification under WOLFSSL_NO_MALLOC
This commit is contained in:
David Garske
2026-07-10 07:56:03 -07:00
committed by GitHub
4 changed files with 260 additions and 38 deletions
+6
View File
@@ -82,6 +82,12 @@ jobs:
"--enable-staticmemory",
"CFLAGS=-DWOLFSSL_NO_MALLOC -pedantic -Wdeclaration-after-statement -Wnull-dereference -DTEST_LIBWOLFSSL_SOURCES_INCLUSION_SEQUENCE"],
"check": false,
"run": [["./wolfcrypt/test/testwolfcrypt"]]},
{"name": "no-heap-cert", "minutes": 0.8,
"configure": ["--enable-rsa", "--enable-keygen", "--enable-ecc",
"--enable-acert", "--disable-dh", "--disable-filesystem",
"CFLAGS=-DWOLFSSL_NO_MALLOC -DNO_WOLFSSL_MEMORY -DRSA_MIN_SIZE=1024 -DWOLFSSL_TEST_CERT -DUSE_CERT_BUFFERS_2048 -DUSE_CERT_BUFFERS_256 -pedantic -Wdeclaration-after-statement -Wnull-dereference -DTEST_LIBWOLFSSL_SOURCES_INCLUSION_SEQUENCE"],
"check": false,
"run": [["./wolfcrypt/test/testwolfcrypt"]]}
]
EOF
+133 -37
View File
@@ -156,6 +156,15 @@ ASN Options:
* WOLFSSL_ALLOW_CRIT_AKID: Allow critical Auth Key Identifier
* WOLFSSL_ALLOW_CRIT_SKID: Allow critical Subject Key Identifier
* WC_ASN_UNKNOWN_EXT_CB: Callback for unknown extensions
* WC_ASN_NO_HEAP: Zero-allocation cert parse: reference key/alt-name
data in the source DER instead of heap copies, so the source buffer must
outlive the DecodedCert. Auto-defined when WOLFSSL_NO_MALLOC and
NO_WOLFSSL_MEMORY are set without XMALLOC_USER or WOLFSSL_STATIC_MEMORY.
Limitation: IP and registeredID SAN entries need a parsed string form that
has no in-place source, so such certs are rejected with ASN_PARSE_E. SAN
DNS_entry.name is NOT NUL-terminated in this mode; only .len is authoritative.
* WC_ASN_MAX_ALTNAMES: No-heap SAN pool slot count (default 8); excess
subject alternative names are rejected.
*
* ASN.1 Parsing:
* WOLFSSL_ASN_ALL: Enable all ASN.1 features
@@ -12579,7 +12588,14 @@ void FreeAltNames(DNS_entry* altNames, void* heap)
altNames->ridStringStored = 0;
}
#endif
XFREE(altNames, heap, DYNAMIC_TYPE_ALTNAME);
#ifdef WC_ASN_NO_HEAP
/* Only free heap nodes; no-heap pool nodes aren't owned. */
if (altNames->entryStored) {
XFREE(altNames, heap, DYNAMIC_TYPE_ALTNAME);
}
#else
XFREE(altNames, heap, DYNAMIC_TYPE_ALTNAME);
#endif
altNames = tmp;
}
}
@@ -12591,6 +12607,9 @@ DNS_entry* AltNameNew(void* heap)
ret = (DNS_entry*)XMALLOC(sizeof(DNS_entry), heap, DYNAMIC_TYPE_ALTNAME);
if (ret != NULL) {
XMEMSET(ret, 0, sizeof(DNS_entry));
#ifdef WC_ASN_NO_HEAP
ret->entryStored = 1; /* heap-allocated node; FreeAltNames frees it */
#endif
}
(void)heap;
return ret;
@@ -12739,7 +12758,9 @@ static int StoreKey(DecodedCert* cert, const byte* source, word32* srcIdx,
{
int ret;
int length;
#ifndef WC_ASN_NO_HEAP
byte* publicKey;
#endif
ret = CheckBitString(source, srcIdx, &length, maxIdx, 1, NULL);
if (ret == 0) {
@@ -12749,6 +12770,17 @@ static int StoreKey(DecodedCert* cert, const byte* source, word32* srcIdx,
}
if (ret == 0) {
#endif
#ifdef WC_ASN_NO_HEAP
/* No heap: reference the key in place; source must outlive the cert. */
cert->publicKey = (byte*)&source[*srcIdx];
cert->pubKeyStored = 0;
cert->pubKeySize = (word32)length;
#ifdef HAVE_OCSP_RESPONDER
cert->publicKeyForHash = cert->publicKey;
cert->pubKeyForHashSize = cert->pubKeySize;
#endif
*srcIdx += (word32)length;
#else
publicKey = (byte*)XMALLOC((size_t)length, cert->heap,
DYNAMIC_TYPE_PUBLIC_KEY);
if (publicKey == NULL) {
@@ -12767,6 +12799,7 @@ static int StoreKey(DecodedCert* cert, const byte* source, word32* srcIdx,
*srcIdx += (word32)length;
}
#endif
}
return ret;
@@ -13407,7 +13440,9 @@ static int StoreEccKey(DecodedCert* cert, const byte* source, word32* srcIdx,
{
int ret = 0;
DECL_ASNGETDATA(dataASN, eccCertKeyASN_Length);
#ifndef WC_ASN_NO_HEAP
byte* publicKey;
#endif
/* Validate parameters. */
if (pubKey == NULL) {
@@ -13477,6 +13512,12 @@ static int StoreEccKey(DecodedCert* cert, const byte* source, word32* srcIdx,
#endif
/* Store public key data length. */
cert->pubKeySize = pubKeyLen;
#ifdef WC_ASN_NO_HEAP
/* No heap: point at pubKey in the input DER, so that buffer must stay
* valid for the DecodedCert's lifetime. */
cert->publicKey = (byte*)pubKey;
cert->pubKeyStored = 0;
#else
/* Must allocated space for key.
* Don't memcpy into constant pointer so use temp. */
publicKey = (byte*)XMALLOC(cert->pubKeySize, cert->heap,
@@ -13491,6 +13532,7 @@ static int StoreEccKey(DecodedCert* cert, const byte* source, word32* srcIdx,
/* Indicate publicKey needs to be freed. */
cert->pubKeyStored = 1;
}
#endif
}
FREE_ASNGETDATA(dataASN, cert->heap);
@@ -14357,7 +14399,7 @@ static const byte rdnChoice[] = {
};
#endif
#ifdef WOLFSSL_IP_ALT_NAME
#if defined(WOLFSSL_IP_ALT_NAME) && !defined(WC_ASN_NO_HEAP)
/* used to set the human readable string for the IP address with a ASN_IP_TYPE
* DNS entry
* return 0 on success
@@ -14426,9 +14468,9 @@ static int GenerateDNSEntryIPString(DNS_entry* entry, void* heap)
return ret;
}
#endif /* WOLFSSL_IP_ALT_NAME */
#endif /* WOLFSSL_IP_ALT_NAME && !WC_ASN_NO_HEAP */
#ifdef WOLFSSL_RID_ALT_NAME
#if defined(WOLFSSL_RID_ALT_NAME) && !defined(WC_ASN_NO_HEAP)
/* used to set the human readable string for the registeredID with an
* ASN_RID_TYPE DNS entry
* return 0 on success
@@ -14525,7 +14567,7 @@ static int GenerateDNSEntryRIDString(DNS_entry* entry, void* heap)
return ret;
}
#endif /* WOLFSSL_RID_ALT_NAME */
#endif /* WOLFSSL_RID_ALT_NAME && !WC_ASN_NO_HEAP */
#ifdef WOLFSSL_ASN_TEMPLATE
@@ -14574,13 +14616,57 @@ static int AddDNSEntryToList(DNS_entry** lst, DNS_entry* entry)
* @return 0 on success.
* @return MEMORY_E when dynamic memory allocation fails.
*/
static int SetDNSEntry(void* heap, const char* str, int strLen,
int type, DNS_entry** entries)
/* No-heap SAN entries come from a caller pool; pass NULL,NULL if none. */
#ifdef WC_ASN_NO_HEAP
#define WC_DNS_POOL(obj) (obj)->altNamePool, &(obj)->altNamePoolUsed
#else
#define WC_DNS_POOL(obj) NULL, NULL
#endif
static int SetDNSEntry(void* heap, DNS_entry* pool, word32* poolUsed,
const char* str, int strLen, int type,
DNS_entry** entries)
{
DNS_entry* dnsEntry;
int ret = 0;
#ifndef WC_ASN_NO_HEAP
char *dnsEntry_name = NULL;
#endif
#ifdef WC_ASN_NO_HEAP
/* No heap: borrow a pool slot; name points into the source DER. */
(void)heap;
#ifdef WOLFSSL_IP_ALT_NAME
/* No-heap path can't parse an ipString/ridString; reject rather than skip. */
if (type == ASN_IP_TYPE) {
return ASN_PARSE_E;
}
#endif
#ifdef WOLFSSL_RID_ALT_NAME
if (type == ASN_RID_TYPE) {
return ASN_PARSE_E;
}
#endif
if ((pool == NULL) || (*poolUsed >= WC_ASN_MAX_ALTNAMES)) {
/* Distinguish pool exhaustion from a real allocation failure. */
WOLFSSL_MSG("No-heap SAN pool exhausted; raise WC_ASN_MAX_ALTNAMES");
ret = MEMORY_E;
dnsEntry = NULL;
}
else {
dnsEntry = &pool[(*poolUsed)++];
XMEMSET(dnsEntry, 0, sizeof(*dnsEntry));
dnsEntry->type = type;
dnsEntry->len = strLen;
dnsEntry->name = (char*)str; /* points into the source DER */
dnsEntry->nameStored = 0;
}
if (ret == 0) {
ret = AddDNSEntryToList(entries, dnsEntry);
}
#else
(void)pool;
(void)poolUsed;
/* TODO: consider one malloc. */
/* Allocate DNS Entry object. */
dnsEntry = AltNameNew(heap);
@@ -14625,6 +14711,7 @@ static int SetDNSEntry(void* heap, const char* str, int strLen,
XFREE(dnsEntry_name, heap, DYNAMIC_TYPE_ALTNAME);
XFREE(dnsEntry, heap, DYNAMIC_TYPE_ALTNAME);
}
#endif
return ret;
}
@@ -14665,7 +14752,7 @@ int wc_SetDNSEntry(void* heap, const char* str, int strLen, int type,
return BAD_FUNC_ARG;
}
return SetDNSEntry(heap, str, strLen, type, entries);
return SetDNSEntry(heap, NULL, NULL, str, strLen, type, entries);
}
#endif /* WOLFSSL_CERT_GEN && WOLFSSL_ALT_NAMES */
#endif
@@ -19147,7 +19234,8 @@ static int DecodeOtherHelper(ASNGetData* dataASN, DecodedCert* cert, int oid)
}
if (ret == 0) {
ret = SetDNSEntry(cert->heap, buf, (int)bufLen, ASN_OTHER_TYPE, &entry);
ret = SetDNSEntry(cert->heap, WC_DNS_POOL(cert), buf, (int)bufLen,
ASN_OTHER_TYPE, &entry);
if (ret == 0) {
#ifdef WOLFSSL_FPKI
entry->oidSum = oid;
@@ -19209,8 +19297,8 @@ static int DecodeOtherName(DecodedCert* cert, const byte* input,
break;
default:
WOLFSSL_MSG("\tadding unsupported OID");
ret = SetDNSEntry(cert->heap, name, len, ASN_OTHER_TYPE,
&cert->altNames);
ret = SetDNSEntry(cert->heap, WC_DNS_POOL(cert), name, len,
ASN_OTHER_TYPE, &cert->altNames);
break;
}
}
@@ -19248,8 +19336,9 @@ static int DecodeGeneralName(const byte* input, word32* inOutIdx, byte tag,
* reference hostname. The result is DOMAIN_NAME_MISMATCH at verification
* time rather than ASN_PARSE_E at parse time. */
if (tag == (ASN_CONTEXT_SPECIFIC | ASN_DNS_TYPE)) {
ret = SetDNSEntry(cert->heap, (const char*)(input + idx), len,
ASN_DNS_TYPE, &cert->altNames);
ret = SetDNSEntry(cert->heap, WC_DNS_POOL(cert),
(const char*)(input + idx), len, ASN_DNS_TYPE,
&cert->altNames);
if (ret == 0) {
idx += (word32)len;
}
@@ -19267,16 +19356,18 @@ static int DecodeGeneralName(const byte* input, word32* inOutIdx, byte tag,
return ASN_PARSE_E;
}
ret = SetDNSEntry(cert->heap, (const char*)(input + idxDir), strLen,
ASN_DIR_TYPE, &cert->altDirNames);
ret = SetDNSEntry(cert->heap, WC_DNS_POOL(cert),
(const char*)(input + idxDir), strLen, ASN_DIR_TYPE,
&cert->altDirNames);
if (ret == 0) {
idx += (word32)len;
}
}
/* GeneralName choice: rfc822Name */
else if (tag == (ASN_CONTEXT_SPECIFIC | ASN_RFC822_TYPE)) {
ret = SetDNSEntry(cert->heap, (const char*)(input + idx), len,
ASN_RFC822_TYPE, &cert->altEmailNames);
ret = SetDNSEntry(cert->heap, WC_DNS_POOL(cert),
(const char*)(input + idx), len, ASN_RFC822_TYPE,
&cert->altEmailNames);
if (ret == 0) {
idx += (word32)len;
}
@@ -19322,8 +19413,9 @@ static int DecodeGeneralName(const byte* input, word32* inOutIdx, byte tag,
}
#endif
ret = SetDNSEntry(cert->heap, (const char*)(input + idx), len,
ASN_URI_TYPE, &cert->altNames);
ret = SetDNSEntry(cert->heap, WC_DNS_POOL(cert),
(const char*)(input + idx), len, ASN_URI_TYPE,
&cert->altNames);
if (ret == 0) {
idx += (word32)len;
}
@@ -19355,8 +19447,9 @@ static int DecodeGeneralName(const byte* input, word32* inOutIdx, byte tag,
* ASN_IP_TYPE case under WOLFSSL_GEN_IPADD in src/x509.c).
*/
else if (tag == (ASN_CONTEXT_SPECIFIC | ASN_IP_TYPE)) {
ret = SetDNSEntry(cert->heap, (const char*)(input + idx), len,
ASN_IP_TYPE, &cert->altNames);
ret = SetDNSEntry(cert->heap, WC_DNS_POOL(cert),
(const char*)(input + idx), len, ASN_IP_TYPE,
&cert->altNames);
if (ret == 0) {
idx += (word32)len;
}
@@ -19387,8 +19480,9 @@ static int DecodeGeneralName(const byte* input, word32* inOutIdx, byte tag,
* when ridString is not generated, instead of failing the
* whole print operation. */
else if (tag == (ASN_CONTEXT_SPECIFIC | ASN_RID_TYPE)) {
ret = SetDNSEntry(cert->heap, (const char*)(input + idx), len,
ASN_RID_TYPE, &cert->altNames);
ret = SetDNSEntry(cert->heap, WC_DNS_POOL(cert),
(const char*)(input + idx), len, ASN_RID_TYPE,
&cert->altNames);
if (ret == 0) {
idx += (word32)len;
}
@@ -19403,8 +19497,9 @@ static int DecodeGeneralName(const byte* input, word32* inOutIdx, byte tag,
* the public altNames view (used by OpenSSL-compat APIs) reflects
* exactly what the SAN extension carries. */
else if (tag == (ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED | ASN_OTHER_TYPE)) {
ret = SetDNSEntry(cert->heap, (const char*)(input + idx), len,
ASN_OTHER_TYPE, &cert->altOtherNamesRaw);
ret = SetDNSEntry(cert->heap, WC_DNS_POOL(cert),
(const char*)(input + idx), len, ASN_OTHER_TYPE,
&cert->altOtherNamesRaw);
if (ret != 0) {
return ret;
}
@@ -24372,6 +24467,7 @@ int FillSigner(Signer* signer, DecodedCert* cert, int type, DerBuffer *der)
(void)der;
#endif
signer->keyOID = cert->keyOID;
/* pubKeyStored stays 0 under WC_ASN_NO_HEAP (signer uses heap). */
if (cert->pubKeyStored) {
signer->publicKey = cert->publicKey;
signer->pubKeySize = cert->pubKeySize;
@@ -39002,8 +39098,8 @@ static int DecodeAcertGeneralName(const byte* input, word32* inOutIdx,
/* GeneralName choice: dnsName */
if (tag == (ASN_CONTEXT_SPECIFIC | ASN_DNS_TYPE)) {
ret = SetDNSEntry(acert->heap, (const char*)(input + idx), len,
ASN_DNS_TYPE, entries);
ret = SetDNSEntry(acert->heap, WC_DNS_POOL(acert),
(const char*)(input + idx), len, ASN_DNS_TYPE, entries);
if (ret == 0) {
idx += (word32)len;
}
@@ -39021,16 +39117,16 @@ static int DecodeAcertGeneralName(const byte* input, word32* inOutIdx,
return ASN_PARSE_E;
}
ret = SetDNSEntry(acert->heap, (const char*)(input + idxDir), strLen,
ASN_DIR_TYPE, entries);
ret = SetDNSEntry(acert->heap, WC_DNS_POOL(acert),
(const char*)(input + idxDir), strLen, ASN_DIR_TYPE, entries);
if (ret == 0) {
idx += (word32)len;
}
}
/* GeneralName choice: rfc822Name */
else if (tag == (ASN_CONTEXT_SPECIFIC | ASN_RFC822_TYPE)) {
ret = SetDNSEntry(acert->heap, (const char*)(input + idx), len,
ASN_RFC822_TYPE, entries);
ret = SetDNSEntry(acert->heap, WC_DNS_POOL(acert),
(const char*)(input + idx), len, ASN_RFC822_TYPE, entries);
if (ret == 0) {
idx += (word32)len;
}
@@ -39076,8 +39172,8 @@ static int DecodeAcertGeneralName(const byte* input, word32* inOutIdx,
}
#endif
ret = SetDNSEntry(acert->heap, (const char*)(input + idx), len,
ASN_URI_TYPE, entries);
ret = SetDNSEntry(acert->heap, WC_DNS_POOL(acert),
(const char*)(input + idx), len, ASN_URI_TYPE, entries);
if (ret == 0) {
idx += (word32)len;
}
@@ -39094,8 +39190,8 @@ static int DecodeAcertGeneralName(const byte* input, word32* inOutIdx,
* IP-SAN compat layer). If iPAddress name-constraint enforcement is
* ever extended to attribute certificates, this gate must drop. */
else if (tag == (ASN_CONTEXT_SPECIFIC | ASN_IP_TYPE)) {
ret = SetDNSEntry(acert->heap, (const char*)(input + idx), len,
ASN_IP_TYPE, entries);
ret = SetDNSEntry(acert->heap, WC_DNS_POOL(acert),
(const char*)(input + idx), len, ASN_IP_TYPE, entries);
if (ret == 0) {
idx += (word32)len;
}
@@ -39105,8 +39201,8 @@ static int DecodeAcertGeneralName(const byte* input, word32* inOutIdx,
#ifdef OPENSSL_ALL
/* GeneralName choice: registeredID */
else if (tag == (ASN_CONTEXT_SPECIFIC | ASN_RID_TYPE)) {
ret = SetDNSEntry(acert->heap, (const char*)(input + idx), len,
ASN_RID_TYPE, entries);
ret = SetDNSEntry(acert->heap, WC_DNS_POOL(acert),
(const char*)(input + idx), len, ASN_RID_TYPE, entries);
if (ret == 0) {
idx += (word32)len;
}
+91
View File
@@ -1040,6 +1040,10 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t scrypt_test(void);
WOLFSSL_TEST_SUBROUTINE wc_test_ret_t cert_test(void);
static wc_test_ret_t fill_signer_twice_test(void);
#endif
#if defined(WOLFSSL_TEST_CERT) && defined(USE_CERT_BUFFERS_2048) && \
!defined(NO_RSA)
static wc_test_ret_t cert_no_malloc_test(void);
#endif
#if defined(WOLFSSL_CERT_EXT) && defined(WOLFSSL_TEST_CERT) && \
!defined(NO_FILESYSTEM) && !defined(NO_RSA) && defined(WOLFSSL_GEN_CERT)
WOLFSSL_TEST_SUBROUTINE wc_test_ret_t certext_test(void);
@@ -3098,6 +3102,14 @@ options: [-s max_relative_stack_bytes] [-m max_relative_heap_memory_bytes]\n\
TEST_PASS("FILL SIGNER test passed!\n");
#endif
#if defined(WOLFSSL_TEST_CERT) && defined(USE_CERT_BUFFERS_2048) && \
!defined(NO_RSA)
if ( (ret = cert_no_malloc_test()) != 0)
TEST_FAIL("CERT NOMALLOC test failed!\n", ret);
else
TEST_PASS("CERT NOMALLOC test passed!\n");
#endif
#if defined(WOLFSSL_CERT_EXT) && defined(WOLFSSL_TEST_CERT) && \
!defined(NO_FILESYSTEM) && !defined(NO_RSA) && defined(WOLFSSL_GEN_CERT)
if ( (ret = certext_test()) != 0)
@@ -26387,6 +26399,85 @@ done:
}
#endif /* WOLFSSL_TEST_CERT */
#if defined(WOLFSSL_TEST_CERT) && defined(USE_CERT_BUFFERS_2048) && \
!defined(NO_RSA)
/* Heap/file-free parse from a const DER buffer; checks in-place refs under
* WC_ASN_NO_HEAP. Kept outside the NO_FILESYSTEM cert block so it runs in real
* no-malloc/no-filesystem builds. */
static wc_test_ret_t cert_no_malloc_test(void)
{
DecodedCert cert;
wc_test_ret_t ret;
#if defined(WC_ASN_NO_HEAP) && !defined(WOLFSSL_IP_ALT_NAME)
DNS_entry* dns;
#endif
WOLFSSL_ENTER("cert_no_malloc_test");
#if defined(WC_ASN_NO_HEAP) && defined(WOLFSSL_IP_ALT_NAME)
/* server_cert_der_2048 carries an IP SAN that the no-heap path fail-closes
* (rejection is gated on WOLFSSL_IP_ALT_NAME); confirm it rather than a
* successful parse. */
InitDecodedCert(&cert, server_cert_der_2048, sizeof_server_cert_der_2048,
NULL);
ret = ParseCert(&cert, CERT_TYPE, NO_VERIFY, NULL);
FreeDecodedCert(&cert);
if (ret != WC_NO_ERR_TRACE(ASN_PARSE_E)) {
return WC_TEST_RET_ENC_NC;
}
ret = 0;
#else
InitDecodedCert(&cert, server_cert_der_2048, sizeof_server_cert_der_2048,
NULL);
ret = ParseCert(&cert, CERT_TYPE, NO_VERIFY, NULL);
if ((ret == 0) && ((cert.publicKey == NULL) || (cert.pubKeySize == 0))) {
ret = WC_TEST_RET_ENC_NC;
}
#ifdef WC_ASN_NO_HEAP
if ((ret == 0) && ((cert.pubKeyStored != 0) ||
((wc_ptr_t)cert.publicKey < (wc_ptr_t)cert.source) ||
((wc_ptr_t)cert.publicKey >=
(wc_ptr_t)cert.source + cert.maxIdx))) {
ret = WC_TEST_RET_ENC_NC;
}
/* Every SAN node must reference the source DER in place, not a heap copy. */
for (dns = cert.altNames; (ret == 0) && (dns != NULL); dns = dns->next) {
if ((dns->entryStored != 0) ||
((wc_ptr_t)dns->name < (wc_ptr_t)cert.source) ||
((wc_ptr_t)dns->name >= (wc_ptr_t)cert.source + cert.maxIdx)) {
ret = WC_TEST_RET_ENC_NC;
}
}
#endif
FreeDecodedCert(&cert);
#endif
#if defined(HAVE_ECC) && defined(USE_CERT_BUFFERS_256)
/* ECC leaf with no IP/RID SAN: exercises StoreEccKey in-place key ref. */
if (ret == 0) {
InitDecodedCert(&cert, ca_ecc_cert_der_256,
sizeof_ca_ecc_cert_der_256, NULL);
ret = ParseCert(&cert, CERT_TYPE, NO_VERIFY, NULL);
if ((ret == 0) &&
((cert.publicKey == NULL) || (cert.pubKeySize == 0))) {
ret = WC_TEST_RET_ENC_NC;
}
#ifdef WC_ASN_NO_HEAP
if ((ret == 0) && ((cert.pubKeyStored != 0) ||
((wc_ptr_t)cert.publicKey < (wc_ptr_t)cert.source) ||
((wc_ptr_t)cert.publicKey >=
(wc_ptr_t)cert.source + cert.maxIdx))) {
ret = WC_TEST_RET_ENC_NC;
}
#endif
FreeDecodedCert(&cert);
}
#endif
return ret;
}
#endif /* WOLFSSL_TEST_CERT && USE_CERT_BUFFERS_2048 && !NO_RSA */
#if !defined(NO_ASN_TIME) && !defined(NO_RSA) && defined(WOLFSSL_TEST_CERT) && \
!defined(NO_FILESYSTEM)
/* Test that FillSigner clears pubKeyStored/subjectCNStored after transferring
+30 -1
View File
@@ -1502,6 +1502,19 @@ enum KeyIdType {
#define WOLFSSL_IP6_ADDR_LEN 16
#endif /* OPENSSL_ALL || WOLFSSL_IP_ALT_NAME */
/* No allocator: reference key/alt-name data in the source DER, not copies. */
#if defined(WOLFSSL_NO_MALLOC) && defined(NO_WOLFSSL_MEMORY) && \
!defined(XMALLOC_USER) && !defined(WOLFSSL_STATIC_MEMORY)
#define WC_ASN_NO_HEAP
#endif
#ifdef WC_ASN_NO_HEAP
#ifndef WC_ASN_MAX_ALTNAMES
/* Total no-heap SAN pool slots across all lists; excess is rejected. */
#define WC_ASN_MAX_ALTNAMES 8
#endif
#endif
typedef struct DNS_entry DNS_entry;
struct DNS_entry {
@@ -1509,7 +1522,8 @@ struct DNS_entry {
int type; /* i.e. ASN_DNS_TYPE */
int len; /* actual DNS len */
const char*
name; /* actual DNS name */
name; /* actual DNS name; under WC_ASN_NO_HEAP this points into
* the source DER and is NOT NUL-terminated - use len */
int nameStored;
#ifdef WOLFSSL_IP_ALT_NAME
char* ipString; /* human readable form of IP address */
@@ -1523,6 +1537,9 @@ struct DNS_entry {
#ifdef WOLFSSL_FPKI
int oidSum; /* provide oid sum for verification */
#endif
#ifdef WC_ASN_NO_HEAP
WC_BITFIELD entryStored:1; /* 1 = heap node to free; 0 = no-heap pool node */
#endif
};
#ifdef WOLFSSL_FPKI
@@ -2231,6 +2248,12 @@ struct DecodedCert {
/* Appended to preserve the offsets of existing members. */
word32 extExtKeyUsageOidCnt; /* Number of EKU KeyPurposeIds seen,
* recognized or not */
#ifdef WC_ASN_NO_HEAP
/* No-heap SAN pool; entries chain through altNames into the source DER.
* Adds ~WC_ASN_MAX_ALTNAMES * sizeof(DNS_entry) of stack per parse. */
DNS_entry altNamePool[WC_ASN_MAX_ALTNAMES];
word32 altNamePoolUsed;
#endif
};
#if defined(WOLFSSL_SM2) && defined(WOLFSSL_SM3)
@@ -3278,6 +3301,12 @@ struct DecodedAcert {
const byte * rawAttr; /* Not owned, points into raw acert. */
word32 rawAttrLen;
SignatureCtx sigCtx;
#ifdef WC_ASN_NO_HEAP
/* No-heap alt-name pool, used like DecodedCert.altNamePool.
* Adds ~WC_ASN_MAX_ALTNAMES * sizeof(DNS_entry) of stack per parse. */
DNS_entry altNamePool[WC_ASN_MAX_ALTNAMES];
word32 altNamePoolUsed;
#endif
};
typedef struct DecodedAcert DecodedAcert;