/*
- * Copyright 2003-2021 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2003-2023 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
#include "internal/cryptlib.h"
#include "internal/numbers.h"
+#include "internal/safe_math.h"
#include <stdio.h>
#include "crypto/asn1.h"
#include <openssl/asn1t.h>
#include "crypto/punycode.h"
#include "ext_dat.h"
+OSSL_SAFE_MATH_SIGNED(int, int)
+
static void *v2i_NAME_CONSTRAINTS(const X509V3_EXT_METHOD *method,
X509V3_CTX *ctx,
STACK_OF(CONF_VALUE) *nval);
static int print_nc_ipadd(BIO *bp, ASN1_OCTET_STRING *ip);
static int nc_match(GENERAL_NAME *gen, NAME_CONSTRAINTS *nc);
-static int nc_match_single(GENERAL_NAME *sub, GENERAL_NAME *gen);
+static int nc_match_single(int effective_type, GENERAL_NAME *sub,
+ GENERAL_NAME *gen);
static int nc_dn(const X509_NAME *sub, const X509_NAME *nm);
static int nc_dns(ASN1_IA5STRING *sub, ASN1_IA5STRING *dns);
static int nc_email(ASN1_IA5STRING *sub, ASN1_IA5STRING *eml);
GENERAL_SUBTREE *sub = NULL;
ncons = NAME_CONSTRAINTS_new();
- if (ncons == NULL)
- goto memerr;
+ if (ncons == NULL) {
+ ERR_raise(ERR_LIB_X509V3, ERR_R_ASN1_LIB);
+ goto err;
+ }
for (i = 0; i < sk_CONF_VALUE_num(nval); i++) {
val = sk_CONF_VALUE_value(nval, i);
- if (strncmp(val->name, "permitted", 9) == 0 && val->name[9]) {
+ if (HAS_PREFIX(val->name, "permitted") && val->name[9]) {
ptree = &ncons->permittedSubtrees;
tval.name = val->name + 10;
- } else if (strncmp(val->name, "excluded", 8) == 0 && val->name[8]) {
+ } else if (HAS_PREFIX(val->name, "excluded") && val->name[8]) {
ptree = &ncons->excludedSubtrees;
tval.name = val->name + 9;
} else {
}
tval.value = val->value;
sub = GENERAL_SUBTREE_new();
- if (sub == NULL)
- goto memerr;
- if (!v2i_GENERAL_NAME_ex(sub->base, method, ctx, &tval, 1))
+ if (sub == NULL) {
+ ERR_raise(ERR_LIB_X509V3, ERR_R_ASN1_LIB);
+ goto err;
+ }
+ if (!v2i_GENERAL_NAME_ex(sub->base, method, ctx, &tval, 1)) {
+ ERR_raise(ERR_LIB_X509V3, ERR_R_X509V3_LIB);
goto err;
+ }
if (*ptree == NULL)
*ptree = sk_GENERAL_SUBTREE_new_null();
- if (*ptree == NULL || !sk_GENERAL_SUBTREE_push(*ptree, sub))
- goto memerr;
+ if (*ptree == NULL || !sk_GENERAL_SUBTREE_push(*ptree, sub)) {
+ ERR_raise(ERR_LIB_X509V3, ERR_R_CRYPTO_LIB);
+ goto err;
+ }
sub = NULL;
}
return ncons;
- memerr:
- ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE);
err:
NAME_CONSTRAINTS_free(ncons);
GENERAL_SUBTREE_free(sub);
static int add_lengths(int *out, int a, int b)
{
+ int err = 0;
+
/* sk_FOO_num(NULL) returns -1 but is effectively 0 when iterating. */
if (a < 0)
a = 0;
if (b < 0)
b = 0;
- if (a > INT_MAX - b)
- return 0;
- *out = a + b;
- return 1;
+ *out = safe_add_int(a, b, &err);
+ return !err;
}
/*-
ne = X509_NAME_get_entry(nm, i);
cn = X509_NAME_ENTRY_get_data(ne);
- /* Only process attributes that look like host names */
+ /* Only process attributes that look like hostnames */
if ((r = cn2dnsid(cn, &idval, &idlen)) != X509_V_OK)
return r;
if (idlen == 0)
{
GENERAL_SUBTREE *sub;
int i, r, match = 0;
+ int effective_type = gen->type;
+
/*
* We need to compare not gen->type field but an "effective" type because
* the otherName field may contain EAI email address treated specially
* according to RFC 8398, section 6
*/
- int effective_type = ((gen->type == GEN_OTHERNAME) &&
- (OBJ_obj2nid(gen->d.otherName->type_id) ==
- NID_id_on_SmtpUTF8Mailbox)) ? GEN_EMAIL : gen->type;
+ if (effective_type == GEN_OTHERNAME &&
+ (OBJ_obj2nid(gen->d.otherName->type_id) == NID_id_on_SmtpUTF8Mailbox)) {
+ effective_type = GEN_EMAIL;
+ }
/*
* Permitted subtrees: if any subtrees exist of matching the type at
for (i = 0; i < sk_GENERAL_SUBTREE_num(nc->permittedSubtrees); i++) {
sub = sk_GENERAL_SUBTREE_value(nc->permittedSubtrees, i);
- if (effective_type != sub->base->type)
+ if (effective_type != sub->base->type
+ || (effective_type == GEN_OTHERNAME &&
+ OBJ_cmp(gen->d.otherName->type_id,
+ sub->base->d.otherName->type_id) != 0))
continue;
if (!nc_minmax_valid(sub))
return X509_V_ERR_SUBTREE_MINMAX;
continue;
if (match == 0)
match = 1;
- r = nc_match_single(gen, sub->base);
+ r = nc_match_single(effective_type, gen, sub->base);
if (r == X509_V_OK)
match = 2;
else if (r != X509_V_ERR_PERMITTED_VIOLATION)
for (i = 0; i < sk_GENERAL_SUBTREE_num(nc->excludedSubtrees); i++) {
sub = sk_GENERAL_SUBTREE_value(nc->excludedSubtrees, i);
- if (effective_type != sub->base->type)
+ if (effective_type != sub->base->type
+ || (effective_type == GEN_OTHERNAME &&
+ OBJ_cmp(gen->d.otherName->type_id,
+ sub->base->d.otherName->type_id) != 0))
continue;
if (!nc_minmax_valid(sub))
return X509_V_ERR_SUBTREE_MINMAX;
- r = nc_match_single(gen, sub->base);
+ r = nc_match_single(effective_type, gen, sub->base);
if (r == X509_V_OK)
return X509_V_ERR_EXCLUDED_VIOLATION;
else if (r != X509_V_ERR_PERMITTED_VIOLATION)
}
-static int nc_match_single(GENERAL_NAME *gen, GENERAL_NAME *base)
+static int nc_match_single(int effective_type, GENERAL_NAME *gen,
+ GENERAL_NAME *base)
{
switch (gen->type) {
case GEN_OTHERNAME:
- /*
- * We are here only when we have SmtpUTF8 name,
- * so we match the value of othername with base->d.rfc822Name
- */
- return nc_email_eai(gen->d.otherName->value, base->d.rfc822Name);
+ switch (effective_type) {
+ case GEN_EMAIL:
+ /*
+ * We are here only when we have SmtpUTF8 name,
+ * so we match the value of othername with base->d.rfc822Name
+ */
+ return nc_email_eai(gen->d.otherName->value, base->d.rfc822Name);
+
+ default:
+ return X509_V_ERR_UNSUPPORTED_CONSTRAINT_TYPE;
+ }
case GEN_DIRNAME:
return nc_dn(gen->d.directoryName, base->d.directoryName);
const char *emlptr;
const char *emlat;
char ulabel[256];
- size_t size = sizeof(ulabel) - 1;
+ size_t size = sizeof(ulabel);
int ret = X509_V_OK;
size_t emlhostlen;
goto end;
}
- memset(ulabel, 0, sizeof(ulabel));
/* Special case: initial '.' is RHS match */
if (*baseptr == '.') {
ulabel[0] = '.';
- size -= 1;
- if (ossl_a2ulabel(baseptr, ulabel + 1, &size) <= 0) {
+ if (ossl_a2ulabel(baseptr, ulabel + 1, size - 1) <= 0) {
ret = X509_V_ERR_UNSPECIFIED;
goto end;
}
if ((size_t)eml->length > strlen(ulabel)) {
- emlptr += eml->length - (strlen(ulabel));
+ emlptr += eml->length - strlen(ulabel);
/* X509_V_OK */
if (ia5ncasecmp(ulabel, emlptr, strlen(ulabel)) == 0)
goto end;
goto end;
}
- if (ossl_a2ulabel(baseptr, ulabel, &size) <= 0) {
+ if (ossl_a2ulabel(baseptr, ulabel, size) <= 0) {
ret = X509_V_ERR_UNSPECIFIED;
goto end;
}
if (baseat != baseptr) {
if ((baseat - baseptr) != (emlat - emlptr))
return X509_V_ERR_PERMITTED_VIOLATION;
+ if (memchr(baseptr, 0, baseat - baseptr) ||
+ memchr(emlptr, 0, emlat - emlptr))
+ return X509_V_ERR_UNSUPPORTED_NAME_SYNTAX;
/* Case sensitive match of local part */
if (strncmp(baseptr, emlptr, emlat - emlptr))
return X509_V_ERR_PERMITTED_VIOLATION;