Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
165 changes: 91 additions & 74 deletions src/x509.c
Original file line number Diff line number Diff line change
Expand Up @@ -6228,6 +6228,44 @@ int wolfSSL_NAME_CONSTRAINTS_check_name(WOLFSSL_NAME_CONSTRAINTS* nc,
}
#endif /* !IGNORE_NAME_CONSTRAINTS */

#ifndef NO_BIO
static int wolfssl_x509_name_esc_value(const char* in, int inSz,
unsigned long flags, char* out);

/* Write pfx then val to bio with control characters escaped.
*
* Returns WOLFSSL_SUCCESS on success, WOLFSSL_FAILURE on failure.
*/
static int X509PrintEscStr(WOLFSSL_BIO* bio, const char* pfx,
const char* val, int valSz)
{
char buf[96];
int ret = WOLFSSL_SUCCESS;
int pfxSz = (int)XSTRLEN(pfx);
int inSz = 0;
int escSz;
int i;

if ((pfxSz > 0) && (wolfSSL_BIO_write(bio, pfx, pfxSz) != pfxSz)) {
ret = WOLFSSL_FAILURE;
}
/* ESC_CTRL ignores position and at most triples a byte, so chunk it. */
for (i = 0; (ret == WOLFSSL_SUCCESS) && (i < valSz); i += inSz) {
inSz = valSz - i;
if (inSz > (int)sizeof(buf) / 3) {
inSz = (int)sizeof(buf) / 3;
}
escSz = wolfssl_x509_name_esc_value(val + i, inSz,
WOLFSSL_ASN1_STRFLGS_ESC_CTRL, buf);
if (wolfSSL_BIO_write(bio, buf, escSz) != escSz) {
ret = WOLFSSL_FAILURE;
}
}

return ret;
}
#endif /* !NO_BIO */

