From 5dcffa6b4060eee79b644b672aebadb8c3964695 Mon Sep 17 00:00:00 2001 From: John Safranek Date: Thu, 9 Jan 2020 15:34:45 -0800 Subject: [PATCH] Maintenance: X509 1. Fix for issue #2724. When making a certificate out of an X.509 structure, the subject alt names weren't getting correctly copied. 2. Added a function to flatten the DNS_entries into a sequence of GeneralNames. 3. Put the proper certificate extension wrapping around the flattened general names. --- src/ssl.c | 19 +--------- wolfcrypt/src/asn.c | 82 ++++++++++++++++++++++++++++++++++++++--- wolfssl/wolfcrypt/asn.h | 1 + 3 files changed, 79 insertions(+), 23 deletions(-) diff --git a/src/ssl.c b/src/ssl.c index 99da25cd0..882c05bc0 100644 --- a/src/ssl.c +++ b/src/ssl.c @@ -37084,24 +37084,9 @@ void* wolfSSL_GetDhAgreeCtx(WOLFSSL* ssl) cert->afterDateSz = 0; } - /* copy over alt names */ - { - int idx = 0; - DNS_entry* dns = x509->altNames; + cert->altNamesSz = FlattenAltNames(cert->altNames, + sizeof(cert->altNames), x509->altNames); - while (dns != NULL) { - int sz = (int)XSTRLEN(dns->name); - - if (sz < 0 || sz + idx > CTC_MAX_ALT_SIZE) { - WOLFSSL_MSG("Issue with copying over alt names"); - return WOLFSSL_FAILURE; - } - XMEMCPY(cert->altNames, dns->name, sz); - idx += sz; - dns = dns->next; - } - cert->altNamesSz = idx; - } #endif /* WOLFSSL_ALT_NAMES */ cert->sigType = wolfSSL_X509_get_signature_type(x509); diff --git a/wolfcrypt/src/asn.c b/wolfcrypt/src/asn.c index 44887763f..9923c700b 100644 --- a/wolfcrypt/src/asn.c +++ b/wolfcrypt/src/asn.c @@ -12155,21 +12155,91 @@ static int SetCertificatePolicies(byte *output, } #endif /* WOLFSSL_CERT_EXT */ + #ifdef WOLFSSL_ALT_NAMES + /* encode Alternative Names, return total bytes written */ -static int SetAltNames(byte *out, word32 outSz, byte *input, word32 length) +static int SetAltNames(byte *output, word32 outSz, + const byte *input, word32 length) { - if (out == NULL || input == NULL) + byte san_len[1 + MAX_LENGTH_SZ]; + int idx = 0, san_lenSz; + static const byte san_oid[] = { 0x06, 0x03, 0x55, 0x1d, 0x11 }; + + if (output == NULL || input == NULL) return BAD_FUNC_ARG; if (outSz < length) return BUFFER_E; - /* Alternative Names come from certificate or computed by - * external function, so already encoded. Just copy value */ - XMEMCPY(out, input, length); - return length; + /* Octet String header */ + san_lenSz = SetOctetString(length, san_len); + + if (outSz < MAX_SEQ_SZ) + return BUFFER_E; + + idx = SetSequence(length + sizeof(san_oid) + san_lenSz, output); + + if ((length + sizeof(san_oid) + san_lenSz) > outSz) + return BUFFER_E; + + /* put oid */ + XMEMCPY(output+idx, san_oid, sizeof(san_oid)); + idx += sizeof(san_oid); + + /* put octet header */ + XMEMCPY(output+idx, san_len, san_lenSz); + idx += san_lenSz; + + /* put value */ + XMEMCPY(output+idx, input, length); + idx += length; + + return idx; } + + +#ifdef WOLFSSL_CERT_GEN + +int FlattenAltNames(byte* output, word32 outputSz, const DNS_entry* names) +{ + word32 idx; + const DNS_entry* curName; + word32 namesSz = 0; + + if (output == NULL) + return BAD_FUNC_ARG; + + if (names == NULL) + return 0; + + curName = names; + do { + namesSz += curName->len + 2 + + ((curName->len < ASN_LONG_LENGTH) ? 0 + : BytePrecision(curName->len)); + curName = curName->next; + } while (curName != NULL); + + if (outputSz < MAX_SEQ_SZ + namesSz) + return BUFFER_E; + + idx = SetSequence(namesSz, output); + + curName = names; + do { + output[idx++] = ASN_CONTEXT_SPECIFIC | curName->type; + idx += SetLength(curName->len, output + idx); + XMEMCPY(output + idx, curName->name, curName->len); + idx += curName->len; + curName = curName->next; + } while (curName != NULL); + + return idx; +} + +#endif /* WOLFSSL_CERT_GEN */ + #endif /* WOLFSL_ALT_NAMES */ /* Encodes one attribute of the name (issuer/subject) diff --git a/wolfssl/wolfcrypt/asn.h b/wolfssl/wolfcrypt/asn.h index 95d1c9429..72ac9e108 100644 --- a/wolfssl/wolfcrypt/asn.h +++ b/wolfssl/wolfcrypt/asn.h @@ -1161,6 +1161,7 @@ WOLFSSL_LOCAL int GetNameHash(const byte* source, word32* idx, byte* hash, int maxIdx); WOLFSSL_LOCAL int wc_CheckPrivateKey(byte* key, word32 keySz, DecodedCert* der); WOLFSSL_LOCAL int StoreDHparams(byte* out, word32* outLen, mp_int* p, mp_int* g); +WOLFSSL_LOCAL int FlattenAltNames( byte*, word32, const DNS_entry*); #ifdef HAVE_ECC /* ASN sig helpers */