#if defined(OPENSSL_ALL) && !defined(NO_BIO)
/* Outputs name string of the given WOLFSSL_GENERAL_NAME_OBJECT to WOLFSSL_BIO.
* Can handle following GENERAL_NAME_OBJECT types:
Expand Down Expand Up @@ -6272,18 +6310,16 @@ int wolfSSL_GENERAL_NAME_print(WOLFSSL_BIO* out, WOLFSSL_GENERAL_NAME* gen)
break;

case GEN_EMAIL:
ret = wolfSSL_BIO_printf(out, "email:");
ret = (ret > 0) ? WOLFSSL_SUCCESS : WOLFSSL_FAILURE;
if (ret == WOLFSSL_SUCCESS) {
ret = wolfSSL_ASN1_STRING_print(out, gen->d.rfc822Name);
if (gen->d.rfc822Name != NULL) {
ret = X509PrintEscStr(out, "email:", gen->d.rfc822Name->data,
gen->d.rfc822Name->length);
}
break;

case GEN_DNS:
ret = wolfSSL_BIO_printf(out, "DNS:");
ret = (ret > 0) ? WOLFSSL_SUCCESS : WOLFSSL_FAILURE;
if (ret == WOLFSSL_SUCCESS) {
ret = wolfSSL_ASN1_STRING_print(out, gen->d.dNSName);
if (gen->d.dNSName != NULL) {
ret = X509PrintEscStr(out, "DNS:", gen->d.dNSName->data,
gen->d.dNSName->length);
}
break;

Expand All @@ -6307,11 +6343,10 @@ int wolfSSL_GENERAL_NAME_print(WOLFSSL_BIO* out, WOLFSSL_GENERAL_NAME* gen)
break;

case GEN_URI:
ret = wolfSSL_BIO_printf(out, "URI:");
ret = (ret > 0) ? WOLFSSL_SUCCESS : WOLFSSL_FAILURE;
if (ret == WOLFSSL_SUCCESS) {
ret = wolfSSL_ASN1_STRING_print(out,
gen->d.uniformResourceIdentifier);
if (gen->d.uniformResourceIdentifier != NULL) {
ret = X509PrintEscStr(out, "URI:",
gen->d.uniformResourceIdentifier->data,
gen->d.uniformResourceIdentifier->length);
}
break;

Expand Down Expand Up @@ -7252,32 +7287,29 @@ static struct acert_dir_print_t acert_dir_print[ACERT_NUM_DIR_TAGS] =
{ "CN=", {0x55, 0x04, ASN_COMMON_NAME} },
};

/* Print an entry of ASN_DIR_TYPE into dst of length max_len.
/* Print an entry of ASN_DIR_TYPE to bio.
*
* Returns total_len of str on success.
* Returns < 0 on failure.
* Returns WOLFSSL_SUCCESS on success.
* Returns WOLFSSL_FAILURE on failure.
* */
static int X509PrintDirType(char * dst, int max_len, const DNS_entry * entry)
static int X509PrintDirType(WOLFSSL_BIO* bio, const DNS_entry * entry)
{
word32 k = 0;
word32 i = 0;
const char * src = entry->name;
word32 src_len = 0;
int total_len = 0;
int bytes_left = max_len;
int fld_len = 0;
int ret = WOLFSSL_SUCCESS;
int match_found = 0;

XMEMSET(dst, 0, max_len);

/* The entry holds raw DER which may contain zero bytes, and under
* WC_ASN_NO_HEAP it is not NUL terminated, so use the stored length. */
if (entry->len > 0) {
src_len = (word32)entry->len;
}

/* loop over printable DIR tags. */
for (k = 0; k < ACERT_NUM_DIR_TAGS; ++k) {
for (k = 0; (ret == WOLFSSL_SUCCESS) && (k < ACERT_NUM_DIR_TAGS); ++k) {
const char * pfx = acert_dir_print[k].pfx;
const byte * tag = acert_dir_print[k].tag;
byte asn_tag;
Expand All @@ -7289,19 +7321,6 @@ static int X509PrintDirType(char * dst, int max_len, const DNS_entry * entry)
* underflowing the bound. */
for (i = 0; i + 5 <= src_len; ++i) {
if (XMEMCMP(tag, &src[i], 3) == 0) {
if (bytes_left < 5) {
/* Not enough space left for name oid + tag + len. */
break;
}

if (match_found) {
/* append a {',', ' '} before doing anything else. */
*dst++ = ',';
*dst++ = ' ';
total_len += 2;
bytes_left -= 2;
}

i += 3;

/* Get the ASN Tag. */
Expand All @@ -7324,35 +7343,32 @@ static int X509PrintDirType(char * dst, int max_len, const DNS_entry * entry)
break;
}

/* Make sure we have space to fit it. */
if ((int) XSTRLEN(pfx) > bytes_left) {
/* Not enough space left. */
break;
if (match_found && (wolfSSL_BIO_puts(bio, ", ") <= 0)) {
ret = WOLFSSL_FAILURE;
}

/* Copy it in, decrement available space. */
XSTRNCPY(dst, pfx, bytes_left);
dst += XSTRLEN(pfx);
total_len += (int)XSTRLEN(pfx);
bytes_left -= (int)XSTRLEN(pfx);

if (fld_len > bytes_left) {
/* Not enough space left. */
if (ret == WOLFSSL_SUCCESS) {
ret = X509PrintEscStr(bio, pfx, &src[i], fld_len);
}
if (ret != WOLFSSL_SUCCESS) {
break;
}

XMEMCPY(dst, &src[i], fld_len);
i += fld_len;
dst += fld_len;
total_len += fld_len;
bytes_left -= fld_len;

match_found = 1;
}
}
}

return total_len;
if ((ret == WOLFSSL_SUCCESS) && !match_found) {
/* Nothing in the encoding was printable. Emit a placeholder, as the
* other unsupported entry types do, rather than failing the print of
* the whole certificate. */
if (wolfSSL_BIO_puts(bio, "DirName:<unprintable>") <= 0) {
ret = WOLFSSL_FAILURE;
}
}

return ret;
}
static int X509_print_name_entry(WOLFSSL_BIO* bio,
const DNS_entry* entry, int indent)
Expand Down Expand Up @@ -7384,8 +7400,10 @@ static int X509_print_name_entry(WOLFSSL_BIO* bio,
}
}

/* Escaped values go straight to bio, the rest through scratch. */
len = 0;
if (entry->type == ASN_DNS_TYPE) {
len = XSNPRINTF(scratch, MAX_WIDTH, "DNS:%s", entry->name);
ret = X509PrintEscStr(bio, "DNS:", entry->name, entry->len);
}
#if defined(OPENSSL_ALL) || defined(WOLFSSL_IP_ALT_NAME)
else if (entry->type == ASN_IP_TYPE) {
Expand All @@ -7402,21 +7420,13 @@ static int X509_print_name_entry(WOLFSSL_BIO* bio,
}
#endif /* OPENSSL_ALL || WOLFSSL_IP_ALT_NAME */
else if (entry->type == ASN_RFC822_TYPE) {
len = XSNPRINTF(scratch, MAX_WIDTH, "email:%s",
entry->name);
ret = X509PrintEscStr(bio, "email:", entry->name, entry->len);
}
else if (entry->type == ASN_DIR_TYPE) {
len = X509PrintDirType(scratch, MAX_WIDTH, entry);
if (len == 0) {
/* Nothing in the encoding was printable. Emit a placeholder,
* as the other unsupported entry types do, rather than
* failing the print of the whole certificate. */
len = XSNPRINTF(scratch, MAX_WIDTH, "DirName:<unprintable>");
}
ret = X509PrintDirType(bio, entry);
}
else if (entry->type == ASN_URI_TYPE) {
len = XSNPRINTF(scratch, MAX_WIDTH, "URI:%s",
entry->name);
ret = X509PrintEscStr(bio, "URI:", entry->name, entry->len);
}
#ifdef WOLFSSL_RID_ALT_NAME
else if (entry->type == ASN_RID_TYPE) {
Expand All @@ -7441,12 +7451,11 @@ static int X509_print_name_entry(WOLFSSL_BIO* bio,
ret = WOLFSSL_FAILURE;
break;
}
if (len >= MAX_WIDTH) {
if ((ret != WOLFSSL_SUCCESS) || (len < 0) || (len >= MAX_WIDTH)) {
ret = WOLFSSL_FAILURE;
break;
}
if (wolfSSL_BIO_write(bio, scratch, (int)XSTRLEN(scratch))
<= 0) {
if ((len > 0) && (wolfSSL_BIO_write(bio, scratch, len) <= 0)) {
ret = WOLFSSL_FAILURE;
break;
}
Expand Down Expand Up @@ -8256,7 +8265,8 @@ static int X509PrintName(WOLFSSL_BIO* bio, WOLFSSL_X509_NAME* name,
if (wolfSSL_BIO_write(bio, scratch, scratchLen) <= 0) {
return WOLFSSL_FAILURE;
}
if (wolfSSL_X509_NAME_print_ex(bio, name, 1, 0) <= 0) {
if (wolfSSL_X509_NAME_print_ex(bio, name, 1,
WOLFSSL_ASN1_STRFLGS_ESC_CTRL) <= 0) {
return WOLFSSL_FAILURE;
}
if (wolfSSL_BIO_write(bio, "\n", (int)XSTRLEN("\n")) <= 0) {
Expand Down Expand Up @@ -8342,14 +8352,17 @@ static int X509PrintReqAttributes(WOLFSSL_BIO* bio, WOLFSSL_X509* x509,
WOLFSSL_MSG("No REQ attribute found when expected");
return WOLFSSL_FAILURE;
}
if ((scratchLen = XSNPRINTF(scratch, MAX_WIDTH,
"%*s%s%*s:%s\n", indent+4, "",
lName, (NAME_SZ/4)-lNameSz, "", data))
if (XSNPRINTF(scratch, MAX_WIDTH,
"%*s%s%*s:", indent+4, "",
lName, (NAME_SZ/4)-lNameSz, "")
>= MAX_WIDTH)
{
return WOLFSSL_FAILURE;
}
if (wolfSSL_BIO_write(bio, scratch, scratchLen) <= 0) {
if ((X509PrintEscStr(bio, scratch, (const char*)data,
wolfSSL_ASN1_STRING_length(
attr->value->value.asn1_string)) != WOLFSSL_SUCCESS) ||
(wolfSSL_BIO_write(bio, "\n", 1) <= 0)) {
WOLFSSL_MSG("Error writing REQ attribute");
return WOLFSSL_FAILURE;
}
Expand Down Expand Up @@ -11159,6 +11172,10 @@ int wolfSSL_X509_VERIFY_PARAM_inherit(WOLFSSL_X509_VERIFY_PARAM *to,
if (!(ret = wolfSSL_X509_VERIFY_PARAM_set1_host(to, from->hostName,
(unsigned int)XSTRLEN(from->hostName))))
return ret;
}
/* host flags */
if (isOverWrite ||
(from->hostFlags != 0 && (to->hostFlags == 0 || isDefault))) {
to->hostFlags = from->hostFlags;
}
/* ip ascii */
Expand Down
Loading
Loading