diff --git a/crypto/asn1/a_bitstr.c b/crypto/asn1/a_bitstr.c index 1bb58e2ba1..5b97efa043 100644 --- a/crypto/asn1/a_bitstr.c +++ b/crypto/asn1/a_bitstr.c @@ -66,195 +66,200 @@ #include "internal.h" -int ASN1_BIT_STRING_set(ASN1_BIT_STRING *x, const unsigned char *d, int len) -{ - return ASN1_STRING_set(x, d, len); +int ASN1_BIT_STRING_set(ASN1_BIT_STRING *x, const unsigned char *d, int len) { + return ASN1_STRING_set(x, d, len); } int asn1_bit_string_length(const ASN1_BIT_STRING *str, uint8_t *out_padding_bits) { - int len = str->length; - if (str->flags & ASN1_STRING_FLAG_BITS_LEFT) { - // If the string is already empty, it cannot have padding bits. - *out_padding_bits = len == 0 ? 0 : str->flags & 0x07; - return len; - } + int len = str->length; + if (str->flags & ASN1_STRING_FLAG_BITS_LEFT) { + // If the string is already empty, it cannot have padding bits. + *out_padding_bits = len == 0 ? 0 : str->flags & 0x07; + return len; + } - // TODO(https://crbug.com/boringssl/447): If we move this logic to - // |ASN1_BIT_STRING_set_bit|, can we remove this representation? - while (len > 0 && str->data[len - 1] == 0) { - len--; - } - uint8_t padding_bits = 0; - if (len > 0) { - uint8_t last = str->data[len - 1]; - assert(last != 0); - for (; padding_bits < 7; padding_bits++) { - if (last & (1 << padding_bits)) { - break; - } - } + // TODO(https://crbug.com/boringssl/447): If we move this logic to + // |ASN1_BIT_STRING_set_bit|, can we remove this representation? + while (len > 0 && str->data[len - 1] == 0) { + len--; + } + uint8_t padding_bits = 0; + if (len > 0) { + uint8_t last = str->data[len - 1]; + assert(last != 0); + for (; padding_bits < 7; padding_bits++) { + if (last & (1 << padding_bits)) { + break; + } } - *out_padding_bits = padding_bits; - return len; + } + *out_padding_bits = padding_bits; + return len; } int ASN1_BIT_STRING_num_bytes(const ASN1_BIT_STRING *str, size_t *out) { - uint8_t padding_bits; - int len = asn1_bit_string_length(str, &padding_bits); - if (padding_bits != 0) { - return 0; - } - *out = len; - return 1; + uint8_t padding_bits; + int len = asn1_bit_string_length(str, &padding_bits); + if (padding_bits != 0) { + return 0; + } + *out = len; + return 1; } -int i2c_ASN1_BIT_STRING(const ASN1_BIT_STRING *a, unsigned char **pp) -{ - if (a == NULL) { - return 0; - } +int i2c_ASN1_BIT_STRING(const ASN1_BIT_STRING *a, unsigned char **pp) { + if (a == NULL) { + return 0; + } - uint8_t bits; - int len = asn1_bit_string_length(a, &bits); - int ret = 1 + len; - if (pp == NULL) { - return ret; - } + uint8_t bits; + int len = asn1_bit_string_length(a, &bits); + int ret = 1 + len; + if (pp == NULL) { + return ret; + } - uint8_t *p = *pp; - *(p++) = bits; - OPENSSL_memcpy(p, a->data, len); - if (len > 0) { - p[len - 1] &= (0xff << bits); - } - p += len; - *pp = p; - return (ret); + uint8_t *p = *pp; + *(p++) = bits; + OPENSSL_memcpy(p, a->data, len); + if (len > 0) { + p[len - 1] &= (0xff << bits); + } + p += len; + *pp = p; + return (ret); } ASN1_BIT_STRING *c2i_ASN1_BIT_STRING(ASN1_BIT_STRING **a, - const unsigned char **pp, long len) -{ - ASN1_BIT_STRING *ret = NULL; - const unsigned char *p; - unsigned char *s; - int padding; + const unsigned char **pp, long len) { + ASN1_BIT_STRING *ret = NULL; + const unsigned char *p; + unsigned char *s; + int padding; - if (len < 1) { - OPENSSL_PUT_ERROR(ASN1, ASN1_R_STRING_TOO_SHORT); - goto err; - } + if (len < 1) { + OPENSSL_PUT_ERROR(ASN1, ASN1_R_STRING_TOO_SHORT); + goto err; + } - if (len > INT_MAX) { - OPENSSL_PUT_ERROR(ASN1, ASN1_R_STRING_TOO_LONG); - goto err; - } + if (len > INT_MAX) { + OPENSSL_PUT_ERROR(ASN1, ASN1_R_STRING_TOO_LONG); + goto err; + } - if ((a == NULL) || ((*a) == NULL)) { - if ((ret = ASN1_BIT_STRING_new()) == NULL) - return (NULL); - } else - ret = (*a); - - p = *pp; - padding = *(p++); - len--; - if (padding > 7) { - OPENSSL_PUT_ERROR(ASN1, ASN1_R_INVALID_BIT_STRING_BITS_LEFT); - goto err; + if ((a == NULL) || ((*a) == NULL)) { + if ((ret = ASN1_BIT_STRING_new()) == NULL) { + return (NULL); } + } else { + ret = (*a); + } - /* Unused bits in a BIT STRING must be zero. */ - uint8_t padding_mask = (1 << padding) - 1; - if (padding != 0 && - (len < 1 || (p[len - 1] & padding_mask) != 0)) { - OPENSSL_PUT_ERROR(ASN1, ASN1_R_INVALID_BIT_STRING_PADDING); - goto err; - } + p = *pp; + padding = *(p++); + len--; + if (padding > 7) { + OPENSSL_PUT_ERROR(ASN1, ASN1_R_INVALID_BIT_STRING_BITS_LEFT); + goto err; + } - /* - * We do this to preserve the settings. If we modify the settings, via - * the _set_bit function, we will recalculate on output - */ - ret->flags &= ~(ASN1_STRING_FLAG_BITS_LEFT | 0x07); /* clear */ - ret->flags |= (ASN1_STRING_FLAG_BITS_LEFT | padding); /* set */ + /* Unused bits in a BIT STRING must be zero. */ + uint8_t padding_mask = (1 << padding) - 1; + if (padding != 0 && (len < 1 || (p[len - 1] & padding_mask) != 0)) { + OPENSSL_PUT_ERROR(ASN1, ASN1_R_INVALID_BIT_STRING_PADDING); + goto err; + } - if (len > 0) { - s = OPENSSL_memdup(p, len); - if (s == NULL) { - OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE); - goto err; - } - p += len; - } else { - s = NULL; + /* + * We do this to preserve the settings. If we modify the settings, via + * the _set_bit function, we will recalculate on output + */ + ret->flags &= ~(ASN1_STRING_FLAG_BITS_LEFT | 0x07); /* clear */ + ret->flags |= (ASN1_STRING_FLAG_BITS_LEFT | padding); /* set */ + + if (len > 0) { + s = OPENSSL_memdup(p, len); + if (s == NULL) { + OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE); + goto err; } + p += len; + } else { + s = NULL; + } - ret->length = (int)len; - OPENSSL_free(ret->data); - ret->data = s; - ret->type = V_ASN1_BIT_STRING; - if (a != NULL) - (*a) = ret; - *pp = p; - return (ret); - err: - if ((ret != NULL) && ((a == NULL) || (*a != ret))) - ASN1_BIT_STRING_free(ret); - return (NULL); + ret->length = (int)len; + OPENSSL_free(ret->data); + ret->data = s; + ret->type = V_ASN1_BIT_STRING; + if (a != NULL) { + (*a) = ret; + } + *pp = p; + return (ret); +err: + if ((ret != NULL) && ((a == NULL) || (*a != ret))) { + ASN1_BIT_STRING_free(ret); + } + return (NULL); } /* * These next 2 functions from Goetz Babin-Ebell */ -int ASN1_BIT_STRING_set_bit(ASN1_BIT_STRING *a, int n, int value) -{ - int w, v, iv; - unsigned char *c; +int ASN1_BIT_STRING_set_bit(ASN1_BIT_STRING *a, int n, int value) { + int w, v, iv; + unsigned char *c; - w = n / 8; - v = 1 << (7 - (n & 0x07)); - iv = ~v; - if (!value) - v = 0; + w = n / 8; + v = 1 << (7 - (n & 0x07)); + iv = ~v; + if (!value) { + v = 0; + } - if (a == NULL) - return 0; + if (a == NULL) { + return 0; + } - a->flags &= ~(ASN1_STRING_FLAG_BITS_LEFT | 0x07); /* clear, set on write */ + a->flags &= ~(ASN1_STRING_FLAG_BITS_LEFT | 0x07); /* clear, set on write */ - if ((a->length < (w + 1)) || (a->data == NULL)) { - if (!value) - return (1); /* Don't need to set */ - if (a->data == NULL) - c = (unsigned char *)OPENSSL_malloc(w + 1); - else - c = (unsigned char *)OPENSSL_realloc(a->data, w + 1); - if (c == NULL) { - OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE); - return 0; - } - if (w + 1 - a->length > 0) - OPENSSL_memset(c + a->length, 0, w + 1 - a->length); - a->data = c; - a->length = w + 1; + if ((a->length < (w + 1)) || (a->data == NULL)) { + if (!value) { + return (1); /* Don't need to set */ } - a->data[w] = ((a->data[w]) & iv) | v; - while ((a->length > 0) && (a->data[a->length - 1] == 0)) - a->length--; - return (1); + if (a->data == NULL) { + c = (unsigned char *)OPENSSL_malloc(w + 1); + } else { + c = (unsigned char *)OPENSSL_realloc(a->data, w + 1); + } + if (c == NULL) { + OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE); + return 0; + } + if (w + 1 - a->length > 0) { + OPENSSL_memset(c + a->length, 0, w + 1 - a->length); + } + a->data = c; + a->length = w + 1; + } + a->data[w] = ((a->data[w]) & iv) | v; + while ((a->length > 0) && (a->data[a->length - 1] == 0)) { + a->length--; + } + return (1); } -int ASN1_BIT_STRING_get_bit(const ASN1_BIT_STRING *a, int n) -{ - int w, v; +int ASN1_BIT_STRING_get_bit(const ASN1_BIT_STRING *a, int n) { + int w, v; - w = n / 8; - v = 1 << (7 - (n & 0x07)); - if ((a == NULL) || (a->length < (w + 1)) || (a->data == NULL)) - return (0); - return ((a->data[w] & v) != 0); + w = n / 8; + v = 1 << (7 - (n & 0x07)); + if ((a == NULL) || (a->length < (w + 1)) || (a->data == NULL)) { + return (0); + } + return ((a->data[w] & v) != 0); } /* @@ -263,22 +268,22 @@ int ASN1_BIT_STRING_get_bit(const ASN1_BIT_STRING *a, int n) * which is not specified in 'flags', 1 otherwise. * 'len' is the length of 'flags'. */ -int ASN1_BIT_STRING_check(const ASN1_BIT_STRING *a, - const unsigned char *flags, int flags_len) -{ - int i, ok; - /* Check if there is one bit set at all. */ - if (!a || !a->data) - return 1; +int ASN1_BIT_STRING_check(const ASN1_BIT_STRING *a, const unsigned char *flags, + int flags_len) { + int i, ok; + /* Check if there is one bit set at all. */ + if (!a || !a->data) { + return 1; + } - /* - * Check each byte of the internal representation of the bit string. - */ - ok = 1; - for (i = 0; i < a->length && ok; ++i) { - unsigned char mask = i < flags_len ? ~flags[i] : 0xff; - /* We are done if there is an unneeded bit set. */ - ok = (a->data[i] & mask) == 0; - } - return ok; + /* + * Check each byte of the internal representation of the bit string. + */ + ok = 1; + for (i = 0; i < a->length && ok; ++i) { + unsigned char mask = i < flags_len ? ~flags[i] : 0xff; + /* We are done if there is an unneeded bit set. */ + ok = (a->data[i] & mask) == 0; + } + return ok; } diff --git a/crypto/asn1/a_bool.c b/crypto/asn1/a_bool.c index 3f32e8070d..daf96fccd8 100644 --- a/crypto/asn1/a_bool.c +++ b/crypto/asn1/a_bool.c @@ -59,64 +59,64 @@ #include #include -int i2d_ASN1_BOOLEAN(ASN1_BOOLEAN a, unsigned char **pp) -{ - int r; - unsigned char *p, *allocated = NULL; +int i2d_ASN1_BOOLEAN(ASN1_BOOLEAN a, unsigned char **pp) { + int r; + unsigned char *p, *allocated = NULL; - r = ASN1_object_size(0, 1, V_ASN1_BOOLEAN); - if (pp == NULL) - return (r); + r = ASN1_object_size(0, 1, V_ASN1_BOOLEAN); + if (pp == NULL) { + return (r); + } - if (*pp == NULL) { - if ((p = allocated = OPENSSL_malloc(r)) == NULL) { - OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE); - return -1; - } - } else { - p = *pp; + if (*pp == NULL) { + if ((p = allocated = OPENSSL_malloc(r)) == NULL) { + OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE); + return -1; } + } else { + p = *pp; + } - ASN1_put_object(&p, 0, 1, V_ASN1_BOOLEAN, V_ASN1_UNIVERSAL); - *p = a ? 0xff : 0x00; + ASN1_put_object(&p, 0, 1, V_ASN1_BOOLEAN, V_ASN1_UNIVERSAL); + *p = a ? 0xff : 0x00; - /* - * If a new buffer was allocated, just return it back. - * If not, return the incremented buffer pointer. - */ - *pp = allocated != NULL ? allocated : p + 1; - return r; + /* + * If a new buffer was allocated, just return it back. + * If not, return the incremented buffer pointer. + */ + *pp = allocated != NULL ? allocated : p + 1; + return r; } ASN1_BOOLEAN d2i_ASN1_BOOLEAN(ASN1_BOOLEAN *a, const unsigned char **pp, long length) { - const unsigned char *p = *pp; - long len; - int inf, tag, xclass; - inf = ASN1_get_object(&p, &len, &tag, &xclass, length); - if (inf & 0x80) { - OPENSSL_PUT_ERROR(ASN1, ASN1_R_BAD_OBJECT_HEADER); - return -1; - } + const unsigned char *p = *pp; + long len; + int inf, tag, xclass; + inf = ASN1_get_object(&p, &len, &tag, &xclass, length); + if (inf & 0x80) { + OPENSSL_PUT_ERROR(ASN1, ASN1_R_BAD_OBJECT_HEADER); + return -1; + } - if (inf & V_ASN1_CONSTRUCTED) { - OPENSSL_PUT_ERROR(ASN1, ASN1_R_TYPE_NOT_PRIMITIVE); - return -1; - } + if (inf & V_ASN1_CONSTRUCTED) { + OPENSSL_PUT_ERROR(ASN1, ASN1_R_TYPE_NOT_PRIMITIVE); + return -1; + } - if (tag != V_ASN1_BOOLEAN || xclass != V_ASN1_UNIVERSAL) { - OPENSSL_PUT_ERROR(ASN1, ASN1_R_EXPECTING_A_BOOLEAN); - return -1; - } + if (tag != V_ASN1_BOOLEAN || xclass != V_ASN1_UNIVERSAL) { + OPENSSL_PUT_ERROR(ASN1, ASN1_R_EXPECTING_A_BOOLEAN); + return -1; + } - if (len != 1) { - OPENSSL_PUT_ERROR(ASN1, ASN1_R_BOOLEAN_IS_WRONG_LENGTH); - return -1; - } - ASN1_BOOLEAN ret = (ASN1_BOOLEAN)*(p++); - if (a != NULL) { - (*a) = ret; - } - *pp = p; - return ret; + if (len != 1) { + OPENSSL_PUT_ERROR(ASN1, ASN1_R_BOOLEAN_IS_WRONG_LENGTH); + return -1; + } + ASN1_BOOLEAN ret = (ASN1_BOOLEAN) * (p++); + if (a != NULL) { + (*a) = ret; + } + *pp = p; + return ret; } diff --git a/crypto/asn1/a_d2i_fp.c b/crypto/asn1/a_d2i_fp.c index d0d6d03ad2..36c9d6996d 100644 --- a/crypto/asn1/a_d2i_fp.c +++ b/crypto/asn1/a_d2i_fp.c @@ -63,29 +63,27 @@ #include -void *ASN1_item_d2i_bio(const ASN1_ITEM *it, BIO *in, void *x) -{ - uint8_t *data; - size_t len; - // Historically, this function did not impose a limit in OpenSSL and is used - // to read CRLs, so we leave this without an external bound. - if (!BIO_read_asn1(in, &data, &len, INT_MAX)) { - return NULL; - } - const uint8_t *ptr = data; - void *ret = ASN1_item_d2i(x, &ptr, len, it); - OPENSSL_free(data); - return ret; +void *ASN1_item_d2i_bio(const ASN1_ITEM *it, BIO *in, void *x) { + uint8_t *data; + size_t len; + // Historically, this function did not impose a limit in OpenSSL and is used + // to read CRLs, so we leave this without an external bound. + if (!BIO_read_asn1(in, &data, &len, INT_MAX)) { + return NULL; + } + const uint8_t *ptr = data; + void *ret = ASN1_item_d2i(x, &ptr, len, it); + OPENSSL_free(data); + return ret; } -void *ASN1_item_d2i_fp(const ASN1_ITEM *it, FILE *in, void *x) -{ - BIO *b = BIO_new_fp(in, BIO_NOCLOSE); - if (b == NULL) { - OPENSSL_PUT_ERROR(ASN1, ERR_R_BUF_LIB); - return NULL; - } - void *ret = ASN1_item_d2i_bio(it, b, x); - BIO_free(b); - return ret; +void *ASN1_item_d2i_fp(const ASN1_ITEM *it, FILE *in, void *x) { + BIO *b = BIO_new_fp(in, BIO_NOCLOSE); + if (b == NULL) { + OPENSSL_PUT_ERROR(ASN1, ERR_R_BUF_LIB); + return NULL; + } + void *ret = ASN1_item_d2i_bio(it, b, x); + BIO_free(b); + return ret; } diff --git a/crypto/asn1/a_dup.c b/crypto/asn1/a_dup.c index 9ede851178..5434b783a3 100644 --- a/crypto/asn1/a_dup.c +++ b/crypto/asn1/a_dup.c @@ -65,23 +65,23 @@ * directly dup the underlying structure instead of doing and encode and * decode. */ -void *ASN1_item_dup(const ASN1_ITEM *it, void *x) -{ - unsigned char *b = NULL; - const unsigned char *p; - long i; - void *ret; +void *ASN1_item_dup(const ASN1_ITEM *it, void *x) { + unsigned char *b = NULL; + const unsigned char *p; + long i; + void *ret; - if (x == NULL) - return (NULL); + if (x == NULL) { + return (NULL); + } - i = ASN1_item_i2d(x, &b, it); - if (b == NULL) { - OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE); - return (NULL); - } - p = b; - ret = ASN1_item_d2i(NULL, &p, i, it); - OPENSSL_free(b); - return (ret); + i = ASN1_item_i2d(x, &b, it); + if (b == NULL) { + OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE); + return (NULL); + } + p = b; + ret = ASN1_item_d2i(NULL, &p, i, it); + OPENSSL_free(b); + return (ret); } diff --git a/crypto/asn1/a_gentm.c b/crypto/asn1/a_gentm.c index 3e6f14e3f7..00a1282d5d 100644 --- a/crypto/asn1/a_gentm.c +++ b/crypto/asn1/a_gentm.c @@ -55,212 +55,109 @@ * [including the GNU Public Licence.] */ #include +#include +#include +#include #include #include -#include -#include - #include "internal.h" -int asn1_generalizedtime_to_tm(struct tm *tm, const ASN1_GENERALIZEDTIME *d) -{ - static const int min[9] = { 0, 0, 1, 1, 0, 0, 0, 0, 0 }; - static const int max[9] = { 99, 99, 12, 31, 23, 59, 59, 12, 59 }; - char *a; - int n, i, l, o; - - if (d->type != V_ASN1_GENERALIZEDTIME) - return (0); - l = d->length; - a = (char *)d->data; - o = 0; - /* - * GENERALIZEDTIME is similar to UTCTIME except the year is represented - * as YYYY. This stuff treats everything as a two digit field so make - * first two fields 00 to 99 - */ - if (l < 13) - goto err; - for (i = 0; i < 7; i++) { - if ((i == 6) && ((a[o] == 'Z') || (a[o] == '+') || (a[o] == '-'))) { - i++; - if (tm) - tm->tm_sec = 0; - break; - } - if ((a[o] < '0') || (a[o] > '9')) - goto err; - n = a[o] - '0'; - if (++o > l) - goto err; - - if ((a[o] < '0') || (a[o] > '9')) - goto err; - n = (n * 10) + a[o] - '0'; - if (++o > l) - goto err; - - if ((n < min[i]) || (n > max[i])) - goto err; - if (tm) { - switch (i) { - case 0: - tm->tm_year = n * 100 - 1900; - break; - case 1: - tm->tm_year += n; - break; - case 2: - tm->tm_mon = n - 1; - break; - case 3: - tm->tm_mday = n; - break; - case 4: - tm->tm_hour = n; - break; - case 5: - tm->tm_min = n; - break; - case 6: - tm->tm_sec = n; - break; - } - } - } - /* - * Optional fractional seconds: decimal point followed by one or more - * digits. - */ - if (a[o] == '.') { - if (++o > l) - goto err; - i = o; - while ((a[o] >= '0') && (a[o] <= '9') && (o <= l)) - o++; - /* Must have at least one digit after decimal point */ - if (i == o) - goto err; - } - - if (a[o] == 'Z') - o++; - else if ((a[o] == '+') || (a[o] == '-')) { - int offsign = a[o] == '-' ? 1 : -1, offset = 0; - o++; - if (o + 4 > l) - goto err; - for (i = 7; i < 9; i++) { - if ((a[o] < '0') || (a[o] > '9')) - goto err; - n = a[o] - '0'; - o++; - if ((a[o] < '0') || (a[o] > '9')) - goto err; - n = (n * 10) + a[o] - '0'; - if ((n < min[i]) || (n > max[i])) - goto err; - if (tm) { - if (i == 7) - offset = n * 3600; - else if (i == 8) - offset += n * 60; - } - o++; - } - if (offset && !OPENSSL_gmtime_adj(tm, 0, offset * offsign)) - return 0; - } else if (a[o]) { - /* Missing time zone information. */ - goto err; - } - return (o == l); - err: - return (0); +int asn1_generalizedtime_to_tm(struct tm *tm, const ASN1_GENERALIZEDTIME *d) { + if (d->type != V_ASN1_GENERALIZEDTIME) { + return 0; + } + CBS cbs; + CBS_init(&cbs, d->data, (size_t)d->length); + if (!CBS_parse_generalized_time(&cbs, tm, /*allow_timezone_offset=*/0)) { + return 0; + } + return 1; } -int ASN1_GENERALIZEDTIME_check(const ASN1_GENERALIZEDTIME *d) -{ - return asn1_generalizedtime_to_tm(NULL, d); +int ASN1_GENERALIZEDTIME_check(const ASN1_GENERALIZEDTIME *d) { + return asn1_generalizedtime_to_tm(NULL, d); } -int ASN1_GENERALIZEDTIME_set_string(ASN1_GENERALIZEDTIME *s, const char *str) -{ - ASN1_GENERALIZEDTIME t; - - t.type = V_ASN1_GENERALIZEDTIME; - t.length = strlen(str); - t.data = (unsigned char *)str; - if (ASN1_GENERALIZEDTIME_check(&t)) { - if (s != NULL) { - if (!ASN1_STRING_set((ASN1_STRING *)s, - (unsigned char *)str, t.length)) - return 0; - s->type = V_ASN1_GENERALIZEDTIME; - } - return (1); - } else - return (0); +int ASN1_GENERALIZEDTIME_set_string(ASN1_GENERALIZEDTIME *s, const char *str) { + ASN1_GENERALIZEDTIME t; + + t.type = V_ASN1_GENERALIZEDTIME; + t.length = strlen(str); + t.data = (unsigned char *)str; + if (ASN1_GENERALIZEDTIME_check(&t)) { + if (s != NULL) { + if (!ASN1_STRING_set((ASN1_STRING *)s, (unsigned char *)str, t.length)) { + return 0; + } + s->type = V_ASN1_GENERALIZEDTIME; + } + return (1); + } else { + return (0); + } } ASN1_GENERALIZEDTIME *ASN1_GENERALIZEDTIME_set(ASN1_GENERALIZEDTIME *s, - time_t t) -{ - return ASN1_GENERALIZEDTIME_adj(s, t, 0, 0); + time_t t) { + return ASN1_GENERALIZEDTIME_adj(s, t, 0, 0); } ASN1_GENERALIZEDTIME *ASN1_GENERALIZEDTIME_adj(ASN1_GENERALIZEDTIME *s, time_t t, int offset_day, - long offset_sec) -{ - char *p; - struct tm *ts; - struct tm data; - size_t len = 20; - ASN1_GENERALIZEDTIME *tmps = NULL; - - if (s == NULL) - tmps = ASN1_GENERALIZEDTIME_new(); - else - tmps = s; - if (tmps == NULL) - return NULL; - - ts = OPENSSL_gmtime(&t, &data); - if (ts == NULL) - goto err; + long offset_sec) { + char *p; + struct tm *ts; + struct tm data; + size_t len = 20; + ASN1_GENERALIZEDTIME *tmps = NULL; + + if (s == NULL) { + tmps = ASN1_GENERALIZEDTIME_new(); + } else { + tmps = s; + } + if (tmps == NULL) { + return NULL; + } - if (offset_day || offset_sec) { - if (!OPENSSL_gmtime_adj(ts, offset_day, offset_sec)) - goto err; - } + ts = OPENSSL_gmtime(&t, &data); + if (ts == NULL) { + goto err; + } - if (ts->tm_year < 0 - 1900 || ts->tm_year > 9999 - 1900) { - OPENSSL_PUT_ERROR(ASN1, ASN1_R_ILLEGAL_TIME_VALUE); - goto err; + if (offset_day || offset_sec) { + if (!OPENSSL_gmtime_adj(ts, offset_day, offset_sec)) { + goto err; } - - p = (char *)tmps->data; - if ((p == NULL) || ((size_t)tmps->length < len)) { - p = OPENSSL_malloc(len); - if (p == NULL) { - OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE); - goto err; - } - OPENSSL_free(tmps->data); - tmps->data = (unsigned char *)p; + } + + if (ts->tm_year < 0 - 1900 || ts->tm_year > 9999 - 1900) { + OPENSSL_PUT_ERROR(ASN1, ASN1_R_ILLEGAL_TIME_VALUE); + goto err; + } + + p = (char *)tmps->data; + if ((p == NULL) || ((size_t)tmps->length < len)) { + p = OPENSSL_malloc(len); + if (p == NULL) { + OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE); + goto err; } - - BIO_snprintf(p, len, "%04d%02d%02d%02d%02d%02dZ", ts->tm_year + 1900, - ts->tm_mon + 1, ts->tm_mday, ts->tm_hour, ts->tm_min, - ts->tm_sec); - tmps->length = strlen(p); - tmps->type = V_ASN1_GENERALIZEDTIME; - return tmps; - err: - if (s == NULL) - ASN1_GENERALIZEDTIME_free(tmps); - return NULL; + OPENSSL_free(tmps->data); + tmps->data = (unsigned char *)p; + } + + BIO_snprintf(p, len, "%04d%02d%02d%02d%02d%02dZ", ts->tm_year + 1900, + ts->tm_mon + 1, ts->tm_mday, ts->tm_hour, ts->tm_min, + ts->tm_sec); + tmps->length = strlen(p); + tmps->type = V_ASN1_GENERALIZEDTIME; + return tmps; +err: + if (s == NULL) { + ASN1_GENERALIZEDTIME_free(tmps); + } + return NULL; } diff --git a/crypto/asn1/a_i2d_fp.c b/crypto/asn1/a_i2d_fp.c index db0d812284..4a14f2bcc1 100644 --- a/crypto/asn1/a_i2d_fp.c +++ b/crypto/asn1/a_i2d_fp.c @@ -61,28 +61,26 @@ #include -int ASN1_item_i2d_fp(const ASN1_ITEM *it, FILE *out, void *x) -{ - BIO *b = BIO_new_fp(out, BIO_NOCLOSE); - if (b == NULL) { - OPENSSL_PUT_ERROR(ASN1, ERR_R_BUF_LIB); - return 0; - } - int ret = ASN1_item_i2d_bio(it, b, x); - BIO_free(b); - return ret; +int ASN1_item_i2d_fp(const ASN1_ITEM *it, FILE *out, void *x) { + BIO *b = BIO_new_fp(out, BIO_NOCLOSE); + if (b == NULL) { + OPENSSL_PUT_ERROR(ASN1, ERR_R_BUF_LIB); + return 0; + } + int ret = ASN1_item_i2d_bio(it, b, x); + BIO_free(b); + return ret; } -int ASN1_item_i2d_bio(const ASN1_ITEM *it, BIO *out, void *x) -{ - unsigned char *b = NULL; - int n = ASN1_item_i2d(x, &b, it); - if (b == NULL) { - OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE); - return 0; - } +int ASN1_item_i2d_bio(const ASN1_ITEM *it, BIO *out, void *x) { + unsigned char *b = NULL; + int n = ASN1_item_i2d(x, &b, it); + if (b == NULL) { + OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE); + return 0; + } - int ret = BIO_write_all(out, b, n); - OPENSSL_free(b); - return ret; + int ret = BIO_write_all(out, b, n); + OPENSSL_free(b); + return ret; } diff --git a/crypto/asn1/a_int.c b/crypto/asn1/a_int.c index aa6db9d6c2..c1343c9e8f 100644 --- a/crypto/asn1/a_int.c +++ b/crypto/asn1/a_int.c @@ -56,8 +56,8 @@ #include -#include #include +#include #include #include @@ -67,396 +67,374 @@ #include "../internal.h" -ASN1_INTEGER *ASN1_INTEGER_dup(const ASN1_INTEGER *x) -{ - return ASN1_STRING_dup(x); +ASN1_INTEGER *ASN1_INTEGER_dup(const ASN1_INTEGER *x) { + return ASN1_STRING_dup(x); } -int ASN1_INTEGER_cmp(const ASN1_INTEGER *x, const ASN1_INTEGER *y) -{ - /* Compare signs. */ - int neg = x->type & V_ASN1_NEG; - if (neg != (y->type & V_ASN1_NEG)) { - return neg ? -1 : 1; - } - - int ret = ASN1_STRING_cmp(x, y); - if (neg) { - /* This could be |-ret|, but |ASN1_STRING_cmp| is not forbidden from - * returning |INT_MIN|. */ - if (ret < 0) { - return 1; - } else if (ret > 0) { - return -1; - } else { - return 0; - } +int ASN1_INTEGER_cmp(const ASN1_INTEGER *x, const ASN1_INTEGER *y) { + /* Compare signs. */ + int neg = x->type & V_ASN1_NEG; + if (neg != (y->type & V_ASN1_NEG)) { + return neg ? -1 : 1; + } + + int ret = ASN1_STRING_cmp(x, y); + if (neg) { + /* This could be |-ret|, but |ASN1_STRING_cmp| is not forbidden from + * returning |INT_MIN|. */ + if (ret < 0) { + return 1; + } else if (ret > 0) { + return -1; + } else { + return 0; } + } - return ret; + return ret; } /* negate_twos_complement negates |len| bytes from |buf| in-place, interpreted * as a signed, big-endian two's complement value. */ -static void negate_twos_complement(uint8_t *buf, size_t len) -{ - uint8_t borrow = 0; - for (size_t i = len - 1; i < len; i--) { - uint8_t t = buf[i]; - buf[i] = 0u - borrow - t; - borrow |= t != 0; - } +static void negate_twos_complement(uint8_t *buf, size_t len) { + uint8_t borrow = 0; + for (size_t i = len - 1; i < len; i--) { + uint8_t t = buf[i]; + buf[i] = 0u - borrow - t; + borrow |= t != 0; + } } static int is_all_zeros(const uint8_t *in, size_t len) { - for (size_t i = 0; i < len; i++) { - if (in[i] != 0) { - return 0; - } + for (size_t i = 0; i < len; i++) { + if (in[i] != 0) { + return 0; } - return 1; + } + return 1; } -int i2c_ASN1_INTEGER(const ASN1_INTEGER *in, unsigned char **outp) -{ - if (in == NULL) { - return 0; - } - - /* |ASN1_INTEGER|s should be represented minimally, but it is possible to - * construct invalid ones. Skip leading zeros so this does not produce an - * invalid encoding or break invariants. */ - int start = 0; - while (start < in->length && in->data[start] == 0) { - start++; - } - - int is_negative = (in->type & V_ASN1_NEG) != 0; - int pad; - if (start >= in->length) { - /* Zero is represented as a single byte. */ - is_negative = 0; - pad = 1; - } else if (is_negative) { - /* 0x80...01 through 0xff...ff have a two's complement of 0x7f...ff - * through 0x00...01 and need an extra byte to be negative. - * 0x01...00 through 0x80...00 have a two's complement of 0xfe...ff - * through 0x80...00 and can be negated as-is. */ - pad = in->data[start] > 0x80 || - (in->data[start] == 0x80 && - !is_all_zeros(in->data + start + 1, in->length - start - 1)); - } else { - /* If the high bit is set, the signed representation needs an extra - * byte to be positive. */ - pad = (in->data[start] & 0x80) != 0; - } - - if (in->length - start > INT_MAX - pad) { - OPENSSL_PUT_ERROR(ASN1, ERR_R_OVERFLOW); - return 0; - } - int len = pad + in->length - start; - assert(len > 0); - if (outp == NULL) { - return len; - } - - if (pad) { - (*outp)[0] = 0; - } - OPENSSL_memcpy(*outp + pad, in->data + start, in->length - start); - if (is_negative) { - negate_twos_complement(*outp, len); - assert((*outp)[0] >= 0x80); - } else { - assert((*outp)[0] < 0x80); - } - *outp += len; +int i2c_ASN1_INTEGER(const ASN1_INTEGER *in, unsigned char **outp) { + if (in == NULL) { + return 0; + } + + /* |ASN1_INTEGER|s should be represented minimally, but it is possible to + * construct invalid ones. Skip leading zeros so this does not produce an + * invalid encoding or break invariants. */ + int start = 0; + while (start < in->length && in->data[start] == 0) { + start++; + } + + int is_negative = (in->type & V_ASN1_NEG) != 0; + int pad; + if (start >= in->length) { + /* Zero is represented as a single byte. */ + is_negative = 0; + pad = 1; + } else if (is_negative) { + /* 0x80...01 through 0xff...ff have a two's complement of 0x7f...ff + * through 0x00...01 and need an extra byte to be negative. + * 0x01...00 through 0x80...00 have a two's complement of 0xfe...ff + * through 0x80...00 and can be negated as-is. */ + pad = in->data[start] > 0x80 || + (in->data[start] == 0x80 && + !is_all_zeros(in->data + start + 1, in->length - start - 1)); + } else { + /* If the high bit is set, the signed representation needs an extra + * byte to be positive. */ + pad = (in->data[start] & 0x80) != 0; + } + + if (in->length - start > INT_MAX - pad) { + OPENSSL_PUT_ERROR(ASN1, ERR_R_OVERFLOW); + return 0; + } + int len = pad + in->length - start; + assert(len > 0); + if (outp == NULL) { return len; + } + + if (pad) { + (*outp)[0] = 0; + } + OPENSSL_memcpy(*outp + pad, in->data + start, in->length - start); + if (is_negative) { + negate_twos_complement(*outp, len); + assert((*outp)[0] >= 0x80); + } else { + assert((*outp)[0] < 0x80); + } + *outp += len; + return len; } ASN1_INTEGER *c2i_ASN1_INTEGER(ASN1_INTEGER **out, const unsigned char **inp, - long len) -{ - /* - * This function can handle lengths up to INT_MAX - 1, but the rest of the - * legacy ASN.1 code mixes integer types, so avoid exposing it to - * ASN1_INTEGERS with larger lengths. - */ - if (len < 0 || len > INT_MAX / 2) { - OPENSSL_PUT_ERROR(ASN1, ASN1_R_TOO_LONG); - return NULL; - } - - CBS cbs; - CBS_init(&cbs, *inp, (size_t)len); - int is_negative; - if (!CBS_is_valid_asn1_integer(&cbs, &is_negative)) { - OPENSSL_PUT_ERROR(ASN1, ASN1_R_INVALID_INTEGER); - return NULL; - } - - ASN1_INTEGER *ret = NULL; - if (out == NULL || *out == NULL) { - ret = ASN1_INTEGER_new(); - if (ret == NULL) { - return NULL; - } - } else { - ret = *out; - } - - /* Convert to |ASN1_INTEGER|'s sign-and-magnitude representation. First, - * determine the size needed for a minimal result. */ - if (is_negative) { - /* 0xff00...01 through 0xff7f..ff have a two's complement of 0x00ff...ff - * through 0x000100...001 and need one leading zero removed. 0x8000...00 - * through 0xff00...00 have a two's complement of 0x8000...00 through - * 0x0100...00 and will be minimally-encoded as-is. */ - if (CBS_len(&cbs) > 0 && CBS_data(&cbs)[0] == 0xff && - !is_all_zeros(CBS_data(&cbs) + 1, CBS_len(&cbs) - 1)) { - CBS_skip(&cbs, 1); - } - } else { - /* Remove the leading zero byte, if any. */ - if (CBS_len(&cbs) > 0 && CBS_data(&cbs)[0] == 0x00) { - CBS_skip(&cbs, 1); - } - } - - if (!ASN1_STRING_set(ret, CBS_data(&cbs), CBS_len(&cbs))) { - goto err; - } - - if (is_negative) { - ret->type = V_ASN1_NEG_INTEGER; - negate_twos_complement(ret->data, ret->length); - } else { - ret->type = V_ASN1_INTEGER; - } + long len) { + /* + * This function can handle lengths up to INT_MAX - 1, but the rest of the + * legacy ASN.1 code mixes integer types, so avoid exposing it to + * ASN1_INTEGERS with larger lengths. + */ + if (len < 0 || len > INT_MAX / 2) { + OPENSSL_PUT_ERROR(ASN1, ASN1_R_TOO_LONG); + return NULL; + } - /* The value should be minimally-encoded. */ - assert(ret->length == 0 || ret->data[0] != 0); - /* Zero is not negative. */ - assert(!is_negative || ret->length > 0); + CBS cbs; + CBS_init(&cbs, *inp, (size_t)len); + int is_negative; + if (!CBS_is_valid_asn1_integer(&cbs, &is_negative)) { + OPENSSL_PUT_ERROR(ASN1, ASN1_R_INVALID_INTEGER); + return NULL; + } - *inp += len; - if (out != NULL) { - *out = ret; - } - return ret; + ASN1_INTEGER *ret = NULL; + if (out == NULL || *out == NULL) { + ret = ASN1_INTEGER_new(); + if (ret == NULL) { + return NULL; + } + } else { + ret = *out; + } + + /* Convert to |ASN1_INTEGER|'s sign-and-magnitude representation. First, + * determine the size needed for a minimal result. */ + if (is_negative) { + /* 0xff00...01 through 0xff7f..ff have a two's complement of 0x00ff...ff + * through 0x000100...001 and need one leading zero removed. 0x8000...00 + * through 0xff00...00 have a two's complement of 0x8000...00 through + * 0x0100...00 and will be minimally-encoded as-is. */ + if (CBS_len(&cbs) > 0 && CBS_data(&cbs)[0] == 0xff && + !is_all_zeros(CBS_data(&cbs) + 1, CBS_len(&cbs) - 1)) { + CBS_skip(&cbs, 1); + } + } else { + /* Remove the leading zero byte, if any. */ + if (CBS_len(&cbs) > 0 && CBS_data(&cbs)[0] == 0x00) { + CBS_skip(&cbs, 1); + } + } + + if (!ASN1_STRING_set(ret, CBS_data(&cbs), CBS_len(&cbs))) { + goto err; + } + + if (is_negative) { + ret->type = V_ASN1_NEG_INTEGER; + negate_twos_complement(ret->data, ret->length); + } else { + ret->type = V_ASN1_INTEGER; + } + + /* The value should be minimally-encoded. */ + assert(ret->length == 0 || ret->data[0] != 0); + /* Zero is not negative. */ + assert(!is_negative || ret->length > 0); + + *inp += len; + if (out != NULL) { + *out = ret; + } + return ret; - err: - if (ret != NULL && (out == NULL || *out != ret)) { - ASN1_INTEGER_free(ret); - } - return NULL; +err: + if (ret != NULL && (out == NULL || *out != ret)) { + ASN1_INTEGER_free(ret); + } + return NULL; } -int ASN1_INTEGER_set(ASN1_INTEGER *a, long v) -{ - if (v >= 0) { - return ASN1_INTEGER_set_uint64(a, (uint64_t) v); - } +int ASN1_INTEGER_set(ASN1_INTEGER *a, long v) { + if (v >= 0) { + return ASN1_INTEGER_set_uint64(a, (uint64_t)v); + } - if (!ASN1_INTEGER_set_uint64(a, 0 - (uint64_t) v)) { - return 0; - } + if (!ASN1_INTEGER_set_uint64(a, 0 - (uint64_t)v)) { + return 0; + } - a->type = V_ASN1_NEG_INTEGER; - return 1; + a->type = V_ASN1_NEG_INTEGER; + return 1; } -int ASN1_ENUMERATED_set(ASN1_ENUMERATED *a, long v) -{ - if (v >= 0) { - return ASN1_ENUMERATED_set_uint64(a, (uint64_t) v); - } +int ASN1_ENUMERATED_set(ASN1_ENUMERATED *a, long v) { + if (v >= 0) { + return ASN1_ENUMERATED_set_uint64(a, (uint64_t)v); + } - if (!ASN1_ENUMERATED_set_uint64(a, 0 - (uint64_t) v)) { - return 0; - } + if (!ASN1_ENUMERATED_set_uint64(a, 0 - (uint64_t)v)) { + return 0; + } - a->type = V_ASN1_NEG_ENUMERATED; - return 1; + a->type = V_ASN1_NEG_ENUMERATED; + return 1; } -static int asn1_string_set_uint64(ASN1_STRING *out, uint64_t v, int type) -{ - uint8_t buf[sizeof(uint64_t)]; - CRYPTO_store_u64_be(buf, v); - size_t leading_zeros; - for (leading_zeros = 0; leading_zeros < sizeof(buf); leading_zeros++) { - if (buf[leading_zeros] != 0) { - break; - } - } - - if (!ASN1_STRING_set(out, buf + leading_zeros, - sizeof(buf) - leading_zeros)) { - return 0; - } - out->type = type; - return 1; +static int asn1_string_set_uint64(ASN1_STRING *out, uint64_t v, int type) { + uint8_t buf[sizeof(uint64_t)]; + CRYPTO_store_u64_be(buf, v); + size_t leading_zeros; + for (leading_zeros = 0; leading_zeros < sizeof(buf); leading_zeros++) { + if (buf[leading_zeros] != 0) { + break; + } + } + + if (!ASN1_STRING_set(out, buf + leading_zeros, sizeof(buf) - leading_zeros)) { + return 0; + } + out->type = type; + return 1; } -int ASN1_INTEGER_set_uint64(ASN1_INTEGER *out, uint64_t v) -{ - return asn1_string_set_uint64(out, v, V_ASN1_INTEGER); +int ASN1_INTEGER_set_uint64(ASN1_INTEGER *out, uint64_t v) { + return asn1_string_set_uint64(out, v, V_ASN1_INTEGER); } -int ASN1_ENUMERATED_set_uint64(ASN1_ENUMERATED *out, uint64_t v) -{ - return asn1_string_set_uint64(out, v, V_ASN1_ENUMERATED); +int ASN1_ENUMERATED_set_uint64(ASN1_ENUMERATED *out, uint64_t v) { + return asn1_string_set_uint64(out, v, V_ASN1_ENUMERATED); } static int asn1_string_get_abs_uint64(uint64_t *out, const ASN1_STRING *a, - int type) -{ - if ((a->type & ~V_ASN1_NEG) != type) { - OPENSSL_PUT_ERROR(ASN1, ASN1_R_WRONG_INTEGER_TYPE); - return 0; - } - uint8_t buf[sizeof(uint64_t)] = {0}; - if (a->length > (int)sizeof(buf)) { - OPENSSL_PUT_ERROR(ASN1, ASN1_R_INVALID_INTEGER); - return 0; - } - OPENSSL_memcpy(buf + sizeof(buf) - a->length, a->data, a->length); - *out = CRYPTO_load_u64_be(buf); - return 1; + int type) { + if ((a->type & ~V_ASN1_NEG) != type) { + OPENSSL_PUT_ERROR(ASN1, ASN1_R_WRONG_INTEGER_TYPE); + return 0; + } + uint8_t buf[sizeof(uint64_t)] = {0}; + if (a->length > (int)sizeof(buf)) { + OPENSSL_PUT_ERROR(ASN1, ASN1_R_INVALID_INTEGER); + return 0; + } + OPENSSL_memcpy(buf + sizeof(buf) - a->length, a->data, a->length); + *out = CRYPTO_load_u64_be(buf); + return 1; } -static int asn1_string_get_uint64(uint64_t *out, const ASN1_STRING *a, int type) -{ - if (!asn1_string_get_abs_uint64(out, a, type)) { - return 0; - } - if (a->type & V_ASN1_NEG) { - OPENSSL_PUT_ERROR(ASN1, ASN1_R_INVALID_INTEGER); - return 0; - } - return 1; +static int asn1_string_get_uint64(uint64_t *out, const ASN1_STRING *a, + int type) { + if (!asn1_string_get_abs_uint64(out, a, type)) { + return 0; + } + if (a->type & V_ASN1_NEG) { + OPENSSL_PUT_ERROR(ASN1, ASN1_R_INVALID_INTEGER); + return 0; + } + return 1; } -int ASN1_INTEGER_get_uint64(uint64_t *out, const ASN1_INTEGER *a) -{ - return asn1_string_get_uint64(out, a, V_ASN1_INTEGER); +int ASN1_INTEGER_get_uint64(uint64_t *out, const ASN1_INTEGER *a) { + return asn1_string_get_uint64(out, a, V_ASN1_INTEGER); } -int ASN1_ENUMERATED_get_uint64(uint64_t *out, const ASN1_ENUMERATED *a) -{ - return asn1_string_get_uint64(out, a, V_ASN1_ENUMERATED); +int ASN1_ENUMERATED_get_uint64(uint64_t *out, const ASN1_ENUMERATED *a) { + return asn1_string_get_uint64(out, a, V_ASN1_ENUMERATED); } -static long asn1_string_get_long(const ASN1_STRING *a, int type) -{ - if (a == NULL) { - return 0; - } - - uint64_t v; - if (!asn1_string_get_abs_uint64(&v, a, type)) { - goto err; - } - - int64_t i64; - int fits_in_i64; - /* Check |v != 0| to handle manually-constructed negative zeros. */ - if ((a->type & V_ASN1_NEG) && v != 0) { - i64 = (int64_t)(0u - v); - fits_in_i64 = i64 < 0; - } else { - i64 = (int64_t)v; - fits_in_i64 = i64 >= 0; - } - OPENSSL_STATIC_ASSERT(sizeof(long) <= sizeof(int64_t), long_is_too_big) - - if (fits_in_i64 && LONG_MIN <= i64 && i64 <= LONG_MAX) { - return (long)i64; - } +static long asn1_string_get_long(const ASN1_STRING *a, int type) { + if (a == NULL) { + return 0; + } + + uint64_t v; + if (!asn1_string_get_abs_uint64(&v, a, type)) { + goto err; + } + + int64_t i64; + int fits_in_i64; + /* Check |v != 0| to handle manually-constructed negative zeros. */ + if ((a->type & V_ASN1_NEG) && v != 0) { + i64 = (int64_t)(0u - v); + fits_in_i64 = i64 < 0; + } else { + i64 = (int64_t)v; + fits_in_i64 = i64 >= 0; + } + OPENSSL_STATIC_ASSERT(sizeof(long) <= sizeof(int64_t), long_is_too_big) + + if (fits_in_i64 && LONG_MIN <= i64 && i64 <= LONG_MAX) { + return (long)i64; + } err: - /* This function's return value does not distinguish overflow from -1. */ - ERR_clear_error(); - return -1; + /* This function's return value does not distinguish overflow from -1. */ + ERR_clear_error(); + return -1; } -long ASN1_INTEGER_get(const ASN1_INTEGER *a) -{ - return asn1_string_get_long(a, V_ASN1_INTEGER); +long ASN1_INTEGER_get(const ASN1_INTEGER *a) { + return asn1_string_get_long(a, V_ASN1_INTEGER); } -long ASN1_ENUMERATED_get(const ASN1_ENUMERATED *a) -{ - return asn1_string_get_long(a, V_ASN1_ENUMERATED); +long ASN1_ENUMERATED_get(const ASN1_ENUMERATED *a) { + return asn1_string_get_long(a, V_ASN1_ENUMERATED); } static ASN1_STRING *bn_to_asn1_string(const BIGNUM *bn, ASN1_STRING *ai, - int type) -{ - ASN1_INTEGER *ret; - if (ai == NULL) { - ret = ASN1_STRING_type_new(type); - } else { - ret = ai; - } - if (ret == NULL) { - OPENSSL_PUT_ERROR(ASN1, ASN1_R_NESTED_ASN1_ERROR); - goto err; - } - - if (BN_is_negative(bn) && !BN_is_zero(bn)) { - ret->type = type | V_ASN1_NEG; - } else { - ret->type = type; - } - - int len = BN_num_bytes(bn); - if (!ASN1_STRING_set(ret, NULL, len) || - !BN_bn2bin_padded(ret->data, len, bn)) { - goto err; - } - return ret; + int type) { + ASN1_INTEGER *ret; + if (ai == NULL) { + ret = ASN1_STRING_type_new(type); + } else { + ret = ai; + } + if (ret == NULL) { + OPENSSL_PUT_ERROR(ASN1, ASN1_R_NESTED_ASN1_ERROR); + goto err; + } + + if (BN_is_negative(bn) && !BN_is_zero(bn)) { + ret->type = type | V_ASN1_NEG; + } else { + ret->type = type; + } + + int len = BN_num_bytes(bn); + if (!ASN1_STRING_set(ret, NULL, len) || + !BN_bn2bin_padded(ret->data, len, bn)) { + goto err; + } + return ret; - err: - if (ret != ai) { - ASN1_STRING_free(ret); - } - return NULL; +err: + if (ret != ai) { + ASN1_STRING_free(ret); + } + return NULL; } -ASN1_INTEGER *BN_to_ASN1_INTEGER(const BIGNUM *bn, ASN1_INTEGER *ai) -{ - return bn_to_asn1_string(bn, ai, V_ASN1_INTEGER); +ASN1_INTEGER *BN_to_ASN1_INTEGER(const BIGNUM *bn, ASN1_INTEGER *ai) { + return bn_to_asn1_string(bn, ai, V_ASN1_INTEGER); } -ASN1_ENUMERATED *BN_to_ASN1_ENUMERATED(const BIGNUM *bn, ASN1_ENUMERATED *ai) -{ - return bn_to_asn1_string(bn, ai, V_ASN1_ENUMERATED); +ASN1_ENUMERATED *BN_to_ASN1_ENUMERATED(const BIGNUM *bn, ASN1_ENUMERATED *ai) { + return bn_to_asn1_string(bn, ai, V_ASN1_ENUMERATED); } -static BIGNUM *asn1_string_to_bn(const ASN1_STRING *ai, BIGNUM *bn, int type) -{ - if ((ai->type & ~V_ASN1_NEG) != type) { - OPENSSL_PUT_ERROR(ASN1, ASN1_R_WRONG_INTEGER_TYPE); - return NULL; - } - - BIGNUM *ret; - if ((ret = BN_bin2bn(ai->data, ai->length, bn)) == NULL) - OPENSSL_PUT_ERROR(ASN1, ASN1_R_BN_LIB); - else if (ai->type & V_ASN1_NEG) - BN_set_negative(ret, 1); - return (ret); +static BIGNUM *asn1_string_to_bn(const ASN1_STRING *ai, BIGNUM *bn, int type) { + if ((ai->type & ~V_ASN1_NEG) != type) { + OPENSSL_PUT_ERROR(ASN1, ASN1_R_WRONG_INTEGER_TYPE); + return NULL; + } + + BIGNUM *ret; + if ((ret = BN_bin2bn(ai->data, ai->length, bn)) == NULL) { + OPENSSL_PUT_ERROR(ASN1, ASN1_R_BN_LIB); + } else if (ai->type & V_ASN1_NEG) { + BN_set_negative(ret, 1); + } + return (ret); } -BIGNUM *ASN1_INTEGER_to_BN(const ASN1_INTEGER *ai, BIGNUM *bn) -{ - return asn1_string_to_bn(ai, bn, V_ASN1_INTEGER); +BIGNUM *ASN1_INTEGER_to_BN(const ASN1_INTEGER *ai, BIGNUM *bn) { + return asn1_string_to_bn(ai, bn, V_ASN1_INTEGER); } -BIGNUM *ASN1_ENUMERATED_to_BN(const ASN1_ENUMERATED *ai, BIGNUM *bn) -{ - return asn1_string_to_bn(ai, bn, V_ASN1_ENUMERATED); +BIGNUM *ASN1_ENUMERATED_to_BN(const ASN1_ENUMERATED *ai, BIGNUM *bn) { + return asn1_string_to_bn(ai, bn, V_ASN1_ENUMERATED); } diff --git a/crypto/asn1/a_mbstr.c b/crypto/asn1/a_mbstr.c index 5853b72358..fd5562c209 100644 --- a/crypto/asn1/a_mbstr.c +++ b/crypto/asn1/a_mbstr.c @@ -63,8 +63,8 @@ #include #include -#include "internal.h" #include "../bytestring/internal.h" +#include "internal.h" /* * These functions take a string in UTF8, ASCII or multibyte form and a mask @@ -76,9 +76,8 @@ */ int ASN1_mbstring_copy(ASN1_STRING **out, const unsigned char *in, int len, - int inform, unsigned long mask) -{ - return ASN1_mbstring_ncopy(out, in, len, inform, mask, 0, 0); + int inform, unsigned long mask) { + return ASN1_mbstring_ncopy(out, in, len, inform, mask, 0, 0); } OPENSSL_DECLARE_ERROR_REASON(ASN1, INVALID_BMPSTRING) @@ -86,213 +85,211 @@ OPENSSL_DECLARE_ERROR_REASON(ASN1, INVALID_UNIVERSALSTRING) OPENSSL_DECLARE_ERROR_REASON(ASN1, INVALID_UTF8STRING) int ASN1_mbstring_ncopy(ASN1_STRING **out, const unsigned char *in, int len, - int inform, unsigned long mask, - long minsize, long maxsize) -{ - int str_type; - char free_out; - ASN1_STRING *dest; - size_t nchar = 0; - char strbuf[32]; - if (len == -1) - len = strlen((const char *)in); - if (!mask) - mask = DIRSTRING_TYPE; + int inform, unsigned long mask, long minsize, + long maxsize) { + int str_type; + char free_out; + ASN1_STRING *dest; + size_t nchar = 0; + char strbuf[32]; + if (len == -1) { + len = strlen((const char *)in); + } + if (!mask) { + mask = DIRSTRING_TYPE; + } - int (*decode_func)(CBS *, uint32_t*); - int error; - switch (inform) { + int (*decode_func)(CBS *, uint32_t *); + int error; + switch (inform) { case MBSTRING_BMP: - decode_func = cbs_get_ucs2_be; - error = ASN1_R_INVALID_BMPSTRING; - break; + decode_func = cbs_get_ucs2_be; + error = ASN1_R_INVALID_BMPSTRING; + break; case MBSTRING_UNIV: - decode_func = cbs_get_utf32_be; - error = ASN1_R_INVALID_UNIVERSALSTRING; - break; + decode_func = cbs_get_utf32_be; + error = ASN1_R_INVALID_UNIVERSALSTRING; + break; case MBSTRING_UTF8: - decode_func = cbs_get_utf8; - error = ASN1_R_INVALID_UTF8STRING; - break; + decode_func = cbs_get_utf8; + error = ASN1_R_INVALID_UTF8STRING; + break; case MBSTRING_ASC: - decode_func = cbs_get_latin1; - error = ERR_R_INTERNAL_ERROR; // Latin-1 inputs are never invalid. - break; + decode_func = cbs_get_latin1; + error = ERR_R_INTERNAL_ERROR; // Latin-1 inputs are never invalid. + break; default: - OPENSSL_PUT_ERROR(ASN1, ASN1_R_UNKNOWN_FORMAT); - return -1; - } + OPENSSL_PUT_ERROR(ASN1, ASN1_R_UNKNOWN_FORMAT); + return -1; + } - /* Check |minsize| and |maxsize| and work out the minimal type, if any. */ - CBS cbs; - CBS_init(&cbs, in, len); - size_t utf8_len = 0; - while (CBS_len(&cbs) != 0) { - uint32_t c; - if (!decode_func(&cbs, &c)) { - OPENSSL_PUT_ERROR(ASN1, error); - return -1; - } - if (nchar == 0 && - (inform == MBSTRING_BMP || inform == MBSTRING_UNIV) && - c == 0xfeff) { - /* Reject byte-order mark. We could drop it but that would mean - * adding ambiguity around whether a BOM was included or not when - * matching strings. - * - * For a little-endian UCS-2 string, the BOM will appear as 0xfffe - * and will be rejected as noncharacter, below. */ - OPENSSL_PUT_ERROR(ASN1, ASN1_R_ILLEGAL_CHARACTERS); - return -1; - } - - /* Update which output formats are still possible. */ - if ((mask & B_ASN1_PRINTABLESTRING) && !asn1_is_printable(c)) { - mask &= ~B_ASN1_PRINTABLESTRING; - } - if ((mask & B_ASN1_IA5STRING) && (c > 127)) { - mask &= ~B_ASN1_IA5STRING; - } - if ((mask & B_ASN1_T61STRING) && (c > 0xff)) { - mask &= ~B_ASN1_T61STRING; - } - if ((mask & B_ASN1_BMPSTRING) && (c > 0xffff)) { - mask &= ~B_ASN1_BMPSTRING; - } - if (!mask) { - OPENSSL_PUT_ERROR(ASN1, ASN1_R_ILLEGAL_CHARACTERS); - return -1; - } - - nchar++; - utf8_len += cbb_get_utf8_len(c); + /* Check |minsize| and |maxsize| and work out the minimal type, if any. */ + CBS cbs; + CBS_init(&cbs, in, len); + size_t utf8_len = 0; + while (CBS_len(&cbs) != 0) { + uint32_t c; + if (!decode_func(&cbs, &c)) { + OPENSSL_PUT_ERROR(ASN1, error); + return -1; } - - if (minsize > 0 && nchar < (size_t)minsize) { - OPENSSL_PUT_ERROR(ASN1, ASN1_R_STRING_TOO_SHORT); - BIO_snprintf(strbuf, sizeof strbuf, "%ld", minsize); - ERR_add_error_data(2, "minsize=", strbuf); - return -1; + if (nchar == 0 && (inform == MBSTRING_BMP || inform == MBSTRING_UNIV) && + c == 0xfeff) { + /* Reject byte-order mark. We could drop it but that would mean + * adding ambiguity around whether a BOM was included or not when + * matching strings. + * + * For a little-endian UCS-2 string, the BOM will appear as 0xfffe + * and will be rejected as noncharacter, below. */ + OPENSSL_PUT_ERROR(ASN1, ASN1_R_ILLEGAL_CHARACTERS); + return -1; } - if (maxsize > 0 && nchar > (size_t)maxsize) { - OPENSSL_PUT_ERROR(ASN1, ASN1_R_STRING_TOO_LONG); - BIO_snprintf(strbuf, sizeof strbuf, "%ld", maxsize); - ERR_add_error_data(2, "maxsize=", strbuf); - return -1; + /* Update which output formats are still possible. */ + if ((mask & B_ASN1_PRINTABLESTRING) && !asn1_is_printable(c)) { + mask &= ~B_ASN1_PRINTABLESTRING; } - - /* Now work out output format and string type */ - int (*encode_func)(CBB *, uint32_t) = cbb_add_latin1; - size_t size_estimate = nchar; - int outform = MBSTRING_ASC; - if (mask & B_ASN1_PRINTABLESTRING) { - str_type = V_ASN1_PRINTABLESTRING; - } else if (mask & B_ASN1_IA5STRING) { - str_type = V_ASN1_IA5STRING; - } else if (mask & B_ASN1_T61STRING) { - str_type = V_ASN1_T61STRING; - } else if (mask & B_ASN1_BMPSTRING) { - str_type = V_ASN1_BMPSTRING; - outform = MBSTRING_BMP; - encode_func = cbb_add_ucs2_be; - size_estimate = 2 * nchar; - } else if (mask & B_ASN1_UNIVERSALSTRING) { - str_type = V_ASN1_UNIVERSALSTRING; - encode_func = cbb_add_utf32_be; - size_estimate = 4 * nchar; - outform = MBSTRING_UNIV; - } else if (mask & B_ASN1_UTF8STRING) { - str_type = V_ASN1_UTF8STRING; - outform = MBSTRING_UTF8; - encode_func = cbb_add_utf8; - size_estimate = utf8_len; - } else { - OPENSSL_PUT_ERROR(ASN1, ASN1_R_ILLEGAL_CHARACTERS); - return -1; + if ((mask & B_ASN1_IA5STRING) && (c > 127)) { + mask &= ~B_ASN1_IA5STRING; } - - if (!out) - return str_type; - if (*out) { - free_out = 0; - dest = *out; - if (dest->data) { - dest->length = 0; - OPENSSL_free(dest->data); - dest->data = NULL; - } - dest->type = str_type; - } else { - free_out = 1; - dest = ASN1_STRING_type_new(str_type); - if (!dest) { - OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE); - return -1; - } - *out = dest; + if ((mask & B_ASN1_T61STRING) && (c > 0xff)) { + mask &= ~B_ASN1_T61STRING; } - - /* If both the same type just copy across */ - if (inform == outform) { - if (!ASN1_STRING_set(dest, in, len)) { - OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE); - return -1; - } - return str_type; + if ((mask & B_ASN1_BMPSTRING) && (c > 0xffff)) { + mask &= ~B_ASN1_BMPSTRING; } + if (!mask) { + OPENSSL_PUT_ERROR(ASN1, ASN1_R_ILLEGAL_CHARACTERS); + return -1; + } + + nchar++; + utf8_len += cbb_get_utf8_len(c); + } - CBB cbb; - if (!CBB_init(&cbb, size_estimate + 1)) { - OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE); - goto err; + if (minsize > 0 && nchar < (size_t)minsize) { + OPENSSL_PUT_ERROR(ASN1, ASN1_R_STRING_TOO_SHORT); + BIO_snprintf(strbuf, sizeof strbuf, "%ld", minsize); + ERR_add_error_data(2, "minsize=", strbuf); + return -1; + } + + if (maxsize > 0 && nchar > (size_t)maxsize) { + OPENSSL_PUT_ERROR(ASN1, ASN1_R_STRING_TOO_LONG); + BIO_snprintf(strbuf, sizeof strbuf, "%ld", maxsize); + ERR_add_error_data(2, "maxsize=", strbuf); + return -1; + } + + /* Now work out output format and string type */ + int (*encode_func)(CBB *, uint32_t) = cbb_add_latin1; + size_t size_estimate = nchar; + int outform = MBSTRING_ASC; + if (mask & B_ASN1_PRINTABLESTRING) { + str_type = V_ASN1_PRINTABLESTRING; + } else if (mask & B_ASN1_IA5STRING) { + str_type = V_ASN1_IA5STRING; + } else if (mask & B_ASN1_T61STRING) { + str_type = V_ASN1_T61STRING; + } else if (mask & B_ASN1_BMPSTRING) { + str_type = V_ASN1_BMPSTRING; + outform = MBSTRING_BMP; + encode_func = cbb_add_ucs2_be; + size_estimate = 2 * nchar; + } else if (mask & B_ASN1_UNIVERSALSTRING) { + str_type = V_ASN1_UNIVERSALSTRING; + encode_func = cbb_add_utf32_be; + size_estimate = 4 * nchar; + outform = MBSTRING_UNIV; + } else if (mask & B_ASN1_UTF8STRING) { + str_type = V_ASN1_UTF8STRING; + outform = MBSTRING_UTF8; + encode_func = cbb_add_utf8; + size_estimate = utf8_len; + } else { + OPENSSL_PUT_ERROR(ASN1, ASN1_R_ILLEGAL_CHARACTERS); + return -1; + } + + if (!out) { + return str_type; + } + if (*out) { + free_out = 0; + dest = *out; + if (dest->data) { + dest->length = 0; + OPENSSL_free(dest->data); + dest->data = NULL; } - CBS_init(&cbs, in, len); - while (CBS_len(&cbs) != 0) { - uint32_t c; - if (!decode_func(&cbs, &c) || - !encode_func(&cbb, c)) { - OPENSSL_PUT_ERROR(ASN1, ERR_R_INTERNAL_ERROR); - goto err; - } + dest->type = str_type; + } else { + free_out = 1; + dest = ASN1_STRING_type_new(str_type); + if (!dest) { + OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE); + return -1; } - uint8_t *data = NULL; - size_t data_len; - if (/* OpenSSL historically NUL-terminated this value with a single byte, - * even for |MBSTRING_BMP| and |MBSTRING_UNIV|. */ - !CBB_add_u8(&cbb, 0) || - !CBB_finish(&cbb, &data, &data_len) || - data_len < 1 || - data_len > INT_MAX) { - OPENSSL_PUT_ERROR(ASN1, ERR_R_INTERNAL_ERROR); - OPENSSL_free(data); - goto err; + *out = dest; + } + + /* If both the same type just copy across */ + if (inform == outform) { + if (!ASN1_STRING_set(dest, in, len)) { + OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE); + return -1; } - dest->length = (int)(data_len - 1); - dest->data = data; return str_type; + } - err: - if (free_out) - ASN1_STRING_free(dest); - CBB_cleanup(&cbb); - return -1; + CBB cbb; + if (!CBB_init(&cbb, size_estimate + 1)) { + OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE); + goto err; + } + CBS_init(&cbs, in, len); + while (CBS_len(&cbs) != 0) { + uint32_t c; + if (!decode_func(&cbs, &c) || !encode_func(&cbb, c)) { + OPENSSL_PUT_ERROR(ASN1, ERR_R_INTERNAL_ERROR); + goto err; + } + } + uint8_t *data = NULL; + size_t data_len; + if (/* OpenSSL historically NUL-terminated this value with a single byte, + * even for |MBSTRING_BMP| and |MBSTRING_UNIV|. */ + !CBB_add_u8(&cbb, 0) || !CBB_finish(&cbb, &data, &data_len) || + data_len < 1 || data_len > INT_MAX) { + OPENSSL_PUT_ERROR(ASN1, ERR_R_INTERNAL_ERROR); + OPENSSL_free(data); + goto err; + } + dest->length = (int)(data_len - 1); + dest->data = data; + return str_type; + +err: + if (free_out) { + ASN1_STRING_free(dest); + } + CBB_cleanup(&cbb); + return -1; } -int asn1_is_printable(uint32_t value) -{ - if (value > 0x7f) { - return 0; - } - /* Note we cannot use |isalnum| because it is locale-dependent. */ - return ('a' <= value && value <= 'z') || // - ('A' <= value && value <= 'Z') || // - ('0' <= value && value <= '9') || // - value == ' ' || value == '\'' || value == '(' || value == ')' || - value == '+' || value == ',' || value == '-' || value == '.' || - value == '/' || value == ':' || value == '=' || value == '?'; +int asn1_is_printable(uint32_t value) { + if (value > 0x7f) { + return 0; + } + /* Note we cannot use |isalnum| because it is locale-dependent. */ + return ('a' <= value && value <= 'z') || // + ('A' <= value && value <= 'Z') || // + ('0' <= value && value <= '9') || // + value == ' ' || value == '\'' || value == '(' || value == ')' || + value == '+' || value == ',' || value == '-' || value == '.' || + value == '/' || value == ':' || value == '=' || value == '?'; } diff --git a/crypto/asn1/a_object.c b/crypto/asn1/a_object.c index 30a656d324..e157d903c9 100644 --- a/crypto/asn1/a_object.c +++ b/crypto/asn1/a_object.c @@ -67,233 +67,230 @@ #include "internal.h" -int i2d_ASN1_OBJECT(const ASN1_OBJECT *a, unsigned char **pp) -{ - if (a == NULL) { - OPENSSL_PUT_ERROR(ASN1, ERR_R_PASSED_NULL_PARAMETER); - return -1; - } +int i2d_ASN1_OBJECT(const ASN1_OBJECT *a, unsigned char **pp) { + if (a == NULL) { + OPENSSL_PUT_ERROR(ASN1, ERR_R_PASSED_NULL_PARAMETER); + return -1; + } - if (a->length == 0) { - OPENSSL_PUT_ERROR(ASN1, ASN1_R_ILLEGAL_OBJECT); - return -1; - } + if (a->length == 0) { + OPENSSL_PUT_ERROR(ASN1, ASN1_R_ILLEGAL_OBJECT); + return -1; + } - int objsize = ASN1_object_size(0, a->length, V_ASN1_OBJECT); - if (pp == NULL || objsize == -1) { - return objsize; - } + int objsize = ASN1_object_size(0, a->length, V_ASN1_OBJECT); + if (pp == NULL || objsize == -1) { + return objsize; + } - unsigned char *p, *allocated = NULL; - if (*pp == NULL) { - if ((p = allocated = OPENSSL_malloc(objsize)) == NULL) { - OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE); - return -1; - } - } else { - p = *pp; + unsigned char *p, *allocated = NULL; + if (*pp == NULL) { + if ((p = allocated = OPENSSL_malloc(objsize)) == NULL) { + OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE); + return -1; } + } else { + p = *pp; + } - ASN1_put_object(&p, 0, a->length, V_ASN1_OBJECT, V_ASN1_UNIVERSAL); - OPENSSL_memcpy(p, a->data, a->length); + ASN1_put_object(&p, 0, a->length, V_ASN1_OBJECT, V_ASN1_UNIVERSAL); + OPENSSL_memcpy(p, a->data, a->length); - /* - * If a new buffer was allocated, just return it back. - * If not, return the incremented buffer pointer. - */ - *pp = allocated != NULL ? allocated : p + a->length; - return objsize; + /* + * If a new buffer was allocated, just return it back. + * If not, return the incremented buffer pointer. + */ + *pp = allocated != NULL ? allocated : p + a->length; + return objsize; } -int i2t_ASN1_OBJECT(char *buf, int buf_len, const ASN1_OBJECT *a) -{ - return OBJ_obj2txt(buf, buf_len, a, 0); +int i2t_ASN1_OBJECT(char *buf, int buf_len, const ASN1_OBJECT *a) { + return OBJ_obj2txt(buf, buf_len, a, 0); } -static int write_str(BIO *bp, const char *str) -{ - int len = strlen(str); - return BIO_write(bp, str, len) == len ? len : -1; +static int write_str(BIO *bp, const char *str) { + int len = strlen(str); + return BIO_write(bp, str, len) == len ? len : -1; } -int i2a_ASN1_OBJECT(BIO *bp, const ASN1_OBJECT *a) -{ - if (a == NULL || a->data == NULL) { - return write_str(bp, "NULL"); - } +int i2a_ASN1_OBJECT(BIO *bp, const ASN1_OBJECT *a) { + if (a == NULL || a->data == NULL) { + return write_str(bp, "NULL"); + } - char buf[80], *allocated = NULL; - const char *str = buf; - int len = i2t_ASN1_OBJECT(buf, sizeof(buf), a); - if (len > (int)sizeof(buf) - 1) { - /* The input was truncated. Allocate a buffer that fits. */ - allocated = OPENSSL_malloc(len + 1); - if (allocated == NULL) { - return -1; - } - len = i2t_ASN1_OBJECT(allocated, len + 1, a); - str = allocated; - } - if (len <= 0) { - str = ""; + char buf[80], *allocated = NULL; + const char *str = buf; + int len = i2t_ASN1_OBJECT(buf, sizeof(buf), a); + if (len > (int)sizeof(buf) - 1) { + /* The input was truncated. Allocate a buffer that fits. */ + allocated = OPENSSL_malloc(len + 1); + if (allocated == NULL) { + return -1; } + len = i2t_ASN1_OBJECT(allocated, len + 1, a); + str = allocated; + } + if (len <= 0) { + str = ""; + } - int ret = write_str(bp, str); - OPENSSL_free(allocated); - return ret; + int ret = write_str(bp, str); + OPENSSL_free(allocated); + return ret; } ASN1_OBJECT *d2i_ASN1_OBJECT(ASN1_OBJECT **a, const unsigned char **pp, - long length) -{ - long len; - int tag, xclass; - const unsigned char *p = *pp; - int inf = ASN1_get_object(&p, &len, &tag, &xclass, length); - if (inf & 0x80) { - OPENSSL_PUT_ERROR(ASN1, ASN1_R_BAD_OBJECT_HEADER); - return NULL; - } + long length) { + long len; + int tag, xclass; + const unsigned char *p = *pp; + int inf = ASN1_get_object(&p, &len, &tag, &xclass, length); + if (inf & 0x80) { + OPENSSL_PUT_ERROR(ASN1, ASN1_R_BAD_OBJECT_HEADER); + return NULL; + } - if (inf & V_ASN1_CONSTRUCTED) { - OPENSSL_PUT_ERROR(ASN1, ASN1_R_TYPE_NOT_PRIMITIVE); - return NULL; - } + if (inf & V_ASN1_CONSTRUCTED) { + OPENSSL_PUT_ERROR(ASN1, ASN1_R_TYPE_NOT_PRIMITIVE); + return NULL; + } - if (tag != V_ASN1_OBJECT || xclass != V_ASN1_UNIVERSAL) { - OPENSSL_PUT_ERROR(ASN1, ASN1_R_EXPECTING_AN_OBJECT); - return NULL; - } - ASN1_OBJECT *ret = c2i_ASN1_OBJECT(a, &p, len); - if (ret) { - *pp = p; - } - return ret; + if (tag != V_ASN1_OBJECT || xclass != V_ASN1_UNIVERSAL) { + OPENSSL_PUT_ERROR(ASN1, ASN1_R_EXPECTING_AN_OBJECT); + return NULL; + } + ASN1_OBJECT *ret = c2i_ASN1_OBJECT(a, &p, len); + if (ret) { + *pp = p; + } + return ret; } ASN1_OBJECT *c2i_ASN1_OBJECT(ASN1_OBJECT **a, const unsigned char **pp, - long len) -{ - ASN1_OBJECT *ret = NULL; - const unsigned char *p; - unsigned char *data; - int i, length; + long len) { + ASN1_OBJECT *ret = NULL; + const unsigned char *p; + unsigned char *data; + int i, length; - /* - * Sanity check OID encoding. Need at least one content octet. MSB must - * be clear in the last octet. can't have leading 0x80 in subidentifiers, - * see: X.690 8.19.2 - */ - if (len <= 0 || len > INT_MAX || pp == NULL || (p = *pp) == NULL || - p[len - 1] & 0x80) { - OPENSSL_PUT_ERROR(ASN1, ASN1_R_INVALID_OBJECT_ENCODING); - return NULL; - } - /* Now 0 < len <= INT_MAX, so the cast is safe. */ - length = (int)len; - for (i = 0; i < length; i++, p++) { - if (*p == 0x80 && (!i || !(p[-1] & 0x80))) { - OPENSSL_PUT_ERROR(ASN1, ASN1_R_INVALID_OBJECT_ENCODING); - return NULL; - } + /* + * Sanity check OID encoding. Need at least one content octet. MSB must + * be clear in the last octet. can't have leading 0x80 in subidentifiers, + * see: X.690 8.19.2 + */ + if (len <= 0 || len > INT_MAX || pp == NULL || (p = *pp) == NULL || + p[len - 1] & 0x80) { + OPENSSL_PUT_ERROR(ASN1, ASN1_R_INVALID_OBJECT_ENCODING); + return NULL; + } + /* Now 0 < len <= INT_MAX, so the cast is safe. */ + length = (int)len; + for (i = 0; i < length; i++, p++) { + if (*p == 0x80 && (!i || !(p[-1] & 0x80))) { + OPENSSL_PUT_ERROR(ASN1, ASN1_R_INVALID_OBJECT_ENCODING); + return NULL; } + } - if ((a == NULL) || ((*a) == NULL) || - !((*a)->flags & ASN1_OBJECT_FLAG_DYNAMIC)) { - if ((ret = ASN1_OBJECT_new()) == NULL) - return (NULL); - } else { - ret = (*a); + if ((a == NULL) || ((*a) == NULL) || + !((*a)->flags & ASN1_OBJECT_FLAG_DYNAMIC)) { + if ((ret = ASN1_OBJECT_new()) == NULL) { + return (NULL); } + } else { + ret = (*a); + } - p = *pp; - /* detach data from object */ - data = (unsigned char *)ret->data; - ret->data = NULL; - /* once detached we can change it */ - if ((data == NULL) || (ret->length < length)) { - ret->length = 0; - if (data != NULL) - OPENSSL_free(data); - data = (unsigned char *)OPENSSL_malloc(length); - if (data == NULL) { - i = ERR_R_MALLOC_FAILURE; - goto err; - } - ret->flags |= ASN1_OBJECT_FLAG_DYNAMIC_DATA; + p = *pp; + /* detach data from object */ + data = (unsigned char *)ret->data; + ret->data = NULL; + /* once detached we can change it */ + if ((data == NULL) || (ret->length < length)) { + ret->length = 0; + if (data != NULL) { + OPENSSL_free(data); } - OPENSSL_memcpy(data, p, length); - /* If there are dynamic strings, free them here, and clear the flag */ - if ((ret->flags & ASN1_OBJECT_FLAG_DYNAMIC_STRINGS) != 0) { - OPENSSL_free((char *)ret->sn); - OPENSSL_free((char *)ret->ln); - ret->flags &= ~ASN1_OBJECT_FLAG_DYNAMIC_STRINGS; + data = (unsigned char *)OPENSSL_malloc(length); + if (data == NULL) { + i = ERR_R_MALLOC_FAILURE; + goto err; } - /* reattach data to object, after which it remains const */ - ret->data = data; - ret->length = length; - ret->sn = NULL; - ret->ln = NULL; - p += length; + ret->flags |= ASN1_OBJECT_FLAG_DYNAMIC_DATA; + } + OPENSSL_memcpy(data, p, length); + /* If there are dynamic strings, free them here, and clear the flag */ + if ((ret->flags & ASN1_OBJECT_FLAG_DYNAMIC_STRINGS) != 0) { + OPENSSL_free((char *)ret->sn); + OPENSSL_free((char *)ret->ln); + ret->flags &= ~ASN1_OBJECT_FLAG_DYNAMIC_STRINGS; + } + /* reattach data to object, after which it remains const */ + ret->data = data; + ret->length = length; + ret->sn = NULL; + ret->ln = NULL; + p += length; - if (a != NULL) - (*a) = ret; - *pp = p; - return (ret); - err: - OPENSSL_PUT_ERROR(ASN1, i); - if ((ret != NULL) && ((a == NULL) || (*a != ret))) - ASN1_OBJECT_free(ret); - return (NULL); + if (a != NULL) { + (*a) = ret; + } + *pp = p; + return (ret); +err: + OPENSSL_PUT_ERROR(ASN1, i); + if ((ret != NULL) && ((a == NULL) || (*a != ret))) { + ASN1_OBJECT_free(ret); + } + return (NULL); } -ASN1_OBJECT *ASN1_OBJECT_new(void) -{ - ASN1_OBJECT *ret; +ASN1_OBJECT *ASN1_OBJECT_new(void) { + ASN1_OBJECT *ret; - ret = (ASN1_OBJECT *)OPENSSL_malloc(sizeof(ASN1_OBJECT)); - if (ret == NULL) { - OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE); - return (NULL); - } - ret->length = 0; - ret->data = NULL; - ret->nid = 0; - ret->sn = NULL; - ret->ln = NULL; - ret->flags = ASN1_OBJECT_FLAG_DYNAMIC; - return (ret); + ret = (ASN1_OBJECT *)OPENSSL_malloc(sizeof(ASN1_OBJECT)); + if (ret == NULL) { + OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE); + return (NULL); + } + ret->length = 0; + ret->data = NULL; + ret->nid = 0; + ret->sn = NULL; + ret->ln = NULL; + ret->flags = ASN1_OBJECT_FLAG_DYNAMIC; + return (ret); } -void ASN1_OBJECT_free(ASN1_OBJECT *a) -{ - if (a == NULL) - return; - if (a->flags & ASN1_OBJECT_FLAG_DYNAMIC_STRINGS) { - OPENSSL_free((void *)a->sn); - OPENSSL_free((void *)a->ln); - a->sn = a->ln = NULL; - } - if (a->flags & ASN1_OBJECT_FLAG_DYNAMIC_DATA) { - OPENSSL_free((void *)a->data); - a->data = NULL; - a->length = 0; - } - if (a->flags & ASN1_OBJECT_FLAG_DYNAMIC) - OPENSSL_free(a); +void ASN1_OBJECT_free(ASN1_OBJECT *a) { + if (a == NULL) { + return; + } + if (a->flags & ASN1_OBJECT_FLAG_DYNAMIC_STRINGS) { + OPENSSL_free((void *)a->sn); + OPENSSL_free((void *)a->ln); + a->sn = a->ln = NULL; + } + if (a->flags & ASN1_OBJECT_FLAG_DYNAMIC_DATA) { + OPENSSL_free((void *)a->data); + a->data = NULL; + a->length = 0; + } + if (a->flags & ASN1_OBJECT_FLAG_DYNAMIC) { + OPENSSL_free(a); + } } ASN1_OBJECT *ASN1_OBJECT_create(int nid, const unsigned char *data, int len, - const char *sn, const char *ln) -{ - ASN1_OBJECT o; + const char *sn, const char *ln) { + ASN1_OBJECT o; - o.sn = sn; - o.ln = ln; - o.data = data; - o.nid = nid; - o.length = len; - o.flags = ASN1_OBJECT_FLAG_DYNAMIC | ASN1_OBJECT_FLAG_DYNAMIC_STRINGS | - ASN1_OBJECT_FLAG_DYNAMIC_DATA; - return (OBJ_dup(&o)); + o.sn = sn; + o.ln = ln; + o.data = data; + o.nid = nid; + o.length = len; + o.flags = ASN1_OBJECT_FLAG_DYNAMIC | ASN1_OBJECT_FLAG_DYNAMIC_STRINGS | + ASN1_OBJECT_FLAG_DYNAMIC_DATA; + return (OBJ_dup(&o)); } diff --git a/crypto/asn1/a_octet.c b/crypto/asn1/a_octet.c index 312993b9b0..f9c337918a 100644 --- a/crypto/asn1/a_octet.c +++ b/crypto/asn1/a_octet.c @@ -59,19 +59,16 @@ #include #include -ASN1_OCTET_STRING *ASN1_OCTET_STRING_dup(const ASN1_OCTET_STRING *x) -{ - return ASN1_STRING_dup(x); +ASN1_OCTET_STRING *ASN1_OCTET_STRING_dup(const ASN1_OCTET_STRING *x) { + return ASN1_STRING_dup(x); } int ASN1_OCTET_STRING_cmp(const ASN1_OCTET_STRING *a, - const ASN1_OCTET_STRING *b) -{ - return ASN1_STRING_cmp(a, b); + const ASN1_OCTET_STRING *b) { + return ASN1_STRING_cmp(a, b); } int ASN1_OCTET_STRING_set(ASN1_OCTET_STRING *x, const unsigned char *d, - int len) -{ - return ASN1_STRING_set(x, d, len); + int len) { + return ASN1_STRING_set(x, d, len); } diff --git a/crypto/asn1/a_print.c b/crypto/asn1/a_print.c index c7efede8a7..3cd150f164 100644 --- a/crypto/asn1/a_print.c +++ b/crypto/asn1/a_print.c @@ -61,23 +61,22 @@ #include "internal.h" -int ASN1_PRINTABLE_type(const unsigned char *s, int len) -{ - if (len < 0) { - len = strlen((const char *)s); - } +int ASN1_PRINTABLE_type(const unsigned char *s, int len) { + if (len < 0) { + len = strlen((const char *)s); + } - int printable = 1; - for (int i = 0; i < len; i++) { - unsigned char c = s[i]; - if (c & 0x80) { - /* No need to continue iterating. */ - return V_ASN1_T61STRING; - } - if (!asn1_is_printable(c)) { - printable = 0; - } + int printable = 1; + for (int i = 0; i < len; i++) { + unsigned char c = s[i]; + if (c & 0x80) { + /* No need to continue iterating. */ + return V_ASN1_T61STRING; + } + if (!asn1_is_printable(c)) { + printable = 0; } + } - return printable ? V_ASN1_PRINTABLESTRING : V_ASN1_IA5STRING; + return printable ? V_ASN1_PRINTABLESTRING : V_ASN1_IA5STRING; } diff --git a/crypto/asn1/a_strex.c b/crypto/asn1/a_strex.c index 493affb57d..d17cab5dc4 100644 --- a/crypto/asn1/a_strex.c +++ b/crypto/asn1/a_strex.c @@ -72,60 +72,55 @@ (ASN1_STRFLGS_ESC_2253 | ASN1_STRFLGS_ESC_QUOTE | ASN1_STRFLGS_ESC_CTRL | \ ASN1_STRFLGS_ESC_MSB) -static int maybe_write(BIO *out, const void *buf, int len) -{ - /* If |out| is NULL, ignore the output but report the length. */ - return out == NULL || BIO_write(out, buf, len) == len; +static int maybe_write(BIO *out, const void *buf, int len) { + /* If |out| is NULL, ignore the output but report the length. */ + return out == NULL || BIO_write(out, buf, len) == len; } -static int is_control_character(unsigned char c) -{ - return c < 32 || c == 127; -} +static int is_control_character(unsigned char c) { return c < 32 || c == 127; } static int do_esc_char(uint32_t c, unsigned long flags, char *do_quotes, - BIO *out, int is_first, int is_last) -{ - /* |c| is a |uint32_t| because, depending on |ASN1_STRFLGS_UTF8_CONVERT|, - * we may be escaping bytes or Unicode codepoints. */ - char buf[16]; /* Large enough for "\\W01234567". */ - unsigned char u8 = (unsigned char)c; - if (c > 0xffff) { - BIO_snprintf(buf, sizeof(buf), "\\W%08" PRIX32, c); - } else if (c > 0xff) { - BIO_snprintf(buf, sizeof(buf), "\\U%04" PRIX32, c); - } else if ((flags & ASN1_STRFLGS_ESC_MSB) && c > 0x7f) { - BIO_snprintf(buf, sizeof(buf), "\\%02X", c); - } else if ((flags & ASN1_STRFLGS_ESC_CTRL) && is_control_character(c)) { - BIO_snprintf(buf, sizeof(buf), "\\%02X", c); - } else if (flags & ASN1_STRFLGS_ESC_2253) { - /* See RFC 2253, sections 2.4 and 4. */ - if (c == '\\' || c == '"') { - /* Quotes and backslashes are always escaped, quoted or not. */ - BIO_snprintf(buf, sizeof(buf), "\\%c", (int)c); - } else if (c == ',' || c == '+' || c == '<' || c == '>' || c == ';' || - (is_first && (c == ' ' || c == '#')) || - (is_last && (c == ' '))) { - if (flags & ASN1_STRFLGS_ESC_QUOTE) { - /* No need to escape, just tell the caller to quote. */ - if (do_quotes != NULL) { - *do_quotes = 1; - } - return maybe_write(out, &u8, 1) ? 1 : -1; - } - BIO_snprintf(buf, sizeof(buf), "\\%c", (int)c); - } else { - return maybe_write(out, &u8, 1) ? 1 : -1; + BIO *out, int is_first, int is_last) { + /* |c| is a |uint32_t| because, depending on |ASN1_STRFLGS_UTF8_CONVERT|, + * we may be escaping bytes or Unicode codepoints. */ + char buf[16]; /* Large enough for "\\W01234567". */ + unsigned char u8 = (unsigned char)c; + if (c > 0xffff) { + BIO_snprintf(buf, sizeof(buf), "\\W%08" PRIX32, c); + } else if (c > 0xff) { + BIO_snprintf(buf, sizeof(buf), "\\U%04" PRIX32, c); + } else if ((flags & ASN1_STRFLGS_ESC_MSB) && c > 0x7f) { + BIO_snprintf(buf, sizeof(buf), "\\%02X", c); + } else if ((flags & ASN1_STRFLGS_ESC_CTRL) && is_control_character(c)) { + BIO_snprintf(buf, sizeof(buf), "\\%02X", c); + } else if (flags & ASN1_STRFLGS_ESC_2253) { + /* See RFC 2253, sections 2.4 and 4. */ + if (c == '\\' || c == '"') { + /* Quotes and backslashes are always escaped, quoted or not. */ + BIO_snprintf(buf, sizeof(buf), "\\%c", (int)c); + } else if (c == ',' || c == '+' || c == '<' || c == '>' || c == ';' || + (is_first && (c == ' ' || c == '#')) || + (is_last && (c == ' '))) { + if (flags & ASN1_STRFLGS_ESC_QUOTE) { + /* No need to escape, just tell the caller to quote. */ + if (do_quotes != NULL) { + *do_quotes = 1; } - } else if ((flags & ESC_FLAGS) && c == '\\') { - /* If any escape flags are set, also escape backslashes. */ - BIO_snprintf(buf, sizeof(buf), "\\%c", (int)c); - } else { return maybe_write(out, &u8, 1) ? 1 : -1; + } + BIO_snprintf(buf, sizeof(buf), "\\%c", (int)c); + } else { + return maybe_write(out, &u8, 1) ? 1 : -1; } + } else if ((flags & ESC_FLAGS) && c == '\\') { + /* If any escape flags are set, also escape backslashes. */ + BIO_snprintf(buf, sizeof(buf), "\\%c", (int)c); + } else { + return maybe_write(out, &u8, 1) ? 1 : -1; + } - int len = strlen(buf); - return maybe_write(out, buf, len) ? len : -1; + int len = strlen(buf); + return maybe_write(out, buf, len) ? len : -1; } /* @@ -135,113 +130,113 @@ static int do_esc_char(uint32_t c, unsigned long flags, char *do_quotes, */ static int do_buf(const unsigned char *buf, int buflen, int encoding, - int utf8_convert, unsigned long flags, char *quotes, BIO *out) -{ - /* Reject invalid UCS-4 and UCS-2 lengths without parsing. */ - switch (encoding) { + int utf8_convert, unsigned long flags, char *quotes, + BIO *out) { + /* Reject invalid UCS-4 and UCS-2 lengths without parsing. */ + switch (encoding) { case MBSTRING_UNIV: - if (buflen & 3) { - OPENSSL_PUT_ERROR(ASN1, ASN1_R_INVALID_UNIVERSALSTRING); - return -1; - } - break; + if (buflen & 3) { + OPENSSL_PUT_ERROR(ASN1, ASN1_R_INVALID_UNIVERSALSTRING); + return -1; + } + break; case MBSTRING_BMP: - if (buflen & 1) { - OPENSSL_PUT_ERROR(ASN1, ASN1_R_INVALID_BMPSTRING); - return -1; - } + if (buflen & 1) { + OPENSSL_PUT_ERROR(ASN1, ASN1_R_INVALID_BMPSTRING); + return -1; + } + break; + } + + const unsigned char *p = buf; + const unsigned char *q = buf + buflen; + int outlen = 0; + while (p != q) { + const int is_first = p == buf; + /* TODO(davidben): Replace this with |cbs_get_ucs2_be|, etc., to check + * for invalid codepoints. Before doing that, enforce it in the parser, + * https://crbug.com/boringssl/427, so these error cases are not + * reachable from parsed objects. */ + uint32_t c; + switch (encoding) { + case MBSTRING_UNIV: + c = ((uint32_t)*p++) << 24; + c |= ((uint32_t)*p++) << 16; + c |= ((uint32_t)*p++) << 8; + c |= *p++; break; - } - const unsigned char *p = buf; - const unsigned char *q = buf + buflen; - int outlen = 0; - while (p != q) { - const int is_first = p == buf; - /* TODO(davidben): Replace this with |cbs_get_ucs2_be|, etc., to check - * for invalid codepoints. Before doing that, enforce it in the parser, - * https://crbug.com/boringssl/427, so these error cases are not - * reachable from parsed objects. */ - uint32_t c; - switch (encoding) { - case MBSTRING_UNIV: - c = ((uint32_t)*p++) << 24; - c |= ((uint32_t)*p++) << 16; - c |= ((uint32_t)*p++) << 8; - c |= *p++; - break; - - case MBSTRING_BMP: - c = ((uint32_t)*p++) << 8; - c |= *p++; - break; - - case MBSTRING_ASC: - c = *p++; - break; - - case MBSTRING_UTF8: { - int consumed = UTF8_getc(p, buflen, &c); - if (consumed < 0) - return -1; /* Invalid UTF8String */ - buflen -= consumed; - p += consumed; - break; - } + case MBSTRING_BMP: + c = ((uint32_t)*p++) << 8; + c |= *p++; + break; + + case MBSTRING_ASC: + c = *p++; + break; - default: - assert(0); - return -1; + case MBSTRING_UTF8: { + int consumed = UTF8_getc(p, buflen, &c); + if (consumed < 0) { + return -1; /* Invalid UTF8String */ } - const int is_last = p == q; - if (utf8_convert) { - unsigned char utfbuf[6]; - int utflen; - utflen = UTF8_putc(utfbuf, sizeof utfbuf, c); - for (int i = 0; i < utflen; i++) { - /* - * We don't need to worry about setting orflags correctly - * because if utflen==1 its value will be correct anyway - * otherwise each character will be > 0x7f and so the - * character will never be escaped on first and last. - */ - int len = do_esc_char(utfbuf[i], flags, quotes, out, is_first, - is_last); - if (len < 0) { - return -1; - } - outlen += len; - } - } else { - int len = do_esc_char(c, flags, quotes, out, is_first, is_last); - if (len < 0) { - return -1; - } - outlen += len; + buflen -= consumed; + p += consumed; + break; + } + + default: + assert(0); + return -1; + } + const int is_last = p == q; + if (utf8_convert) { + unsigned char utfbuf[6]; + int utflen; + utflen = UTF8_putc(utfbuf, sizeof utfbuf, c); + for (int i = 0; i < utflen; i++) { + /* + * We don't need to worry about setting orflags correctly + * because if utflen==1 its value will be correct anyway + * otherwise each character will be > 0x7f and so the + * character will never be escaped on first and last. + */ + int len = do_esc_char(utfbuf[i], flags, quotes, out, is_first, is_last); + if (len < 0) { + return -1; } + outlen += len; + } + } else { + int len = do_esc_char(c, flags, quotes, out, is_first, is_last); + if (len < 0) { + return -1; + } + outlen += len; } - return outlen; + } + return outlen; } /* This function hex dumps a buffer of characters */ -static int do_hex_dump(BIO *out, unsigned char *buf, int buflen) -{ - static const char hexdig[] = "0123456789ABCDEF"; - unsigned char *p, *q; - char hextmp[2]; - if (out) { - p = buf; - q = buf + buflen; - while (p != q) { - hextmp[0] = hexdig[*p >> 4]; - hextmp[1] = hexdig[*p & 0xf]; - if (!maybe_write(out, hextmp, 2)) - return -1; - p++; - } +static int do_hex_dump(BIO *out, unsigned char *buf, int buflen) { + static const char hexdig[] = "0123456789ABCDEF"; + unsigned char *p, *q; + char hextmp[2]; + if (out) { + p = buf; + q = buf + buflen; + while (p != q) { + hextmp[0] = hexdig[*p >> 4]; + hextmp[1] = hexdig[*p & 0xf]; + if (!maybe_write(out, hextmp, 2)) { + return -1; + } + p++; } - return buflen << 1; + } + return buflen << 1; } /* @@ -250,64 +245,63 @@ static int do_hex_dump(BIO *out, unsigned char *buf, int buflen) * encoding. This uses the RFC 2253 #01234 format. */ -static int do_dump(unsigned long flags, BIO *out, const ASN1_STRING *str) -{ - if (!maybe_write(out, "#", 1)) { - return -1; - } - - /* If we don't dump DER encoding just dump content octets */ - if (!(flags & ASN1_STRFLGS_DUMP_DER)) { - int outlen = do_hex_dump(out, str->data, str->length); - if (outlen < 0) { - return -1; - } - return outlen + 1; - } +static int do_dump(unsigned long flags, BIO *out, const ASN1_STRING *str) { + if (!maybe_write(out, "#", 1)) { + return -1; + } - /* - * Placing the ASN1_STRING in a temporary ASN1_TYPE allows the DER encoding - * to readily obtained. - */ - ASN1_TYPE t; - t.type = str->type; - /* Negative INTEGER and ENUMERATED values are the only case where - * |ASN1_STRING| and |ASN1_TYPE| types do not match. - * - * TODO(davidben): There are also some type fields which, in |ASN1_TYPE|, do - * not correspond to |ASN1_STRING|. It is unclear whether those are allowed - * in |ASN1_STRING| at all, or what the space of allowed types is. - * |ASN1_item_ex_d2i| will never produce such a value so, for now, we say - * this is an invalid input. But this corner of the library in general - * should be more robust. */ - if (t.type == V_ASN1_NEG_INTEGER) { - t.type = V_ASN1_INTEGER; - } else if (t.type == V_ASN1_NEG_ENUMERATED) { - t.type = V_ASN1_ENUMERATED; - } - t.value.asn1_string = (ASN1_STRING *)str; - unsigned char *der_buf = NULL; - int der_len = i2d_ASN1_TYPE(&t, &der_buf); - if (der_len < 0) { - return -1; - } - int outlen = do_hex_dump(out, der_buf, der_len); - OPENSSL_free(der_buf); + /* If we don't dump DER encoding just dump content octets */ + if (!(flags & ASN1_STRFLGS_DUMP_DER)) { + int outlen = do_hex_dump(out, str->data, str->length); if (outlen < 0) { - return -1; + return -1; } return outlen + 1; + } + + /* + * Placing the ASN1_STRING in a temporary ASN1_TYPE allows the DER encoding + * to readily obtained. + */ + ASN1_TYPE t; + t.type = str->type; + /* Negative INTEGER and ENUMERATED values are the only case where + * |ASN1_STRING| and |ASN1_TYPE| types do not match. + * + * TODO(davidben): There are also some type fields which, in |ASN1_TYPE|, do + * not correspond to |ASN1_STRING|. It is unclear whether those are allowed + * in |ASN1_STRING| at all, or what the space of allowed types is. + * |ASN1_item_ex_d2i| will never produce such a value so, for now, we say + * this is an invalid input. But this corner of the library in general + * should be more robust. */ + if (t.type == V_ASN1_NEG_INTEGER) { + t.type = V_ASN1_INTEGER; + } else if (t.type == V_ASN1_NEG_ENUMERATED) { + t.type = V_ASN1_ENUMERATED; + } + t.value.asn1_string = (ASN1_STRING *)str; + unsigned char *der_buf = NULL; + int der_len = i2d_ASN1_TYPE(&t, &der_buf); + if (der_len < 0) { + return -1; + } + int outlen = do_hex_dump(out, der_buf, der_len); + OPENSSL_free(der_buf); + if (outlen < 0) { + return -1; + } + return outlen + 1; } /* string_type_to_encoding returns the |MBSTRING_*| constant for the encoding * used by the |ASN1_STRING| type |type|, or -1 if |tag| is not a string * type. */ static int string_type_to_encoding(int type) { - /* This function is sometimes passed ASN.1 universal types and sometimes - * passed |ASN1_STRING| type values */ - switch (type) { + /* This function is sometimes passed ASN.1 universal types and sometimes + * passed |ASN1_STRING| type values */ + switch (type) { case V_ASN1_UTF8STRING: - return MBSTRING_UTF8; + return MBSTRING_UTF8; case V_ASN1_NUMERICSTRING: case V_ASN1_PRINTABLESTRING: case V_ASN1_T61STRING: @@ -315,14 +309,14 @@ static int string_type_to_encoding(int type) { case V_ASN1_UTCTIME: case V_ASN1_GENERALIZEDTIME: case V_ASN1_ISO64STRING: - /* |MBSTRING_ASC| refers to Latin-1, not ASCII. */ - return MBSTRING_ASC; + /* |MBSTRING_ASC| refers to Latin-1, not ASCII. */ + return MBSTRING_ASC; case V_ASN1_UNIVERSALSTRING: - return MBSTRING_UNIV; + return MBSTRING_UNIV; case V_ASN1_BMPSTRING: - return MBSTRING_BMP; - } - return -1; + return MBSTRING_BMP; + } + return -1; } /* @@ -331,219 +325,227 @@ static int string_type_to_encoding(int type) { * an error occurred. */ -int ASN1_STRING_print_ex(BIO *out, const ASN1_STRING *str, unsigned long flags) -{ - int type = str->type; - int outlen = 0; - if (flags & ASN1_STRFLGS_SHOW_TYPE) { - const char *tagname = ASN1_tag2str(type); - outlen += strlen(tagname); - if (!maybe_write(out, tagname, outlen) || !maybe_write(out, ":", 1)) - return -1; - outlen++; - } - - /* Decide what to do with |str|, either dump the contents or display it. */ - int encoding; - if (flags & ASN1_STRFLGS_DUMP_ALL) { - /* Dump everything. */ - encoding = -1; - } else if (flags & ASN1_STRFLGS_IGNORE_TYPE) { - /* Ignore the string type and interpret the contents as Latin-1. */ - encoding = MBSTRING_ASC; - } else { - encoding = string_type_to_encoding(type); - if (encoding == -1 && (flags & ASN1_STRFLGS_DUMP_UNKNOWN) == 0) { - encoding = MBSTRING_ASC; - } - } - - if (encoding == -1) { - int len = do_dump(flags, out, str); - if (len < 0) - return -1; - outlen += len; - return outlen; +int ASN1_STRING_print_ex(BIO *out, const ASN1_STRING *str, + unsigned long flags) { + int type = str->type; + int outlen = 0; + if (flags & ASN1_STRFLGS_SHOW_TYPE) { + const char *tagname = ASN1_tag2str(type); + outlen += strlen(tagname); + if (!maybe_write(out, tagname, outlen) || !maybe_write(out, ":", 1)) { + return -1; } + outlen++; + } - int utf8_convert = 0; - if (flags & ASN1_STRFLGS_UTF8_CONVERT) { - /* If the string is UTF-8, skip decoding and just interpret it as 1 byte - * per character to avoid converting twice. - * - * TODO(davidben): This is not quite a valid optimization if the input - * was invalid UTF-8. */ - if (encoding == MBSTRING_UTF8) { - encoding = MBSTRING_ASC; - } else { - utf8_convert = 1; - } + /* Decide what to do with |str|, either dump the contents or display it. */ + int encoding; + if (flags & ASN1_STRFLGS_DUMP_ALL) { + /* Dump everything. */ + encoding = -1; + } else if (flags & ASN1_STRFLGS_IGNORE_TYPE) { + /* Ignore the string type and interpret the contents as Latin-1. */ + encoding = MBSTRING_ASC; + } else { + encoding = string_type_to_encoding(type); + if (encoding == -1 && (flags & ASN1_STRFLGS_DUMP_UNKNOWN) == 0) { + encoding = MBSTRING_ASC; } + } - /* Measure the length. */ - char quotes = 0; - int len = do_buf(str->data, str->length, encoding, utf8_convert, flags, - "es, NULL); + if (encoding == -1) { + int len = do_dump(flags, out, str); if (len < 0) { - return -1; + return -1; } outlen += len; - if (quotes) { - outlen += 2; - } - if (!out) { - return outlen; - } + return outlen; + } - /* Encode the value. */ - if ((quotes && !maybe_write(out, "\"", 1)) || - do_buf(str->data, str->length, encoding, utf8_convert, flags, NULL, - out) < 0 || - (quotes && !maybe_write(out, "\"", 1))) { - return -1; + int utf8_convert = 0; + if (flags & ASN1_STRFLGS_UTF8_CONVERT) { + /* If the string is UTF-8, skip decoding and just interpret it as 1 byte + * per character to avoid converting twice. + * + * TODO(davidben): This is not quite a valid optimization if the input + * was invalid UTF-8. */ + if (encoding == MBSTRING_UTF8) { + encoding = MBSTRING_ASC; + } else { + utf8_convert = 1; } + } + + /* Measure the length. */ + char quotes = 0; + int len = do_buf(str->data, str->length, encoding, utf8_convert, flags, + "es, NULL); + if (len < 0) { + return -1; + } + outlen += len; + if (quotes) { + outlen += 2; + } + if (!out) { return outlen; + } + + /* Encode the value. */ + if ((quotes && !maybe_write(out, "\"", 1)) || + do_buf(str->data, str->length, encoding, utf8_convert, flags, NULL, out) < + 0 || + (quotes && !maybe_write(out, "\"", 1))) { + return -1; + } + return outlen; } int ASN1_STRING_print_ex_fp(FILE *fp, const ASN1_STRING *str, - unsigned long flags) -{ - BIO *bio = NULL; - if (fp != NULL) { - /* If |fp| is NULL, this function returns the number of bytes without - * writing. */ - bio = BIO_new_fp(fp, BIO_NOCLOSE); - if (bio == NULL) { - return -1; - } + unsigned long flags) { + BIO *bio = NULL; + if (fp != NULL) { + /* If |fp| is NULL, this function returns the number of bytes without + * writing. */ + bio = BIO_new_fp(fp, BIO_NOCLOSE); + if (bio == NULL) { + return -1; } - int ret = ASN1_STRING_print_ex(bio, str, flags); - BIO_free(bio); - return ret; + } + int ret = ASN1_STRING_print_ex(bio, str, flags); + BIO_free(bio); + return ret; } -int ASN1_STRING_to_UTF8(unsigned char **out, const ASN1_STRING *in) -{ - if (!in) - return -1; - int mbflag = string_type_to_encoding(in->type); - if (mbflag == -1) { - OPENSSL_PUT_ERROR(ASN1, ASN1_R_UNKNOWN_TAG); - return -1; - } - ASN1_STRING stmp, *str = &stmp; - stmp.data = NULL; - stmp.length = 0; - stmp.flags = 0; - int ret = ASN1_mbstring_copy(&str, in->data, in->length, mbflag, - B_ASN1_UTF8STRING); - if (ret < 0) - return ret; - *out = stmp.data; - return stmp.length; +int ASN1_STRING_to_UTF8(unsigned char **out, const ASN1_STRING *in) { + if (!in) { + return -1; + } + int mbflag = string_type_to_encoding(in->type); + if (mbflag == -1) { + OPENSSL_PUT_ERROR(ASN1, ASN1_R_UNKNOWN_TAG); + return -1; + } + ASN1_STRING stmp, *str = &stmp; + stmp.data = NULL; + stmp.length = 0; + stmp.flags = 0; + int ret = + ASN1_mbstring_copy(&str, in->data, in->length, mbflag, B_ASN1_UTF8STRING); + if (ret < 0) { + return ret; + } + *out = stmp.data; + return stmp.length; } -int ASN1_STRING_print(BIO *bp, const ASN1_STRING *v) -{ - int i, n; - char buf[80]; - const char *p; +int ASN1_STRING_print(BIO *bp, const ASN1_STRING *v) { + int i, n; + char buf[80]; + const char *p; - if (v == NULL) + if (v == NULL) { + return (0); + } + n = 0; + p = (const char *)v->data; + for (i = 0; i < v->length; i++) { + if ((p[i] > '~') || ((p[i] < ' ') && (p[i] != '\n') && (p[i] != '\r'))) { + buf[n] = '.'; + } else { + buf[n] = p[i]; + } + n++; + if (n >= 80) { + if (BIO_write(bp, buf, n) <= 0) { return (0); - n = 0; - p = (const char *)v->data; - for (i = 0; i < v->length; i++) { - if ((p[i] > '~') || ((p[i] < ' ') && - (p[i] != '\n') && (p[i] != '\r'))) - buf[n] = '.'; - else - buf[n] = p[i]; - n++; - if (n >= 80) { - if (BIO_write(bp, buf, n) <= 0) - return (0); - n = 0; - } + } + n = 0; } - if (n > 0) - if (BIO_write(bp, buf, n) <= 0) - return (0); - return (1); + } + if (n > 0) { + if (BIO_write(bp, buf, n) <= 0) { + return (0); + } + } + return (1); } -int ASN1_TIME_print(BIO *bp, const ASN1_TIME *tm) -{ - if (tm->type == V_ASN1_UTCTIME) - return ASN1_UTCTIME_print(bp, tm); - if (tm->type == V_ASN1_GENERALIZEDTIME) - return ASN1_GENERALIZEDTIME_print(bp, tm); - BIO_write(bp, "Bad time value", 14); - return (0); +int ASN1_TIME_print(BIO *bp, const ASN1_TIME *tm) { + if (tm->type == V_ASN1_UTCTIME) { + return ASN1_UTCTIME_print(bp, tm); + } + if (tm->type == V_ASN1_GENERALIZEDTIME) { + return ASN1_GENERALIZEDTIME_print(bp, tm); + } + BIO_write(bp, "Bad time value", 14); + return (0); } -static const char *const mon[12] = { - "Jan", "Feb", "Mar", "Apr", "May", "Jun", - "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" -}; - -int ASN1_GENERALIZEDTIME_print(BIO *bp, const ASN1_GENERALIZEDTIME *tm) -{ - char *v; - int gmt = 0; - int i; - int y = 0, M = 0, d = 0, h = 0, m = 0, s = 0; - char *f = NULL; - int f_len = 0; - - i = tm->length; - v = (char *)tm->data; - - if (i < 12) - goto err; - if (v[i - 1] == 'Z') - gmt = 1; - for (i = 0; i < 12; i++) - if ((v[i] > '9') || (v[i] < '0')) - goto err; - y = (v[0] - '0') * 1000 + (v[1] - '0') * 100 + (v[2] - '0') * 10 + (v[3] - - '0'); - M = (v[4] - '0') * 10 + (v[5] - '0'); - if ((M > 12) || (M < 1)) - goto err; - d = (v[6] - '0') * 10 + (v[7] - '0'); - h = (v[8] - '0') * 10 + (v[9] - '0'); - m = (v[10] - '0') * 10 + (v[11] - '0'); - if (tm->length >= 14 && - (v[12] >= '0') && (v[12] <= '9') && - (v[13] >= '0') && (v[13] <= '9')) { - s = (v[12] - '0') * 10 + (v[13] - '0'); - /* Check for fractions of seconds. */ - if (tm->length >= 15 && v[14] == '.') { - int l = tm->length; - f = &v[14]; /* The decimal point. */ - f_len = 1; - while (14 + f_len < l && f[f_len] >= '0' && f[f_len] <= '9') - ++f_len; - } +static const char *const mon[12] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun", + "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"}; + +int ASN1_GENERALIZEDTIME_print(BIO *bp, const ASN1_GENERALIZEDTIME *tm) { + char *v; + int gmt = 0; + int i; + int y = 0, M = 0, d = 0, h = 0, m = 0, s = 0; + char *f = NULL; + int f_len = 0; + + i = tm->length; + v = (char *)tm->data; + + if (i < 12) { + goto err; + } + if (v[i - 1] == 'Z') { + gmt = 1; + } + for (i = 0; i < 12; i++) { + if ((v[i] > '9') || (v[i] < '0')) { + goto err; + } + } + y = (v[0] - '0') * 1000 + (v[1] - '0') * 100 + (v[2] - '0') * 10 + + (v[3] - '0'); + M = (v[4] - '0') * 10 + (v[5] - '0'); + if ((M > 12) || (M < 1)) { + goto err; + } + d = (v[6] - '0') * 10 + (v[7] - '0'); + h = (v[8] - '0') * 10 + (v[9] - '0'); + m = (v[10] - '0') * 10 + (v[11] - '0'); + if (tm->length >= 14 && (v[12] >= '0') && (v[12] <= '9') && (v[13] >= '0') && + (v[13] <= '9')) { + s = (v[12] - '0') * 10 + (v[13] - '0'); + /* Check for fractions of seconds. */ + if (tm->length >= 15 && v[14] == '.') { + int l = tm->length; + f = &v[14]; /* The decimal point. */ + f_len = 1; + while (14 + f_len < l && f[f_len] >= '0' && f[f_len] <= '9') { + ++f_len; + } } + } - if (BIO_printf(bp, "%s %2d %02d:%02d:%02d%.*s %d%s", - mon[M - 1], d, h, m, s, f_len, f, y, - (gmt) ? " GMT" : "") <= 0) - return (0); - else - return (1); - err: - BIO_write(bp, "Bad time value", 14); + if (BIO_printf(bp, "%s %2d %02d:%02d:%02d%.*s %d%s", mon[M - 1], d, h, m, s, + f_len, f, y, (gmt) ? " GMT" : "") <= 0) { return (0); + } else { + return (1); + } +err: + BIO_write(bp, "Bad time value", 14); + return (0); } // consume_two_digits is a helper function for ASN1_UTCTIME_print. If |*v|, // assumed to be |*len| bytes long, has two leading digits, updates |*out| with // their value, updates |v| and |len|, and returns one. Otherwise, returns // zero. -static int consume_two_digits(int* out, const char **v, int *len) { +static int consume_two_digits(int *out, const char **v, int *len) { if (*len < 2 || !isdigit((unsigned char)((*v)[0])) || !isdigit((unsigned char)((*v)[1]))) { return 0; @@ -573,10 +575,8 @@ int ASN1_UTCTIME_print(BIO *bp, const ASN1_UTCTIME *tm) { int Y = 0, M = 0, D = 0, h = 0, m = 0, s = 0; // YYMMDDhhmm are required to be present. - if (!consume_two_digits(&Y, &v, &len) || - !consume_two_digits(&M, &v, &len) || - !consume_two_digits(&D, &v, &len) || - !consume_two_digits(&h, &v, &len) || + if (!consume_two_digits(&Y, &v, &len) || !consume_two_digits(&M, &v, &len) || + !consume_two_digits(&D, &v, &len) || !consume_two_digits(&h, &v, &len) || !consume_two_digits(&m, &v, &len)) { goto err; } diff --git a/crypto/asn1/a_strnid.c b/crypto/asn1/a_strnid.c index bc9226a3a6..937b7949a3 100644 --- a/crypto/asn1/a_strnid.c +++ b/crypto/asn1/a_strnid.c @@ -74,19 +74,11 @@ DEFINE_LHASH_OF(ASN1_STRING_TABLE) static LHASH_OF(ASN1_STRING_TABLE) *string_tables = NULL; static struct CRYPTO_STATIC_MUTEX string_tables_lock = CRYPTO_STATIC_MUTEX_INIT; -void ASN1_STRING_set_default_mask(unsigned long mask) -{ -} +void ASN1_STRING_set_default_mask(unsigned long mask) {} -unsigned long ASN1_STRING_get_default_mask(void) -{ - return B_ASN1_UTF8STRING; -} +unsigned long ASN1_STRING_get_default_mask(void) { return B_ASN1_UTF8STRING; } -int ASN1_STRING_set_default_mask_asc(const char *p) -{ - return 1; -} +int ASN1_STRING_set_default_mask_asc(const char *p) { return 1; } static const ASN1_STRING_TABLE *asn1_string_table_get(int nid); @@ -97,28 +89,27 @@ static const ASN1_STRING_TABLE *asn1_string_table_get(int nid); */ ASN1_STRING *ASN1_STRING_set_by_NID(ASN1_STRING **out, const unsigned char *in, - int len, int inform, int nid) -{ - ASN1_STRING *str = NULL; - int ret; - if (!out) { - out = &str; - } - const ASN1_STRING_TABLE *tbl = asn1_string_table_get(nid); - if (tbl != NULL) { - unsigned long mask = tbl->mask; - if (!(tbl->flags & STABLE_NO_MASK)) { - mask &= B_ASN1_UTF8STRING; - } - ret = ASN1_mbstring_ncopy(out, in, len, inform, mask, tbl->minsize, - tbl->maxsize); - } else { - ret = ASN1_mbstring_copy(out, in, len, inform, B_ASN1_UTF8STRING); - } - if (ret <= 0) { - return NULL; + int len, int inform, int nid) { + ASN1_STRING *str = NULL; + int ret; + if (!out) { + out = &str; + } + const ASN1_STRING_TABLE *tbl = asn1_string_table_get(nid); + if (tbl != NULL) { + unsigned long mask = tbl->mask; + if (!(tbl->flags & STABLE_NO_MASK)) { + mask &= B_ASN1_UTF8STRING; } - return *out; + ret = ASN1_mbstring_ncopy(out, in, len, inform, mask, tbl->minsize, + tbl->maxsize); + } else { + ret = ASN1_mbstring_copy(out, in, len, inform, B_ASN1_UTF8STRING); + } + if (ret <= 0) { + return NULL; + } + return *out; } /* @@ -126,14 +117,14 @@ ASN1_STRING *ASN1_STRING_set_by_NID(ASN1_STRING **out, const unsigned char *in, */ /* See RFC 5280. */ -#define ub_name 32768 -#define ub_common_name 64 -#define ub_locality_name 128 -#define ub_state_name 128 -#define ub_organization_name 64 -#define ub_organization_unit_name 64 -#define ub_email_address 128 -#define ub_serial_number 64 +#define ub_name 32768 +#define ub_common_name 64 +#define ub_locality_name 128 +#define ub_state_name 128 +#define ub_organization_name 64 +#define ub_organization_unit_name 64 +#define ub_email_address 128 +#define ub_serial_number 64 /* This table must be kept in NID order */ @@ -159,108 +150,100 @@ static const ASN1_STRING_TABLE tbl_standard[] = { {NID_name, 1, ub_name, DIRSTRING_TYPE, 0}, {NID_dnQualifier, -1, -1, B_ASN1_PRINTABLESTRING, STABLE_NO_MASK}, {NID_domainComponent, 1, -1, B_ASN1_IA5STRING, STABLE_NO_MASK}, - {NID_ms_csp_name, -1, -1, B_ASN1_BMPSTRING, STABLE_NO_MASK} -}; + {NID_ms_csp_name, -1, -1, B_ASN1_BMPSTRING, STABLE_NO_MASK}}; -static int table_cmp(const ASN1_STRING_TABLE *a, const ASN1_STRING_TABLE *b) -{ - if (a->nid < b->nid) { - return -1; - } - if (a->nid > b->nid) { - return 1; - } - return 0; +static int table_cmp(const ASN1_STRING_TABLE *a, const ASN1_STRING_TABLE *b) { + if (a->nid < b->nid) { + return -1; + } + if (a->nid > b->nid) { + return 1; + } + return 0; } -static int table_cmp_void(const void *a, const void *b) -{ - return table_cmp(a, b); +static int table_cmp_void(const void *a, const void *b) { + return table_cmp(a, b); } -static uint32_t table_hash(const ASN1_STRING_TABLE *tbl) -{ - return OPENSSL_hash32(&tbl->nid, sizeof(tbl->nid)); +static uint32_t table_hash(const ASN1_STRING_TABLE *tbl) { + return OPENSSL_hash32(&tbl->nid, sizeof(tbl->nid)); } -static const ASN1_STRING_TABLE *asn1_string_table_get(int nid) -{ - ASN1_STRING_TABLE key; - key.nid = nid; - const ASN1_STRING_TABLE *tbl = - bsearch(&key, tbl_standard, OPENSSL_ARRAY_SIZE(tbl_standard), - sizeof(ASN1_STRING_TABLE), table_cmp_void); - if (tbl != NULL) { - return tbl; - } - - CRYPTO_STATIC_MUTEX_lock_read(&string_tables_lock); - if (string_tables != NULL) { - tbl = lh_ASN1_STRING_TABLE_retrieve(string_tables, &key); - } - CRYPTO_STATIC_MUTEX_unlock_read(&string_tables_lock); - /* Note returning |tbl| without the lock is only safe because - * |ASN1_STRING_TABLE_add| cannot modify or delete existing entries. If we - * wish to support that, this function must copy the result under a lock. */ +static const ASN1_STRING_TABLE *asn1_string_table_get(int nid) { + ASN1_STRING_TABLE key; + key.nid = nid; + const ASN1_STRING_TABLE *tbl = + bsearch(&key, tbl_standard, OPENSSL_ARRAY_SIZE(tbl_standard), + sizeof(ASN1_STRING_TABLE), table_cmp_void); + if (tbl != NULL) { return tbl; + } + + CRYPTO_STATIC_MUTEX_lock_read(&string_tables_lock); + if (string_tables != NULL) { + tbl = lh_ASN1_STRING_TABLE_retrieve(string_tables, &key); + } + CRYPTO_STATIC_MUTEX_unlock_read(&string_tables_lock); + /* Note returning |tbl| without the lock is only safe because + * |ASN1_STRING_TABLE_add| cannot modify or delete existing entries. If we + * wish to support that, this function must copy the result under a lock. */ + return tbl; } int ASN1_STRING_TABLE_add(int nid, long minsize, long maxsize, - unsigned long mask, unsigned long flags) -{ - /* Existing entries cannot be overwritten. */ - if (asn1_string_table_get(nid) != NULL) { - OPENSSL_PUT_ERROR(ASN1, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); - return 0; - } + unsigned long mask, unsigned long flags) { + /* Existing entries cannot be overwritten. */ + if (asn1_string_table_get(nid) != NULL) { + OPENSSL_PUT_ERROR(ASN1, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); + return 0; + } - int ret = 0; - CRYPTO_STATIC_MUTEX_lock_write(&string_tables_lock); + int ret = 0; + CRYPTO_STATIC_MUTEX_lock_write(&string_tables_lock); + if (string_tables == NULL) { + string_tables = lh_ASN1_STRING_TABLE_new(table_hash, table_cmp); if (string_tables == NULL) { - string_tables = lh_ASN1_STRING_TABLE_new(table_hash, table_cmp); - if (string_tables == NULL) { - goto err; - } - } else { - /* Check again for an existing entry. One may have been added while - * unlocked. */ - ASN1_STRING_TABLE key; - key.nid = nid; - if (lh_ASN1_STRING_TABLE_retrieve(string_tables, &key) != NULL) { - OPENSSL_PUT_ERROR(ASN1, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); - goto err; - } + goto err; } - - ASN1_STRING_TABLE *tbl = OPENSSL_malloc(sizeof(ASN1_STRING_TABLE)); - if (tbl == NULL) { - goto err; - } - tbl->nid = nid; - tbl->flags = flags; - tbl->minsize = minsize; - tbl->maxsize = maxsize; - tbl->mask = mask; - ASN1_STRING_TABLE *old_tbl; - if (!lh_ASN1_STRING_TABLE_insert(string_tables, &old_tbl, tbl)) { - OPENSSL_free(tbl); - goto err; + } else { + /* Check again for an existing entry. One may have been added while + * unlocked. */ + ASN1_STRING_TABLE key; + key.nid = nid; + if (lh_ASN1_STRING_TABLE_retrieve(string_tables, &key) != NULL) { + OPENSSL_PUT_ERROR(ASN1, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); + goto err; } - assert(old_tbl == NULL); - ret = 1; + } + + ASN1_STRING_TABLE *tbl = OPENSSL_malloc(sizeof(ASN1_STRING_TABLE)); + if (tbl == NULL) { + goto err; + } + tbl->nid = nid; + tbl->flags = flags; + tbl->minsize = minsize; + tbl->maxsize = maxsize; + tbl->mask = mask; + ASN1_STRING_TABLE *old_tbl; + if (!lh_ASN1_STRING_TABLE_insert(string_tables, &old_tbl, tbl)) { + OPENSSL_free(tbl); + goto err; + } + assert(old_tbl == NULL); + ret = 1; err: - CRYPTO_STATIC_MUTEX_unlock_write(&string_tables_lock); - return ret; + CRYPTO_STATIC_MUTEX_unlock_write(&string_tables_lock); + return ret; } -void ASN1_STRING_TABLE_cleanup(void) -{ -} +void ASN1_STRING_TABLE_cleanup(void) {} void asn1_get_string_table_for_testing(const ASN1_STRING_TABLE **out_ptr, size_t *out_len) { - *out_ptr = tbl_standard; - *out_len = OPENSSL_ARRAY_SIZE(tbl_standard); + *out_ptr = tbl_standard; + *out_len = OPENSSL_ARRAY_SIZE(tbl_standard); } diff --git a/crypto/asn1/a_time.c b/crypto/asn1/a_time.c index 1195569d43..5fdbc336ba 100644 --- a/crypto/asn1/a_time.c +++ b/crypto/asn1/a_time.c @@ -75,138 +75,147 @@ IMPLEMENT_ASN1_MSTRING(ASN1_TIME, B_ASN1_TIME) IMPLEMENT_ASN1_FUNCTIONS_const(ASN1_TIME) -ASN1_TIME *ASN1_TIME_set(ASN1_TIME *s, time_t t) -{ - return ASN1_TIME_adj(s, t, 0, 0); +ASN1_TIME *ASN1_TIME_set(ASN1_TIME *s, time_t t) { + return ASN1_TIME_adj(s, t, 0, 0); } -ASN1_TIME *ASN1_TIME_adj(ASN1_TIME *s, time_t t, - int offset_day, long offset_sec) -{ - struct tm *ts; - struct tm data; +ASN1_TIME *ASN1_TIME_adj(ASN1_TIME *s, time_t t, int offset_day, + long offset_sec) { + struct tm *ts; + struct tm data; - ts = OPENSSL_gmtime(&t, &data); - if (ts == NULL) { - OPENSSL_PUT_ERROR(ASN1, ASN1_R_ERROR_GETTING_TIME); - return NULL; - } - if (offset_day || offset_sec) { - if (!OPENSSL_gmtime_adj(ts, offset_day, offset_sec)) - return NULL; + ts = OPENSSL_gmtime(&t, &data); + if (ts == NULL) { + OPENSSL_PUT_ERROR(ASN1, ASN1_R_ERROR_GETTING_TIME); + return NULL; + } + if (offset_day || offset_sec) { + if (!OPENSSL_gmtime_adj(ts, offset_day, offset_sec)) { + return NULL; } - if ((ts->tm_year >= 50) && (ts->tm_year < 150)) - return ASN1_UTCTIME_adj(s, t, offset_day, offset_sec); - return ASN1_GENERALIZEDTIME_adj(s, t, offset_day, offset_sec); + } + if ((ts->tm_year >= 50) && (ts->tm_year < 150)) { + return ASN1_UTCTIME_adj(s, t, offset_day, offset_sec); + } + return ASN1_GENERALIZEDTIME_adj(s, t, offset_day, offset_sec); } -int ASN1_TIME_check(const ASN1_TIME *t) -{ - if (t->type == V_ASN1_GENERALIZEDTIME) - return ASN1_GENERALIZEDTIME_check(t); - else if (t->type == V_ASN1_UTCTIME) - return ASN1_UTCTIME_check(t); - return 0; +int ASN1_TIME_check(const ASN1_TIME *t) { + if (t->type == V_ASN1_GENERALIZEDTIME) { + return ASN1_GENERALIZEDTIME_check(t); + } else if (t->type == V_ASN1_UTCTIME) { + return ASN1_UTCTIME_check(t); + } + return 0; } /* Convert an ASN1_TIME structure to GeneralizedTime */ ASN1_GENERALIZEDTIME *ASN1_TIME_to_generalizedtime(const ASN1_TIME *t, - ASN1_GENERALIZEDTIME **out) -{ - ASN1_GENERALIZEDTIME *ret = NULL; - char *str; - int newlen; - - if (!ASN1_TIME_check(t)) - return NULL; - - if (!out || !*out) { - if (!(ret = ASN1_GENERALIZEDTIME_new())) - goto err; - } else { - ret = *out; - } + ASN1_GENERALIZEDTIME **out) { + ASN1_GENERALIZEDTIME *ret = NULL; + char *str; + int newlen; - /* If already GeneralizedTime just copy across */ - if (t->type == V_ASN1_GENERALIZEDTIME) { - if (!ASN1_STRING_set(ret, t->data, t->length)) - goto err; - goto done; - } - - /* grow the string */ - if (!ASN1_STRING_set(ret, NULL, t->length + 2)) - goto err; - /* ASN1_STRING_set() allocated 'len + 1' bytes. */ - newlen = t->length + 2 + 1; - str = (char *)ret->data; - /* Work out the century and prepend */ - if (t->data[0] >= '5') - OPENSSL_strlcpy(str, "19", newlen); - else - OPENSSL_strlcpy(str, "20", newlen); - - OPENSSL_strlcat(str, (char *)t->data, newlen); - - done: - if (out != NULL && *out == NULL) - *out = ret; - return ret; - - err: - if (out == NULL || *out != ret) - ASN1_GENERALIZEDTIME_free(ret); + if (!ASN1_TIME_check(t)) { return NULL; + } + + if (!out || !*out) { + if (!(ret = ASN1_GENERALIZEDTIME_new())) { + goto err; + } + } else { + ret = *out; + } + + /* If already GeneralizedTime just copy across */ + if (t->type == V_ASN1_GENERALIZEDTIME) { + if (!ASN1_STRING_set(ret, t->data, t->length)) { + goto err; + } + goto done; + } + + /* grow the string */ + if (!ASN1_STRING_set(ret, NULL, t->length + 2)) { + goto err; + } + /* ASN1_STRING_set() allocated 'len + 1' bytes. */ + newlen = t->length + 2 + 1; + str = (char *)ret->data; + /* Work out the century and prepend */ + if (t->data[0] >= '5') { + OPENSSL_strlcpy(str, "19", newlen); + } else { + OPENSSL_strlcpy(str, "20", newlen); + } + + OPENSSL_strlcat(str, (char *)t->data, newlen); + +done: + if (out != NULL && *out == NULL) { + *out = ret; + } + return ret; + +err: + if (out == NULL || *out != ret) { + ASN1_GENERALIZEDTIME_free(ret); + } + return NULL; } -int ASN1_TIME_set_string(ASN1_TIME *s, const char *str) -{ - ASN1_TIME t; +int ASN1_TIME_set_string(ASN1_TIME *s, const char *str) { + ASN1_TIME t; - t.length = strlen(str); - t.data = (unsigned char *)str; - t.flags = 0; + t.length = strlen(str); + t.data = (unsigned char *)str; + t.flags = 0; - t.type = V_ASN1_UTCTIME; + t.type = V_ASN1_UTCTIME; + if (!ASN1_TIME_check(&t)) { + t.type = V_ASN1_GENERALIZEDTIME; if (!ASN1_TIME_check(&t)) { - t.type = V_ASN1_GENERALIZEDTIME; - if (!ASN1_TIME_check(&t)) - return 0; + return 0; } + } - if (s && !ASN1_STRING_copy((ASN1_STRING *)s, (ASN1_STRING *)&t)) - return 0; + if (s && !ASN1_STRING_copy((ASN1_STRING *)s, (ASN1_STRING *)&t)) { + return 0; + } - return 1; + return 1; } -static int asn1_time_to_tm(struct tm *tm, const ASN1_TIME *t) -{ - if (t == NULL) { - time_t now_t; - time(&now_t); - if (OPENSSL_gmtime(&now_t, tm)) - return 1; - return 0; +static int asn1_time_to_tm(struct tm *tm, const ASN1_TIME *t) { + if (t == NULL) { + time_t now_t; + time(&now_t); + if (OPENSSL_gmtime(&now_t, tm)) { + return 1; } + return 0; + } - if (t->type == V_ASN1_UTCTIME) - return asn1_utctime_to_tm(tm, t); - else if (t->type == V_ASN1_GENERALIZEDTIME) - return asn1_generalizedtime_to_tm(tm, t); + if (t->type == V_ASN1_UTCTIME) { + return asn1_utctime_to_tm(tm, t); + } else if (t->type == V_ASN1_GENERALIZEDTIME) { + return asn1_generalizedtime_to_tm(tm, t); + } - return 0; + return 0; } -int ASN1_TIME_diff(int *out_days, int *out_seconds, - const ASN1_TIME *from, const ASN1_TIME *to) -{ - struct tm tm_from, tm_to; - if (!asn1_time_to_tm(&tm_from, from)) - return 0; - if (!asn1_time_to_tm(&tm_to, to)) - return 0; - return OPENSSL_gmtime_diff(out_days, out_seconds, &tm_from, &tm_to); +int ASN1_TIME_diff(int *out_days, int *out_seconds, const ASN1_TIME *from, + const ASN1_TIME *to) { + struct tm tm_from, tm_to; + if (!asn1_time_to_tm(&tm_from, from)) { + return 0; + } + if (!asn1_time_to_tm(&tm_to, to)) { + return 0; + } + return OPENSSL_gmtime_diff(out_days, out_seconds, &tm_from, &tm_to); } diff --git a/crypto/asn1/a_type.c b/crypto/asn1/a_type.c index c63030b97b..1a53c93958 100644 --- a/crypto/asn1/a_type.c +++ b/crypto/asn1/a_type.c @@ -64,76 +64,75 @@ #include "internal.h" -int ASN1_TYPE_get(const ASN1_TYPE *a) -{ - if (a->type == V_ASN1_BOOLEAN || a->type == V_ASN1_NULL || - a->value.ptr != NULL) { - return a->type; - } - return 0; +int ASN1_TYPE_get(const ASN1_TYPE *a) { + if (a->type == V_ASN1_BOOLEAN || a->type == V_ASN1_NULL || + a->value.ptr != NULL) { + return a->type; + } + return 0; } -const void *asn1_type_value_as_pointer(const ASN1_TYPE *a) -{ - if (a->type == V_ASN1_BOOLEAN) { - return a->value.boolean ? (void *)0xff : NULL; - } - if (a->type == V_ASN1_NULL) { - return NULL; - } - return a->value.ptr; +const void *asn1_type_value_as_pointer(const ASN1_TYPE *a) { + if (a->type == V_ASN1_BOOLEAN) { + return a->value.boolean ? (void *)0xff : NULL; + } + if (a->type == V_ASN1_NULL) { + return NULL; + } + return a->value.ptr; } -void ASN1_TYPE_set(ASN1_TYPE *a, int type, void *value) -{ - ASN1_TYPE **tmp_a = &a; - ASN1_primitive_free((ASN1_VALUE **)tmp_a, NULL); - a->type = type; - if (type == V_ASN1_BOOLEAN) - a->value.boolean = value ? 0xff : 0; - else - a->value.ptr = value; +void ASN1_TYPE_set(ASN1_TYPE *a, int type, void *value) { + ASN1_TYPE **tmp_a = &a; + ASN1_primitive_free((ASN1_VALUE **)tmp_a, NULL); + a->type = type; + if (type == V_ASN1_BOOLEAN) { + a->value.boolean = value ? 0xff : 0; + } else { + a->value.ptr = value; + } } -int ASN1_TYPE_set1(ASN1_TYPE *a, int type, const void *value) -{ - if (!value || (type == V_ASN1_BOOLEAN)) { - void *p = (void *)value; - ASN1_TYPE_set(a, type, p); - } else if (type == V_ASN1_OBJECT) { - ASN1_OBJECT *odup; - odup = OBJ_dup(value); - if (!odup) - return 0; - ASN1_TYPE_set(a, type, odup); - } else { - ASN1_STRING *sdup; - sdup = ASN1_STRING_dup(value); - if (!sdup) - return 0; - ASN1_TYPE_set(a, type, sdup); +int ASN1_TYPE_set1(ASN1_TYPE *a, int type, const void *value) { + if (!value || (type == V_ASN1_BOOLEAN)) { + void *p = (void *)value; + ASN1_TYPE_set(a, type, p); + } else if (type == V_ASN1_OBJECT) { + ASN1_OBJECT *odup; + odup = OBJ_dup(value); + if (!odup) { + return 0; } - return 1; + ASN1_TYPE_set(a, type, odup); + } else { + ASN1_STRING *sdup; + sdup = ASN1_STRING_dup(value); + if (!sdup) { + return 0; + } + ASN1_TYPE_set(a, type, sdup); + } + return 1; } /* Returns 0 if they are equal, != 0 otherwise. */ -int ASN1_TYPE_cmp(const ASN1_TYPE *a, const ASN1_TYPE *b) -{ - int result = -1; +int ASN1_TYPE_cmp(const ASN1_TYPE *a, const ASN1_TYPE *b) { + int result = -1; - if (!a || !b || a->type != b->type) - return -1; + if (!a || !b || a->type != b->type) { + return -1; + } - switch (a->type) { + switch (a->type) { case V_ASN1_OBJECT: - result = OBJ_cmp(a->value.object, b->value.object); - break; + result = OBJ_cmp(a->value.object, b->value.object); + break; case V_ASN1_NULL: - result = 0; /* They do not have content. */ - break; + result = 0; /* They do not have content. */ + break; case V_ASN1_BOOLEAN: - result = a->value.boolean - b->value.boolean; - break; + result = a->value.boolean - b->value.boolean; + break; case V_ASN1_INTEGER: case V_ASN1_ENUMERATED: case V_ASN1_BIT_STRING: @@ -155,9 +154,9 @@ int ASN1_TYPE_cmp(const ASN1_TYPE *a, const ASN1_TYPE *b) case V_ASN1_UTF8STRING: case V_ASN1_OTHER: default: - result = ASN1_STRING_cmp(a->value.asn1_string, b->value.asn1_string); - break; - } + result = ASN1_STRING_cmp(a->value.asn1_string, b->value.asn1_string); + break; + } - return result; + return result; } diff --git a/crypto/asn1/a_utctm.c b/crypto/asn1/a_utctm.c index 21ea2cc3eb..c0cc2f9c89 100644 --- a/crypto/asn1/a_utctm.c +++ b/crypto/asn1/a_utctm.c @@ -55,210 +55,138 @@ * [including the GNU Public Licence.] */ #include +#include +#include +#include #include #include -#include -#include - #include "internal.h" - -int asn1_utctime_to_tm(struct tm *tm, const ASN1_UTCTIME *d) -{ - static const int min[8] = { 0, 1, 1, 0, 0, 0, 0, 0 }; - static const int max[8] = { 99, 12, 31, 23, 59, 59, 12, 59 }; - char *a; - int n, i, l, o; - - if (d->type != V_ASN1_UTCTIME) - return (0); - l = d->length; - a = (char *)d->data; - o = 0; - - if (l < 11) - goto err; - for (i = 0; i < 6; i++) { - if ((i == 5) && ((a[o] == 'Z') || (a[o] == '+') || (a[o] == '-'))) { - i++; - if (tm) - tm->tm_sec = 0; - break; - } - if ((a[o] < '0') || (a[o] > '9')) - goto err; - n = a[o] - '0'; - if (++o > l) - goto err; - - if ((a[o] < '0') || (a[o] > '9')) - goto err; - n = (n * 10) + a[o] - '0'; - if (++o > l) - goto err; - - if ((n < min[i]) || (n > max[i])) - goto err; - if (tm) { - switch (i) { - case 0: - tm->tm_year = n < 50 ? n + 100 : n; - break; - case 1: - tm->tm_mon = n - 1; - break; - case 2: - tm->tm_mday = n; - break; - case 3: - tm->tm_hour = n; - break; - case 4: - tm->tm_min = n; - break; - case 5: - tm->tm_sec = n; - break; - } - } - } - if (a[o] == 'Z') - o++; - else if ((a[o] == '+') || (a[o] == '-')) { - int offsign = a[o] == '-' ? 1 : -1, offset = 0; - o++; - if (o + 4 > l) - goto err; - for (i = 6; i < 8; i++) { - if ((a[o] < '0') || (a[o] > '9')) - goto err; - n = a[o] - '0'; - o++; - if ((a[o] < '0') || (a[o] > '9')) - goto err; - n = (n * 10) + a[o] - '0'; - if ((n < min[i]) || (n > max[i])) - goto err; - if (tm) { - if (i == 6) - offset = n * 3600; - else if (i == 7) - offset += n * 60; - } - o++; - } - if (offset && !OPENSSL_gmtime_adj(tm, 0, offset * offsign)) - return 0; - } - return o == l; - err: +int asn1_utctime_to_tm(struct tm *tm, const ASN1_UTCTIME *d) { + if (d->type != V_ASN1_UTCTIME) { + return 0; + } + CBS cbs; + CBS_init(&cbs, d->data, (size_t)d->length); + if (!CBS_parse_utc_time(&cbs, tm, /*allow_timezone_offset=*/1)) { return 0; + } + return 1; } -int ASN1_UTCTIME_check(const ASN1_UTCTIME *d) -{ - return asn1_utctime_to_tm(NULL, d); +int ASN1_UTCTIME_check(const ASN1_UTCTIME *d) { + return asn1_utctime_to_tm(NULL, d); } -int ASN1_UTCTIME_set_string(ASN1_UTCTIME *s, const char *str) -{ - ASN1_UTCTIME t; - - t.type = V_ASN1_UTCTIME; - t.length = strlen(str); - t.data = (unsigned char *)str; - if (ASN1_UTCTIME_check(&t)) { - if (s != NULL) { - if (!ASN1_STRING_set((ASN1_STRING *)s, - (unsigned char *)str, t.length)) - return 0; - s->type = V_ASN1_UTCTIME; - } - return (1); - } else - return (0); +int ASN1_UTCTIME_set_string(ASN1_UTCTIME *s, const char *str) { + ASN1_UTCTIME t; + + t.type = V_ASN1_UTCTIME; + t.length = strlen(str); + t.data = (unsigned char *)str; + if (ASN1_UTCTIME_check(&t)) { + if (s != NULL) { + if (!ASN1_STRING_set((ASN1_STRING *)s, (unsigned char *)str, t.length)) { + return 0; + } + s->type = V_ASN1_UTCTIME; + } + return (1); + } else { + return (0); + } } -ASN1_UTCTIME *ASN1_UTCTIME_set(ASN1_UTCTIME *s, time_t t) -{ - return ASN1_UTCTIME_adj(s, t, 0, 0); +ASN1_UTCTIME *ASN1_UTCTIME_set(ASN1_UTCTIME *s, time_t t) { + return ASN1_UTCTIME_adj(s, t, 0, 0); } -ASN1_UTCTIME *ASN1_UTCTIME_adj(ASN1_UTCTIME *s, time_t t, - int offset_day, long offset_sec) -{ - char *p; - struct tm *ts; - struct tm data; - size_t len = 20; - int free_s = 0; - - if (s == NULL) { - free_s = 1; - s = ASN1_UTCTIME_new(); +ASN1_UTCTIME *ASN1_UTCTIME_adj(ASN1_UTCTIME *s, time_t t, int offset_day, + long offset_sec) { + char *p; + struct tm *ts; + struct tm data; + size_t len = 20; + int free_s = 0; + + if (s == NULL) { + free_s = 1; + s = ASN1_UTCTIME_new(); + } + if (s == NULL) { + goto err; + } + + ts = OPENSSL_gmtime(&t, &data); + if (ts == NULL) { + goto err; + } + + if (offset_day || offset_sec) { + if (!OPENSSL_gmtime_adj(ts, offset_day, offset_sec)) { + goto err; } - if (s == NULL) - goto err; - - ts = OPENSSL_gmtime(&t, &data); - if (ts == NULL) - goto err; - - if (offset_day || offset_sec) { - if (!OPENSSL_gmtime_adj(ts, offset_day, offset_sec)) - goto err; + } + + if ((ts->tm_year < 50) || (ts->tm_year >= 150)) { + goto err; + } + + p = (char *)s->data; + if ((p == NULL) || ((size_t)s->length < len)) { + p = OPENSSL_malloc(len); + if (p == NULL) { + OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE); + goto err; } - - if ((ts->tm_year < 50) || (ts->tm_year >= 150)) - goto err; - - p = (char *)s->data; - if ((p == NULL) || ((size_t)s->length < len)) { - p = OPENSSL_malloc(len); - if (p == NULL) { - OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE); - goto err; - } - if (s->data != NULL) - OPENSSL_free(s->data); - s->data = (unsigned char *)p; + if (s->data != NULL) { + OPENSSL_free(s->data); } - - BIO_snprintf(p, len, "%02d%02d%02d%02d%02d%02dZ", ts->tm_year % 100, - ts->tm_mon + 1, ts->tm_mday, ts->tm_hour, ts->tm_min, - ts->tm_sec); - s->length = strlen(p); - s->type = V_ASN1_UTCTIME; - return (s); - err: - if (free_s && s) - ASN1_UTCTIME_free(s); - return NULL; + s->data = (unsigned char *)p; + } + + BIO_snprintf(p, len, "%02d%02d%02d%02d%02d%02dZ", ts->tm_year % 100, + ts->tm_mon + 1, ts->tm_mday, ts->tm_hour, ts->tm_min, + ts->tm_sec); + s->length = strlen(p); + s->type = V_ASN1_UTCTIME; + return (s); +err: + if (free_s && s) { + ASN1_UTCTIME_free(s); + } + return NULL; } -int ASN1_UTCTIME_cmp_time_t(const ASN1_UTCTIME *s, time_t t) -{ - struct tm stm, ttm; - int day, sec; - - if (!asn1_utctime_to_tm(&stm, s)) - return -2; - - if (!OPENSSL_gmtime(&t, &ttm)) - return -2; - - if (!OPENSSL_gmtime_diff(&day, &sec, &ttm, &stm)) - return -2; - - if (day > 0) - return 1; - if (day < 0) - return -1; - if (sec > 0) - return 1; - if (sec < 0) - return -1; - return 0; +int ASN1_UTCTIME_cmp_time_t(const ASN1_UTCTIME *s, time_t t) { + struct tm stm, ttm; + int day, sec; + + if (!asn1_utctime_to_tm(&stm, s)) { + return -2; + } + + if (!OPENSSL_gmtime(&t, &ttm)) { + return -2; + } + + if (!OPENSSL_gmtime_diff(&day, &sec, &ttm, &stm)) { + return -2; + } + + if (day > 0) { + return 1; + } + if (day < 0) { + return -1; + } + if (sec > 0) { + return 1; + } + if (sec < 0) { + return -1; + } + return 0; } diff --git a/crypto/asn1/a_utf8.c b/crypto/asn1/a_utf8.c index 922a780010..0f2cba6488 100644 --- a/crypto/asn1/a_utf8.c +++ b/crypto/asn1/a_utf8.c @@ -72,93 +72,103 @@ * incorrectly (not minimal length). */ -int UTF8_getc(const unsigned char *str, int len, uint32_t *val) -{ - const unsigned char *p; - uint32_t value; - int ret; - if (len <= 0) - return 0; - p = str; +int UTF8_getc(const unsigned char *str, int len, uint32_t *val) { + const unsigned char *p; + uint32_t value; + int ret; + if (len <= 0) { + return 0; + } + p = str; - /* Check syntax and work out the encoded value (if correct) */ - if ((*p & 0x80) == 0) { - value = *p++ & 0x7f; - ret = 1; - } else if ((*p & 0xe0) == 0xc0) { - if (len < 2) - return -1; - if ((p[1] & 0xc0) != 0x80) - return -3; - value = (*p++ & 0x1f) << 6; - value |= *p++ & 0x3f; - if (value < 0x80) - return -4; - ret = 2; - } else if ((*p & 0xf0) == 0xe0) { - if (len < 3) - return -1; - if (((p[1] & 0xc0) != 0x80) - || ((p[2] & 0xc0) != 0x80)) - return -3; - value = (*p++ & 0xf) << 12; - value |= (*p++ & 0x3f) << 6; - value |= *p++ & 0x3f; - if (value < 0x800) - return -4; - ret = 3; - } else if ((*p & 0xf8) == 0xf0) { - if (len < 4) - return -1; - if (((p[1] & 0xc0) != 0x80) - || ((p[2] & 0xc0) != 0x80) - || ((p[3] & 0xc0) != 0x80)) - return -3; - value = ((uint32_t)(*p++ & 0x7)) << 18; - value |= (*p++ & 0x3f) << 12; - value |= (*p++ & 0x3f) << 6; - value |= *p++ & 0x3f; - if (value < 0x10000) - return -4; - ret = 4; - } else if ((*p & 0xfc) == 0xf8) { - if (len < 5) - return -1; - if (((p[1] & 0xc0) != 0x80) - || ((p[2] & 0xc0) != 0x80) - || ((p[3] & 0xc0) != 0x80) - || ((p[4] & 0xc0) != 0x80)) - return -3; - value = ((uint32_t)(*p++ & 0x3)) << 24; - value |= ((uint32_t)(*p++ & 0x3f)) << 18; - value |= ((uint32_t)(*p++ & 0x3f)) << 12; - value |= (*p++ & 0x3f) << 6; - value |= *p++ & 0x3f; - if (value < 0x200000) - return -4; - ret = 5; - } else if ((*p & 0xfe) == 0xfc) { - if (len < 6) - return -1; - if (((p[1] & 0xc0) != 0x80) - || ((p[2] & 0xc0) != 0x80) - || ((p[3] & 0xc0) != 0x80) - || ((p[4] & 0xc0) != 0x80) - || ((p[5] & 0xc0) != 0x80)) - return -3; - value = ((uint32_t)(*p++ & 0x1)) << 30; - value |= ((uint32_t)(*p++ & 0x3f)) << 24; - value |= ((uint32_t)(*p++ & 0x3f)) << 18; - value |= ((uint32_t)(*p++ & 0x3f)) << 12; - value |= (*p++ & 0x3f) << 6; - value |= *p++ & 0x3f; - if (value < 0x4000000) - return -4; - ret = 6; - } else - return -2; - *val = value; - return ret; + /* Check syntax and work out the encoded value (if correct) */ + if ((*p & 0x80) == 0) { + value = *p++ & 0x7f; + ret = 1; + } else if ((*p & 0xe0) == 0xc0) { + if (len < 2) { + return -1; + } + if ((p[1] & 0xc0) != 0x80) { + return -3; + } + value = (*p++ & 0x1f) << 6; + value |= *p++ & 0x3f; + if (value < 0x80) { + return -4; + } + ret = 2; + } else if ((*p & 0xf0) == 0xe0) { + if (len < 3) { + return -1; + } + if (((p[1] & 0xc0) != 0x80) || ((p[2] & 0xc0) != 0x80)) { + return -3; + } + value = (*p++ & 0xf) << 12; + value |= (*p++ & 0x3f) << 6; + value |= *p++ & 0x3f; + if (value < 0x800) { + return -4; + } + ret = 3; + } else if ((*p & 0xf8) == 0xf0) { + if (len < 4) { + return -1; + } + if (((p[1] & 0xc0) != 0x80) || ((p[2] & 0xc0) != 0x80) || + ((p[3] & 0xc0) != 0x80)) { + return -3; + } + value = ((uint32_t)(*p++ & 0x7)) << 18; + value |= (*p++ & 0x3f) << 12; + value |= (*p++ & 0x3f) << 6; + value |= *p++ & 0x3f; + if (value < 0x10000) { + return -4; + } + ret = 4; + } else if ((*p & 0xfc) == 0xf8) { + if (len < 5) { + return -1; + } + if (((p[1] & 0xc0) != 0x80) || ((p[2] & 0xc0) != 0x80) || + ((p[3] & 0xc0) != 0x80) || ((p[4] & 0xc0) != 0x80)) { + return -3; + } + value = ((uint32_t)(*p++ & 0x3)) << 24; + value |= ((uint32_t)(*p++ & 0x3f)) << 18; + value |= ((uint32_t)(*p++ & 0x3f)) << 12; + value |= (*p++ & 0x3f) << 6; + value |= *p++ & 0x3f; + if (value < 0x200000) { + return -4; + } + ret = 5; + } else if ((*p & 0xfe) == 0xfc) { + if (len < 6) { + return -1; + } + if (((p[1] & 0xc0) != 0x80) || ((p[2] & 0xc0) != 0x80) || + ((p[3] & 0xc0) != 0x80) || ((p[4] & 0xc0) != 0x80) || + ((p[5] & 0xc0) != 0x80)) { + return -3; + } + value = ((uint32_t)(*p++ & 0x1)) << 30; + value |= ((uint32_t)(*p++ & 0x3f)) << 24; + value |= ((uint32_t)(*p++ & 0x3f)) << 18; + value |= ((uint32_t)(*p++ & 0x3f)) << 12; + value |= (*p++ & 0x3f) << 6; + value |= *p++ & 0x3f; + if (value < 0x4000000) { + return -4; + } + ret = 6; + } else { + return -2; + } + *val = value; + return ret; } /* @@ -169,68 +179,74 @@ int UTF8_getc(const unsigned char *str, int len, uint32_t *val) * most 6 characters. */ -int UTF8_putc(unsigned char *str, int len, uint32_t value) -{ - if (!str) - len = 6; /* Maximum we will need */ - else if (len <= 0) - return -1; - if (value < 0x80) { - if (str) - *str = (unsigned char)value; - return 1; +int UTF8_putc(unsigned char *str, int len, uint32_t value) { + if (!str) { + len = 6; /* Maximum we will need */ + } else if (len <= 0) { + return -1; + } + if (value < 0x80) { + if (str) { + *str = (unsigned char)value; } - if (value < 0x800) { - if (len < 2) - return -1; - if (str) { - *str++ = (unsigned char)(((value >> 6) & 0x1f) | 0xc0); - *str = (unsigned char)((value & 0x3f) | 0x80); - } - return 2; + return 1; + } + if (value < 0x800) { + if (len < 2) { + return -1; } - if (value < 0x10000) { - if (len < 3) - return -1; - if (str) { - *str++ = (unsigned char)(((value >> 12) & 0xf) | 0xe0); - *str++ = (unsigned char)(((value >> 6) & 0x3f) | 0x80); - *str = (unsigned char)((value & 0x3f) | 0x80); - } - return 3; + if (str) { + *str++ = (unsigned char)(((value >> 6) & 0x1f) | 0xc0); + *str = (unsigned char)((value & 0x3f) | 0x80); } - if (value < 0x200000) { - if (len < 4) - return -1; - if (str) { - *str++ = (unsigned char)(((value >> 18) & 0x7) | 0xf0); - *str++ = (unsigned char)(((value >> 12) & 0x3f) | 0x80); - *str++ = (unsigned char)(((value >> 6) & 0x3f) | 0x80); - *str = (unsigned char)((value & 0x3f) | 0x80); - } - return 4; + return 2; + } + if (value < 0x10000) { + if (len < 3) { + return -1; + } + if (str) { + *str++ = (unsigned char)(((value >> 12) & 0xf) | 0xe0); + *str++ = (unsigned char)(((value >> 6) & 0x3f) | 0x80); + *str = (unsigned char)((value & 0x3f) | 0x80); + } + return 3; + } + if (value < 0x200000) { + if (len < 4) { + return -1; } - if (value < 0x4000000) { - if (len < 5) - return -1; - if (str) { - *str++ = (unsigned char)(((value >> 24) & 0x3) | 0xf8); - *str++ = (unsigned char)(((value >> 18) & 0x3f) | 0x80); - *str++ = (unsigned char)(((value >> 12) & 0x3f) | 0x80); - *str++ = (unsigned char)(((value >> 6) & 0x3f) | 0x80); - *str = (unsigned char)((value & 0x3f) | 0x80); - } - return 5; - } - if (len < 6) - return -1; if (str) { - *str++ = (unsigned char)(((value >> 30) & 0x1) | 0xfc); - *str++ = (unsigned char)(((value >> 24) & 0x3f) | 0x80); - *str++ = (unsigned char)(((value >> 18) & 0x3f) | 0x80); - *str++ = (unsigned char)(((value >> 12) & 0x3f) | 0x80); - *str++ = (unsigned char)(((value >> 6) & 0x3f) | 0x80); - *str = (unsigned char)((value & 0x3f) | 0x80); - } - return 6; + *str++ = (unsigned char)(((value >> 18) & 0x7) | 0xf0); + *str++ = (unsigned char)(((value >> 12) & 0x3f) | 0x80); + *str++ = (unsigned char)(((value >> 6) & 0x3f) | 0x80); + *str = (unsigned char)((value & 0x3f) | 0x80); + } + return 4; + } + if (value < 0x4000000) { + if (len < 5) { + return -1; + } + if (str) { + *str++ = (unsigned char)(((value >> 24) & 0x3) | 0xf8); + *str++ = (unsigned char)(((value >> 18) & 0x3f) | 0x80); + *str++ = (unsigned char)(((value >> 12) & 0x3f) | 0x80); + *str++ = (unsigned char)(((value >> 6) & 0x3f) | 0x80); + *str = (unsigned char)((value & 0x3f) | 0x80); + } + return 5; + } + if (len < 6) { + return -1; + } + if (str) { + *str++ = (unsigned char)(((value >> 30) & 0x1) | 0xfc); + *str++ = (unsigned char)(((value >> 24) & 0x3f) | 0x80); + *str++ = (unsigned char)(((value >> 18) & 0x3f) | 0x80); + *str++ = (unsigned char)(((value >> 12) & 0x3f) | 0x80); + *str++ = (unsigned char)(((value >> 6) & 0x3f) | 0x80); + *str = (unsigned char)((value & 0x3f) | 0x80); + } + return 6; } diff --git a/crypto/asn1/asn1_lib.c b/crypto/asn1/asn1_lib.c index 14bb385079..bc5470659c 100644 --- a/crypto/asn1/asn1_lib.c +++ b/crypto/asn1/asn1_lib.c @@ -107,304 +107,288 @@ OPENSSL_DECLARE_ERROR_REASON(ASN1, UNSUPPORTED_TYPE) static void asn1_put_length(unsigned char **pp, int length); int ASN1_get_object(const unsigned char **inp, long *out_len, int *out_tag, - int *out_class, long in_len) -{ - if (in_len < 0) { - OPENSSL_PUT_ERROR(ASN1, ASN1_R_HEADER_TOO_LONG); - return 0x80; - } - - /* TODO(https://crbug.com/boringssl/354): This should use |CBS_get_asn1| to - * reject non-minimal lengths, which are only allowed in BER. However, - * Android sometimes needs allow a non-minimal length in certificate - * signature fields (see b/18228011). Make this only apply to that field, - * while requiring DER elsewhere. Better yet, it should be limited to an - * preprocessing step in that part of Android. */ - unsigned tag; - size_t header_len; - int indefinite; - CBS cbs, body; - CBS_init(&cbs, *inp, (size_t)in_len); - if (!CBS_get_any_ber_asn1_element(&cbs, &body, &tag, &header_len, - /*out_ber_found=*/NULL, &indefinite) || - indefinite || - !CBS_skip(&body, header_len) || - /* Bound the length to comfortably fit in an int. Lengths in this - * module often switch between int and long without overflow checks. */ - CBS_len(&body) > INT_MAX / 2) { - OPENSSL_PUT_ERROR(ASN1, ASN1_R_HEADER_TOO_LONG); - return 0x80; - } - - /* Convert between tag representations. */ - int tag_class = (tag & CBS_ASN1_CLASS_MASK) >> CBS_ASN1_TAG_SHIFT; - int constructed = (tag & CBS_ASN1_CONSTRUCTED) >> CBS_ASN1_TAG_SHIFT; - int tag_number = tag & CBS_ASN1_TAG_NUMBER_MASK; - - /* To avoid ambiguity with V_ASN1_NEG, impose a limit on universal tags. */ - if (tag_class == V_ASN1_UNIVERSAL && tag_number > V_ASN1_MAX_UNIVERSAL) { - OPENSSL_PUT_ERROR(ASN1, ASN1_R_HEADER_TOO_LONG); - return 0x80; - } - - *inp = CBS_data(&body); - *out_len = CBS_len(&body); - *out_tag = tag_number; - *out_class = tag_class; - return constructed; + int *out_class, long in_len) { + if (in_len < 0) { + OPENSSL_PUT_ERROR(ASN1, ASN1_R_HEADER_TOO_LONG); + return 0x80; + } + + /* TODO(https://crbug.com/boringssl/354): This should use |CBS_get_asn1| to + * reject non-minimal lengths, which are only allowed in BER. However, + * Android sometimes needs allow a non-minimal length in certificate + * signature fields (see b/18228011). Make this only apply to that field, + * while requiring DER elsewhere. Better yet, it should be limited to an + * preprocessing step in that part of Android. */ + unsigned tag; + size_t header_len; + int indefinite; + CBS cbs, body; + CBS_init(&cbs, *inp, (size_t)in_len); + if (!CBS_get_any_ber_asn1_element(&cbs, &body, &tag, &header_len, + /*out_ber_found=*/NULL, &indefinite) || + indefinite || !CBS_skip(&body, header_len) || + /* Bound the length to comfortably fit in an int. Lengths in this + * module often switch between int and long without overflow checks. */ + CBS_len(&body) > INT_MAX / 2) { + OPENSSL_PUT_ERROR(ASN1, ASN1_R_HEADER_TOO_LONG); + return 0x80; + } + + /* Convert between tag representations. */ + int tag_class = (tag & CBS_ASN1_CLASS_MASK) >> CBS_ASN1_TAG_SHIFT; + int constructed = (tag & CBS_ASN1_CONSTRUCTED) >> CBS_ASN1_TAG_SHIFT; + int tag_number = tag & CBS_ASN1_TAG_NUMBER_MASK; + + /* To avoid ambiguity with V_ASN1_NEG, impose a limit on universal tags. */ + if (tag_class == V_ASN1_UNIVERSAL && tag_number > V_ASN1_MAX_UNIVERSAL) { + OPENSSL_PUT_ERROR(ASN1, ASN1_R_HEADER_TOO_LONG); + return 0x80; + } + + *inp = CBS_data(&body); + *out_len = CBS_len(&body); + *out_tag = tag_number; + *out_class = tag_class; + return constructed; } /* * class 0 is constructed constructed == 2 for indefinite length constructed */ void ASN1_put_object(unsigned char **pp, int constructed, int length, int tag, - int xclass) -{ - unsigned char *p = *pp; - int i, ttag; - - i = (constructed) ? V_ASN1_CONSTRUCTED : 0; - i |= (xclass & V_ASN1_PRIVATE); - if (tag < 31) - *(p++) = i | (tag & V_ASN1_PRIMITIVE_TAG); - else { - *(p++) = i | V_ASN1_PRIMITIVE_TAG; - for (i = 0, ttag = tag; ttag > 0; i++) - ttag >>= 7; - ttag = i; - while (i-- > 0) { - p[i] = tag & 0x7f; - if (i != (ttag - 1)) - p[i] |= 0x80; - tag >>= 7; - } - p += ttag; + int xclass) { + unsigned char *p = *pp; + int i, ttag; + + i = (constructed) ? V_ASN1_CONSTRUCTED : 0; + i |= (xclass & V_ASN1_PRIVATE); + if (tag < 31) { + *(p++) = i | (tag & V_ASN1_PRIMITIVE_TAG); + } else { + *(p++) = i | V_ASN1_PRIMITIVE_TAG; + for (i = 0, ttag = tag; ttag > 0; i++) { + ttag >>= 7; + } + ttag = i; + while (i-- > 0) { + p[i] = tag & 0x7f; + if (i != (ttag - 1)) { + p[i] |= 0x80; + } + tag >>= 7; } - if (constructed == 2) - *(p++) = 0x80; - else - asn1_put_length(&p, length); - *pp = p; + p += ttag; + } + if (constructed == 2) { + *(p++) = 0x80; + } else { + asn1_put_length(&p, length); + } + *pp = p; } -int ASN1_put_eoc(unsigned char **pp) -{ - /* This function is no longer used in the library, but some external code - * uses it. */ - unsigned char *p = *pp; - *p++ = 0; - *p++ = 0; - *pp = p; - return 2; +int ASN1_put_eoc(unsigned char **pp) { + /* This function is no longer used in the library, but some external code + * uses it. */ + unsigned char *p = *pp; + *p++ = 0; + *p++ = 0; + *pp = p; + return 2; } -static void asn1_put_length(unsigned char **pp, int length) -{ - unsigned char *p = *pp; - int i, l; - if (length <= 127) - *(p++) = (unsigned char)length; - else { - l = length; - for (i = 0; l > 0; i++) - l >>= 8; - *(p++) = i | 0x80; - l = i; - while (i-- > 0) { - p[i] = length & 0xff; - length >>= 8; - } - p += l; +static void asn1_put_length(unsigned char **pp, int length) { + unsigned char *p = *pp; + int i, l; + if (length <= 127) { + *(p++) = (unsigned char)length; + } else { + l = length; + for (i = 0; l > 0; i++) { + l >>= 8; } - *pp = p; + *(p++) = i | 0x80; + l = i; + while (i-- > 0) { + p[i] = length & 0xff; + length >>= 8; + } + p += l; + } + *pp = p; } -int ASN1_object_size(int constructed, int length, int tag) -{ - int ret = 1; - if (length < 0) - return -1; - if (tag >= 31) { - while (tag > 0) { - tag >>= 7; - ret++; - } +int ASN1_object_size(int constructed, int length, int tag) { + int ret = 1; + if (length < 0) { + return -1; + } + if (tag >= 31) { + while (tag > 0) { + tag >>= 7; + ret++; } - if (constructed == 2) { - ret += 3; - } else { + } + if (constructed == 2) { + ret += 3; + } else { + ret++; + if (length > 127) { + int tmplen = length; + while (tmplen > 0) { + tmplen >>= 8; ret++; - if (length > 127) { - int tmplen = length; - while (tmplen > 0) { - tmplen >>= 8; - ret++; - } - } + } } - if (ret >= INT_MAX - length) - return -1; - return ret + length; + } + if (ret >= INT_MAX - length) { + return -1; + } + return ret + length; } -int ASN1_STRING_copy(ASN1_STRING *dst, const ASN1_STRING *str) -{ - if (str == NULL) - return 0; - if (!ASN1_STRING_set(dst, str->data, str->length)) - return 0; - dst->type = str->type; - dst->flags = str->flags; - return 1; +int ASN1_STRING_copy(ASN1_STRING *dst, const ASN1_STRING *str) { + if (str == NULL) { + return 0; + } + if (!ASN1_STRING_set(dst, str->data, str->length)) { + return 0; + } + dst->type = str->type; + dst->flags = str->flags; + return 1; } -ASN1_STRING *ASN1_STRING_dup(const ASN1_STRING *str) -{ - ASN1_STRING *ret; - if (!str) - return NULL; - ret = ASN1_STRING_new(); - if (!ret) - return NULL; - if (!ASN1_STRING_copy(ret, str)) { - ASN1_STRING_free(ret); - return NULL; - } - return ret; +ASN1_STRING *ASN1_STRING_dup(const ASN1_STRING *str) { + ASN1_STRING *ret; + if (!str) { + return NULL; + } + ret = ASN1_STRING_new(); + if (!ret) { + return NULL; + } + if (!ASN1_STRING_copy(ret, str)) { + ASN1_STRING_free(ret); + return NULL; + } + return ret; } -int ASN1_STRING_set(ASN1_STRING *str, const void *_data, int len) -{ - unsigned char *c; - const char *data = _data; +int ASN1_STRING_set(ASN1_STRING *str, const void *_data, int len) { + unsigned char *c; + const char *data = _data; - if (len < 0) { - if (data == NULL) - return (0); - else - len = strlen(data); - } - if ((str->length <= len) || (str->data == NULL)) { - c = str->data; - if (c == NULL) - str->data = OPENSSL_malloc(len + 1); - else - str->data = OPENSSL_realloc(c, len + 1); - - if (str->data == NULL) { - OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE); - str->data = c; - return (0); - } + if (len < 0) { + if (data == NULL) { + return (0); + } else { + len = strlen(data); } - str->length = len; - if (data != NULL) { - OPENSSL_memcpy(str->data, data, len); - /* an allowance for strings :-) */ - str->data[len] = '\0'; + } + if ((str->length <= len) || (str->data == NULL)) { + c = str->data; + if (c == NULL) { + str->data = OPENSSL_malloc(len + 1); + } else { + str->data = OPENSSL_realloc(c, len + 1); } - return (1); -} -void ASN1_STRING_set0(ASN1_STRING *str, void *data, int len) -{ - OPENSSL_free(str->data); - str->data = data; - str->length = len; + if (str->data == NULL) { + OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE); + str->data = c; + return (0); + } + } + str->length = len; + if (data != NULL) { + OPENSSL_memcpy(str->data, data, len); + /* an allowance for strings :-) */ + str->data[len] = '\0'; + } + return (1); } -ASN1_STRING *ASN1_STRING_new(void) -{ - return (ASN1_STRING_type_new(V_ASN1_OCTET_STRING)); +void ASN1_STRING_set0(ASN1_STRING *str, void *data, int len) { + OPENSSL_free(str->data); + str->data = data; + str->length = len; } -ASN1_STRING *ASN1_STRING_type_new(int type) -{ - ASN1_STRING *ret; - - ret = (ASN1_STRING *)OPENSSL_malloc(sizeof(ASN1_STRING)); - if (ret == NULL) { - OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE); - return (NULL); - } - ret->length = 0; - ret->type = type; - ret->data = NULL; - ret->flags = 0; - return (ret); +ASN1_STRING *ASN1_STRING_new(void) { + return (ASN1_STRING_type_new(V_ASN1_OCTET_STRING)); } -void ASN1_STRING_free(ASN1_STRING *str) -{ - if (str == NULL) - return; - OPENSSL_free(str->data); - OPENSSL_free(str); +ASN1_STRING *ASN1_STRING_type_new(int type) { + ASN1_STRING *ret; + + ret = (ASN1_STRING *)OPENSSL_malloc(sizeof(ASN1_STRING)); + if (ret == NULL) { + OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE); + return (NULL); + } + ret->length = 0; + ret->type = type; + ret->data = NULL; + ret->flags = 0; + return (ret); } -void ASN1_STRING_clear_free(ASN1_STRING *str) -{ - ASN1_STRING_free(str); +void ASN1_STRING_free(ASN1_STRING *str) { + if (str == NULL) { + return; + } + OPENSSL_free(str->data); + OPENSSL_free(str); } -int ASN1_STRING_cmp(const ASN1_STRING *a, const ASN1_STRING *b) -{ - /* Capture padding bits and implicit truncation in BIT STRINGs. */ - int a_length = a->length, b_length = b->length; - uint8_t a_padding = 0, b_padding = 0; - if (a->type == V_ASN1_BIT_STRING) { - a_length = asn1_bit_string_length(a, &a_padding); - } - if (b->type == V_ASN1_BIT_STRING) { - b_length = asn1_bit_string_length(b, &b_padding); - } - - if (a_length < b_length) { - return -1; - } - if (a_length > b_length) { - return 1; - } - /* In a BIT STRING, the number of bits is 8 * length - padding. Invert this - * comparison so we compare by lengths. */ - if (a_padding > b_padding) { - return -1; - } - if (a_padding < b_padding) { - return 1; - } +int ASN1_STRING_cmp(const ASN1_STRING *a, const ASN1_STRING *b) { + /* Capture padding bits and implicit truncation in BIT STRINGs. */ + int a_length = a->length, b_length = b->length; + uint8_t a_padding = 0, b_padding = 0; + if (a->type == V_ASN1_BIT_STRING) { + a_length = asn1_bit_string_length(a, &a_padding); + } + if (b->type == V_ASN1_BIT_STRING) { + b_length = asn1_bit_string_length(b, &b_padding); + } + + if (a_length < b_length) { + return -1; + } + if (a_length > b_length) { + return 1; + } + /* In a BIT STRING, the number of bits is 8 * length - padding. Invert this + * comparison so we compare by lengths. */ + if (a_padding > b_padding) { + return -1; + } + if (a_padding < b_padding) { + return 1; + } - int ret = OPENSSL_memcmp(a->data, b->data, a_length); - if (ret != 0) { - return ret; - } + int ret = OPENSSL_memcmp(a->data, b->data, a_length); + if (ret != 0) { + return ret; + } - /* Comparing the type first is more natural, but this matches OpenSSL. */ - if (a->type < b->type) { - return -1; - } - if (a->type > b->type) { - return 1; - } - return 0; + /* Comparing the type first is more natural, but this matches OpenSSL. */ + if (a->type < b->type) { + return -1; + } + if (a->type > b->type) { + return 1; + } + return 0; } -int ASN1_STRING_length(const ASN1_STRING *str) -{ - return str->length; -} +int ASN1_STRING_length(const ASN1_STRING *str) { return str->length; } -int ASN1_STRING_type(const ASN1_STRING *str) -{ - return str->type; -} +int ASN1_STRING_type(const ASN1_STRING *str) { return str->type; } -unsigned char *ASN1_STRING_data(ASN1_STRING *str) -{ - return str->data; -} +unsigned char *ASN1_STRING_data(ASN1_STRING *str) { return str->data; } -const unsigned char *ASN1_STRING_get0_data(const ASN1_STRING *str) -{ - return str->data; +const unsigned char *ASN1_STRING_get0_data(const ASN1_STRING *str) { + return str->data; } diff --git a/crypto/asn1/asn1_par.c b/crypto/asn1/asn1_par.c index dc229843f6..d065e200f6 100644 --- a/crypto/asn1/asn1_par.c +++ b/crypto/asn1/asn1_par.c @@ -57,46 +57,47 @@ #include -const char *ASN1_tag2str(int tag) -{ - static const char *const tag2str[] = { - "EOC", - "BOOLEAN", - "INTEGER", - "BIT STRING", - "OCTET STRING", - "NULL", - "OBJECT", - "OBJECT DESCRIPTOR", - "EXTERNAL", - "REAL", - "ENUMERATED", - "", - "UTF8STRING", - "", - "", - "", - "SEQUENCE", - "SET", - "NUMERICSTRING", - "PRINTABLESTRING", - "T61STRING", - "VIDEOTEXSTRING", - "IA5STRING", - "UTCTIME", - "GENERALIZEDTIME", - "GRAPHICSTRING", - "VISIBLESTRING", - "GENERALSTRING", - "UNIVERSALSTRING", - "", - "BMPSTRING", - }; +const char *ASN1_tag2str(int tag) { + static const char *const tag2str[] = { + "EOC", + "BOOLEAN", + "INTEGER", + "BIT STRING", + "OCTET STRING", + "NULL", + "OBJECT", + "OBJECT DESCRIPTOR", + "EXTERNAL", + "REAL", + "ENUMERATED", + "", + "UTF8STRING", + "", + "", + "", + "SEQUENCE", + "SET", + "NUMERICSTRING", + "PRINTABLESTRING", + "T61STRING", + "VIDEOTEXSTRING", + "IA5STRING", + "UTCTIME", + "GENERALIZEDTIME", + "GRAPHICSTRING", + "VISIBLESTRING", + "GENERALSTRING", + "UNIVERSALSTRING", + "", + "BMPSTRING", + }; - if ((tag == V_ASN1_NEG_INTEGER) || (tag == V_ASN1_NEG_ENUMERATED)) - tag &= ~V_ASN1_NEG; + if ((tag == V_ASN1_NEG_INTEGER) || (tag == V_ASN1_NEG_ENUMERATED)) { + tag &= ~V_ASN1_NEG; + } - if (tag < 0 || tag > 30) - return "(unknown)"; - return tag2str[tag]; + if (tag < 0 || tag > 30) { + return "(unknown)"; + } + return tag2str[tag]; } diff --git a/crypto/asn1/asn1_test.cc b/crypto/asn1/asn1_test.cc index 6087ef4462..ec6b3719c0 100644 --- a/crypto/asn1/asn1_test.cc +++ b/crypto/asn1/asn1_test.cc @@ -901,6 +901,31 @@ static std::string ASN1StringToStdString(const ASN1_STRING *str) { ASN1_STRING_get0_data(str) + ASN1_STRING_length(str)); } +static bool ASN1Time_check_time_t(const ASN1_TIME *s, time_t t) { + struct tm stm, ttm; + int day, sec; + + switch (ASN1_STRING_type(s)) { + case V_ASN1_GENERALIZEDTIME: + if (!asn1_generalizedtime_to_tm(&stm, s)) { + return false; + } + break; + case V_ASN1_UTCTIME: + if (!asn1_utctime_to_tm(&stm, s)) { + return false; + } + break; + default: + return 0; + } + if (!OPENSSL_gmtime(&t, &ttm) || + !OPENSSL_gmtime_diff(&day, &sec, &ttm, &stm)) { + return false; + } + return day == 0 && sec ==0; +} + TEST(ASN1Test, SetTime) { static const struct { time_t time; @@ -911,6 +936,7 @@ TEST(ASN1Test, SetTime) { {-631152000, "19500101000000Z", "500101000000Z"}, {0, "19700101000000Z", "700101000000Z"}, {981173106, "20010203040506Z", "010203040506Z"}, + {951804000, "20000229060000Z", "000229060000Z"}, #if defined(OPENSSL_64_BIT) // TODO(https://crbug.com/boringssl/416): These cases overflow 32-bit // |time_t| and do not consistently work on 32-bit platforms. For now, @@ -939,6 +965,7 @@ TEST(ASN1Test, SetTime) { ASSERT_TRUE(utc); EXPECT_EQ(V_ASN1_UTCTIME, ASN1_STRING_type(utc.get())); EXPECT_EQ(t.utc, ASN1StringToStdString(utc.get())); + EXPECT_TRUE(ASN1Time_check_time_t(utc.get(), t.time)); } else { EXPECT_FALSE(utc); } @@ -949,6 +976,7 @@ TEST(ASN1Test, SetTime) { ASSERT_TRUE(generalized); EXPECT_EQ(V_ASN1_GENERALIZEDTIME, ASN1_STRING_type(generalized.get())); EXPECT_EQ(t.generalized, ASN1StringToStdString(generalized.get())); + EXPECT_TRUE(ASN1Time_check_time_t(generalized.get(), t.time)); } else { EXPECT_FALSE(generalized); } @@ -963,6 +991,7 @@ TEST(ASN1Test, SetTime) { EXPECT_EQ(V_ASN1_GENERALIZEDTIME, ASN1_STRING_type(choice.get())); EXPECT_EQ(t.generalized, ASN1StringToStdString(choice.get())); } + EXPECT_TRUE(ASN1Time_check_time_t(choice.get(), t.time)); } else { EXPECT_FALSE(choice); } diff --git a/crypto/asn1/asn_pack.c b/crypto/asn1/asn_pack.c index 9124f23d5c..069cef0b3c 100644 --- a/crypto/asn1/asn_pack.c +++ b/crypto/asn1/asn_pack.c @@ -60,42 +60,40 @@ #include -ASN1_STRING *ASN1_item_pack(void *obj, const ASN1_ITEM *it, ASN1_STRING **out) -{ - uint8_t *new_data = NULL; - int len = ASN1_item_i2d(obj, &new_data, it); - if (len <= 0) { - OPENSSL_PUT_ERROR(ASN1, ASN1_R_ENCODE_ERROR); - return NULL; - } +ASN1_STRING *ASN1_item_pack(void *obj, const ASN1_ITEM *it, ASN1_STRING **out) { + uint8_t *new_data = NULL; + int len = ASN1_item_i2d(obj, &new_data, it); + if (len <= 0) { + OPENSSL_PUT_ERROR(ASN1, ASN1_R_ENCODE_ERROR); + return NULL; + } - ASN1_STRING *ret = NULL; - if (out == NULL || *out == NULL) { - ret = ASN1_STRING_new(); - if (ret == NULL) { - OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE); - OPENSSL_free(new_data); - return NULL; - } - } else { - ret = *out; + ASN1_STRING *ret = NULL; + if (out == NULL || *out == NULL) { + ret = ASN1_STRING_new(); + if (ret == NULL) { + OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE); + OPENSSL_free(new_data); + return NULL; } + } else { + ret = *out; + } - ASN1_STRING_set0(ret, new_data, len); - if (out != NULL) { - *out = ret; - } - return ret; + ASN1_STRING_set0(ret, new_data, len); + if (out != NULL) { + *out = ret; + } + return ret; } -void *ASN1_item_unpack(const ASN1_STRING *oct, const ASN1_ITEM *it) -{ - const unsigned char *p = oct->data; - void *ret = ASN1_item_d2i(NULL, &p, oct->length, it); - if (ret == NULL || p != oct->data + oct->length) { - OPENSSL_PUT_ERROR(ASN1, ASN1_R_DECODE_ERROR); - ASN1_item_free(ret, it); - return NULL; - } - return ret; +void *ASN1_item_unpack(const ASN1_STRING *oct, const ASN1_ITEM *it) { + const unsigned char *p = oct->data; + void *ret = ASN1_item_d2i(NULL, &p, oct->length, it); + if (ret == NULL || p != oct->data + oct->length) { + OPENSSL_PUT_ERROR(ASN1, ASN1_R_DECODE_ERROR); + ASN1_item_free(ret, it); + return NULL; + } + return ret; } diff --git a/crypto/asn1/f_int.c b/crypto/asn1/f_int.c index c2597888bf..84bf667fc4 100644 --- a/crypto/asn1/f_int.c +++ b/crypto/asn1/f_int.c @@ -58,45 +58,48 @@ #include -int i2a_ASN1_INTEGER(BIO *bp, const ASN1_INTEGER *a) -{ - int i, n = 0; - static const char *h = "0123456789ABCDEF"; - char buf[2]; +int i2a_ASN1_INTEGER(BIO *bp, const ASN1_INTEGER *a) { + int i, n = 0; + static const char *h = "0123456789ABCDEF"; + char buf[2]; - if (a == NULL) - return (0); + if (a == NULL) { + return (0); + } - if (a->type & V_ASN1_NEG) { - if (BIO_write(bp, "-", 1) != 1) - goto err; - n = 1; + if (a->type & V_ASN1_NEG) { + if (BIO_write(bp, "-", 1) != 1) { + goto err; } + n = 1; + } - if (a->length == 0) { - if (BIO_write(bp, "00", 2) != 2) - goto err; - n += 2; - } else { - for (i = 0; i < a->length; i++) { - if ((i != 0) && (i % 35 == 0)) { - if (BIO_write(bp, "\\\n", 2) != 2) - goto err; - n += 2; - } - buf[0] = h[((unsigned char)a->data[i] >> 4) & 0x0f]; - buf[1] = h[((unsigned char)a->data[i]) & 0x0f]; - if (BIO_write(bp, buf, 2) != 2) - goto err; - n += 2; + if (a->length == 0) { + if (BIO_write(bp, "00", 2) != 2) { + goto err; + } + n += 2; + } else { + for (i = 0; i < a->length; i++) { + if ((i != 0) && (i % 35 == 0)) { + if (BIO_write(bp, "\\\n", 2) != 2) { + goto err; } + n += 2; + } + buf[0] = h[((unsigned char)a->data[i] >> 4) & 0x0f]; + buf[1] = h[((unsigned char)a->data[i]) & 0x0f]; + if (BIO_write(bp, buf, 2) != 2) { + goto err; + } + n += 2; } - return (n); - err: - return (-1); + } + return (n); +err: + return (-1); } -int i2a_ASN1_ENUMERATED(BIO *bp, const ASN1_ENUMERATED *a) -{ - return i2a_ASN1_INTEGER(bp, a); +int i2a_ASN1_ENUMERATED(BIO *bp, const ASN1_ENUMERATED *a) { + return i2a_ASN1_INTEGER(bp, a); } diff --git a/crypto/asn1/f_string.c b/crypto/asn1/f_string.c index 01d9dec002..d0fca61130 100644 --- a/crypto/asn1/f_string.c +++ b/crypto/asn1/f_string.c @@ -58,34 +58,37 @@ #include -int i2a_ASN1_STRING(BIO *bp, const ASN1_STRING *a, int type) -{ - int i, n = 0; - static const char *h = "0123456789ABCDEF"; - char buf[2]; +int i2a_ASN1_STRING(BIO *bp, const ASN1_STRING *a, int type) { + int i, n = 0; + static const char *h = "0123456789ABCDEF"; + char buf[2]; - if (a == NULL) - return (0); + if (a == NULL) { + return (0); + } - if (a->length == 0) { - if (BIO_write(bp, "0", 1) != 1) - goto err; - n = 1; - } else { - for (i = 0; i < a->length; i++) { - if ((i != 0) && (i % 35 == 0)) { - if (BIO_write(bp, "\\\n", 2) != 2) - goto err; - n += 2; - } - buf[0] = h[((unsigned char)a->data[i] >> 4) & 0x0f]; - buf[1] = h[((unsigned char)a->data[i]) & 0x0f]; - if (BIO_write(bp, buf, 2) != 2) - goto err; - n += 2; + if (a->length == 0) { + if (BIO_write(bp, "0", 1) != 1) { + goto err; + } + n = 1; + } else { + for (i = 0; i < a->length; i++) { + if ((i != 0) && (i % 35 == 0)) { + if (BIO_write(bp, "\\\n", 2) != 2) { + goto err; } + n += 2; + } + buf[0] = h[((unsigned char)a->data[i] >> 4) & 0x0f]; + buf[1] = h[((unsigned char)a->data[i]) & 0x0f]; + if (BIO_write(bp, buf, 2) != 2) { + goto err; + } + n += 2; } - return (n); - err: - return (-1); + } + return (n); +err: + return (-1); } diff --git a/crypto/asn1/internal.h b/crypto/asn1/internal.h index 5bdaac8f39..a6929e3ce7 100644 --- a/crypto/asn1/internal.h +++ b/crypto/asn1/internal.h @@ -72,7 +72,7 @@ extern "C" { /* Wrapper functions for time functions. */ /* OPENSSL_gmtime wraps |gmtime_r|. See the manual page for that function. */ -struct tm *OPENSSL_gmtime(const time_t *time, struct tm *result); +OPENSSL_EXPORT struct tm *OPENSSL_gmtime(const time_t *time, struct tm *result); /* OPENSSL_gmtime_adj updates |tm| by adding |offset_day| days and |offset_sec| * seconds. */ @@ -81,9 +81,9 @@ int OPENSSL_gmtime_adj(struct tm *tm, int offset_day, long offset_sec); /* OPENSSL_gmtime_diff calculates the difference between |from| and |to| and * outputs the difference as a number of days and seconds in |*out_days| and * |*out_secs|. */ -int OPENSSL_gmtime_diff(int *out_days, int *out_secs, const struct tm *from, - const struct tm *to); - +OPENSSL_EXPORT int OPENSSL_gmtime_diff(int *out_days, int *out_secs, + const struct tm *from, + const struct tm *to); /* Internal ASN1 structures and functions: not for application use */ @@ -126,8 +126,9 @@ typedef struct ASN1_ENCODING_st { unsigned alias_only_on_next_parse : 1; } ASN1_ENCODING; -int asn1_utctime_to_tm(struct tm *tm, const ASN1_UTCTIME *d); -int asn1_generalizedtime_to_tm(struct tm *tm, const ASN1_GENERALIZEDTIME *d); +OPENSSL_EXPORT int asn1_utctime_to_tm(struct tm *tm, const ASN1_UTCTIME *d); +OPENSSL_EXPORT int asn1_generalizedtime_to_tm(struct tm *tm, + const ASN1_GENERALIZEDTIME *d); void asn1_item_combine_free(ASN1_VALUE **pval, const ASN1_ITEM *it, int combine); @@ -218,7 +219,7 @@ OPENSSL_EXPORT void asn1_get_string_table_for_testing( #if defined(__cplusplus) -} /* extern C */ +} /* extern C */ #endif -#endif /* OPENSSL_HEADER_ASN1_ASN1_LOCL_H */ +#endif /* OPENSSL_HEADER_ASN1_ASN1_LOCL_H */ diff --git a/crypto/asn1/tasn_dec.c b/crypto/asn1/tasn_dec.c index 1d5edb1b35..f86026e3b1 100644 --- a/crypto/asn1/tasn_dec.c +++ b/crypto/asn1/tasn_dec.c @@ -55,14 +55,14 @@ * [including the GNU Public Licence.] */ #include - -#include -#include - #include +#include #include #include +#include +#include + #include "../internal.h" #include "internal.h" @@ -78,20 +78,17 @@ static int asn1_check_tlen(long *olen, int *otag, unsigned char *oclass, char *cst, const unsigned char **in, long len, int exptag, int expclass, char opt); -static int asn1_template_ex_d2i(ASN1_VALUE **pval, - const unsigned char **in, long len, - const ASN1_TEMPLATE *tt, char opt, +static int asn1_template_ex_d2i(ASN1_VALUE **pval, const unsigned char **in, + long len, const ASN1_TEMPLATE *tt, char opt, int depth); -static int asn1_template_noexp_d2i(ASN1_VALUE **val, - const unsigned char **in, long len, - const ASN1_TEMPLATE *tt, char opt, +static int asn1_template_noexp_d2i(ASN1_VALUE **val, const unsigned char **in, + long len, const ASN1_TEMPLATE *tt, char opt, int depth); static int asn1_ex_c2i(ASN1_VALUE **pval, const unsigned char *cont, int len, int utype, const ASN1_ITEM *it); -static int asn1_d2i_ex_primitive(ASN1_VALUE **pval, - const unsigned char **in, long len, - const ASN1_ITEM *it, - int tag, int aclass, char opt); +static int asn1_d2i_ex_primitive(ASN1_VALUE **pval, const unsigned char **in, + long len, const ASN1_ITEM *it, int tag, + int aclass, char opt); static int asn1_item_ex_d2i(ASN1_VALUE **pval, const unsigned char **in, long len, const ASN1_ITEM *it, int tag, int aclass, char opt, int depth); @@ -131,11 +128,11 @@ static const unsigned long tag2bit[31] = { B_ASN1_BMPSTRING, }; -unsigned long ASN1_tag2bit(int tag) -{ - if (tag < 0 || tag > 30) - return 0; - return tag2bit[tag]; +unsigned long ASN1_tag2bit(int tag) { + if (tag < 0 || tag > 30) { + return 0; + } + return tag2bit[tag]; } /* Macro to initialize and invalidate the cache */ @@ -147,17 +144,17 @@ unsigned long ASN1_tag2bit(int tag) * this will simply be a special case. */ -ASN1_VALUE *ASN1_item_d2i(ASN1_VALUE **pval, - const unsigned char **in, long len, - const ASN1_ITEM *it) -{ - ASN1_VALUE *ptmpval = NULL; - if (!pval) - pval = &ptmpval; - - if (asn1_item_ex_d2i(pval, in, len, it, -1, 0, 0, 0) > 0) - return *pval; - return NULL; +ASN1_VALUE *ASN1_item_d2i(ASN1_VALUE **pval, const unsigned char **in, long len, + const ASN1_ITEM *it) { + ASN1_VALUE *ptmpval = NULL; + if (!pval) { + pval = &ptmpval; + } + + if (asn1_item_ex_d2i(pval, in, len, it, -1, 0, 0, 0) > 0) { + return *pval; + } + return NULL; } /* @@ -167,307 +164,316 @@ ASN1_VALUE *ASN1_item_d2i(ASN1_VALUE **pval, static int asn1_item_ex_d2i(ASN1_VALUE **pval, const unsigned char **in, long len, const ASN1_ITEM *it, int tag, int aclass, - char opt, int depth) -{ - const ASN1_TEMPLATE *tt, *errtt = NULL; - const ASN1_EXTERN_FUNCS *ef; - const unsigned char *p = NULL, *q; - unsigned char oclass; - char cst, isopt; - int i; - int otag; - int ret = 0; - ASN1_VALUE **pchptr; - int combine = aclass & ASN1_TFLG_COMBINE; - aclass &= ~ASN1_TFLG_COMBINE; - if (!pval) - return 0; - - /* - * Bound |len| to comfortably fit in an int. Lengths in this module often - * switch between int and long without overflow checks. - */ - if (len > INT_MAX/2) { - len = INT_MAX/2; - } - - if (++depth > ASN1_MAX_CONSTRUCTED_NEST) { - OPENSSL_PUT_ERROR(ASN1, ASN1_R_NESTED_TOO_DEEP); - goto err; - } - - switch (it->itype) { + char opt, int depth) { + const ASN1_TEMPLATE *tt, *errtt = NULL; + const ASN1_EXTERN_FUNCS *ef; + const unsigned char *p = NULL, *q; + unsigned char oclass; + char cst, isopt; + int i; + int otag; + int ret = 0; + ASN1_VALUE **pchptr; + int combine = aclass & ASN1_TFLG_COMBINE; + aclass &= ~ASN1_TFLG_COMBINE; + if (!pval) { + return 0; + } + + /* + * Bound |len| to comfortably fit in an int. Lengths in this module often + * switch between int and long without overflow checks. + */ + if (len > INT_MAX / 2) { + len = INT_MAX / 2; + } + + if (++depth > ASN1_MAX_CONSTRUCTED_NEST) { + OPENSSL_PUT_ERROR(ASN1, ASN1_R_NESTED_TOO_DEEP); + goto err; + } + + switch (it->itype) { case ASN1_ITYPE_PRIMITIVE: - if (it->templates) { - /* - * tagging or OPTIONAL is currently illegal on an item template - * because the flags can't get passed down. In practice this - * isn't a problem: we include the relevant flags from the item - * template in the template itself. - */ - if ((tag != -1) || opt) { - OPENSSL_PUT_ERROR(ASN1, - ASN1_R_ILLEGAL_OPTIONS_ON_ITEM_TEMPLATE); - goto err; - } - return asn1_template_ex_d2i(pval, in, len, - it->templates, opt, depth); - } - return asn1_d2i_ex_primitive(pval, in, len, it, - tag, aclass, opt); - break; - - case ASN1_ITYPE_MSTRING: + if (it->templates) { /* - * It never makes sense for multi-strings to have implicit tagging, so - * if tag != -1, then this looks like an error in the template. + * tagging or OPTIONAL is currently illegal on an item template + * because the flags can't get passed down. In practice this + * isn't a problem: we include the relevant flags from the item + * template in the template itself. */ - if (tag != -1) { - OPENSSL_PUT_ERROR(ASN1, ASN1_R_BAD_TEMPLATE); - goto err; + if ((tag != -1) || opt) { + OPENSSL_PUT_ERROR(ASN1, ASN1_R_ILLEGAL_OPTIONS_ON_ITEM_TEMPLATE); + goto err; } + return asn1_template_ex_d2i(pval, in, len, it->templates, opt, depth); + } + return asn1_d2i_ex_primitive(pval, in, len, it, tag, aclass, opt); + break; - p = *in; - /* Just read in tag and class */ - ret = asn1_check_tlen(NULL, &otag, &oclass, NULL, - &p, len, -1, 0, 1); - if (!ret) { - OPENSSL_PUT_ERROR(ASN1, ASN1_R_NESTED_ASN1_ERROR); - goto err; - } + case ASN1_ITYPE_MSTRING: + /* + * It never makes sense for multi-strings to have implicit tagging, so + * if tag != -1, then this looks like an error in the template. + */ + if (tag != -1) { + OPENSSL_PUT_ERROR(ASN1, ASN1_R_BAD_TEMPLATE); + goto err; + } - /* Must be UNIVERSAL class */ - if (oclass != V_ASN1_UNIVERSAL) { - /* If OPTIONAL, assume this is OK */ - if (opt) - return -1; - OPENSSL_PUT_ERROR(ASN1, ASN1_R_MSTRING_NOT_UNIVERSAL); - goto err; - } + p = *in; + /* Just read in tag and class */ + ret = asn1_check_tlen(NULL, &otag, &oclass, NULL, &p, len, -1, 0, 1); + if (!ret) { + OPENSSL_PUT_ERROR(ASN1, ASN1_R_NESTED_ASN1_ERROR); + goto err; + } - /* Check tag matches bit map */ - if (!(ASN1_tag2bit(otag) & it->utype)) { - /* If OPTIONAL, assume this is OK */ - if (opt) - return -1; - OPENSSL_PUT_ERROR(ASN1, ASN1_R_MSTRING_WRONG_TAG); - goto err; + /* Must be UNIVERSAL class */ + if (oclass != V_ASN1_UNIVERSAL) { + /* If OPTIONAL, assume this is OK */ + if (opt) { + return -1; } - return asn1_d2i_ex_primitive(pval, in, len, it, otag, 0, 0); + OPENSSL_PUT_ERROR(ASN1, ASN1_R_MSTRING_NOT_UNIVERSAL); + goto err; + } + /* Check tag matches bit map */ + if (!(ASN1_tag2bit(otag) & it->utype)) { + /* If OPTIONAL, assume this is OK */ + if (opt) { + return -1; + } + OPENSSL_PUT_ERROR(ASN1, ASN1_R_MSTRING_WRONG_TAG); + goto err; + } + return asn1_d2i_ex_primitive(pval, in, len, it, otag, 0, 0); case ASN1_ITYPE_EXTERN: - /* Use new style d2i */ - ef = it->funcs; - return ef->asn1_ex_d2i(pval, in, len, it, tag, aclass, opt, NULL); + /* Use new style d2i */ + ef = it->funcs; + return ef->asn1_ex_d2i(pval, in, len, it, tag, aclass, opt, NULL); case ASN1_ITYPE_CHOICE: { + /* + * It never makes sense for CHOICE types to have implicit tagging, so if + * tag != -1, then this looks like an error in the template. + */ + if (tag != -1) { + OPENSSL_PUT_ERROR(ASN1, ASN1_R_BAD_TEMPLATE); + goto err; + } + + const ASN1_AUX *aux = it->funcs; + ASN1_aux_cb *asn1_cb = aux != NULL ? aux->asn1_cb : NULL; + if (asn1_cb && !asn1_cb(ASN1_OP_D2I_PRE, pval, it, NULL)) { + goto auxerr; + } + + if (*pval) { + /* Free up and zero CHOICE value if initialised */ + i = asn1_get_choice_selector(pval, it); + if ((i >= 0) && (i < it->tcount)) { + tt = it->templates + i; + pchptr = asn1_get_field_ptr(pval, tt); + ASN1_template_free(pchptr, tt); + asn1_set_choice_selector(pval, -1, it); + } + } else if (!ASN1_item_ex_new(pval, it)) { + OPENSSL_PUT_ERROR(ASN1, ASN1_R_NESTED_ASN1_ERROR); + goto err; + } + /* CHOICE type, try each possibility in turn */ + p = *in; + for (i = 0, tt = it->templates; i < it->tcount; i++, tt++) { + pchptr = asn1_get_field_ptr(pval, tt); /* - * It never makes sense for CHOICE types to have implicit tagging, so if - * tag != -1, then this looks like an error in the template. + * We mark field as OPTIONAL so its absence can be recognised. */ - if (tag != -1) { - OPENSSL_PUT_ERROR(ASN1, ASN1_R_BAD_TEMPLATE); - goto err; - } - - const ASN1_AUX *aux = it->funcs; - ASN1_aux_cb *asn1_cb = aux != NULL ? aux->asn1_cb : NULL; - if (asn1_cb && !asn1_cb(ASN1_OP_D2I_PRE, pval, it, NULL)) - goto auxerr; - - if (*pval) { - /* Free up and zero CHOICE value if initialised */ - i = asn1_get_choice_selector(pval, it); - if ((i >= 0) && (i < it->tcount)) { - tt = it->templates + i; - pchptr = asn1_get_field_ptr(pval, tt); - ASN1_template_free(pchptr, tt); - asn1_set_choice_selector(pval, -1, it); - } - } else if (!ASN1_item_ex_new(pval, it)) { - OPENSSL_PUT_ERROR(ASN1, ASN1_R_NESTED_ASN1_ERROR); - goto err; + ret = asn1_template_ex_d2i(pchptr, &p, len, tt, 1, depth); + /* If field not present, try the next one */ + if (ret == -1) { + continue; } - /* CHOICE type, try each possibility in turn */ - p = *in; - for (i = 0, tt = it->templates; i < it->tcount; i++, tt++) { - pchptr = asn1_get_field_ptr(pval, tt); - /* - * We mark field as OPTIONAL so its absence can be recognised. - */ - ret = asn1_template_ex_d2i(pchptr, &p, len, tt, 1, depth); - /* If field not present, try the next one */ - if (ret == -1) - continue; - /* If positive return, read OK, break loop */ - if (ret > 0) - break; - /* Otherwise must be an ASN1 parsing error */ - errtt = tt; - OPENSSL_PUT_ERROR(ASN1, ASN1_R_NESTED_ASN1_ERROR); - goto err; + /* If positive return, read OK, break loop */ + if (ret > 0) { + break; } + /* Otherwise must be an ASN1 parsing error */ + errtt = tt; + OPENSSL_PUT_ERROR(ASN1, ASN1_R_NESTED_ASN1_ERROR); + goto err; + } - /* Did we fall off the end without reading anything? */ - if (i == it->tcount) { - /* If OPTIONAL, this is OK */ - if (opt) { - /* Free and zero it */ - ASN1_item_ex_free(pval, it); - return -1; - } - OPENSSL_PUT_ERROR(ASN1, ASN1_R_NO_MATCHING_CHOICE_TYPE); - goto err; + /* Did we fall off the end without reading anything? */ + if (i == it->tcount) { + /* If OPTIONAL, this is OK */ + if (opt) { + /* Free and zero it */ + ASN1_item_ex_free(pval, it); + return -1; } - - asn1_set_choice_selector(pval, i, it); - if (asn1_cb && !asn1_cb(ASN1_OP_D2I_POST, pval, it, NULL)) - goto auxerr; - *in = p; - return 1; + OPENSSL_PUT_ERROR(ASN1, ASN1_R_NO_MATCHING_CHOICE_TYPE); + goto err; + } + + asn1_set_choice_selector(pval, i, it); + if (asn1_cb && !asn1_cb(ASN1_OP_D2I_POST, pval, it, NULL)) { + goto auxerr; + } + *in = p; + return 1; } case ASN1_ITYPE_SEQUENCE: { - p = *in; + p = *in; - /* If no IMPLICIT tagging set to SEQUENCE, UNIVERSAL */ - if (tag == -1) { - tag = V_ASN1_SEQUENCE; - aclass = V_ASN1_UNIVERSAL; - } - /* Get SEQUENCE length and update len, p */ - ret = asn1_check_tlen(&len, NULL, NULL, &cst, - &p, len, tag, aclass, opt); - if (!ret) { - OPENSSL_PUT_ERROR(ASN1, ASN1_R_NESTED_ASN1_ERROR); - goto err; - } else if (ret == -1) - return -1; - if (!cst) { - OPENSSL_PUT_ERROR(ASN1, ASN1_R_SEQUENCE_NOT_CONSTRUCTED); - goto err; - } - - if (!*pval && !ASN1_item_ex_new(pval, it)) { - OPENSSL_PUT_ERROR(ASN1, ASN1_R_NESTED_ASN1_ERROR); - goto err; - } - - const ASN1_AUX *aux = it->funcs; - ASN1_aux_cb *asn1_cb = aux != NULL ? aux->asn1_cb : NULL; - if (asn1_cb && !asn1_cb(ASN1_OP_D2I_PRE, pval, it, NULL)) - goto auxerr; - - /* Free up and zero any ADB found */ - for (i = 0, tt = it->templates; i < it->tcount; i++, tt++) { - if (tt->flags & ASN1_TFLG_ADB_MASK) { - const ASN1_TEMPLATE *seqtt; - ASN1_VALUE **pseqval; - seqtt = asn1_do_adb(pval, tt, 0); - if (seqtt == NULL) - continue; - pseqval = asn1_get_field_ptr(pval, seqtt); - ASN1_template_free(pseqval, seqtt); - } - } - - /* Get each field entry */ - for (i = 0, tt = it->templates; i < it->tcount; i++, tt++) { - const ASN1_TEMPLATE *seqtt; - ASN1_VALUE **pseqval; - seqtt = asn1_do_adb(pval, tt, 1); - if (seqtt == NULL) - goto err; - pseqval = asn1_get_field_ptr(pval, seqtt); - /* Have we ran out of data? */ - if (!len) - break; - q = p; - /* - * This determines the OPTIONAL flag value. The field cannot be - * omitted if it is the last of a SEQUENCE and there is still - * data to be read. This isn't strictly necessary but it - * increases efficiency in some cases. - */ - if (i == (it->tcount - 1)) - isopt = 0; - else - isopt = (char)(seqtt->flags & ASN1_TFLG_OPTIONAL); - /* - * attempt to read in field, allowing each to be OPTIONAL - */ - - ret = asn1_template_ex_d2i(pseqval, &p, len, seqtt, isopt, depth); - if (!ret) { - errtt = seqtt; - goto err; - } else if (ret == -1) { - /* - * OPTIONAL component absent. Free and zero the field. - */ - ASN1_template_free(pseqval, seqtt); - continue; - } - /* Update length */ - len -= p - q; - } + /* If no IMPLICIT tagging set to SEQUENCE, UNIVERSAL */ + if (tag == -1) { + tag = V_ASN1_SEQUENCE; + aclass = V_ASN1_UNIVERSAL; + } + /* Get SEQUENCE length and update len, p */ + ret = asn1_check_tlen(&len, NULL, NULL, &cst, &p, len, tag, aclass, opt); + if (!ret) { + OPENSSL_PUT_ERROR(ASN1, ASN1_R_NESTED_ASN1_ERROR); + goto err; + } else if (ret == -1) { + return -1; + } + if (!cst) { + OPENSSL_PUT_ERROR(ASN1, ASN1_R_SEQUENCE_NOT_CONSTRUCTED); + goto err; + } - /* Check all data read */ - if (len) { - OPENSSL_PUT_ERROR(ASN1, ASN1_R_SEQUENCE_LENGTH_MISMATCH); - goto err; + if (!*pval && !ASN1_item_ex_new(pval, it)) { + OPENSSL_PUT_ERROR(ASN1, ASN1_R_NESTED_ASN1_ERROR); + goto err; + } + + const ASN1_AUX *aux = it->funcs; + ASN1_aux_cb *asn1_cb = aux != NULL ? aux->asn1_cb : NULL; + if (asn1_cb && !asn1_cb(ASN1_OP_D2I_PRE, pval, it, NULL)) { + goto auxerr; + } + + /* Free up and zero any ADB found */ + for (i = 0, tt = it->templates; i < it->tcount; i++, tt++) { + if (tt->flags & ASN1_TFLG_ADB_MASK) { + const ASN1_TEMPLATE *seqtt; + ASN1_VALUE **pseqval; + seqtt = asn1_do_adb(pval, tt, 0); + if (seqtt == NULL) { + continue; + } + pseqval = asn1_get_field_ptr(pval, seqtt); + ASN1_template_free(pseqval, seqtt); + } + } + + /* Get each field entry */ + for (i = 0, tt = it->templates; i < it->tcount; i++, tt++) { + const ASN1_TEMPLATE *seqtt; + ASN1_VALUE **pseqval; + seqtt = asn1_do_adb(pval, tt, 1); + if (seqtt == NULL) { + goto err; + } + pseqval = asn1_get_field_ptr(pval, seqtt); + /* Have we ran out of data? */ + if (!len) { + break; } - + q = p; /* - * If we get here we've got no more data in the SEQUENCE, however we - * may not have read all fields so check all remaining are OPTIONAL - * and clear any that are. + * This determines the OPTIONAL flag value. The field cannot be + * omitted if it is the last of a SEQUENCE and there is still + * data to be read. This isn't strictly necessary but it + * increases efficiency in some cases. */ - for (; i < it->tcount; tt++, i++) { - const ASN1_TEMPLATE *seqtt; - seqtt = asn1_do_adb(pval, tt, 1); - if (seqtt == NULL) - goto err; - if (seqtt->flags & ASN1_TFLG_OPTIONAL) { - ASN1_VALUE **pseqval; - pseqval = asn1_get_field_ptr(pval, seqtt); - ASN1_template_free(pseqval, seqtt); - } else { - errtt = seqtt; - OPENSSL_PUT_ERROR(ASN1, ASN1_R_FIELD_MISSING); - goto err; - } + if (i == (it->tcount - 1)) { + isopt = 0; + } else { + isopt = (char)(seqtt->flags & ASN1_TFLG_OPTIONAL); } - /* Save encoding */ - if (!asn1_enc_save(pval, *in, p - *in, it)) - goto auxerr; - if (asn1_cb && !asn1_cb(ASN1_OP_D2I_POST, pval, it, NULL)) - goto auxerr; - *in = p; - return 1; + /* + * attempt to read in field, allowing each to be OPTIONAL + */ + + ret = asn1_template_ex_d2i(pseqval, &p, len, seqtt, isopt, depth); + if (!ret) { + errtt = seqtt; + goto err; + } else if (ret == -1) { + /* + * OPTIONAL component absent. Free and zero the field. + */ + ASN1_template_free(pseqval, seqtt); + continue; + } + /* Update length */ + len -= p - q; + } + + /* Check all data read */ + if (len) { + OPENSSL_PUT_ERROR(ASN1, ASN1_R_SEQUENCE_LENGTH_MISMATCH); + goto err; + } + + /* + * If we get here we've got no more data in the SEQUENCE, however we + * may not have read all fields so check all remaining are OPTIONAL + * and clear any that are. + */ + for (; i < it->tcount; tt++, i++) { + const ASN1_TEMPLATE *seqtt; + seqtt = asn1_do_adb(pval, tt, 1); + if (seqtt == NULL) { + goto err; + } + if (seqtt->flags & ASN1_TFLG_OPTIONAL) { + ASN1_VALUE **pseqval; + pseqval = asn1_get_field_ptr(pval, seqtt); + ASN1_template_free(pseqval, seqtt); + } else { + errtt = seqtt; + OPENSSL_PUT_ERROR(ASN1, ASN1_R_FIELD_MISSING); + goto err; + } + } + /* Save encoding */ + if (!asn1_enc_save(pval, *in, p - *in, it)) { + goto auxerr; + } + if (asn1_cb && !asn1_cb(ASN1_OP_D2I_POST, pval, it, NULL)) { + goto auxerr; + } + *in = p; + return 1; } default: - return 0; - } - auxerr: - OPENSSL_PUT_ERROR(ASN1, ASN1_R_AUX_ERROR); - err: - if (combine == 0) - ASN1_item_ex_free(pval, it); - if (errtt) - ERR_add_error_data(4, "Field=", errtt->field_name, - ", Type=", it->sname); - else - ERR_add_error_data(2, "Type=", it->sname); - return 0; + return 0; + } +auxerr: + OPENSSL_PUT_ERROR(ASN1, ASN1_R_AUX_ERROR); +err: + if (combine == 0) { + ASN1_item_ex_free(pval, it); + } + if (errtt) { + ERR_add_error_data(4, "Field=", errtt->field_name, ", Type=", it->sname); + } else { + ERR_add_error_data(2, "Type=", it->sname); + } + return 0; } int ASN1_item_ex_d2i(ASN1_VALUE **pval, const unsigned char **in, long len, - const ASN1_ITEM *it, - int tag, int aclass, char opt, ASN1_TLC *ctx) -{ - return asn1_item_ex_d2i(pval, in, len, it, tag, aclass, opt, 0); + const ASN1_ITEM *it, int tag, int aclass, char opt, + ASN1_TLC *ctx) { + return asn1_item_ex_d2i(pval, in, len, it, tag, aclass, opt, 0); } /* @@ -475,326 +481,334 @@ int ASN1_item_ex_d2i(ASN1_VALUE **pval, const unsigned char **in, long len, * EXPLICIT tag and the other handles the rest. */ -static int asn1_template_ex_d2i(ASN1_VALUE **val, - const unsigned char **in, long inlen, - const ASN1_TEMPLATE *tt, char opt, - int depth) -{ - int flags, aclass; - int ret; - long len; - const unsigned char *p, *q; - if (!val) - return 0; - flags = tt->flags; - aclass = flags & ASN1_TFLG_TAG_CLASS; +static int asn1_template_ex_d2i(ASN1_VALUE **val, const unsigned char **in, + long inlen, const ASN1_TEMPLATE *tt, char opt, + int depth) { + int flags, aclass; + int ret; + long len; + const unsigned char *p, *q; + if (!val) { + return 0; + } + flags = tt->flags; + aclass = flags & ASN1_TFLG_TAG_CLASS; - p = *in; + p = *in; - /* Check if EXPLICIT tag expected */ - if (flags & ASN1_TFLG_EXPTAG) { - char cst; - /* - * Need to work out amount of data available to the inner content and - * where it starts: so read in EXPLICIT header to get the info. - */ - ret = asn1_check_tlen(&len, NULL, NULL, &cst, - &p, inlen, tt->tag, aclass, opt); - q = p; - if (!ret) { - OPENSSL_PUT_ERROR(ASN1, ASN1_R_NESTED_ASN1_ERROR); - return 0; - } else if (ret == -1) - return -1; - if (!cst) { - OPENSSL_PUT_ERROR(ASN1, ASN1_R_EXPLICIT_TAG_NOT_CONSTRUCTED); - return 0; - } - /* We've found the field so it can't be OPTIONAL now */ - ret = asn1_template_noexp_d2i(val, &p, len, tt, 0, depth); - if (!ret) { - OPENSSL_PUT_ERROR(ASN1, ASN1_R_NESTED_ASN1_ERROR); - return 0; - } - /* We read the field in OK so update length */ - len -= p - q; - /* Check for trailing data. */ - if (len) { - OPENSSL_PUT_ERROR(ASN1, ASN1_R_EXPLICIT_LENGTH_MISMATCH); - goto err; - } - } else - return asn1_template_noexp_d2i(val, in, inlen, tt, opt, depth); + /* Check if EXPLICIT tag expected */ + if (flags & ASN1_TFLG_EXPTAG) { + char cst; + /* + * Need to work out amount of data available to the inner content and + * where it starts: so read in EXPLICIT header to get the info. + */ + ret = asn1_check_tlen(&len, NULL, NULL, &cst, &p, inlen, tt->tag, aclass, + opt); + q = p; + if (!ret) { + OPENSSL_PUT_ERROR(ASN1, ASN1_R_NESTED_ASN1_ERROR); + return 0; + } else if (ret == -1) { + return -1; + } + if (!cst) { + OPENSSL_PUT_ERROR(ASN1, ASN1_R_EXPLICIT_TAG_NOT_CONSTRUCTED); + return 0; + } + /* We've found the field so it can't be OPTIONAL now */ + ret = asn1_template_noexp_d2i(val, &p, len, tt, 0, depth); + if (!ret) { + OPENSSL_PUT_ERROR(ASN1, ASN1_R_NESTED_ASN1_ERROR); + return 0; + } + /* We read the field in OK so update length */ + len -= p - q; + /* Check for trailing data. */ + if (len) { + OPENSSL_PUT_ERROR(ASN1, ASN1_R_EXPLICIT_LENGTH_MISMATCH); + goto err; + } + } else { + return asn1_template_noexp_d2i(val, in, inlen, tt, opt, depth); + } - *in = p; - return 1; + *in = p; + return 1; - err: - ASN1_template_free(val, tt); - return 0; +err: + ASN1_template_free(val, tt); + return 0; } -static int asn1_template_noexp_d2i(ASN1_VALUE **val, - const unsigned char **in, long len, - const ASN1_TEMPLATE *tt, char opt, - int depth) -{ - int flags, aclass; - int ret; - const unsigned char *p; - if (!val) - return 0; - flags = tt->flags; - aclass = flags & ASN1_TFLG_TAG_CLASS; - - p = *in; - - if (flags & ASN1_TFLG_SK_MASK) { - /* SET OF, SEQUENCE OF */ - int sktag, skaclass; - /* First work out expected inner tag value */ - if (flags & ASN1_TFLG_IMPTAG) { - sktag = tt->tag; - skaclass = aclass; - } else { - skaclass = V_ASN1_UNIVERSAL; - if (flags & ASN1_TFLG_SET_OF) - sktag = V_ASN1_SET; - else - sktag = V_ASN1_SEQUENCE; - } - /* Get the tag */ - ret = asn1_check_tlen(&len, NULL, NULL, NULL, - &p, len, sktag, skaclass, opt); - if (!ret) { - OPENSSL_PUT_ERROR(ASN1, ASN1_R_NESTED_ASN1_ERROR); - return 0; - } else if (ret == -1) - return -1; - if (!*val) - *val = (ASN1_VALUE *)sk_ASN1_VALUE_new_null(); - else { - /* - * We've got a valid STACK: free up any items present - */ - STACK_OF(ASN1_VALUE) *sktmp = (STACK_OF(ASN1_VALUE) *)*val; - ASN1_VALUE *vtmp; - while (sk_ASN1_VALUE_num(sktmp) > 0) { - vtmp = sk_ASN1_VALUE_pop(sktmp); - ASN1_item_ex_free(&vtmp, ASN1_ITEM_ptr(tt->item)); - } - } +static int asn1_template_noexp_d2i(ASN1_VALUE **val, const unsigned char **in, + long len, const ASN1_TEMPLATE *tt, char opt, + int depth) { + int flags, aclass; + int ret; + const unsigned char *p; + if (!val) { + return 0; + } + flags = tt->flags; + aclass = flags & ASN1_TFLG_TAG_CLASS; + + p = *in; + + if (flags & ASN1_TFLG_SK_MASK) { + /* SET OF, SEQUENCE OF */ + int sktag, skaclass; + /* First work out expected inner tag value */ + if (flags & ASN1_TFLG_IMPTAG) { + sktag = tt->tag; + skaclass = aclass; + } else { + skaclass = V_ASN1_UNIVERSAL; + if (flags & ASN1_TFLG_SET_OF) { + sktag = V_ASN1_SET; + } else { + sktag = V_ASN1_SEQUENCE; + } + } + /* Get the tag */ + ret = + asn1_check_tlen(&len, NULL, NULL, NULL, &p, len, sktag, skaclass, opt); + if (!ret) { + OPENSSL_PUT_ERROR(ASN1, ASN1_R_NESTED_ASN1_ERROR); + return 0; + } else if (ret == -1) { + return -1; + } + if (!*val) { + *val = (ASN1_VALUE *)sk_ASN1_VALUE_new_null(); + } else { + /* + * We've got a valid STACK: free up any items present + */ + STACK_OF(ASN1_VALUE) *sktmp = (STACK_OF(ASN1_VALUE) *)*val; + ASN1_VALUE *vtmp; + while (sk_ASN1_VALUE_num(sktmp) > 0) { + vtmp = sk_ASN1_VALUE_pop(sktmp); + ASN1_item_ex_free(&vtmp, ASN1_ITEM_ptr(tt->item)); + } + } - if (!*val) { - OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE); - goto err; - } + if (!*val) { + OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE); + goto err; + } - /* Read as many items as we can */ - while (len > 0) { - ASN1_VALUE *skfield; - const unsigned char *q = p; - skfield = NULL; - if (!asn1_item_ex_d2i(&skfield, &p, len, ASN1_ITEM_ptr(tt->item), - -1, 0, 0, depth)) { - OPENSSL_PUT_ERROR(ASN1, ASN1_R_NESTED_ASN1_ERROR); - goto err; - } - len -= p - q; - if (!sk_ASN1_VALUE_push((STACK_OF(ASN1_VALUE) *)*val, skfield)) { - ASN1_item_ex_free(&skfield, ASN1_ITEM_ptr(tt->item)); - OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE); - goto err; - } - } - } else if (flags & ASN1_TFLG_IMPTAG) { - /* IMPLICIT tagging */ - ret = asn1_item_ex_d2i(val, &p, len, ASN1_ITEM_ptr(tt->item), tt->tag, - aclass, opt, depth); - if (!ret) { - OPENSSL_PUT_ERROR(ASN1, ASN1_R_NESTED_ASN1_ERROR); - goto err; - } else if (ret == -1) - return -1; - } else { - /* Nothing special */ - ret = asn1_item_ex_d2i(val, &p, len, ASN1_ITEM_ptr(tt->item), - -1, tt->flags & ASN1_TFLG_COMBINE, opt, - depth); - if (!ret) { - OPENSSL_PUT_ERROR(ASN1, ASN1_R_NESTED_ASN1_ERROR); - goto err; - } else if (ret == -1) - return -1; + /* Read as many items as we can */ + while (len > 0) { + ASN1_VALUE *skfield; + const unsigned char *q = p; + skfield = NULL; + if (!asn1_item_ex_d2i(&skfield, &p, len, ASN1_ITEM_ptr(tt->item), -1, 0, + 0, depth)) { + OPENSSL_PUT_ERROR(ASN1, ASN1_R_NESTED_ASN1_ERROR); + goto err; + } + len -= p - q; + if (!sk_ASN1_VALUE_push((STACK_OF(ASN1_VALUE) *)*val, skfield)) { + ASN1_item_ex_free(&skfield, ASN1_ITEM_ptr(tt->item)); + OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE); + goto err; + } } + } else if (flags & ASN1_TFLG_IMPTAG) { + /* IMPLICIT tagging */ + ret = asn1_item_ex_d2i(val, &p, len, ASN1_ITEM_ptr(tt->item), tt->tag, + aclass, opt, depth); + if (!ret) { + OPENSSL_PUT_ERROR(ASN1, ASN1_R_NESTED_ASN1_ERROR); + goto err; + } else if (ret == -1) { + return -1; + } + } else { + /* Nothing special */ + ret = asn1_item_ex_d2i(val, &p, len, ASN1_ITEM_ptr(tt->item), -1, + tt->flags & ASN1_TFLG_COMBINE, opt, depth); + if (!ret) { + OPENSSL_PUT_ERROR(ASN1, ASN1_R_NESTED_ASN1_ERROR); + goto err; + } else if (ret == -1) { + return -1; + } + } - *in = p; - return 1; + *in = p; + return 1; - err: - ASN1_template_free(val, tt); - return 0; +err: + ASN1_template_free(val, tt); + return 0; } -static int asn1_d2i_ex_primitive(ASN1_VALUE **pval, - const unsigned char **in, long inlen, - const ASN1_ITEM *it, - int tag, int aclass, char opt) -{ - int ret = 0, utype; - long plen; - char cst; - const unsigned char *p; - const unsigned char *cont = NULL; - long len; - if (!pval) { - OPENSSL_PUT_ERROR(ASN1, ASN1_R_ILLEGAL_NULL); - return 0; /* Should never happen */ - } - - if (it->itype == ASN1_ITYPE_MSTRING) { - utype = tag; - tag = -1; - } else - utype = it->utype; - - if (utype == V_ASN1_ANY) { - /* If type is ANY need to figure out type from tag */ - unsigned char oclass; - if (tag >= 0) { - OPENSSL_PUT_ERROR(ASN1, ASN1_R_ILLEGAL_TAGGED_ANY); - return 0; - } - if (opt) { - OPENSSL_PUT_ERROR(ASN1, ASN1_R_ILLEGAL_OPTIONAL_ANY); - return 0; - } - p = *in; - ret = asn1_check_tlen(NULL, &utype, &oclass, NULL, - &p, inlen, -1, 0, 0); - if (!ret) { - OPENSSL_PUT_ERROR(ASN1, ASN1_R_NESTED_ASN1_ERROR); - return 0; - } - if (oclass != V_ASN1_UNIVERSAL) - utype = V_ASN1_OTHER; +static int asn1_d2i_ex_primitive(ASN1_VALUE **pval, const unsigned char **in, + long inlen, const ASN1_ITEM *it, int tag, + int aclass, char opt) { + int ret = 0, utype; + long plen; + char cst; + const unsigned char *p; + const unsigned char *cont = NULL; + long len; + if (!pval) { + OPENSSL_PUT_ERROR(ASN1, ASN1_R_ILLEGAL_NULL); + return 0; /* Should never happen */ + } + + if (it->itype == ASN1_ITYPE_MSTRING) { + utype = tag; + tag = -1; + } else { + utype = it->utype; + } + + if (utype == V_ASN1_ANY) { + /* If type is ANY need to figure out type from tag */ + unsigned char oclass; + if (tag >= 0) { + OPENSSL_PUT_ERROR(ASN1, ASN1_R_ILLEGAL_TAGGED_ANY); + return 0; } - if (tag == -1) { - tag = utype; - aclass = V_ASN1_UNIVERSAL; + if (opt) { + OPENSSL_PUT_ERROR(ASN1, ASN1_R_ILLEGAL_OPTIONAL_ANY); + return 0; } p = *in; - /* Check header */ - ret = asn1_check_tlen(&plen, NULL, NULL, &cst, - &p, inlen, tag, aclass, opt); + ret = asn1_check_tlen(NULL, &utype, &oclass, NULL, &p, inlen, -1, 0, 0); if (!ret) { - OPENSSL_PUT_ERROR(ASN1, ASN1_R_NESTED_ASN1_ERROR); - return 0; - } else if (ret == -1) - return -1; - ret = 0; - /* SEQUENCE, SET and "OTHER" are left in encoded form */ - if ((utype == V_ASN1_SEQUENCE) - || (utype == V_ASN1_SET) || (utype == V_ASN1_OTHER)) { - /* SEQUENCE and SET must be constructed */ - if (utype != V_ASN1_OTHER && !cst) { - OPENSSL_PUT_ERROR(ASN1, ASN1_R_TYPE_NOT_CONSTRUCTED); - return 0; - } - - cont = *in; - len = p - cont + plen; - p += plen; - } else if (cst) { - /* This parser historically supported BER constructed strings. We no - * longer do and will gradually tighten this parser into a DER - * parser. BER types should use |CBS_asn1_ber_to_der|. */ - OPENSSL_PUT_ERROR(ASN1, ASN1_R_TYPE_NOT_PRIMITIVE); - return 0; - } else { - cont = p; - len = plen; - p += plen; + OPENSSL_PUT_ERROR(ASN1, ASN1_R_NESTED_ASN1_ERROR); + return 0; + } + if (oclass != V_ASN1_UNIVERSAL) { + utype = V_ASN1_OTHER; + } + } + if (tag == -1) { + tag = utype; + aclass = V_ASN1_UNIVERSAL; + } + p = *in; + /* Check header */ + ret = asn1_check_tlen(&plen, NULL, NULL, &cst, &p, inlen, tag, aclass, opt); + if (!ret) { + OPENSSL_PUT_ERROR(ASN1, ASN1_R_NESTED_ASN1_ERROR); + return 0; + } else if (ret == -1) { + return -1; + } + ret = 0; + /* SEQUENCE, SET and "OTHER" are left in encoded form */ + if ((utype == V_ASN1_SEQUENCE) || (utype == V_ASN1_SET) || + (utype == V_ASN1_OTHER)) { + /* SEQUENCE and SET must be constructed */ + if (utype != V_ASN1_OTHER && !cst) { + OPENSSL_PUT_ERROR(ASN1, ASN1_R_TYPE_NOT_CONSTRUCTED); + return 0; } - /* We now have content length and type: translate into a structure */ - if (!asn1_ex_c2i(pval, cont, len, utype, it)) - goto err; - - *in = p; - ret = 1; - err: - return ret; + cont = *in; + len = p - cont + plen; + p += plen; + } else if (cst) { + /* This parser historically supported BER constructed strings. We no + * longer do and will gradually tighten this parser into a DER + * parser. BER types should use |CBS_asn1_ber_to_der|. */ + OPENSSL_PUT_ERROR(ASN1, ASN1_R_TYPE_NOT_PRIMITIVE); + return 0; + } else { + cont = p; + len = plen; + p += plen; + } + + /* We now have content length and type: translate into a structure */ + if (!asn1_ex_c2i(pval, cont, len, utype, it)) { + goto err; + } + + *in = p; + ret = 1; +err: + return ret; } /* Translate ASN1 content octets into a structure */ static int asn1_ex_c2i(ASN1_VALUE **pval, const unsigned char *cont, int len, - int utype, const ASN1_ITEM *it) -{ - ASN1_VALUE **opval = NULL; - ASN1_STRING *stmp; - ASN1_TYPE *typ = NULL; - int ret = 0; - ASN1_INTEGER **tint; - - /* Historically, |it->funcs| for primitive types contained an - * |ASN1_PRIMITIVE_FUNCS| table of callbacks. */ - assert(it->funcs == NULL); - - /* If ANY type clear type and set pointer to internal value */ - if (it->utype == V_ASN1_ANY) { - if (!*pval) { - typ = ASN1_TYPE_new(); - if (typ == NULL) - goto err; - *pval = (ASN1_VALUE *)typ; - } else - typ = (ASN1_TYPE *)*pval; - - if (utype != typ->type) - ASN1_TYPE_set(typ, utype, NULL); - opval = pval; - pval = &typ->value.asn1_value; + int utype, const ASN1_ITEM *it) { + ASN1_VALUE **opval = NULL; + ASN1_STRING *stmp; + ASN1_TYPE *typ = NULL; + int ret = 0; + ASN1_INTEGER **tint; + + /* Historically, |it->funcs| for primitive types contained an + * |ASN1_PRIMITIVE_FUNCS| table of callbacks. */ + assert(it->funcs == NULL); + + /* If ANY type clear type and set pointer to internal value */ + if (it->utype == V_ASN1_ANY) { + if (!*pval) { + typ = ASN1_TYPE_new(); + if (typ == NULL) { + goto err; + } + *pval = (ASN1_VALUE *)typ; + } else { + typ = (ASN1_TYPE *)*pval; + } + + if (utype != typ->type) { + ASN1_TYPE_set(typ, utype, NULL); } - switch (utype) { + opval = pval; + pval = &typ->value.asn1_value; + } + switch (utype) { case V_ASN1_OBJECT: - if (!c2i_ASN1_OBJECT((ASN1_OBJECT **)pval, &cont, len)) - goto err; - break; + if (!c2i_ASN1_OBJECT((ASN1_OBJECT **)pval, &cont, len)) { + goto err; + } + break; case V_ASN1_NULL: - if (len) { - OPENSSL_PUT_ERROR(ASN1, ASN1_R_NULL_IS_WRONG_LENGTH); - goto err; - } - *pval = (ASN1_VALUE *)1; - break; + if (len) { + OPENSSL_PUT_ERROR(ASN1, ASN1_R_NULL_IS_WRONG_LENGTH); + goto err; + } + *pval = (ASN1_VALUE *)1; + break; case V_ASN1_BOOLEAN: - if (len != 1) { - OPENSSL_PUT_ERROR(ASN1, ASN1_R_BOOLEAN_IS_WRONG_LENGTH); - goto err; - } else { - ASN1_BOOLEAN *tbool; - tbool = (ASN1_BOOLEAN *)pval; - *tbool = *cont; - } - break; + if (len != 1) { + OPENSSL_PUT_ERROR(ASN1, ASN1_R_BOOLEAN_IS_WRONG_LENGTH); + goto err; + } else { + ASN1_BOOLEAN *tbool; + tbool = (ASN1_BOOLEAN *)pval; + *tbool = *cont; + } + break; case V_ASN1_BIT_STRING: - if (!c2i_ASN1_BIT_STRING((ASN1_BIT_STRING **)pval, &cont, len)) - goto err; - break; + if (!c2i_ASN1_BIT_STRING((ASN1_BIT_STRING **)pval, &cont, len)) { + goto err; + } + break; case V_ASN1_INTEGER: case V_ASN1_ENUMERATED: - tint = (ASN1_INTEGER **)pval; - if (!c2i_ASN1_INTEGER(tint, &cont, len)) - goto err; - /* Fixup type to match the expected form */ - (*tint)->type = utype | ((*tint)->type & V_ASN1_NEG); - break; + tint = (ASN1_INTEGER **)pval; + if (!c2i_ASN1_INTEGER(tint, &cont, len)) { + goto err; + } + /* Fixup type to match the expected form */ + (*tint)->type = utype | ((*tint)->type & V_ASN1_NEG); + break; case V_ASN1_OCTET_STRING: case V_ASN1_NUMERICSTRING: @@ -814,46 +828,65 @@ static int asn1_ex_c2i(ASN1_VALUE **pval, const unsigned char *cont, int len, case V_ASN1_SET: case V_ASN1_SEQUENCE: default: - if (utype == V_ASN1_BMPSTRING && (len & 1)) { - OPENSSL_PUT_ERROR(ASN1, ASN1_R_BMPSTRING_IS_WRONG_LENGTH); - goto err; - } - if (utype == V_ASN1_UNIVERSALSTRING && (len & 3)) { - OPENSSL_PUT_ERROR(ASN1, ASN1_R_UNIVERSALSTRING_IS_WRONG_LENGTH); - goto err; - } - /* All based on ASN1_STRING and handled the same */ - if (!*pval) { - stmp = ASN1_STRING_type_new(utype); - if (!stmp) { - OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE); - goto err; - } - *pval = (ASN1_VALUE *)stmp; - } else { - stmp = (ASN1_STRING *)*pval; - stmp->type = utype; - } - if (!ASN1_STRING_set(stmp, cont, len)) { - OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE); - ASN1_STRING_free(stmp); - *pval = NULL; - goto err; - } - break; - } - /* If ASN1_ANY and NULL type fix up value */ - if (typ && (utype == V_ASN1_NULL)) - typ->value.ptr = NULL; - - ret = 1; - err: - if (!ret) { - ASN1_TYPE_free(typ); - if (opval) - *opval = NULL; + if (utype == V_ASN1_BMPSTRING && (len & 1)) { + OPENSSL_PUT_ERROR(ASN1, ASN1_R_BMPSTRING_IS_WRONG_LENGTH); + goto err; + } + if (utype == V_ASN1_UNIVERSALSTRING && (len & 3)) { + OPENSSL_PUT_ERROR(ASN1, ASN1_R_UNIVERSALSTRING_IS_WRONG_LENGTH); + goto err; + } + if (utype == V_ASN1_UTCTIME) { + CBS cbs; + CBS_init(&cbs, cont, (size_t)len); + if (!CBS_parse_utc_time(&cbs, NULL, /*allow_timezone_offset=*/1)) { + OPENSSL_PUT_ERROR(ASN1, ASN1_R_INVALID_TIME_FORMAT); + goto err; + } + } + if (utype == V_ASN1_GENERALIZEDTIME) { + CBS cbs; + CBS_init(&cbs, cont, (size_t)len); + if (!CBS_parse_generalized_time(&cbs, NULL, + /*allow_timezone_offset=*/0)) { + OPENSSL_PUT_ERROR(ASN1, ASN1_R_INVALID_TIME_FORMAT); + goto err; + } + } + /* All based on ASN1_STRING and handled the same */ + if (!*pval) { + stmp = ASN1_STRING_type_new(utype); + if (!stmp) { + OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE); + goto err; + } + *pval = (ASN1_VALUE *)stmp; + } else { + stmp = (ASN1_STRING *)*pval; + stmp->type = utype; + } + if (!ASN1_STRING_set(stmp, cont, len)) { + OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE); + ASN1_STRING_free(stmp); + *pval = NULL; + goto err; + } + break; + } + /* If ASN1_ANY and NULL type fix up value */ + if (typ && (utype == V_ASN1_NULL)) { + typ->value.ptr = NULL; + } + + ret = 1; +err: + if (!ret) { + ASN1_TYPE_free(typ); + if (opval) { + *opval = NULL; } - return ret; + } + return ret; } /* @@ -863,43 +896,47 @@ static int asn1_ex_c2i(ASN1_VALUE **pval, const unsigned char *cont, int len, static int asn1_check_tlen(long *olen, int *otag, unsigned char *oclass, char *cst, const unsigned char **in, long len, - int exptag, int expclass, char opt) -{ - int i; - int ptag, pclass; - long plen; - const unsigned char *p; - p = *in; - - i = ASN1_get_object(&p, &plen, &ptag, &pclass, len); - if (i & 0x80) { - OPENSSL_PUT_ERROR(ASN1, ASN1_R_BAD_OBJECT_HEADER); - return 0; - } - if (exptag >= 0) { - if ((exptag != ptag) || (expclass != pclass)) { - /* - * If type is OPTIONAL, not an error: indicate missing type. - */ - if (opt) - return -1; - OPENSSL_PUT_ERROR(ASN1, ASN1_R_WRONG_TAG); - return 0; - } + int exptag, int expclass, char opt) { + int i; + int ptag, pclass; + long plen; + const unsigned char *p; + p = *in; + + i = ASN1_get_object(&p, &plen, &ptag, &pclass, len); + if (i & 0x80) { + OPENSSL_PUT_ERROR(ASN1, ASN1_R_BAD_OBJECT_HEADER); + return 0; + } + if (exptag >= 0) { + if ((exptag != ptag) || (expclass != pclass)) { + /* + * If type is OPTIONAL, not an error: indicate missing type. + */ + if (opt) { + return -1; + } + OPENSSL_PUT_ERROR(ASN1, ASN1_R_WRONG_TAG); + return 0; } + } - if (cst) - *cst = i & V_ASN1_CONSTRUCTED; + if (cst) { + *cst = i & V_ASN1_CONSTRUCTED; + } - if (olen) - *olen = plen; + if (olen) { + *olen = plen; + } - if (oclass) - *oclass = pclass; + if (oclass) { + *oclass = pclass; + } - if (otag) - *otag = ptag; + if (otag) { + *otag = ptag; + } - *in = p; - return 1; + *in = p; + return 1; } diff --git a/crypto/asn1/tasn_enc.c b/crypto/asn1/tasn_enc.c index 0af9e9df10..c46df2d03f 100644 --- a/crypto/asn1/tasn_enc.c +++ b/crypto/asn1/tasn_enc.c @@ -84,30 +84,29 @@ static int asn1_template_ex_i2d(ASN1_VALUE **pval, unsigned char **out, * Top level i2d equivalents */ -int ASN1_item_i2d(ASN1_VALUE *val, unsigned char **out, const ASN1_ITEM *it) -{ - if (out && !*out) { - unsigned char *p, *buf; - int len = ASN1_item_ex_i2d(&val, NULL, it, /*tag=*/-1, /*aclass=*/0); - if (len <= 0) { - return len; - } - buf = OPENSSL_malloc(len); - if (!buf) { - OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE); - return -1; - } - p = buf; - int len2 = ASN1_item_ex_i2d(&val, &p, it, /*tag=*/-1, /*aclass=*/0); - if (len2 <= 0) { - return len2; - } - assert(len == len2); - *out = buf; - return len; +int ASN1_item_i2d(ASN1_VALUE *val, unsigned char **out, const ASN1_ITEM *it) { + if (out && !*out) { + unsigned char *p, *buf; + int len = ASN1_item_ex_i2d(&val, NULL, it, /*tag=*/-1, /*aclass=*/0); + if (len <= 0) { + return len; + } + buf = OPENSSL_malloc(len); + if (!buf) { + OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE); + return -1; } + p = buf; + int len2 = ASN1_item_ex_i2d(&val, &p, it, /*tag=*/-1, /*aclass=*/0); + if (len2 <= 0) { + return len2; + } + assert(len == len2); + *out = buf; + return len; + } - return ASN1_item_ex_i2d(&val, out, it, /*tag=*/-1, /*aclass=*/0); + return ASN1_item_ex_i2d(&val, out, it, /*tag=*/-1, /*aclass=*/0); } /* @@ -116,151 +115,154 @@ int ASN1_item_i2d(ASN1_VALUE *val, unsigned char **out, const ASN1_ITEM *it) */ int ASN1_item_ex_i2d(ASN1_VALUE **pval, unsigned char **out, - const ASN1_ITEM *it, int tag, int aclass) -{ - int ret = asn1_item_ex_i2d_opt(pval, out, it, tag, aclass, /*optional=*/0); - assert(ret != 0); - return ret; + const ASN1_ITEM *it, int tag, int aclass) { + int ret = asn1_item_ex_i2d_opt(pval, out, it, tag, aclass, /*optional=*/0); + assert(ret != 0); + return ret; } /* asn1_item_ex_i2d_opt behaves like |ASN1_item_ex_i2d| but, if |optional| is * non-zero and |*pval| is omitted, it returns zero and writes no bytes. */ int asn1_item_ex_i2d_opt(ASN1_VALUE **pval, unsigned char **out, const ASN1_ITEM *it, int tag, int aclass, - int optional) -{ - const ASN1_TEMPLATE *tt = NULL; - int i, seqcontlen, seqlen; - - /* Historically, |aclass| was repurposed to pass additional flags into the - * encoding process. */ - assert((aclass & ASN1_TFLG_TAG_CLASS) == aclass); - /* If not overridding the tag, |aclass| is ignored and should be zero. */ - assert(tag != -1 || aclass == 0); - - /* All fields are pointers, except for boolean |ASN1_ITYPE_PRIMITIVE|s. - * Optional primitives are handled later. */ - if ((it->itype != ASN1_ITYPE_PRIMITIVE) && !*pval) { - if (optional) { - return 0; - } - OPENSSL_PUT_ERROR(ASN1, ASN1_R_MISSING_VALUE); - return -1; + int optional) { + const ASN1_TEMPLATE *tt = NULL; + int i, seqcontlen, seqlen; + + /* Historically, |aclass| was repurposed to pass additional flags into the + * encoding process. */ + assert((aclass & ASN1_TFLG_TAG_CLASS) == aclass); + /* If not overridding the tag, |aclass| is ignored and should be zero. */ + assert(tag != -1 || aclass == 0); + + /* All fields are pointers, except for boolean |ASN1_ITYPE_PRIMITIVE|s. + * Optional primitives are handled later. */ + if ((it->itype != ASN1_ITYPE_PRIMITIVE) && !*pval) { + if (optional) { + return 0; } + OPENSSL_PUT_ERROR(ASN1, ASN1_R_MISSING_VALUE); + return -1; + } - switch (it->itype) { - + switch (it->itype) { case ASN1_ITYPE_PRIMITIVE: - if (it->templates) { - if (it->templates->flags & ASN1_TFLG_OPTIONAL) { - OPENSSL_PUT_ERROR(ASN1, ASN1_R_BAD_TEMPLATE); - return -1; - } - return asn1_template_ex_i2d(pval, out, it->templates, tag, aclass); + if (it->templates) { + if (it->templates->flags & ASN1_TFLG_OPTIONAL) { + OPENSSL_PUT_ERROR(ASN1, ASN1_R_BAD_TEMPLATE); + return -1; } - return asn1_i2d_ex_primitive(pval, out, it, tag, aclass, optional); + return asn1_template_ex_i2d(pval, out, it->templates, tag, aclass); + } + return asn1_i2d_ex_primitive(pval, out, it, tag, aclass, optional); case ASN1_ITYPE_MSTRING: - /* - * It never makes sense for multi-strings to have implicit tagging, so - * if tag != -1, then this looks like an error in the template. - */ - if (tag != -1) { - OPENSSL_PUT_ERROR(ASN1, ASN1_R_BAD_TEMPLATE); - return -1; - } - return asn1_i2d_ex_primitive(pval, out, it, -1, 0, optional); + /* + * It never makes sense for multi-strings to have implicit tagging, so + * if tag != -1, then this looks like an error in the template. + */ + if (tag != -1) { + OPENSSL_PUT_ERROR(ASN1, ASN1_R_BAD_TEMPLATE); + return -1; + } + return asn1_i2d_ex_primitive(pval, out, it, -1, 0, optional); case ASN1_ITYPE_CHOICE: { - /* - * It never makes sense for CHOICE types to have implicit tagging, so if - * tag != -1, then this looks like an error in the template. - */ - if (tag != -1) { - OPENSSL_PUT_ERROR(ASN1, ASN1_R_BAD_TEMPLATE); - return -1; - } - i = asn1_get_choice_selector(pval, it); - if (i < 0 || i >= it->tcount) { - OPENSSL_PUT_ERROR(ASN1, ASN1_R_NO_MATCHING_CHOICE_TYPE); - return -1; - } - const ASN1_TEMPLATE *chtt = it->templates + i; - if (chtt->flags & ASN1_TFLG_OPTIONAL) { - OPENSSL_PUT_ERROR(ASN1, ASN1_R_BAD_TEMPLATE); - return -1; - } - ASN1_VALUE **pchval = asn1_get_field_ptr(pval, chtt); - return asn1_template_ex_i2d(pchval, out, chtt, -1, 0); + /* + * It never makes sense for CHOICE types to have implicit tagging, so if + * tag != -1, then this looks like an error in the template. + */ + if (tag != -1) { + OPENSSL_PUT_ERROR(ASN1, ASN1_R_BAD_TEMPLATE); + return -1; + } + i = asn1_get_choice_selector(pval, it); + if (i < 0 || i >= it->tcount) { + OPENSSL_PUT_ERROR(ASN1, ASN1_R_NO_MATCHING_CHOICE_TYPE); + return -1; + } + const ASN1_TEMPLATE *chtt = it->templates + i; + if (chtt->flags & ASN1_TFLG_OPTIONAL) { + OPENSSL_PUT_ERROR(ASN1, ASN1_R_BAD_TEMPLATE); + return -1; + } + ASN1_VALUE **pchval = asn1_get_field_ptr(pval, chtt); + return asn1_template_ex_i2d(pchval, out, chtt, -1, 0); } case ASN1_ITYPE_EXTERN: { - /* If new style i2d it does all the work */ - const ASN1_EXTERN_FUNCS *ef = it->funcs; - int ret = ef->asn1_ex_i2d(pval, out, it, tag, aclass); - if (ret == 0) { - /* |asn1_ex_i2d| should never return zero. We have already checked - * for optional values generically, and |ASN1_ITYPE_EXTERN| fields - * must be pointers. */ - OPENSSL_PUT_ERROR(ASN1, ERR_R_INTERNAL_ERROR); - return -1; - } - return ret; + /* If new style i2d it does all the work */ + const ASN1_EXTERN_FUNCS *ef = it->funcs; + int ret = ef->asn1_ex_i2d(pval, out, it, tag, aclass); + if (ret == 0) { + /* |asn1_ex_i2d| should never return zero. We have already checked + * for optional values generically, and |ASN1_ITYPE_EXTERN| fields + * must be pointers. */ + OPENSSL_PUT_ERROR(ASN1, ERR_R_INTERNAL_ERROR); + return -1; + } + return ret; } case ASN1_ITYPE_SEQUENCE: { - i = asn1_enc_restore(&seqcontlen, out, pval, it); - /* An error occurred */ - if (i < 0) - return -1; - /* We have a valid cached encoding... */ - if (i > 0) - return seqcontlen; - /* Otherwise carry on */ - seqcontlen = 0; - /* If no IMPLICIT tagging set to SEQUENCE, UNIVERSAL */ - if (tag == -1) { - tag = V_ASN1_SEQUENCE; - aclass = V_ASN1_UNIVERSAL; + i = asn1_enc_restore(&seqcontlen, out, pval, it); + /* An error occurred */ + if (i < 0) { + return -1; + } + /* We have a valid cached encoding... */ + if (i > 0) { + return seqcontlen; + } + /* Otherwise carry on */ + seqcontlen = 0; + /* If no IMPLICIT tagging set to SEQUENCE, UNIVERSAL */ + if (tag == -1) { + tag = V_ASN1_SEQUENCE; + aclass = V_ASN1_UNIVERSAL; + } + /* First work out sequence content length */ + for (i = 0, tt = it->templates; i < it->tcount; tt++, i++) { + const ASN1_TEMPLATE *seqtt; + ASN1_VALUE **pseqval; + int tmplen; + seqtt = asn1_do_adb(pval, tt, 1); + if (!seqtt) { + return -1; } - /* First work out sequence content length */ - for (i = 0, tt = it->templates; i < it->tcount; tt++, i++) { - const ASN1_TEMPLATE *seqtt; - ASN1_VALUE **pseqval; - int tmplen; - seqtt = asn1_do_adb(pval, tt, 1); - if (!seqtt) - return -1; - pseqval = asn1_get_field_ptr(pval, seqtt); - tmplen = asn1_template_ex_i2d(pseqval, NULL, seqtt, -1, 0); - if (tmplen == -1 || (tmplen > INT_MAX - seqcontlen)) - return -1; - seqcontlen += tmplen; + pseqval = asn1_get_field_ptr(pval, seqtt); + tmplen = asn1_template_ex_i2d(pseqval, NULL, seqtt, -1, 0); + if (tmplen == -1 || (tmplen > INT_MAX - seqcontlen)) { + return -1; } + seqcontlen += tmplen; + } - seqlen = ASN1_object_size(/*constructed=*/1, seqcontlen, tag); - if (!out || seqlen == -1) - return seqlen; - /* Output SEQUENCE header */ - ASN1_put_object(out, /*constructed=*/1, seqcontlen, tag, aclass); - for (i = 0, tt = it->templates; i < it->tcount; tt++, i++) { - const ASN1_TEMPLATE *seqtt; - ASN1_VALUE **pseqval; - seqtt = asn1_do_adb(pval, tt, 1); - if (!seqtt) - return -1; - pseqval = asn1_get_field_ptr(pval, seqtt); - if (asn1_template_ex_i2d(pseqval, out, seqtt, -1, 0) < 0) { - return -1; - } - } + seqlen = ASN1_object_size(/*constructed=*/1, seqcontlen, tag); + if (!out || seqlen == -1) { return seqlen; + } + /* Output SEQUENCE header */ + ASN1_put_object(out, /*constructed=*/1, seqcontlen, tag, aclass); + for (i = 0, tt = it->templates; i < it->tcount; tt++, i++) { + const ASN1_TEMPLATE *seqtt; + ASN1_VALUE **pseqval; + seqtt = asn1_do_adb(pval, tt, 1); + if (!seqtt) { + return -1; + } + pseqval = asn1_get_field_ptr(pval, seqtt); + if (asn1_template_ex_i2d(pseqval, out, seqtt, -1, 0) < 0) { + return -1; + } + } + return seqlen; } default: - OPENSSL_PUT_ERROR(ASN1, ASN1_R_BAD_TEMPLATE); - return -1; - } + OPENSSL_PUT_ERROR(ASN1, ASN1_R_BAD_TEMPLATE); + return -1; + } } /* asn1_template_ex_i2d behaves like |asn1_item_ex_i2d_opt| but uses an @@ -268,166 +270,168 @@ int asn1_item_ex_i2d_opt(ASN1_VALUE **pval, unsigned char **out, * |ASN1_ITEM| with modifiers such as tagging, SEQUENCE or SET, etc. Instead of * taking an |optional| parameter, it uses the |ASN1_TFLG_OPTIONAL| flag. */ static int asn1_template_ex_i2d(ASN1_VALUE **pval, unsigned char **out, - const ASN1_TEMPLATE *tt, int tag, int iclass) -{ - int i, ret, flags, ttag, tclass; - size_t j; - flags = tt->flags; - - /* Historically, |iclass| was repurposed to pass additional flags into the - * encoding process. */ - assert((iclass & ASN1_TFLG_TAG_CLASS) == iclass); - /* If not overridding the tag, |iclass| is ignored and should be zero. */ - assert(tag != -1 || iclass == 0); + const ASN1_TEMPLATE *tt, int tag, int iclass) { + int i, ret, flags, ttag, tclass; + size_t j; + flags = tt->flags; + + /* Historically, |iclass| was repurposed to pass additional flags into the + * encoding process. */ + assert((iclass & ASN1_TFLG_TAG_CLASS) == iclass); + /* If not overridding the tag, |iclass| is ignored and should be zero. */ + assert(tag != -1 || iclass == 0); + + /* + * Work out tag and class to use: tagging may come either from the + * template or the arguments, not both because this would create + * ambiguity. + */ + if (flags & ASN1_TFLG_TAG_MASK) { + /* Error if argument and template tagging */ + if (tag != -1) { + OPENSSL_PUT_ERROR(ASN1, ASN1_R_BAD_TEMPLATE); + return -1; + } + /* Get tagging from template */ + ttag = tt->tag; + tclass = flags & ASN1_TFLG_TAG_CLASS; + } else if (tag != -1) { + /* No template tagging, get from arguments */ + ttag = tag; + tclass = iclass & ASN1_TFLG_TAG_CLASS; + } else { + ttag = -1; + tclass = 0; + } + + const int optional = (flags & ASN1_TFLG_OPTIONAL) != 0; + + /* + * At this point 'ttag' contains the outer tag to use, and 'tclass' is the + * class. + */ + + if (flags & ASN1_TFLG_SK_MASK) { + /* SET OF, SEQUENCE OF */ + STACK_OF(ASN1_VALUE) *sk = (STACK_OF(ASN1_VALUE) *)*pval; + int isset, sktag, skaclass; + int skcontlen, sklen; + ASN1_VALUE *skitem; + + if (!*pval) { + if (optional) { + return 0; + } + OPENSSL_PUT_ERROR(ASN1, ASN1_R_MISSING_VALUE); + return -1; + } - /* - * Work out tag and class to use: tagging may come either from the - * template or the arguments, not both because this would create - * ambiguity. - */ - if (flags & ASN1_TFLG_TAG_MASK) { - /* Error if argument and template tagging */ - if (tag != -1) { - OPENSSL_PUT_ERROR(ASN1, ASN1_R_BAD_TEMPLATE); - return -1; - } - /* Get tagging from template */ - ttag = tt->tag; - tclass = flags & ASN1_TFLG_TAG_CLASS; - } else if (tag != -1) { - /* No template tagging, get from arguments */ - ttag = tag; - tclass = iclass & ASN1_TFLG_TAG_CLASS; + if (flags & ASN1_TFLG_SET_OF) { + isset = 1; + /* Historically, types with both bits set were mutated when + * serialized to apply the sort. We no longer support this. */ + assert((flags & ASN1_TFLG_SEQUENCE_OF) == 0); } else { - ttag = -1; - tclass = 0; + isset = 0; } - const int optional = (flags & ASN1_TFLG_OPTIONAL) != 0; - /* - * At this point 'ttag' contains the outer tag to use, and 'tclass' is the - * class. + * Work out inner tag value: if EXPLICIT or no tagging use underlying + * type. */ + if ((ttag != -1) && !(flags & ASN1_TFLG_EXPTAG)) { + sktag = ttag; + skaclass = tclass; + } else { + skaclass = V_ASN1_UNIVERSAL; + if (isset) { + sktag = V_ASN1_SET; + } else { + sktag = V_ASN1_SEQUENCE; + } + } - if (flags & ASN1_TFLG_SK_MASK) { - /* SET OF, SEQUENCE OF */ - STACK_OF(ASN1_VALUE) *sk = (STACK_OF(ASN1_VALUE) *)*pval; - int isset, sktag, skaclass; - int skcontlen, sklen; - ASN1_VALUE *skitem; - - if (!*pval) { - if (optional) { - return 0; - } - OPENSSL_PUT_ERROR(ASN1, ASN1_R_MISSING_VALUE); - return -1; - } - - if (flags & ASN1_TFLG_SET_OF) { - isset = 1; - /* Historically, types with both bits set were mutated when - * serialized to apply the sort. We no longer support this. */ - assert((flags & ASN1_TFLG_SEQUENCE_OF) == 0); - } else { - isset = 0; - } - - /* - * Work out inner tag value: if EXPLICIT or no tagging use underlying - * type. - */ - if ((ttag != -1) && !(flags & ASN1_TFLG_EXPTAG)) { - sktag = ttag; - skaclass = tclass; - } else { - skaclass = V_ASN1_UNIVERSAL; - if (isset) - sktag = V_ASN1_SET; - else - sktag = V_ASN1_SEQUENCE; - } + /* Determine total length of items */ + skcontlen = 0; + for (j = 0; j < sk_ASN1_VALUE_num(sk); j++) { + int tmplen; + skitem = sk_ASN1_VALUE_value(sk, j); + tmplen = ASN1_item_ex_i2d(&skitem, NULL, ASN1_ITEM_ptr(tt->item), -1, 0); + if (tmplen == -1 || (skcontlen > INT_MAX - tmplen)) { + return -1; + } + skcontlen += tmplen; + } + sklen = ASN1_object_size(/*constructed=*/1, skcontlen, sktag); + if (sklen == -1) { + return -1; + } + /* If EXPLICIT need length of surrounding tag */ + if (flags & ASN1_TFLG_EXPTAG) { + ret = ASN1_object_size(/*constructed=*/1, sklen, ttag); + } else { + ret = sklen; + } - /* Determine total length of items */ - skcontlen = 0; - for (j = 0; j < sk_ASN1_VALUE_num(sk); j++) { - int tmplen; - skitem = sk_ASN1_VALUE_value(sk, j); - tmplen = ASN1_item_ex_i2d(&skitem, NULL, ASN1_ITEM_ptr(tt->item), - -1, 0); - if (tmplen == -1 || (skcontlen > INT_MAX - tmplen)) - return -1; - skcontlen += tmplen; - } - sklen = ASN1_object_size(/*constructed=*/1, skcontlen, sktag); - if (sklen == -1) - return -1; - /* If EXPLICIT need length of surrounding tag */ - if (flags & ASN1_TFLG_EXPTAG) - ret = ASN1_object_size(/*constructed=*/1, sklen, ttag); - else - ret = sklen; - - if (!out || ret == -1) - return ret; - - /* Now encode this lot... */ - /* EXPLICIT tag */ - if (flags & ASN1_TFLG_EXPTAG) - ASN1_put_object(out, /*constructed=*/1, sklen, ttag, tclass); - /* SET or SEQUENCE and IMPLICIT tag */ - ASN1_put_object(out, /*constructed=*/1, skcontlen, sktag, skaclass); - /* And the stuff itself */ - if (!asn1_set_seq_out(sk, out, skcontlen, ASN1_ITEM_ptr(tt->item), - isset)) { - return -1; - } - return ret; + if (!out || ret == -1) { + return ret; } + /* Now encode this lot... */ + /* EXPLICIT tag */ if (flags & ASN1_TFLG_EXPTAG) { - /* EXPLICIT tagging */ - /* Find length of tagged item */ - i = asn1_item_ex_i2d_opt(pval, NULL, ASN1_ITEM_ptr(tt->item), -1, 0, - optional); - if (i <= 0) - return i; - /* Find length of EXPLICIT tag */ - ret = ASN1_object_size(/*constructed=*/1, i, ttag); - if (out && ret != -1) { - /* Output tag and item */ - ASN1_put_object(out, /*constructed=*/1, i, ttag, tclass); - if (ASN1_item_ex_i2d(pval, out, ASN1_ITEM_ptr(tt->item), -1, - 0) < 0) { - return -1; - } - } - return ret; + ASN1_put_object(out, /*constructed=*/1, sklen, ttag, tclass); } + /* SET or SEQUENCE and IMPLICIT tag */ + ASN1_put_object(out, /*constructed=*/1, skcontlen, sktag, skaclass); + /* And the stuff itself */ + if (!asn1_set_seq_out(sk, out, skcontlen, ASN1_ITEM_ptr(tt->item), isset)) { + return -1; + } + return ret; + } + + if (flags & ASN1_TFLG_EXPTAG) { + /* EXPLICIT tagging */ + /* Find length of tagged item */ + i = asn1_item_ex_i2d_opt(pval, NULL, ASN1_ITEM_ptr(tt->item), -1, 0, + optional); + if (i <= 0) { + return i; + } + /* Find length of EXPLICIT tag */ + ret = ASN1_object_size(/*constructed=*/1, i, ttag); + if (out && ret != -1) { + /* Output tag and item */ + ASN1_put_object(out, /*constructed=*/1, i, ttag, tclass); + if (ASN1_item_ex_i2d(pval, out, ASN1_ITEM_ptr(tt->item), -1, 0) < 0) { + return -1; + } + } + return ret; + } - /* Either normal or IMPLICIT tagging */ - return asn1_item_ex_i2d_opt(pval, out, ASN1_ITEM_ptr(tt->item), - ttag, tclass, optional); - + /* Either normal or IMPLICIT tagging */ + return asn1_item_ex_i2d_opt(pval, out, ASN1_ITEM_ptr(tt->item), ttag, tclass, + optional); } /* Temporary structure used to hold DER encoding of items for SET OF */ typedef struct { - unsigned char *data; - int length; + unsigned char *data; + int length; } DER_ENC; -static int der_cmp(const void *a, const void *b) -{ - const DER_ENC *d1 = a, *d2 = b; - int cmplen, i; - cmplen = (d1->length < d2->length) ? d1->length : d2->length; - i = OPENSSL_memcmp(d1->data, d2->data, cmplen); - if (i) - return i; - return d1->length - d2->length; +static int der_cmp(const void *a, const void *b) { + const DER_ENC *d1 = a, *d2 = b; + int cmplen, i; + cmplen = (d1->length < d2->length) ? d1->length : d2->length; + i = OPENSSL_memcmp(d1->data, d2->data, cmplen); + if (i) { + return i; + } + return d1->length - d2->length; } /* asn1_set_seq_out writes |sk| to |out| under the i2d output convention, @@ -436,113 +440,112 @@ static int der_cmp(const void *a, const void *b) * elements are sorted for a SET OF type. Each element of |sk| has type * |item|. */ static int asn1_set_seq_out(STACK_OF(ASN1_VALUE) *sk, unsigned char **out, - int skcontlen, const ASN1_ITEM *item, int do_sort) -{ - /* No need to sort if there are fewer than two items. */ - if (!do_sort || sk_ASN1_VALUE_num(sk) < 2) { - for (size_t i = 0; i < sk_ASN1_VALUE_num(sk); i++) { - ASN1_VALUE *skitem = sk_ASN1_VALUE_value(sk, i); - if (ASN1_item_ex_i2d(&skitem, out, item, -1, 0) < 0) { - return 0; - } - } - return 1; - } - - if (sk_ASN1_VALUE_num(sk) > ((size_t)-1) / sizeof(DER_ENC)) { - OPENSSL_PUT_ERROR(ASN1, ERR_R_OVERFLOW); + int skcontlen, const ASN1_ITEM *item, int do_sort) { + /* No need to sort if there are fewer than two items. */ + if (!do_sort || sk_ASN1_VALUE_num(sk) < 2) { + for (size_t i = 0; i < sk_ASN1_VALUE_num(sk); i++) { + ASN1_VALUE *skitem = sk_ASN1_VALUE_value(sk, i); + if (ASN1_item_ex_i2d(&skitem, out, item, -1, 0) < 0) { return 0; + } } - - int ret = 0; - unsigned char *const buf = OPENSSL_malloc(skcontlen); - DER_ENC *encoded = OPENSSL_malloc(sk_ASN1_VALUE_num(sk) * sizeof(*encoded)); - if (encoded == NULL || buf == NULL) { - OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE); - goto err; + return 1; + } + + if (sk_ASN1_VALUE_num(sk) > ((size_t)-1) / sizeof(DER_ENC)) { + OPENSSL_PUT_ERROR(ASN1, ERR_R_OVERFLOW); + return 0; + } + + int ret = 0; + unsigned char *const buf = OPENSSL_malloc(skcontlen); + DER_ENC *encoded = OPENSSL_malloc(sk_ASN1_VALUE_num(sk) * sizeof(*encoded)); + if (encoded == NULL || buf == NULL) { + OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE); + goto err; + } + + /* Encode all the elements into |buf| and populate |encoded|. */ + unsigned char *p = buf; + for (size_t i = 0; i < sk_ASN1_VALUE_num(sk); i++) { + ASN1_VALUE *skitem = sk_ASN1_VALUE_value(sk, i); + encoded[i].data = p; + encoded[i].length = ASN1_item_ex_i2d(&skitem, &p, item, -1, 0); + if (encoded[i].length < 0) { + goto err; } + assert(p - buf <= skcontlen); + } - /* Encode all the elements into |buf| and populate |encoded|. */ - unsigned char *p = buf; - for (size_t i = 0; i < sk_ASN1_VALUE_num(sk); i++) { - ASN1_VALUE *skitem = sk_ASN1_VALUE_value(sk, i); - encoded[i].data = p; - encoded[i].length = ASN1_item_ex_i2d(&skitem, &p, item, -1, 0); - if (encoded[i].length < 0) { - goto err; - } - assert(p - buf <= skcontlen); - } - - qsort(encoded, sk_ASN1_VALUE_num(sk), sizeof(*encoded), der_cmp); + qsort(encoded, sk_ASN1_VALUE_num(sk), sizeof(*encoded), der_cmp); - /* Output the elements in sorted order. */ - p = *out; - for (size_t i = 0; i < sk_ASN1_VALUE_num(sk); i++) { - OPENSSL_memcpy(p, encoded[i].data, encoded[i].length); - p += encoded[i].length; - } - *out = p; + /* Output the elements in sorted order. */ + p = *out; + for (size_t i = 0; i < sk_ASN1_VALUE_num(sk); i++) { + OPENSSL_memcpy(p, encoded[i].data, encoded[i].length); + p += encoded[i].length; + } + *out = p; - ret = 1; + ret = 1; err: - OPENSSL_free(encoded); - OPENSSL_free(buf); - return ret; + OPENSSL_free(encoded); + OPENSSL_free(buf); + return ret; } /* asn1_i2d_ex_primitive behaves like |ASN1_item_ex_i2d| but |item| must be a * a PRIMITIVE or MSTRING type that is not an |ASN1_ITEM_TEMPLATE|. */ static int asn1_i2d_ex_primitive(ASN1_VALUE **pval, unsigned char **out, const ASN1_ITEM *it, int tag, int aclass, - int optional) -{ - /* Get length of content octets and maybe find out the underlying type. */ - int omit; - int utype = it->utype; - int len = asn1_ex_i2c(pval, NULL, &omit, &utype, it); - if (len < 0) { - return -1; - } - if (omit) { - if (optional) { - return 0; - } - OPENSSL_PUT_ERROR(ASN1, ASN1_R_MISSING_VALUE); - return -1; - } - - /* - * If SEQUENCE, SET or OTHER then header is included in pseudo content - * octets so don't include tag+length. We need to check here because the - * call to asn1_ex_i2c() could change utype. - */ - int usetag = utype != V_ASN1_SEQUENCE && utype != V_ASN1_SET && - utype != V_ASN1_OTHER; - - /* If not implicitly tagged get tag from underlying type */ - if (tag == -1) - tag = utype; - - /* Output tag+length followed by content octets */ - if (out) { - if (usetag) { - ASN1_put_object(out, /*constructed=*/0, len, tag, aclass); - } - int len2 = asn1_ex_i2c(pval, *out, &omit, &utype, it); - if (len2 < 0) { - return -1; - } - assert(len == len2); - assert(!omit); - *out += len; + int optional) { + /* Get length of content octets and maybe find out the underlying type. */ + int omit; + int utype = it->utype; + int len = asn1_ex_i2c(pval, NULL, &omit, &utype, it); + if (len < 0) { + return -1; + } + if (omit) { + if (optional) { + return 0; } - + OPENSSL_PUT_ERROR(ASN1, ASN1_R_MISSING_VALUE); + return -1; + } + + /* + * If SEQUENCE, SET or OTHER then header is included in pseudo content + * octets so don't include tag+length. We need to check here because the + * call to asn1_ex_i2c() could change utype. + */ + int usetag = + utype != V_ASN1_SEQUENCE && utype != V_ASN1_SET && utype != V_ASN1_OTHER; + + /* If not implicitly tagged get tag from underlying type */ + if (tag == -1) { + tag = utype; + } + + /* Output tag+length followed by content octets */ + if (out) { if (usetag) { - return ASN1_object_size(/*constructed=*/0, len, tag); + ASN1_put_object(out, /*constructed=*/0, len, tag, aclass); } - return len; + int len2 = asn1_ex_i2c(pval, *out, &omit, &utype, it); + if (len2 < 0) { + return -1; + } + assert(len == len2); + assert(!omit); + *out += len; + } + + if (usetag) { + return ASN1_object_size(/*constructed=*/0, len, tag); + } + return len; } /* asn1_ex_i2c writes the |*pval| to |cout| under the i2d output convention, @@ -562,121 +565,119 @@ static int asn1_i2d_ex_primitive(ASN1_VALUE **pval, unsigned char **out, * WARNING: Unlike most functions in this file, |asn1_ex_i2c| can return zero * without omitting the element. ASN.1 values may have empty contents. */ static int asn1_ex_i2c(ASN1_VALUE **pval, unsigned char *cout, int *out_omit, - int *putype, const ASN1_ITEM *it) -{ - ASN1_BOOLEAN *tbool = NULL; - ASN1_STRING *strtmp; - ASN1_OBJECT *otmp; - int utype; - const unsigned char *cont; - unsigned char c; - int len; - - /* Historically, |it->funcs| for primitive types contained an - * |ASN1_PRIMITIVE_FUNCS| table of callbacks. */ - assert(it->funcs == NULL); - - *out_omit = 0; - - /* Should type be omitted? */ - if ((it->itype != ASN1_ITYPE_PRIMITIVE) - || (it->utype != V_ASN1_BOOLEAN)) { - if (!*pval) { - *out_omit = 1; - return 0; - } + int *putype, const ASN1_ITEM *it) { + ASN1_BOOLEAN *tbool = NULL; + ASN1_STRING *strtmp; + ASN1_OBJECT *otmp; + int utype; + const unsigned char *cont; + unsigned char c; + int len; + + /* Historically, |it->funcs| for primitive types contained an + * |ASN1_PRIMITIVE_FUNCS| table of callbacks. */ + assert(it->funcs == NULL); + + *out_omit = 0; + + /* Should type be omitted? */ + if ((it->itype != ASN1_ITYPE_PRIMITIVE) || (it->utype != V_ASN1_BOOLEAN)) { + if (!*pval) { + *out_omit = 1; + return 0; } + } + + if (it->itype == ASN1_ITYPE_MSTRING) { + /* If MSTRING type set the underlying type */ + strtmp = (ASN1_STRING *)*pval; + utype = strtmp->type; + if (utype < 0 && utype != V_ASN1_OTHER) { + /* MSTRINGs can have type -1 when default-constructed. */ + OPENSSL_PUT_ERROR(ASN1, ASN1_R_WRONG_TYPE); + return -1; + } + /* Negative INTEGER and ENUMERATED values use |ASN1_STRING| type values + * that do not match their corresponding utype values. INTEGERs cannot + * participate in MSTRING types, but ENUMERATEDs can. + * + * TODO(davidben): Is this a bug? Although arguably one of the MSTRING + * types should contain more values, rather than less. See + * https://crbug.com/boringssl/412. But it is not possible to fit all + * possible ANY values into an |ASN1_STRING|, so matching the spec here + * is somewhat hopeless. */ + if (utype == V_ASN1_NEG_INTEGER) { + utype = V_ASN1_INTEGER; + } else if (utype == V_ASN1_NEG_ENUMERATED) { + utype = V_ASN1_ENUMERATED; + } + *putype = utype; + } else if (it->utype == V_ASN1_ANY) { + /* If ANY set type and pointer to value */ + ASN1_TYPE *typ; + typ = (ASN1_TYPE *)*pval; + utype = typ->type; + if (utype < 0 && utype != V_ASN1_OTHER) { + /* |ASN1_TYPE|s can have type -1 when default-constructed. */ + OPENSSL_PUT_ERROR(ASN1, ASN1_R_WRONG_TYPE); + return -1; + } + *putype = utype; + pval = &typ->value.asn1_value; + } else { + utype = *putype; + } - if (it->itype == ASN1_ITYPE_MSTRING) { - /* If MSTRING type set the underlying type */ - strtmp = (ASN1_STRING *)*pval; - utype = strtmp->type; - if (utype < 0 && utype != V_ASN1_OTHER) { - /* MSTRINGs can have type -1 when default-constructed. */ - OPENSSL_PUT_ERROR(ASN1, ASN1_R_WRONG_TYPE); - return -1; - } - /* Negative INTEGER and ENUMERATED values use |ASN1_STRING| type values - * that do not match their corresponding utype values. INTEGERs cannot - * participate in MSTRING types, but ENUMERATEDs can. - * - * TODO(davidben): Is this a bug? Although arguably one of the MSTRING - * types should contain more values, rather than less. See - * https://crbug.com/boringssl/412. But it is not possible to fit all - * possible ANY values into an |ASN1_STRING|, so matching the spec here - * is somewhat hopeless. */ - if (utype == V_ASN1_NEG_INTEGER) { - utype = V_ASN1_INTEGER; - } else if (utype == V_ASN1_NEG_ENUMERATED) { - utype = V_ASN1_ENUMERATED; - } - *putype = utype; - } else if (it->utype == V_ASN1_ANY) { - /* If ANY set type and pointer to value */ - ASN1_TYPE *typ; - typ = (ASN1_TYPE *)*pval; - utype = typ->type; - if (utype < 0 && utype != V_ASN1_OTHER) { - /* |ASN1_TYPE|s can have type -1 when default-constructed. */ - OPENSSL_PUT_ERROR(ASN1, ASN1_R_WRONG_TYPE); - return -1; - } - *putype = utype; - pval = &typ->value.asn1_value; - } else - utype = *putype; - - switch (utype) { + switch (utype) { case V_ASN1_OBJECT: - otmp = (ASN1_OBJECT *)*pval; - cont = otmp->data; - len = otmp->length; - if (len == 0) { - /* Some |ASN1_OBJECT|s do not have OIDs and cannot be serialized. */ - OPENSSL_PUT_ERROR(ASN1, ASN1_R_ILLEGAL_OBJECT); - return -1; - } - break; + otmp = (ASN1_OBJECT *)*pval; + cont = otmp->data; + len = otmp->length; + if (len == 0) { + /* Some |ASN1_OBJECT|s do not have OIDs and cannot be serialized. */ + OPENSSL_PUT_ERROR(ASN1, ASN1_R_ILLEGAL_OBJECT); + return -1; + } + break; case V_ASN1_NULL: - cont = NULL; - len = 0; - break; + cont = NULL; + len = 0; + break; case V_ASN1_BOOLEAN: - tbool = (ASN1_BOOLEAN *)pval; - if (*tbool == -1) { - *out_omit = 1; - return 0; - } - if (it->utype != V_ASN1_ANY) { - /* - * Default handling if value == size field then omit - */ - if ((*tbool && (it->size > 0)) || - (!*tbool && !it->size)) { - *out_omit = 1; - return 0; - } + tbool = (ASN1_BOOLEAN *)pval; + if (*tbool == -1) { + *out_omit = 1; + return 0; + } + if (it->utype != V_ASN1_ANY) { + /* + * Default handling if value == size field then omit + */ + if ((*tbool && (it->size > 0)) || (!*tbool && !it->size)) { + *out_omit = 1; + return 0; } - c = *tbool ? 0xff : 0x00; - cont = &c; - len = 1; - break; + } + c = *tbool ? 0xff : 0x00; + cont = &c; + len = 1; + break; case V_ASN1_BIT_STRING: { - int ret = i2c_ASN1_BIT_STRING((ASN1_BIT_STRING *)*pval, - cout ? &cout : NULL); - /* |i2c_ASN1_BIT_STRING| returns zero on error instead of -1. */ - return ret <= 0 ? -1 : ret; + int ret = + i2c_ASN1_BIT_STRING((ASN1_BIT_STRING *)*pval, cout ? &cout : NULL); + /* |i2c_ASN1_BIT_STRING| returns zero on error instead of -1. */ + return ret <= 0 ? -1 : ret; } case V_ASN1_INTEGER: case V_ASN1_ENUMERATED: { - /* |i2c_ASN1_INTEGER| also handles ENUMERATED. */ - int ret = i2c_ASN1_INTEGER((ASN1_INTEGER *)*pval, cout ? &cout : NULL); - /* |i2c_ASN1_INTEGER| returns zero on error instead of -1. */ - return ret <= 0 ? -1 : ret; + /* |i2c_ASN1_INTEGER| also handles ENUMERATED. */ + int ret = i2c_ASN1_INTEGER((ASN1_INTEGER *)*pval, cout ? &cout : NULL); + /* |i2c_ASN1_INTEGER| returns zero on error instead of -1. */ + return ret <= 0 ? -1 : ret; } case V_ASN1_OCTET_STRING: @@ -696,15 +697,15 @@ static int asn1_ex_i2c(ASN1_VALUE **pval, unsigned char *cout, int *out_omit, case V_ASN1_SEQUENCE: case V_ASN1_SET: default: - /* All based on ASN1_STRING and handled the same */ - strtmp = (ASN1_STRING *)*pval; - cont = strtmp->data; - len = strtmp->length; - - break; - - } - if (cout && len) - OPENSSL_memcpy(cout, cont, len); - return len; + /* All based on ASN1_STRING and handled the same */ + strtmp = (ASN1_STRING *)*pval; + cont = strtmp->data; + len = strtmp->length; + + break; + } + if (cout && len) { + OPENSSL_memcpy(cout, cont, len); + } + return len; } diff --git a/crypto/asn1/tasn_fre.c b/crypto/asn1/tasn_fre.c index b8479014c7..be0d33d0e5 100644 --- a/crypto/asn1/tasn_fre.c +++ b/crypto/asn1/tasn_fre.c @@ -65,169 +65,179 @@ /* Free up an ASN1 structure */ -void ASN1_item_free(ASN1_VALUE *val, const ASN1_ITEM *it) -{ - asn1_item_combine_free(&val, it, 0); +void ASN1_item_free(ASN1_VALUE *val, const ASN1_ITEM *it) { + asn1_item_combine_free(&val, it, 0); } -void ASN1_item_ex_free(ASN1_VALUE **pval, const ASN1_ITEM *it) -{ - asn1_item_combine_free(pval, it, 0); +void ASN1_item_ex_free(ASN1_VALUE **pval, const ASN1_ITEM *it) { + asn1_item_combine_free(pval, it, 0); } -void asn1_item_combine_free(ASN1_VALUE **pval, const ASN1_ITEM *it, int combine) -{ - const ASN1_TEMPLATE *tt = NULL, *seqtt; - const ASN1_EXTERN_FUNCS *ef; - int i; - if (!pval) - return; - if ((it->itype != ASN1_ITYPE_PRIMITIVE) && !*pval) - return; - - switch (it->itype) { - +void asn1_item_combine_free(ASN1_VALUE **pval, const ASN1_ITEM *it, + int combine) { + const ASN1_TEMPLATE *tt = NULL, *seqtt; + const ASN1_EXTERN_FUNCS *ef; + int i; + if (!pval) { + return; + } + if ((it->itype != ASN1_ITYPE_PRIMITIVE) && !*pval) { + return; + } + + switch (it->itype) { case ASN1_ITYPE_PRIMITIVE: - if (it->templates) - ASN1_template_free(pval, it->templates); - else - ASN1_primitive_free(pval, it); - break; + if (it->templates) { + ASN1_template_free(pval, it->templates); + } else { + ASN1_primitive_free(pval, it); + } + break; case ASN1_ITYPE_MSTRING: - ASN1_primitive_free(pval, it); - break; + ASN1_primitive_free(pval, it); + break; case ASN1_ITYPE_CHOICE: { - const ASN1_AUX *aux = it->funcs; - ASN1_aux_cb *asn1_cb = aux != NULL ? aux->asn1_cb : NULL; - if (asn1_cb) { - i = asn1_cb(ASN1_OP_FREE_PRE, pval, it, NULL); - if (i == 2) - return; - } - i = asn1_get_choice_selector(pval, it); - if ((i >= 0) && (i < it->tcount)) { - ASN1_VALUE **pchval; - tt = it->templates + i; - pchval = asn1_get_field_ptr(pval, tt); - ASN1_template_free(pchval, tt); + const ASN1_AUX *aux = it->funcs; + ASN1_aux_cb *asn1_cb = aux != NULL ? aux->asn1_cb : NULL; + if (asn1_cb) { + i = asn1_cb(ASN1_OP_FREE_PRE, pval, it, NULL); + if (i == 2) { + return; } - if (asn1_cb) - asn1_cb(ASN1_OP_FREE_POST, pval, it, NULL); - if (!combine) { - OPENSSL_free(*pval); - *pval = NULL; - } - break; + } + i = asn1_get_choice_selector(pval, it); + if ((i >= 0) && (i < it->tcount)) { + ASN1_VALUE **pchval; + tt = it->templates + i; + pchval = asn1_get_field_ptr(pval, tt); + ASN1_template_free(pchval, tt); + } + if (asn1_cb) { + asn1_cb(ASN1_OP_FREE_POST, pval, it, NULL); + } + if (!combine) { + OPENSSL_free(*pval); + *pval = NULL; + } + break; } case ASN1_ITYPE_EXTERN: - ef = it->funcs; - if (ef && ef->asn1_ex_free) - ef->asn1_ex_free(pval, it); - break; + ef = it->funcs; + if (ef && ef->asn1_ex_free) { + ef->asn1_ex_free(pval, it); + } + break; case ASN1_ITYPE_SEQUENCE: { - if (!asn1_refcount_dec_and_test_zero(pval, it)) - return; - const ASN1_AUX *aux = it->funcs; - ASN1_aux_cb *asn1_cb = aux != NULL ? aux->asn1_cb : NULL; - if (asn1_cb) { - i = asn1_cb(ASN1_OP_FREE_PRE, pval, it, NULL); - if (i == 2) - return; - } - asn1_enc_free(pval, it); - /* - * If we free up as normal we will invalidate any ANY DEFINED BY - * field and we wont be able to determine the type of the field it - * defines. So free up in reverse order. - */ - tt = it->templates + it->tcount - 1; - for (i = 0; i < it->tcount; tt--, i++) { - ASN1_VALUE **pseqval; - seqtt = asn1_do_adb(pval, tt, 0); - if (!seqtt) - continue; - pseqval = asn1_get_field_ptr(pval, seqtt); - ASN1_template_free(pseqval, seqtt); + if (!asn1_refcount_dec_and_test_zero(pval, it)) { + return; + } + const ASN1_AUX *aux = it->funcs; + ASN1_aux_cb *asn1_cb = aux != NULL ? aux->asn1_cb : NULL; + if (asn1_cb) { + i = asn1_cb(ASN1_OP_FREE_PRE, pval, it, NULL); + if (i == 2) { + return; } - if (asn1_cb) - asn1_cb(ASN1_OP_FREE_POST, pval, it, NULL); - if (!combine) { - OPENSSL_free(*pval); - *pval = NULL; + } + asn1_enc_free(pval, it); + /* + * If we free up as normal we will invalidate any ANY DEFINED BY + * field and we wont be able to determine the type of the field it + * defines. So free up in reverse order. + */ + tt = it->templates + it->tcount - 1; + for (i = 0; i < it->tcount; tt--, i++) { + ASN1_VALUE **pseqval; + seqtt = asn1_do_adb(pval, tt, 0); + if (!seqtt) { + continue; } - break; - } + pseqval = asn1_get_field_ptr(pval, seqtt); + ASN1_template_free(pseqval, seqtt); + } + if (asn1_cb) { + asn1_cb(ASN1_OP_FREE_POST, pval, it, NULL); + } + if (!combine) { + OPENSSL_free(*pval); + *pval = NULL; + } + break; } + } } -void ASN1_template_free(ASN1_VALUE **pval, const ASN1_TEMPLATE *tt) -{ - size_t i; - if (tt->flags & ASN1_TFLG_SK_MASK) { - STACK_OF(ASN1_VALUE) *sk = (STACK_OF(ASN1_VALUE) *)*pval; - for (i = 0; i < sk_ASN1_VALUE_num(sk); i++) { - ASN1_VALUE *vtmp; - vtmp = sk_ASN1_VALUE_value(sk, i); - asn1_item_combine_free(&vtmp, ASN1_ITEM_ptr(tt->item), 0); - } - sk_ASN1_VALUE_free(sk); - *pval = NULL; - } else - asn1_item_combine_free(pval, ASN1_ITEM_ptr(tt->item), - tt->flags & ASN1_TFLG_COMBINE); +void ASN1_template_free(ASN1_VALUE **pval, const ASN1_TEMPLATE *tt) { + size_t i; + if (tt->flags & ASN1_TFLG_SK_MASK) { + STACK_OF(ASN1_VALUE) *sk = (STACK_OF(ASN1_VALUE) *)*pval; + for (i = 0; i < sk_ASN1_VALUE_num(sk); i++) { + ASN1_VALUE *vtmp; + vtmp = sk_ASN1_VALUE_value(sk, i); + asn1_item_combine_free(&vtmp, ASN1_ITEM_ptr(tt->item), 0); + } + sk_ASN1_VALUE_free(sk); + *pval = NULL; + } else { + asn1_item_combine_free(pval, ASN1_ITEM_ptr(tt->item), + tt->flags & ASN1_TFLG_COMBINE); + } } -void ASN1_primitive_free(ASN1_VALUE **pval, const ASN1_ITEM *it) -{ - int utype; - /* Historically, |it->funcs| for primitive types contained an - * |ASN1_PRIMITIVE_FUNCS| table of calbacks. */ - assert(it == NULL || it->funcs == NULL); - /* Special case: if 'it' is NULL free contents of ASN1_TYPE */ - if (!it) { - ASN1_TYPE *typ = (ASN1_TYPE *)*pval; - utype = typ->type; - pval = &typ->value.asn1_value; - if (utype != V_ASN1_BOOLEAN && !*pval) - return; - } else if (it->itype == ASN1_ITYPE_MSTRING) { - utype = -1; - if (!*pval) - return; - } else { - utype = it->utype; - if ((utype != V_ASN1_BOOLEAN) && !*pval) - return; +void ASN1_primitive_free(ASN1_VALUE **pval, const ASN1_ITEM *it) { + int utype; + /* Historically, |it->funcs| for primitive types contained an + * |ASN1_PRIMITIVE_FUNCS| table of calbacks. */ + assert(it == NULL || it->funcs == NULL); + /* Special case: if 'it' is NULL free contents of ASN1_TYPE */ + if (!it) { + ASN1_TYPE *typ = (ASN1_TYPE *)*pval; + utype = typ->type; + pval = &typ->value.asn1_value; + if (utype != V_ASN1_BOOLEAN && !*pval) { + return; + } + } else if (it->itype == ASN1_ITYPE_MSTRING) { + utype = -1; + if (!*pval) { + return; } + } else { + utype = it->utype; + if ((utype != V_ASN1_BOOLEAN) && !*pval) { + return; + } + } - switch (utype) { + switch (utype) { case V_ASN1_OBJECT: - ASN1_OBJECT_free((ASN1_OBJECT *)*pval); - break; + ASN1_OBJECT_free((ASN1_OBJECT *)*pval); + break; case V_ASN1_BOOLEAN: - if (it) - *(ASN1_BOOLEAN *)pval = it->size; - else - *(ASN1_BOOLEAN *)pval = -1; - return; + if (it) { + *(ASN1_BOOLEAN *)pval = it->size; + } else { + *(ASN1_BOOLEAN *)pval = -1; + } + return; case V_ASN1_NULL: - break; + break; case V_ASN1_ANY: - ASN1_primitive_free(pval, NULL); - OPENSSL_free(*pval); - break; + ASN1_primitive_free(pval, NULL); + OPENSSL_free(*pval); + break; default: - ASN1_STRING_free((ASN1_STRING *)*pval); - *pval = NULL; - break; - } - *pval = NULL; + ASN1_STRING_free((ASN1_STRING *)*pval); + *pval = NULL; + break; + } + *pval = NULL; } diff --git a/crypto/asn1/tasn_new.c b/crypto/asn1/tasn_new.c index eea219d660..f6cd96f916 100644 --- a/crypto/asn1/tasn_new.c +++ b/crypto/asn1/tasn_new.c @@ -63,8 +63,8 @@ #include #include -#include "internal.h" #include "../internal.h" +#include "internal.h" static int asn1_item_ex_combine_new(ASN1_VALUE **pval, const ASN1_ITEM *it, @@ -75,192 +75,198 @@ static void asn1_template_clear(ASN1_VALUE **pval, const ASN1_TEMPLATE *tt); static int ASN1_primitive_new(ASN1_VALUE **pval, const ASN1_ITEM *it); static void asn1_primitive_clear(ASN1_VALUE **pval, const ASN1_ITEM *it); -ASN1_VALUE *ASN1_item_new(const ASN1_ITEM *it) -{ - ASN1_VALUE *ret = NULL; - if (ASN1_item_ex_new(&ret, it) > 0) - return ret; - return NULL; +ASN1_VALUE *ASN1_item_new(const ASN1_ITEM *it) { + ASN1_VALUE *ret = NULL; + if (ASN1_item_ex_new(&ret, it) > 0) { + return ret; + } + return NULL; } /* Allocate an ASN1 structure */ -int ASN1_item_ex_new(ASN1_VALUE **pval, const ASN1_ITEM *it) -{ - return asn1_item_ex_combine_new(pval, it, 0); +int ASN1_item_ex_new(ASN1_VALUE **pval, const ASN1_ITEM *it) { + return asn1_item_ex_combine_new(pval, it, 0); } static int asn1_item_ex_combine_new(ASN1_VALUE **pval, const ASN1_ITEM *it, - int combine) -{ - const ASN1_TEMPLATE *tt = NULL; - const ASN1_EXTERN_FUNCS *ef; - ASN1_VALUE **pseqval; - int i; - - switch (it->itype) { + int combine) { + const ASN1_TEMPLATE *tt = NULL; + const ASN1_EXTERN_FUNCS *ef; + ASN1_VALUE **pseqval; + int i; + switch (it->itype) { case ASN1_ITYPE_EXTERN: - ef = it->funcs; - if (ef && ef->asn1_ex_new) { - if (!ef->asn1_ex_new(pval, it)) - goto memerr; + ef = it->funcs; + if (ef && ef->asn1_ex_new) { + if (!ef->asn1_ex_new(pval, it)) { + goto memerr; } - break; + } + break; case ASN1_ITYPE_PRIMITIVE: - if (it->templates) { - if (!ASN1_template_new(pval, it->templates)) - goto memerr; - } else if (!ASN1_primitive_new(pval, it)) - goto memerr; - break; + if (it->templates) { + if (!ASN1_template_new(pval, it->templates)) { + goto memerr; + } + } else if (!ASN1_primitive_new(pval, it)) { + goto memerr; + } + break; case ASN1_ITYPE_MSTRING: - if (!ASN1_primitive_new(pval, it)) - goto memerr; - break; + if (!ASN1_primitive_new(pval, it)) { + goto memerr; + } + break; case ASN1_ITYPE_CHOICE: { - const ASN1_AUX *aux = it->funcs; - ASN1_aux_cb *asn1_cb = aux != NULL ? aux->asn1_cb : NULL; - if (asn1_cb) { - i = asn1_cb(ASN1_OP_NEW_PRE, pval, it, NULL); - if (!i) - goto auxerr; - if (i == 2) { - return 1; - } + const ASN1_AUX *aux = it->funcs; + ASN1_aux_cb *asn1_cb = aux != NULL ? aux->asn1_cb : NULL; + if (asn1_cb) { + i = asn1_cb(ASN1_OP_NEW_PRE, pval, it, NULL); + if (!i) { + goto auxerr; } - if (!combine) { - *pval = OPENSSL_malloc(it->size); - if (!*pval) - goto memerr; - OPENSSL_memset(*pval, 0, it->size); + if (i == 2) { + return 1; } - asn1_set_choice_selector(pval, -1, it); - if (asn1_cb && !asn1_cb(ASN1_OP_NEW_POST, pval, it, NULL)) - goto auxerr2; - break; + } + if (!combine) { + *pval = OPENSSL_malloc(it->size); + if (!*pval) { + goto memerr; + } + OPENSSL_memset(*pval, 0, it->size); + } + asn1_set_choice_selector(pval, -1, it); + if (asn1_cb && !asn1_cb(ASN1_OP_NEW_POST, pval, it, NULL)) { + goto auxerr2; + } + break; } case ASN1_ITYPE_SEQUENCE: { - const ASN1_AUX *aux = it->funcs; - ASN1_aux_cb *asn1_cb = aux != NULL ? aux->asn1_cb : NULL; - if (asn1_cb) { - i = asn1_cb(ASN1_OP_NEW_PRE, pval, it, NULL); - if (!i) - goto auxerr; - if (i == 2) { - return 1; - } + const ASN1_AUX *aux = it->funcs; + ASN1_aux_cb *asn1_cb = aux != NULL ? aux->asn1_cb : NULL; + if (asn1_cb) { + i = asn1_cb(ASN1_OP_NEW_PRE, pval, it, NULL); + if (!i) { + goto auxerr; } - if (!combine) { - *pval = OPENSSL_malloc(it->size); - if (!*pval) - goto memerr; - OPENSSL_memset(*pval, 0, it->size); - asn1_refcount_set_one(pval, it); - asn1_enc_init(pval, it); + if (i == 2) { + return 1; } - for (i = 0, tt = it->templates; i < it->tcount; tt++, i++) { - pseqval = asn1_get_field_ptr(pval, tt); - if (!ASN1_template_new(pseqval, tt)) - goto memerr2; + } + if (!combine) { + *pval = OPENSSL_malloc(it->size); + if (!*pval) { + goto memerr; } - if (asn1_cb && !asn1_cb(ASN1_OP_NEW_POST, pval, it, NULL)) - goto auxerr2; - break; - } + OPENSSL_memset(*pval, 0, it->size); + asn1_refcount_set_one(pval, it); + asn1_enc_init(pval, it); + } + for (i = 0, tt = it->templates; i < it->tcount; tt++, i++) { + pseqval = asn1_get_field_ptr(pval, tt); + if (!ASN1_template_new(pseqval, tt)) { + goto memerr2; + } + } + if (asn1_cb && !asn1_cb(ASN1_OP_NEW_POST, pval, it, NULL)) { + goto auxerr2; + } + break; } - return 1; - - memerr2: - asn1_item_combine_free(pval, it, combine); - memerr: - OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE); - return 0; - - auxerr2: - asn1_item_combine_free(pval, it, combine); - auxerr: - OPENSSL_PUT_ERROR(ASN1, ASN1_R_AUX_ERROR); - return 0; - + } + return 1; + +memerr2: + asn1_item_combine_free(pval, it, combine); +memerr: + OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE); + return 0; + +auxerr2: + asn1_item_combine_free(pval, it, combine); +auxerr: + OPENSSL_PUT_ERROR(ASN1, ASN1_R_AUX_ERROR); + return 0; } -static void asn1_item_clear(ASN1_VALUE **pval, const ASN1_ITEM *it) -{ - const ASN1_EXTERN_FUNCS *ef; - - switch (it->itype) { +static void asn1_item_clear(ASN1_VALUE **pval, const ASN1_ITEM *it) { + const ASN1_EXTERN_FUNCS *ef; + switch (it->itype) { case ASN1_ITYPE_EXTERN: - ef = it->funcs; - if (ef && ef->asn1_ex_clear) - ef->asn1_ex_clear(pval, it); - else - *pval = NULL; - break; + ef = it->funcs; + if (ef && ef->asn1_ex_clear) { + ef->asn1_ex_clear(pval, it); + } else { + *pval = NULL; + } + break; case ASN1_ITYPE_PRIMITIVE: - if (it->templates) - asn1_template_clear(pval, it->templates); - else - asn1_primitive_clear(pval, it); - break; + if (it->templates) { + asn1_template_clear(pval, it->templates); + } else { + asn1_primitive_clear(pval, it); + } + break; case ASN1_ITYPE_MSTRING: - asn1_primitive_clear(pval, it); - break; + asn1_primitive_clear(pval, it); + break; case ASN1_ITYPE_CHOICE: case ASN1_ITYPE_SEQUENCE: - *pval = NULL; - break; - } + *pval = NULL; + break; + } } -static int ASN1_template_new(ASN1_VALUE **pval, const ASN1_TEMPLATE *tt) -{ - const ASN1_ITEM *it = ASN1_ITEM_ptr(tt->item); - int ret; - if (tt->flags & ASN1_TFLG_OPTIONAL) { - asn1_template_clear(pval, tt); - return 1; - } - /* If ANY DEFINED BY nothing to do */ +static int ASN1_template_new(ASN1_VALUE **pval, const ASN1_TEMPLATE *tt) { + const ASN1_ITEM *it = ASN1_ITEM_ptr(tt->item); + int ret; + if (tt->flags & ASN1_TFLG_OPTIONAL) { + asn1_template_clear(pval, tt); + return 1; + } + /* If ANY DEFINED BY nothing to do */ - if (tt->flags & ASN1_TFLG_ADB_MASK) { - *pval = NULL; - return 1; - } - /* If SET OF or SEQUENCE OF, its a STACK */ - if (tt->flags & ASN1_TFLG_SK_MASK) { - STACK_OF(ASN1_VALUE) *skval; - skval = sk_ASN1_VALUE_new_null(); - if (!skval) { - OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE); - ret = 0; - goto done; - } - *pval = (ASN1_VALUE *)skval; - ret = 1; - goto done; + if (tt->flags & ASN1_TFLG_ADB_MASK) { + *pval = NULL; + return 1; + } + /* If SET OF or SEQUENCE OF, its a STACK */ + if (tt->flags & ASN1_TFLG_SK_MASK) { + STACK_OF(ASN1_VALUE) *skval; + skval = sk_ASN1_VALUE_new_null(); + if (!skval) { + OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE); + ret = 0; + goto done; } - /* Otherwise pass it back to the item routine */ - ret = asn1_item_ex_combine_new(pval, it, tt->flags & ASN1_TFLG_COMBINE); - done: - return ret; + *pval = (ASN1_VALUE *)skval; + ret = 1; + goto done; + } + /* Otherwise pass it back to the item routine */ + ret = asn1_item_ex_combine_new(pval, it, tt->flags & ASN1_TFLG_COMBINE); +done: + return ret; } -static void asn1_template_clear(ASN1_VALUE **pval, const ASN1_TEMPLATE *tt) -{ - /* If ADB or STACK just NULL the field */ - if (tt->flags & (ASN1_TFLG_ADB_MASK | ASN1_TFLG_SK_MASK)) - *pval = NULL; - else - asn1_item_clear(pval, ASN1_ITEM_ptr(tt->item)); +static void asn1_template_clear(ASN1_VALUE **pval, const ASN1_TEMPLATE *tt) { + /* If ADB or STACK just NULL the field */ + if (tt->flags & (ASN1_TFLG_ADB_MASK | ASN1_TFLG_SK_MASK)) { + *pval = NULL; + } else { + asn1_item_clear(pval, ASN1_ITEM_ptr(tt->item)); + } } /* @@ -268,65 +274,69 @@ static void asn1_template_clear(ASN1_VALUE **pval, const ASN1_TEMPLATE *tt) * all the old functions. */ -static int ASN1_primitive_new(ASN1_VALUE **pval, const ASN1_ITEM *it) -{ - ASN1_TYPE *typ; - int utype; +static int ASN1_primitive_new(ASN1_VALUE **pval, const ASN1_ITEM *it) { + ASN1_TYPE *typ; + int utype; - if (!it) - return 0; - - /* Historically, |it->funcs| for primitive types contained an - * |ASN1_PRIMITIVE_FUNCS| table of calbacks. */ - assert(it->funcs == NULL); - - if (it->itype == ASN1_ITYPE_MSTRING) - utype = -1; - else - utype = it->utype; - switch (utype) { + if (!it) { + return 0; + } + + /* Historically, |it->funcs| for primitive types contained an + * |ASN1_PRIMITIVE_FUNCS| table of calbacks. */ + assert(it->funcs == NULL); + + if (it->itype == ASN1_ITYPE_MSTRING) { + utype = -1; + } else { + utype = it->utype; + } + switch (utype) { case V_ASN1_OBJECT: - *pval = (ASN1_VALUE *)OBJ_nid2obj(NID_undef); - return 1; + *pval = (ASN1_VALUE *)OBJ_nid2obj(NID_undef); + return 1; case V_ASN1_BOOLEAN: - *(ASN1_BOOLEAN *)pval = it->size; - return 1; + *(ASN1_BOOLEAN *)pval = it->size; + return 1; case V_ASN1_NULL: - *pval = (ASN1_VALUE *)1; - return 1; + *pval = (ASN1_VALUE *)1; + return 1; case V_ASN1_ANY: - typ = OPENSSL_malloc(sizeof(ASN1_TYPE)); - if (!typ) - return 0; - typ->value.ptr = NULL; - typ->type = -1; - *pval = (ASN1_VALUE *)typ; - break; + typ = OPENSSL_malloc(sizeof(ASN1_TYPE)); + if (!typ) { + return 0; + } + typ->value.ptr = NULL; + typ->type = -1; + *pval = (ASN1_VALUE *)typ; + break; default: - *pval = (ASN1_VALUE *)ASN1_STRING_type_new(utype); - break; - } - if (*pval) - return 1; - return 0; + *pval = (ASN1_VALUE *)ASN1_STRING_type_new(utype); + break; + } + if (*pval) { + return 1; + } + return 0; } -static void asn1_primitive_clear(ASN1_VALUE **pval, const ASN1_ITEM *it) -{ - int utype; - /* Historically, |it->funcs| for primitive types contained an - * |ASN1_PRIMITIVE_FUNCS| table of calbacks. */ - assert(it == NULL || it->funcs == NULL); - if (!it || (it->itype == ASN1_ITYPE_MSTRING)) - utype = -1; - else - utype = it->utype; - if (utype == V_ASN1_BOOLEAN) - *(ASN1_BOOLEAN *)pval = it->size; - else - *pval = NULL; +static void asn1_primitive_clear(ASN1_VALUE **pval, const ASN1_ITEM *it) { + int utype; + /* Historically, |it->funcs| for primitive types contained an + * |ASN1_PRIMITIVE_FUNCS| table of calbacks. */ + assert(it == NULL || it->funcs == NULL); + if (!it || (it->itype == ASN1_ITYPE_MSTRING)) { + utype = -1; + } else { + utype = it->utype; + } + if (utype == V_ASN1_BOOLEAN) { + *(ASN1_BOOLEAN *)pval = it->size; + } else { + *pval = NULL; + } } diff --git a/crypto/asn1/tasn_typ.c b/crypto/asn1/tasn_typ.c index 5cfdd574b8..e38154eae8 100644 --- a/crypto/asn1/tasn_typ.c +++ b/crypto/asn1/tasn_typ.c @@ -60,17 +60,11 @@ /* Declarations for string types */ -#define IMPLEMENT_ASN1_STRING_FUNCTIONS(sname) \ - IMPLEMENT_ASN1_TYPE(sname) \ - IMPLEMENT_ASN1_ENCODE_FUNCTIONS_const_fname(sname, sname, sname) \ - sname *sname##_new(void) \ - { \ - return ASN1_STRING_type_new(V_##sname); \ - } \ - void sname##_free(sname *x) \ - { \ - ASN1_STRING_free(x); \ - } +#define IMPLEMENT_ASN1_STRING_FUNCTIONS(sname) \ + IMPLEMENT_ASN1_TYPE(sname) \ + IMPLEMENT_ASN1_ENCODE_FUNCTIONS_const_fname(sname, sname, sname) \ + sname *sname##_new(void) { return ASN1_STRING_type_new(V_##sname); } \ + void sname##_free(sname *x) { ASN1_STRING_free(x); } IMPLEMENT_ASN1_STRING_FUNCTIONS(ASN1_OCTET_STRING) IMPLEMENT_ASN1_STRING_FUNCTIONS(ASN1_INTEGER) @@ -120,12 +114,15 @@ IMPLEMENT_ASN1_TYPE_ex(ASN1_FBOOLEAN, ASN1_BOOLEAN, 0) /* Special, OCTET STRING with indefinite length constructed support */ ASN1_ITEM_TEMPLATE(ASN1_SEQUENCE_ANY) = - ASN1_EX_TEMPLATE_TYPE(ASN1_TFLG_SEQUENCE_OF, 0, ASN1_SEQUENCE_ANY, ASN1_ANY) + ASN1_EX_TEMPLATE_TYPE(ASN1_TFLG_SEQUENCE_OF, 0, ASN1_SEQUENCE_ANY, ASN1_ANY) ASN1_ITEM_TEMPLATE_END(ASN1_SEQUENCE_ANY) -ASN1_ITEM_TEMPLATE(ASN1_SET_ANY) = - ASN1_EX_TEMPLATE_TYPE(ASN1_TFLG_SET_OF, 0, ASN1_SET_ANY, ASN1_ANY) +ASN1_ITEM_TEMPLATE(ASN1_SET_ANY) = ASN1_EX_TEMPLATE_TYPE(ASN1_TFLG_SET_OF, 0, + ASN1_SET_ANY, ASN1_ANY) ASN1_ITEM_TEMPLATE_END(ASN1_SET_ANY) -IMPLEMENT_ASN1_ENCODE_FUNCTIONS_const_fname(ASN1_SEQUENCE_ANY, ASN1_SEQUENCE_ANY, ASN1_SEQUENCE_ANY) -IMPLEMENT_ASN1_ENCODE_FUNCTIONS_const_fname(ASN1_SEQUENCE_ANY, ASN1_SET_ANY, ASN1_SET_ANY) +IMPLEMENT_ASN1_ENCODE_FUNCTIONS_const_fname(ASN1_SEQUENCE_ANY, + ASN1_SEQUENCE_ANY, + ASN1_SEQUENCE_ANY) +IMPLEMENT_ASN1_ENCODE_FUNCTIONS_const_fname(ASN1_SEQUENCE_ANY, ASN1_SET_ANY, + ASN1_SET_ANY) diff --git a/crypto/asn1/tasn_utl.c b/crypto/asn1/tasn_utl.c index 0b6048c33a..9f52347369 100644 --- a/crypto/asn1/tasn_utl.c +++ b/crypto/asn1/tasn_utl.c @@ -60,9 +60,9 @@ #include #include +#include #include #include -#include #include #include "../internal.h" @@ -173,7 +173,7 @@ int asn1_enc_save(ASN1_VALUE **pval, const unsigned char *in, int inlen, enc->alias_only_on_next_parse = 0; if (enc->alias_only) { - enc->enc = (uint8_t *) in; + enc->enc = (uint8_t *)in; } else { enc->enc = OPENSSL_malloc(inlen); if (!enc->enc) { diff --git a/crypto/asn1/time_support.c b/crypto/asn1/time_support.c index 68c6086aad..5703a54b09 100644 --- a/crypto/asn1/time_support.c +++ b/crypto/asn1/time_support.c @@ -56,7 +56,7 @@ * Hudson (tjh@cryptsoft.com). */ #if defined(__linux__) && !defined(_POSIX_C_SOURCE) -#define _POSIX_C_SOURCE 201410L /* for gmtime_r */ +#define _POSIX_C_SOURCE 201410L /* for gmtime_r */ #endif #include "internal.h" diff --git a/crypto/bio/connect.c b/crypto/bio/connect.c index 3b65acfca7..9b86e5138a 100644 --- a/crypto/bio/connect.c +++ b/crypto/bio/connect.c @@ -117,7 +117,8 @@ static int closesocket(int sock) { // split_host_and_port sets |*out_host| and |*out_port| to the host and port // parsed from |name|. It returns one on success or zero on error. Even when // successful, |*out_port| may be NULL on return if no port was specified. -static int split_host_and_port(char **out_host, char **out_port, const char *name) { +static int split_host_and_port(char **out_host, char **out_port, + const char *name) { const char *host, *port = NULL; size_t host_len = 0; @@ -466,8 +467,7 @@ static long conn_ctrl(BIO *bio, int cmd, long num, void *ptr) { case BIO_CTRL_FLUSH: break; case BIO_CTRL_GET_CALLBACK: { - int (**fptr)(const BIO *bio, int state, int xret); - fptr = (int (**)(const BIO *bio, int state, int xret))ptr; + int (**fptr)(const BIO *bio, int state, int xret) = ptr; *fptr = data->info_callback; } break; default: @@ -485,7 +485,13 @@ static long conn_callback_ctrl(BIO *bio, int cmd, bio_info_cb fp) { switch (cmd) { case BIO_CTRL_SET_CALLBACK: + // This is the actual type signature of |fp|. The caller is expected to + // cast it to |bio_info_cb| due to the |BIO_callback_ctrl| calling + // convention. + OPENSSL_MSVC_PRAGMA(warning(push)) + OPENSSL_MSVC_PRAGMA(warning(disable : 4191)) data->info_callback = (int (*)(const struct bio_st *, int, int))fp; + OPENSSL_MSVC_PRAGMA(warning(pop)) break; default: ret = 0; diff --git a/crypto/bytestring/bytestring_test.cc b/crypto/bytestring/bytestring_test.cc index a8c19132a5..b6b716e56d 100644 --- a/crypto/bytestring/bytestring_test.cc +++ b/crypto/bytestring/bytestring_test.cc @@ -24,9 +24,9 @@ #include #include -#include "internal.h" #include "../internal.h" #include "../test/test_util.h" +#include "internal.h" TEST(CBSTest, Skip) { @@ -1493,3 +1493,127 @@ TEST(CBBTest, Unicode) { EXPECT_EQ(4u, cbb_get_utf8_len(0x10000)); EXPECT_EQ(4u, cbb_get_utf8_len(0x10ffff)); } + +TEST(CBSTest, BogusTime) { + static const struct { + const char *timestring; + } kBogusTimeTests[] = { + {""}, + {"invalidtimesZ"}, + {"Z"}, + {"0000"}, + {"9999Z"}, + {"00000000000000000000000000000Z"}, + {"19491231235959"}, + {"500101000000.001Z"}, + {"500101000000+6"}, + {"-1970010100000Z"}, + {"7a0101000000Z"}, + {"20500101000000-6"}, + {"20500101000000.001"}, + {"20500229000000Z"}, + {"220229000000Z"}, + {"20500132000000Z"}, + {"220132000000Z"}, + {"20500332000000Z"}, + {"220332000000Z"}, + {"20500532000000Z"}, + {"220532000000Z"}, + {"20500732000000Z"}, + {"220732000000Z"}, + {"20500832000000Z"}, + {"220832000000Z"}, + {"20501032000000Z"}, + {"221032000000Z"}, + {"20501232000000Z"}, + {"221232000000Z"}, + {"20500431000000Z"}, + {"220431000000Z"}, + {"20500631000000Z"}, + {"220631000000Z"}, + {"20500931000000Z"}, + {"220931000000Z"}, + {"20501131000000Z"}, + {"221131000000Z"}, + {"20501100000000Z"}, + {"221100000000Z"}, + {"19500101000000+0600"}, + }; + for (const auto &t : kBogusTimeTests) { + SCOPED_TRACE(t.timestring); + CBS cbs; + CBS_init(&cbs, (const uint8_t *)t.timestring, strlen(t.timestring)); + EXPECT_FALSE(CBS_parse_generalized_time(&cbs, NULL, + /*allow_timezone_offset=*/0)); + EXPECT_FALSE(CBS_parse_utc_time(&cbs, NULL, /*allow_timezone_offset=*/1)); + } + static const struct { + const char *timestring; + } kUTCTZTests[] = { + {"480711220333-0700"}, + {"140704000000-0700"}, + {"480222202332-0500"}, + {"480726113216-0000"}, + {"480726113216-2359"}, + }; + for (const auto &t : kUTCTZTests) { + SCOPED_TRACE(t.timestring); + CBS cbs; + CBS_init(&cbs, (const uint8_t *)t.timestring, strlen(t.timestring)); + EXPECT_FALSE(CBS_parse_generalized_time(&cbs, NULL, + /*allow_timezone_offset=*/0)); + EXPECT_FALSE(CBS_parse_generalized_time(&cbs, NULL, + /*allow_timezone_offset=*/1)); + EXPECT_TRUE(CBS_parse_utc_time(&cbs, NULL, /*allow_timezone_offset=*/1)); + EXPECT_FALSE(CBS_parse_utc_time(&cbs, NULL, /*allow_timezone_offset=*/0)); + } + static const struct { + const char *timestring; + } kBogusUTCTZTests[] = { + {"480711220333-0160"}, + {"140704000000-9999"}, + {"480222202332-2400"}, + }; + for (const auto &t : kBogusUTCTZTests) { + SCOPED_TRACE(t.timestring); + CBS cbs; + CBS_init(&cbs, (const uint8_t *)t.timestring, strlen(t.timestring)); + EXPECT_FALSE(CBS_parse_generalized_time(&cbs, NULL, + /*allow_timezone_offset=*/0)); + EXPECT_FALSE(CBS_parse_utc_time(&cbs, NULL, /*allow_timezone_offset=*/1)); + } + static const struct { + const char *timestring; + } kGenTZTests[] = { + {"20480711220333-0000"}, + {"20140704000000-0100"}, + {"20460311174630-0300"}, + {"20140704000000-2359"}, + }; + for (const auto &t : kGenTZTests) { + SCOPED_TRACE(t.timestring); + CBS cbs; + CBS_init(&cbs, (const uint8_t *)t.timestring, strlen(t.timestring)); + EXPECT_FALSE(CBS_parse_generalized_time(&cbs, NULL, + /*allow_timezone_offset=*/0)); + EXPECT_TRUE(CBS_parse_generalized_time(&cbs, NULL, + /*allow_timezone_offset=*/1)); + EXPECT_FALSE(CBS_parse_utc_time(&cbs, NULL, /*allow_timezone_offset=*/1)); + EXPECT_FALSE(CBS_parse_utc_time(&cbs, NULL, /*allow_timezone_offset=*/0)); + } + static const struct { + const char *timestring; + } kBogusGenTZTests[] = { + {"20480222202332-2400"}, + {"20140704000000-9999"}, + {"20480726113216-0160"}, + }; + for (const auto &t : kBogusGenTZTests) { + SCOPED_TRACE(t.timestring); + CBS cbs; + CBS_init(&cbs, (const uint8_t *)t.timestring, strlen(t.timestring)); + EXPECT_FALSE(CBS_parse_generalized_time(&cbs, NULL, + /*allow_timezone_offset=*/0)); + EXPECT_FALSE(CBS_parse_utc_time(&cbs, NULL, /*allow_timezone_offset=*/1)); + } +} diff --git a/crypto/bytestring/cbs.c b/crypto/bytestring/cbs.c index c489718813..0425df0da3 100644 --- a/crypto/bytestring/cbs.c +++ b/crypto/bytestring/cbs.c @@ -12,20 +12,23 @@ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -#include +#include #include +#include #include #ifndef __STDC_FORMAT_MACROS #define __STDC_FORMAT_MACROS #endif +#include #include #include -#include "internal.h" +#include "../asn1/internal.h" #include "../internal.h" +#include "internal.h" void CBS_init(CBS *cbs, const uint8_t *data, size_t len) { @@ -725,3 +728,161 @@ char *CBS_asn1_oid_to_text(const CBS *cbs) { CBB_cleanup(&cbb); return NULL; } + +static int cbs_get_two_digits(CBS *cbs, int *out) { + uint8_t first_digit, second_digit; + if (!CBS_get_u8(cbs, &first_digit)) { + return 0; + } + if (!isdigit(first_digit)) { + return 0; + } + if (!CBS_get_u8(cbs, &second_digit)) { + return 0; + } + if (!isdigit(second_digit)) { + return 0; + } + *out = (first_digit - '0') * 10 + (second_digit - '0'); + return 1; +} + +static int is_valid_day(int year, int month, int day) { + if (day < 1) { + return 0; + } + switch (month) { + case 1: + case 3: + case 5: + case 7: + case 8: + case 10: + case 12: + return day <= 31; + case 4: + case 6: + case 9: + case 11: + return day <= 30; + case 2: + if ((year % 4 == 0 && year % 100 != 0) || year % 400 == 0) { + return day <= 29; + } else { + return day <= 28; + } + default: + return 0; + } +} + +static int CBS_parse_rfc5280_time_internal(const CBS *cbs, int is_gentime, + int allow_timezone_offset, + struct tm *out_tm) { + int year, month, day, hour, min, sec, tmp; + CBS copy = *cbs; + uint8_t tz; + + if (is_gentime) { + if (!cbs_get_two_digits(©, &tmp)) { + return 0; + } + year = tmp * 100; + if (!cbs_get_two_digits(©, &tmp)) { + return 0; + } + year += tmp; + } else { + year = 1900; + if (!cbs_get_two_digits(©, &tmp)) { + return 0; + } + year += tmp; + if (year < 1950) { + year += 100; + } + if (year >= 2050) { + return 0; // A Generalized time must be used. + } + } + if (!cbs_get_two_digits(©, &month) || month < 1 || + month > 12 || // Reject invalid months. + !cbs_get_two_digits(©, &day) || + !is_valid_day(year, month, day) || // Reject invalid days. + !cbs_get_two_digits(©, &hour) || + hour > 23 || // Reject invalid hours. + !cbs_get_two_digits(©, &min) || + min > 59 || // Reject invalid minutes. + !cbs_get_two_digits(©, &sec) || sec > 59 || !CBS_get_u8(©, &tz)) { + return 0; + } + + int offset_sign = 0; + switch (tz) { + case 'Z': + break; // We correctly have 'Z' on the end as per spec. + case '+': + offset_sign = 1; + break; // Should not be allowed per RFC 5280. + case '-': + offset_sign = -1; + break; // Should not be allowed per RFC 5280. + default: + return 0; // Reject anything else after the time. + } + + // If allow_timezone_offset is non-zero, allow for a four digit timezone + // offset to be specified even though this is not allowed by RFC 5280. We are + // permissive of this for UTCTimes due to the unfortunate existence of + // artisinally rolled long lived certificates that were baked into places that + // are now difficult to change. These certificates were generated with the + // 'openssl' command that permissively allowed the creation of certificates + // with notBefore and notAfter times specified as strings for direct + // certificate inclusion on the command line. For context see cl/237068815. + // + // TODO(bbe): This has been expunged from public web-pki as the ecosystem has + // managed to encourage CA compliance with standards. We should find a way to + // get rid of this or make it off by default. + int offset_seconds = 0; + if (offset_sign != 0) { + if (!allow_timezone_offset) { + return 0; + } + int offset_hours, offset_minutes; + if (!cbs_get_two_digits(©, &offset_hours) || + offset_hours > 23 || // Reject invalid hours. + !cbs_get_two_digits(©, &offset_minutes) || + offset_minutes > 59) { // Reject invalid minutes. + return 0; + } + offset_seconds = offset_sign * (offset_hours * 3600 + offset_minutes * 60); + } + + if (CBS_len(©) != 0) { + return 0; // Reject invalid lengths. + } + + if (out_tm != NULL) { + // Fill in the tm fields corresponding to what we validated. + out_tm->tm_year = year - 1900; + out_tm->tm_mon = month - 1; + out_tm->tm_mday = day; + out_tm->tm_hour = hour; + out_tm->tm_min = min; + out_tm->tm_sec = sec; + if (offset_seconds && !OPENSSL_gmtime_adj(out_tm, 0, offset_seconds)) { + return 0; + } + } + return 1; +} + +int CBS_parse_generalized_time(const CBS *cbs, struct tm *out_tm, + int allow_timezone_offset) { + return CBS_parse_rfc5280_time_internal(cbs, 1, allow_timezone_offset, out_tm); +} + +int CBS_parse_utc_time(const CBS *cbs, struct tm *out_tm, + int allow_timezone_offset) { + return CBS_parse_rfc5280_time_internal(cbs, 0, allow_timezone_offset, out_tm); +} diff --git a/crypto/cipher_extra/e_aesctrhmac.c b/crypto/cipher_extra/e_aesctrhmac.c index 24554e83be..3b6d15bef0 100644 --- a/crypto/cipher_extra/e_aesctrhmac.c +++ b/crypto/cipher_extra/e_aesctrhmac.c @@ -38,11 +38,9 @@ struct aead_aes_ctr_hmac_sha256_ctx { OPENSSL_STATIC_ASSERT(sizeof(((EVP_AEAD_CTX *)NULL)->state) >= sizeof(struct aead_aes_ctr_hmac_sha256_ctx), AEAD_state_is_too_small) -#if defined(__GNUC__) || defined(__clang__) OPENSSL_STATIC_ASSERT(alignof(union evp_aead_ctx_st_state) >= alignof(struct aead_aes_ctr_hmac_sha256_ctx), AEAD_state_has_insufficient_alignment) -#endif static void hmac_init(SHA256_CTX *out_inner, SHA256_CTX *out_outer, const uint8_t hmac_key[32]) { diff --git a/crypto/cipher_extra/e_aesgcmsiv.c b/crypto/cipher_extra/e_aesgcmsiv.c index 385babee62..d5936463b9 100644 --- a/crypto/cipher_extra/e_aesgcmsiv.c +++ b/crypto/cipher_extra/e_aesgcmsiv.c @@ -45,10 +45,8 @@ struct aead_aes_gcm_siv_asm_ctx { OPENSSL_STATIC_ASSERT(sizeof(((EVP_AEAD_CTX *)NULL)->state) + 8 >= sizeof(struct aead_aes_gcm_siv_asm_ctx), AEAD_state_is_too_small) -#if defined(__GNUC__) || defined(__clang__) OPENSSL_STATIC_ASSERT(alignof(union evp_aead_ctx_st_state) >= 8, AEAD_state_has_insufficient_alignment) -#endif // asm_ctx_from_ctx returns a 16-byte aligned context pointer from |ctx|. static struct aead_aes_gcm_siv_asm_ctx *asm_ctx_from_ctx( @@ -555,11 +553,9 @@ struct aead_aes_gcm_siv_ctx { OPENSSL_STATIC_ASSERT(sizeof(((EVP_AEAD_CTX *)NULL)->state) >= sizeof(struct aead_aes_gcm_siv_ctx), AEAD_state_is_too_small) -#if defined(__GNUC__) || defined(__clang__) OPENSSL_STATIC_ASSERT(alignof(union evp_aead_ctx_st_state) >= alignof(struct aead_aes_gcm_siv_ctx), AEAD_state_has_insufficient_alignment) -#endif static int aead_aes_gcm_siv_init(EVP_AEAD_CTX *ctx, const uint8_t *key, size_t key_len, size_t tag_len) { diff --git a/crypto/cipher_extra/e_chacha20poly1305.c b/crypto/cipher_extra/e_chacha20poly1305.c index 7eb7e0ce69..c84c69b5c9 100644 --- a/crypto/cipher_extra/e_chacha20poly1305.c +++ b/crypto/cipher_extra/e_chacha20poly1305.c @@ -35,11 +35,9 @@ struct aead_chacha20_poly1305_ctx { OPENSSL_STATIC_ASSERT(sizeof(((EVP_AEAD_CTX *)NULL)->state) >= sizeof(struct aead_chacha20_poly1305_ctx), AEAD_state_is_too_small) -#if defined(__GNUC__) || defined(__clang__) OPENSSL_STATIC_ASSERT(alignof(union evp_aead_ctx_st_state) >= alignof(struct aead_chacha20_poly1305_ctx), AEAD_state_has_insufficient_alignment) -#endif static int aead_chacha20_poly1305_init(EVP_AEAD_CTX *ctx, const uint8_t *key, size_t key_len, size_t tag_len) { diff --git a/crypto/fipsmodule/cipher/e_aes.c b/crypto/fipsmodule/cipher/e_aes.c index 9f1c45b8ba..c4c13179f8 100644 --- a/crypto/fipsmodule/cipher/e_aes.c +++ b/crypto/fipsmodule/cipher/e_aes.c @@ -335,11 +335,9 @@ ctr128_f aes_ctr_set_key(AES_KEY *aes_key, GCM128_KEY *gcm_key, #endif static EVP_AES_GCM_CTX *aes_gcm_from_cipher_ctx(EVP_CIPHER_CTX *ctx) { -#if defined(__GNUC__) || defined(__clang__) OPENSSL_STATIC_ASSERT( alignof(EVP_AES_GCM_CTX) <= 16, EVP_AES_GCM_CTX_needs_more_alignment_than_this_function_provides) -#endif // |malloc| guarantees up to 4-byte alignment on 32-bit and 8-byte alignment // on 64-bit systems, so we need to adjust to reach 16-byte alignment. @@ -1049,11 +1047,9 @@ static int aead_aes_gcm_init_impl(struct aead_aes_gcm_ctx *gcm_ctx, OPENSSL_STATIC_ASSERT(sizeof(((EVP_AEAD_CTX *)NULL)->state) >= sizeof(struct aead_aes_gcm_ctx), AEAD_state_is_too_small) -#if defined(__GNUC__) || defined(__clang__) OPENSSL_STATIC_ASSERT(alignof(union evp_aead_ctx_st_state) >= alignof(struct aead_aes_gcm_ctx), AEAD_state_has_insufficient_alignment) -#endif static int aead_aes_gcm_init(EVP_AEAD_CTX *ctx, const uint8_t *key, size_t key_len, size_t requested_tag_len) { @@ -1388,11 +1384,9 @@ struct aead_aes_gcm_tls12_ctx { OPENSSL_STATIC_ASSERT(sizeof(((EVP_AEAD_CTX *)NULL)->state) >= sizeof(struct aead_aes_gcm_tls12_ctx), AEAD_state_is_too_small) -#if defined(__GNUC__) || defined(__clang__) OPENSSL_STATIC_ASSERT(alignof(union evp_aead_ctx_st_state) >= alignof(struct aead_aes_gcm_tls12_ctx), AEAD_state_has_insufficient_alignment) -#endif static int aead_aes_gcm_tls12_init(EVP_AEAD_CTX *ctx, const uint8_t *key, size_t key_len, size_t requested_tag_len) { @@ -1486,11 +1480,9 @@ struct aead_aes_gcm_tls13_ctx { OPENSSL_STATIC_ASSERT(sizeof(((EVP_AEAD_CTX *)NULL)->state) >= sizeof(struct aead_aes_gcm_tls13_ctx), AEAD_state_is_too_small) -#if defined(__GNUC__) || defined(__clang__) OPENSSL_STATIC_ASSERT(alignof(union evp_aead_ctx_st_state) >= alignof(struct aead_aes_gcm_tls13_ctx), AEAD_state_has_insufficient_alignment) -#endif static int aead_aes_gcm_tls13_init(EVP_AEAD_CTX *ctx, const uint8_t *key, size_t key_len, size_t requested_tag_len) { diff --git a/crypto/fipsmodule/cipher/e_aesccm.c b/crypto/fipsmodule/cipher/e_aesccm.c index 416306876c..394a4bfde3 100644 --- a/crypto/fipsmodule/cipher/e_aesccm.c +++ b/crypto/fipsmodule/cipher/e_aesccm.c @@ -279,11 +279,9 @@ struct aead_aes_ccm_ctx { OPENSSL_STATIC_ASSERT(sizeof(((EVP_AEAD_CTX *)NULL)->state) >= sizeof(struct aead_aes_ccm_ctx), AEAD_state_is_too_small) -#if defined(__GNUC__) || defined(__clang__) OPENSSL_STATIC_ASSERT(alignof(union evp_aead_ctx_st_state) >= alignof(struct aead_aes_ccm_ctx), AEAD_state_has_insufficient_alignment) -#endif static int aead_aes_ccm_init(EVP_AEAD_CTX *ctx, const uint8_t *key, size_t key_len, size_t tag_len, unsigned M, diff --git a/crypto/lhash/internal.h b/crypto/lhash/internal.h index 64dca1d364..512f06df44 100644 --- a/crypto/lhash/internal.h +++ b/crypto/lhash/internal.h @@ -157,6 +157,16 @@ OPENSSL_EXPORT void OPENSSL_lh_doall_arg(_LHASH *lh, void *arg); #define DEFINE_LHASH_OF(type) \ + /* We disable MSVC C4191 in this macro, which warns when pointers are cast \ + * to the wrong type. While the cast itself is valid, it is often a bug \ + * because calling it through the cast is UB. However, we never actually \ + * call functions as |lhash_cmp_func|. The type is just a type-erased \ + * function pointer. (C does not guarantee function pointers fit in \ + * |void*|, and GCC will warn on this.) Thus we just disable the false \ + * positive warning. */ \ + OPENSSL_MSVC_PRAGMA(warning(push)) \ + OPENSSL_MSVC_PRAGMA(warning(disable : 4191)) \ + \ DECLARE_LHASH_OF(type) \ \ typedef int (*lhash_##type##_cmp_func)(const type *, const type *); \ @@ -243,7 +253,9 @@ OPENSSL_EXPORT void OPENSSL_lh_doall_arg(_LHASH *lh, LHASH_OF(type) *lh, void (*func)(type *, void *), void *arg) { \ LHASH_DOALL_##type cb = {func, arg}; \ OPENSSL_lh_doall_arg((_LHASH *)lh, lh_##type##_call_doall_arg, &cb); \ - } + } \ + \ + OPENSSL_MSVC_PRAGMA(warning(pop)) #if defined(__cplusplus) diff --git a/crypto/pem/pem_all.c b/crypto/pem/pem_all.c index 706b7f410c..e211d5d913 100644 --- a/crypto/pem/pem_all.c +++ b/crypto/pem/pem_all.c @@ -133,105 +133,99 @@ IMPLEMENT_PEM_rw(PKCS7, PKCS7, PEM_STRING_PKCS7, PKCS7) * the relevant private key: this means can handle "traditional" and PKCS#8 * formats transparently. */ -static RSA *pkey_get_rsa(EVP_PKEY *key, RSA **rsa) -{ - RSA *rtmp; - if (!key) - return NULL; - rtmp = EVP_PKEY_get1_RSA(key); - EVP_PKEY_free(key); - if (!rtmp) - return NULL; - if (rsa) { - RSA_free(*rsa); - *rsa = rtmp; - } - return rtmp; +static RSA *pkey_get_rsa(EVP_PKEY *key, RSA **rsa) { + RSA *rtmp; + if (!key) { + return NULL; + } + rtmp = EVP_PKEY_get1_RSA(key); + EVP_PKEY_free(key); + if (!rtmp) { + return NULL; + } + if (rsa) { + RSA_free(*rsa); + *rsa = rtmp; + } + return rtmp; } RSA *PEM_read_bio_RSAPrivateKey(BIO *bp, RSA **rsa, pem_password_cb *cb, - void *u) -{ - EVP_PKEY *pktmp; - pktmp = PEM_read_bio_PrivateKey(bp, NULL, cb, u); - return pkey_get_rsa(pktmp, rsa); + void *u) { + EVP_PKEY *pktmp; + pktmp = PEM_read_bio_PrivateKey(bp, NULL, cb, u); + return pkey_get_rsa(pktmp, rsa); } -RSA *PEM_read_RSAPrivateKey(FILE *fp, RSA **rsa, pem_password_cb *cb, void *u) -{ - EVP_PKEY *pktmp; - pktmp = PEM_read_PrivateKey(fp, NULL, cb, u); - return pkey_get_rsa(pktmp, rsa); +RSA *PEM_read_RSAPrivateKey(FILE *fp, RSA **rsa, pem_password_cb *cb, void *u) { + EVP_PKEY *pktmp; + pktmp = PEM_read_PrivateKey(fp, NULL, cb, u); + return pkey_get_rsa(pktmp, rsa); } -IMPLEMENT_PEM_write_cb_const(RSAPrivateKey, RSA, PEM_STRING_RSA, - RSAPrivateKey) +IMPLEMENT_PEM_write_cb_const(RSAPrivateKey, RSA, PEM_STRING_RSA, RSAPrivateKey) -IMPLEMENT_PEM_rw_const(RSAPublicKey, RSA, PEM_STRING_RSA_PUBLIC, - RSAPublicKey) IMPLEMENT_PEM_rw(RSA_PUBKEY, RSA, - PEM_STRING_PUBLIC, - RSA_PUBKEY) +IMPLEMENT_PEM_rw_const(RSAPublicKey, RSA, PEM_STRING_RSA_PUBLIC, RSAPublicKey) +IMPLEMENT_PEM_rw(RSA_PUBKEY, RSA, PEM_STRING_PUBLIC, RSA_PUBKEY) #ifndef OPENSSL_NO_DSA -static DSA *pkey_get_dsa(EVP_PKEY *key, DSA **dsa) -{ - DSA *dtmp; - if (!key) - return NULL; - dtmp = EVP_PKEY_get1_DSA(key); - EVP_PKEY_free(key); - if (!dtmp) - return NULL; - if (dsa) { - DSA_free(*dsa); - *dsa = dtmp; - } - return dtmp; +static DSA *pkey_get_dsa(EVP_PKEY *key, DSA **dsa) { + DSA *dtmp; + if (!key) { + return NULL; + } + dtmp = EVP_PKEY_get1_DSA(key); + EVP_PKEY_free(key); + if (!dtmp) { + return NULL; + } + if (dsa) { + DSA_free(*dsa); + *dsa = dtmp; + } + return dtmp; } DSA *PEM_read_bio_DSAPrivateKey(BIO *bp, DSA **dsa, pem_password_cb *cb, - void *u) -{ - EVP_PKEY *pktmp; - pktmp = PEM_read_bio_PrivateKey(bp, NULL, cb, u); - return pkey_get_dsa(pktmp, dsa); /* will free pktmp */ + void *u) { + EVP_PKEY *pktmp; + pktmp = PEM_read_bio_PrivateKey(bp, NULL, cb, u); + return pkey_get_dsa(pktmp, dsa); /* will free pktmp */ } -IMPLEMENT_PEM_write_cb_const(DSAPrivateKey, DSA, PEM_STRING_DSA, - DSAPrivateKey) +IMPLEMENT_PEM_write_cb_const(DSAPrivateKey, DSA, PEM_STRING_DSA, DSAPrivateKey) IMPLEMENT_PEM_rw(DSA_PUBKEY, DSA, PEM_STRING_PUBLIC, DSA_PUBKEY) -DSA *PEM_read_DSAPrivateKey(FILE *fp, DSA **dsa, pem_password_cb *cb, void *u) -{ - EVP_PKEY *pktmp; - pktmp = PEM_read_PrivateKey(fp, NULL, cb, u); - return pkey_get_dsa(pktmp, dsa); /* will free pktmp */ +DSA *PEM_read_DSAPrivateKey(FILE *fp, DSA **dsa, pem_password_cb *cb, void *u) { + EVP_PKEY *pktmp; + pktmp = PEM_read_PrivateKey(fp, NULL, cb, u); + return pkey_get_dsa(pktmp, dsa); /* will free pktmp */ } IMPLEMENT_PEM_rw_const(DSAparams, DSA, PEM_STRING_DSAPARAMS, DSAparams) #endif -static EC_KEY *pkey_get_eckey(EVP_PKEY *key, EC_KEY **eckey) -{ - EC_KEY *dtmp; - if (!key) - return NULL; - dtmp = EVP_PKEY_get1_EC_KEY(key); - EVP_PKEY_free(key); - if (!dtmp) - return NULL; - if (eckey) { - EC_KEY_free(*eckey); - *eckey = dtmp; - } - return dtmp; +static EC_KEY *pkey_get_eckey(EVP_PKEY *key, EC_KEY **eckey) { + EC_KEY *dtmp; + if (!key) { + return NULL; + } + dtmp = EVP_PKEY_get1_EC_KEY(key); + EVP_PKEY_free(key); + if (!dtmp) { + return NULL; + } + if (eckey) { + EC_KEY_free(*eckey); + *eckey = dtmp; + } + return dtmp; } EC_KEY *PEM_read_bio_ECPrivateKey(BIO *bp, EC_KEY **key, pem_password_cb *cb, - void *u) -{ - EVP_PKEY *pktmp; - pktmp = PEM_read_bio_PrivateKey(bp, NULL, cb, u); - return pkey_get_eckey(pktmp, key); /* will free pktmp */ + void *u) { + EVP_PKEY *pktmp; + pktmp = PEM_read_bio_PrivateKey(bp, NULL, cb, u); + return pkey_get_eckey(pktmp, key); /* will free pktmp */ } IMPLEMENT_PEM_write_cb(ECPrivateKey, EC_KEY, PEM_STRING_ECPRIVATEKEY, @@ -239,11 +233,10 @@ IMPLEMENT_PEM_write_cb(ECPrivateKey, EC_KEY, PEM_STRING_ECPRIVATEKEY, IMPLEMENT_PEM_rw(EC_PUBKEY, EC_KEY, PEM_STRING_PUBLIC, EC_PUBKEY) EC_KEY *PEM_read_ECPrivateKey(FILE *fp, EC_KEY **eckey, pem_password_cb *cb, - void *u) -{ - EVP_PKEY *pktmp; - pktmp = PEM_read_PrivateKey(fp, NULL, cb, u); - return pkey_get_eckey(pktmp, eckey); /* will free pktmp */ + void *u) { + EVP_PKEY *pktmp; + pktmp = PEM_read_PrivateKey(fp, NULL, cb, u); + return pkey_get_eckey(pktmp, eckey); /* will free pktmp */ } diff --git a/crypto/pem/pem_info.c b/crypto/pem/pem_info.c index 3a1d0ccea4..40f34ee6de 100644 --- a/crypto/pem/pem_info.c +++ b/crypto/pem/pem_info.c @@ -71,286 +71,280 @@ #include STACK_OF(X509_INFO) *PEM_X509_INFO_read(FILE *fp, STACK_OF(X509_INFO) *sk, - pem_password_cb *cb, void *u) -{ - BIO *b = BIO_new_fp(fp, BIO_NOCLOSE); - if (b == NULL) { - OPENSSL_PUT_ERROR(PEM, ERR_R_BUF_LIB); - return 0; - } - STACK_OF(X509_INFO) *ret = PEM_X509_INFO_read_bio(b, sk, cb, u); - BIO_free(b); - return ret; + pem_password_cb *cb, void *u) { + BIO *b = BIO_new_fp(fp, BIO_NOCLOSE); + if (b == NULL) { + OPENSSL_PUT_ERROR(PEM, ERR_R_BUF_LIB); + return 0; + } + STACK_OF(X509_INFO) *ret = PEM_X509_INFO_read_bio(b, sk, cb, u); + BIO_free(b); + return ret; } enum parse_result_t { - parse_ok, - parse_error, - parse_new_entry, + parse_ok, + parse_error, + parse_new_entry, }; static enum parse_result_t parse_x509(X509_INFO *info, const uint8_t *data, - size_t len, int key_type) -{ - if (info->x509 != NULL) { - return parse_new_entry; - } - info->x509 = d2i_X509(NULL, &data, len); - return info->x509 != NULL ? parse_ok : parse_error; + size_t len, int key_type) { + if (info->x509 != NULL) { + return parse_new_entry; + } + info->x509 = d2i_X509(NULL, &data, len); + return info->x509 != NULL ? parse_ok : parse_error; } static enum parse_result_t parse_x509_aux(X509_INFO *info, const uint8_t *data, - size_t len, int key_type) -{ - if (info->x509 != NULL) { - return parse_new_entry; - } - info->x509 = d2i_X509_AUX(NULL, &data, len); - return info->x509 != NULL ? parse_ok : parse_error; + size_t len, int key_type) { + if (info->x509 != NULL) { + return parse_new_entry; + } + info->x509 = d2i_X509_AUX(NULL, &data, len); + return info->x509 != NULL ? parse_ok : parse_error; } static enum parse_result_t parse_crl(X509_INFO *info, const uint8_t *data, - size_t len, int key_type) -{ - if (info->crl != NULL) { - return parse_new_entry; - } - info->crl = d2i_X509_CRL(NULL, &data, len); - return info->crl != NULL ? parse_ok : parse_error; + size_t len, int key_type) { + if (info->crl != NULL) { + return parse_new_entry; + } + info->crl = d2i_X509_CRL(NULL, &data, len); + return info->crl != NULL ? parse_ok : parse_error; } static enum parse_result_t parse_key(X509_INFO *info, const uint8_t *data, - size_t len, int key_type) -{ - if (info->x_pkey != NULL) { - return parse_new_entry; - } - info->x_pkey = X509_PKEY_new(); - if (info->x_pkey == NULL) { - return parse_error; - } - info->x_pkey->dec_pkey = d2i_PrivateKey(key_type, NULL, &data, len); - return info->x_pkey->dec_pkey != NULL ? parse_ok : parse_error; + size_t len, int key_type) { + if (info->x_pkey != NULL) { + return parse_new_entry; + } + info->x_pkey = X509_PKEY_new(); + if (info->x_pkey == NULL) { + return parse_error; + } + info->x_pkey->dec_pkey = d2i_PrivateKey(key_type, NULL, &data, len); + return info->x_pkey->dec_pkey != NULL ? parse_ok : parse_error; } STACK_OF(X509_INFO) *PEM_X509_INFO_read_bio(BIO *bp, STACK_OF(X509_INFO) *sk, - pem_password_cb *cb, void *u) -{ - X509_INFO *info = NULL; - char *name = NULL, *header = NULL; - unsigned char *data = NULL; - long len; - int ok = 0; - STACK_OF(X509_INFO) *ret = NULL; + pem_password_cb *cb, void *u) { + X509_INFO *info = NULL; + char *name = NULL, *header = NULL; + unsigned char *data = NULL; + long len; + int ok = 0; + STACK_OF(X509_INFO) *ret = NULL; - if (sk == NULL) { - ret = sk_X509_INFO_new_null(); - if (ret == NULL) { - OPENSSL_PUT_ERROR(PEM, ERR_R_MALLOC_FAILURE); - return NULL; - } - } else { - ret = sk; + if (sk == NULL) { + ret = sk_X509_INFO_new_null(); + if (ret == NULL) { + OPENSSL_PUT_ERROR(PEM, ERR_R_MALLOC_FAILURE); + return NULL; } - size_t orig_num = sk_X509_INFO_num(ret); + } else { + ret = sk; + } + size_t orig_num = sk_X509_INFO_num(ret); - info = X509_INFO_new(); - if (info == NULL) { - goto err; - } + info = X509_INFO_new(); + if (info == NULL) { + goto err; + } - for (;;) { - if (!PEM_read_bio(bp, &name, &header, &data, &len)) { - uint32_t error = ERR_peek_last_error(); - if (ERR_GET_LIB(error) == ERR_LIB_PEM && - ERR_GET_REASON(error) == PEM_R_NO_START_LINE) { - ERR_clear_error(); - break; - } - goto err; - } - - enum parse_result_t (*parse_function)(X509_INFO *, const uint8_t *, - size_t, int) = NULL; - int key_type = EVP_PKEY_NONE; - if (strcmp(name, PEM_STRING_X509) == 0 || - strcmp(name, PEM_STRING_X509_OLD) == 0) { - parse_function = parse_x509; - } else if (strcmp(name, PEM_STRING_X509_TRUSTED) == 0) { - parse_function = parse_x509_aux; - } else if (strcmp(name, PEM_STRING_X509_CRL) == 0) { - parse_function = parse_crl; - } else if (strcmp(name, PEM_STRING_RSA) == 0) { - parse_function = parse_key; - key_type = EVP_PKEY_RSA; - } else if (strcmp(name, PEM_STRING_DSA) == 0) { - parse_function = parse_key; - key_type = EVP_PKEY_DSA; - } else if (strcmp(name, PEM_STRING_ECPRIVATEKEY) == 0) { - parse_function = parse_key; - key_type = EVP_PKEY_EC; - } + for (;;) { + if (!PEM_read_bio(bp, &name, &header, &data, &len)) { + uint32_t error = ERR_peek_last_error(); + if (ERR_GET_LIB(error) == ERR_LIB_PEM && + ERR_GET_REASON(error) == PEM_R_NO_START_LINE) { + ERR_clear_error(); + break; + } + goto err; + } - /* If a private key has a header, assume it is encrypted. */ - if (key_type != EVP_PKEY_NONE && strlen(header) > 10) { - if (info->x_pkey != NULL) { - if (!sk_X509_INFO_push(ret, info)) { - goto err; - } - info = X509_INFO_new(); - if (info == NULL) { - goto err; - } - } - /* Historically, raw entries pushed an empty key. */ - info->x_pkey = X509_PKEY_new(); - if (info->x_pkey == NULL || - !PEM_get_EVP_CIPHER_INFO(header, &info->enc_cipher)) { - goto err; - } - info->enc_data = (char *)data; - info->enc_len = (int)len; - data = NULL; - } else if (parse_function != NULL) { - EVP_CIPHER_INFO cipher; - if (!PEM_get_EVP_CIPHER_INFO(header, &cipher) || - !PEM_do_header(&cipher, data, &len, cb, u)) { - goto err; - } - enum parse_result_t result = - parse_function(info, data, len, key_type); - if (result == parse_new_entry) { - if (!sk_X509_INFO_push(ret, info)) { - goto err; - } - info = X509_INFO_new(); - if (info == NULL) { - goto err; - } - result = parse_function(info, data, len, key_type); - } - if (result != parse_ok) { - OPENSSL_PUT_ERROR(PEM, ERR_R_ASN1_LIB); - goto err; - } - } - OPENSSL_free(name); - OPENSSL_free(header); - OPENSSL_free(data); - name = NULL; - header = NULL; - data = NULL; + enum parse_result_t (*parse_function)(X509_INFO *, const uint8_t *, size_t, + int) = NULL; + int key_type = EVP_PKEY_NONE; + if (strcmp(name, PEM_STRING_X509) == 0 || + strcmp(name, PEM_STRING_X509_OLD) == 0) { + parse_function = parse_x509; + } else if (strcmp(name, PEM_STRING_X509_TRUSTED) == 0) { + parse_function = parse_x509_aux; + } else if (strcmp(name, PEM_STRING_X509_CRL) == 0) { + parse_function = parse_crl; + } else if (strcmp(name, PEM_STRING_RSA) == 0) { + parse_function = parse_key; + key_type = EVP_PKEY_RSA; + } else if (strcmp(name, PEM_STRING_DSA) == 0) { + parse_function = parse_key; + key_type = EVP_PKEY_DSA; + } else if (strcmp(name, PEM_STRING_ECPRIVATEKEY) == 0) { + parse_function = parse_key; + key_type = EVP_PKEY_EC; } - /* Push the last entry on the stack if not empty. */ - if (info->x509 != NULL || info->crl != NULL || - info->x_pkey != NULL || info->enc_data != NULL) { + /* If a private key has a header, assume it is encrypted. */ + if (key_type != EVP_PKEY_NONE && strlen(header) > 10) { + if (info->x_pkey != NULL) { if (!sk_X509_INFO_push(ret, info)) { - goto err; + goto err; } - info = NULL; - } - - ok = 1; - - err: - X509_INFO_free(info); - if (!ok) { - while (sk_X509_INFO_num(ret) > orig_num) { - X509_INFO_free(sk_X509_INFO_pop(ret)); + info = X509_INFO_new(); + if (info == NULL) { + goto err; + } + } + /* Historically, raw entries pushed an empty key. */ + info->x_pkey = X509_PKEY_new(); + if (info->x_pkey == NULL || + !PEM_get_EVP_CIPHER_INFO(header, &info->enc_cipher)) { + goto err; + } + info->enc_data = (char *)data; + info->enc_len = (int)len; + data = NULL; + } else if (parse_function != NULL) { + EVP_CIPHER_INFO cipher; + if (!PEM_get_EVP_CIPHER_INFO(header, &cipher) || + !PEM_do_header(&cipher, data, &len, cb, u)) { + goto err; + } + enum parse_result_t result = parse_function(info, data, len, key_type); + if (result == parse_new_entry) { + if (!sk_X509_INFO_push(ret, info)) { + goto err; } - if (ret != sk) { - sk_X509_INFO_free(ret); + info = X509_INFO_new(); + if (info == NULL) { + goto err; } - ret = NULL; + result = parse_function(info, data, len, key_type); + } + if (result != parse_ok) { + OPENSSL_PUT_ERROR(PEM, ERR_R_ASN1_LIB); + goto err; + } } - OPENSSL_free(name); OPENSSL_free(header); OPENSSL_free(data); - return ret; + name = NULL; + header = NULL; + data = NULL; + } + + /* Push the last entry on the stack if not empty. */ + if (info->x509 != NULL || info->crl != NULL || info->x_pkey != NULL || + info->enc_data != NULL) { + if (!sk_X509_INFO_push(ret, info)) { + goto err; + } + info = NULL; + } + + ok = 1; + +err: + X509_INFO_free(info); + if (!ok) { + while (sk_X509_INFO_num(ret) > orig_num) { + X509_INFO_free(sk_X509_INFO_pop(ret)); + } + if (ret != sk) { + sk_X509_INFO_free(ret); + } + ret = NULL; + } + + OPENSSL_free(name); + OPENSSL_free(header); + OPENSSL_free(data); + return ret; } /* A TJH addition */ int PEM_X509_INFO_write_bio(BIO *bp, X509_INFO *xi, EVP_CIPHER *enc, - unsigned char *kstr, int klen, - pem_password_cb *cb, void *u) -{ - int i, ret = 0; - unsigned char *data = NULL; - const char *objstr = NULL; - char buf[PEM_BUFSIZE]; - unsigned char *iv = NULL; - unsigned iv_len = 0; + unsigned char *kstr, int klen, pem_password_cb *cb, + void *u) { + int i, ret = 0; + unsigned char *data = NULL; + const char *objstr = NULL; + char buf[PEM_BUFSIZE]; + unsigned char *iv = NULL; + unsigned iv_len = 0; - if (enc != NULL) { - iv_len = EVP_CIPHER_iv_length(enc); - objstr = OBJ_nid2sn(EVP_CIPHER_nid(enc)); - if (objstr == NULL) { - OPENSSL_PUT_ERROR(PEM, PEM_R_UNSUPPORTED_CIPHER); - goto err; - } + if (enc != NULL) { + iv_len = EVP_CIPHER_iv_length(enc); + objstr = OBJ_nid2sn(EVP_CIPHER_nid(enc)); + if (objstr == NULL) { + OPENSSL_PUT_ERROR(PEM, PEM_R_UNSUPPORTED_CIPHER); + goto err; } + } - /* - * now for the fun part ... if we have a private key then we have to be - * able to handle a not-yet-decrypted key being written out correctly ... - * if it is decrypted or it is non-encrypted then we use the base code - */ - if (xi->x_pkey != NULL) { - if ((xi->enc_data != NULL) && (xi->enc_len > 0)) { - if (enc == NULL) { - OPENSSL_PUT_ERROR(PEM, PEM_R_CIPHER_IS_NULL); - goto err; - } + /* + * now for the fun part ... if we have a private key then we have to be + * able to handle a not-yet-decrypted key being written out correctly ... + * if it is decrypted or it is non-encrypted then we use the base code + */ + if (xi->x_pkey != NULL) { + if ((xi->enc_data != NULL) && (xi->enc_len > 0)) { + if (enc == NULL) { + OPENSSL_PUT_ERROR(PEM, PEM_R_CIPHER_IS_NULL); + goto err; + } - /* copy from weirdo names into more normal things */ - iv = xi->enc_cipher.iv; - data = (unsigned char *)xi->enc_data; - i = xi->enc_len; + /* copy from weirdo names into more normal things */ + iv = xi->enc_cipher.iv; + data = (unsigned char *)xi->enc_data; + i = xi->enc_len; - /* - * we take the encryption data from the internal stuff rather - * than what the user has passed us ... as we have to match - * exactly for some strange reason - */ - objstr = OBJ_nid2sn(EVP_CIPHER_nid(xi->enc_cipher.cipher)); - if (objstr == NULL) { - OPENSSL_PUT_ERROR(PEM, PEM_R_UNSUPPORTED_CIPHER); - goto err; - } + /* + * we take the encryption data from the internal stuff rather + * than what the user has passed us ... as we have to match + * exactly for some strange reason + */ + objstr = OBJ_nid2sn(EVP_CIPHER_nid(xi->enc_cipher.cipher)); + if (objstr == NULL) { + OPENSSL_PUT_ERROR(PEM, PEM_R_UNSUPPORTED_CIPHER); + goto err; + } - /* create the right magic header stuff */ - assert(strlen(objstr) + 23 + 2 * iv_len + 13 <= sizeof buf); - buf[0] = '\0'; - PEM_proc_type(buf, PEM_TYPE_ENCRYPTED); - PEM_dek_info(buf, objstr, iv_len, (char *)iv); + /* create the right magic header stuff */ + assert(strlen(objstr) + 23 + 2 * iv_len + 13 <= sizeof buf); + buf[0] = '\0'; + PEM_proc_type(buf, PEM_TYPE_ENCRYPTED); + PEM_dek_info(buf, objstr, iv_len, (char *)iv); - /* use the normal code to write things out */ - i = PEM_write_bio(bp, PEM_STRING_RSA, buf, data, i); - if (i <= 0) - goto err; - } else { - /* Add DSA/DH */ - /* normal optionally encrypted stuff */ - if (PEM_write_bio_RSAPrivateKey(bp, - xi->x_pkey->dec_pkey->pkey.rsa, - enc, kstr, klen, cb, u) <= 0) - goto err; - } + /* use the normal code to write things out */ + i = PEM_write_bio(bp, PEM_STRING_RSA, buf, data, i); + if (i <= 0) { + goto err; + } + } else { + /* Add DSA/DH */ + /* normal optionally encrypted stuff */ + if (PEM_write_bio_RSAPrivateKey(bp, xi->x_pkey->dec_pkey->pkey.rsa, enc, + kstr, klen, cb, u) <= 0) { + goto err; + } } + } - /* if we have a certificate then write it out now */ - if ((xi->x509 != NULL) && (PEM_write_bio_X509(bp, xi->x509) <= 0)) - goto err; + /* if we have a certificate then write it out now */ + if ((xi->x509 != NULL) && (PEM_write_bio_X509(bp, xi->x509) <= 0)) { + goto err; + } - /* - * we are ignoring anything else that is loaded into the X509_INFO - * structure for the moment ... as I don't need it so I'm not coding it - * here and Eric can do it when this makes it into the base library --tjh - */ + /* + * we are ignoring anything else that is loaded into the X509_INFO + * structure for the moment ... as I don't need it so I'm not coding it + * here and Eric can do it when this makes it into the base library --tjh + */ - ret = 1; + ret = 1; err: OPENSSL_cleanse(buf, PEM_BUFSIZE); diff --git a/crypto/pem/pem_lib.c b/crypto/pem/pem_lib.c index 747d694ea0..1f7c05f02b 100644 --- a/crypto/pem/pem_lib.c +++ b/crypto/pem/pem_lib.c @@ -74,696 +74,729 @@ #include "../internal.h" -#define MIN_LENGTH 4 +#define MIN_LENGTH 4 static int load_iv(char **fromp, unsigned char *to, int num); static int check_pem(const char *nm, const char *name); -void PEM_proc_type(char *buf, int type) -{ - const char *str; - - if (type == PEM_TYPE_ENCRYPTED) - str = "ENCRYPTED"; - else if (type == PEM_TYPE_MIC_CLEAR) - str = "MIC-CLEAR"; - else if (type == PEM_TYPE_MIC_ONLY) - str = "MIC-ONLY"; - else - str = "BAD-TYPE"; - - OPENSSL_strlcat(buf, "Proc-Type: 4,", PEM_BUFSIZE); - OPENSSL_strlcat(buf, str, PEM_BUFSIZE); - OPENSSL_strlcat(buf, "\n", PEM_BUFSIZE); +void PEM_proc_type(char *buf, int type) { + const char *str; + + if (type == PEM_TYPE_ENCRYPTED) { + str = "ENCRYPTED"; + } else if (type == PEM_TYPE_MIC_CLEAR) { + str = "MIC-CLEAR"; + } else if (type == PEM_TYPE_MIC_ONLY) { + str = "MIC-ONLY"; + } else { + str = "BAD-TYPE"; + } + + OPENSSL_strlcat(buf, "Proc-Type: 4,", PEM_BUFSIZE); + OPENSSL_strlcat(buf, str, PEM_BUFSIZE); + OPENSSL_strlcat(buf, "\n", PEM_BUFSIZE); } -void PEM_dek_info(char *buf, const char *type, int len, char *str) -{ - static const unsigned char map[17] = "0123456789ABCDEF"; - long i; - int j; - - OPENSSL_strlcat(buf, "DEK-Info: ", PEM_BUFSIZE); - OPENSSL_strlcat(buf, type, PEM_BUFSIZE); - OPENSSL_strlcat(buf, ",", PEM_BUFSIZE); - j = strlen(buf); - if (j + (len * 2) + 1 > PEM_BUFSIZE) - return; - for (i = 0; i < len; i++) { - buf[j + i * 2] = map[(str[i] >> 4) & 0x0f]; - buf[j + i * 2 + 1] = map[(str[i]) & 0x0f]; - } - buf[j + i * 2] = '\n'; - buf[j + i * 2 + 1] = '\0'; +void PEM_dek_info(char *buf, const char *type, int len, char *str) { + static const unsigned char map[17] = "0123456789ABCDEF"; + long i; + int j; + + OPENSSL_strlcat(buf, "DEK-Info: ", PEM_BUFSIZE); + OPENSSL_strlcat(buf, type, PEM_BUFSIZE); + OPENSSL_strlcat(buf, ",", PEM_BUFSIZE); + j = strlen(buf); + if (j + (len * 2) + 1 > PEM_BUFSIZE) { + return; + } + for (i = 0; i < len; i++) { + buf[j + i * 2] = map[(str[i] >> 4) & 0x0f]; + buf[j + i * 2 + 1] = map[(str[i]) & 0x0f]; + } + buf[j + i * 2] = '\n'; + buf[j + i * 2 + 1] = '\0'; } void *PEM_ASN1_read(d2i_of_void *d2i, const char *name, FILE *fp, void **x, - pem_password_cb *cb, void *u) -{ - BIO *b = BIO_new_fp(fp, BIO_NOCLOSE); - if (b == NULL) { - OPENSSL_PUT_ERROR(PEM, ERR_R_BUF_LIB); - return NULL; - } - void *ret = PEM_ASN1_read_bio(d2i, name, b, x, cb, u); - BIO_free(b); - return ret; + pem_password_cb *cb, void *u) { + BIO *b = BIO_new_fp(fp, BIO_NOCLOSE); + if (b == NULL) { + OPENSSL_PUT_ERROR(PEM, ERR_R_BUF_LIB); + return NULL; + } + void *ret = PEM_ASN1_read_bio(d2i, name, b, x, cb, u); + BIO_free(b); + return ret; } -static int check_pem(const char *nm, const char *name) -{ - /* Normal matching nm and name */ - if (!strcmp(nm, name)) - return 1; +static int check_pem(const char *nm, const char *name) { + /* Normal matching nm and name */ + if (!strcmp(nm, name)) { + return 1; + } - /* Make PEM_STRING_EVP_PKEY match any private key */ + /* Make PEM_STRING_EVP_PKEY match any private key */ - if (!strcmp(name, PEM_STRING_EVP_PKEY)) { - return !strcmp(nm, PEM_STRING_PKCS8) || - !strcmp(nm, PEM_STRING_PKCS8INF) || - !strcmp(nm, PEM_STRING_RSA) || - !strcmp(nm, PEM_STRING_EC) || - !strcmp(nm, PEM_STRING_DSA); - } + if (!strcmp(name, PEM_STRING_EVP_PKEY)) { + return !strcmp(nm, PEM_STRING_PKCS8) || !strcmp(nm, PEM_STRING_PKCS8INF) || + !strcmp(nm, PEM_STRING_RSA) || !strcmp(nm, PEM_STRING_EC) || + !strcmp(nm, PEM_STRING_DSA); + } - /* Permit older strings */ + /* Permit older strings */ - if (!strcmp(nm, PEM_STRING_X509_OLD) && !strcmp(name, PEM_STRING_X509)) - return 1; + if (!strcmp(nm, PEM_STRING_X509_OLD) && !strcmp(name, PEM_STRING_X509)) { + return 1; + } - if (!strcmp(nm, PEM_STRING_X509_REQ_OLD) && - !strcmp(name, PEM_STRING_X509_REQ)) - return 1; + if (!strcmp(nm, PEM_STRING_X509_REQ_OLD) && + !strcmp(name, PEM_STRING_X509_REQ)) { + return 1; + } - /* Allow normal certs to be read as trusted certs */ - if (!strcmp(nm, PEM_STRING_X509) && - !strcmp(name, PEM_STRING_X509_TRUSTED)) - return 1; + /* Allow normal certs to be read as trusted certs */ + if (!strcmp(nm, PEM_STRING_X509) && !strcmp(name, PEM_STRING_X509_TRUSTED)) { + return 1; + } - if (!strcmp(nm, PEM_STRING_X509_OLD) && - !strcmp(name, PEM_STRING_X509_TRUSTED)) - return 1; + if (!strcmp(nm, PEM_STRING_X509_OLD) && + !strcmp(name, PEM_STRING_X509_TRUSTED)) { + return 1; + } - /* Some CAs use PKCS#7 with CERTIFICATE headers */ - if (!strcmp(nm, PEM_STRING_X509) && !strcmp(name, PEM_STRING_PKCS7)) - return 1; + /* Some CAs use PKCS#7 with CERTIFICATE headers */ + if (!strcmp(nm, PEM_STRING_X509) && !strcmp(name, PEM_STRING_PKCS7)) { + return 1; + } - if (!strcmp(nm, PEM_STRING_PKCS7_SIGNED) && - !strcmp(name, PEM_STRING_PKCS7)) - return 1; + if (!strcmp(nm, PEM_STRING_PKCS7_SIGNED) && !strcmp(name, PEM_STRING_PKCS7)) { + return 1; + } #ifndef OPENSSL_NO_CMS - if (!strcmp(nm, PEM_STRING_X509) && !strcmp(name, PEM_STRING_CMS)) - return 1; - /* Allow CMS to be read from PKCS#7 headers */ - if (!strcmp(nm, PEM_STRING_PKCS7) && !strcmp(name, PEM_STRING_CMS)) - return 1; + if (!strcmp(nm, PEM_STRING_X509) && !strcmp(name, PEM_STRING_CMS)) { + return 1; + } + /* Allow CMS to be read from PKCS#7 headers */ + if (!strcmp(nm, PEM_STRING_PKCS7) && !strcmp(name, PEM_STRING_CMS)) { + return 1; + } #endif - return 0; + return 0; } -static const EVP_CIPHER *cipher_by_name(const char *name) -{ - /* This is similar to the (deprecated) function |EVP_get_cipherbyname|. Note - * the PEM code assumes that ciphers have at least 8 bytes of IV, at most 20 - * bytes of overhead and generally behave like CBC mode. */ - if (0 == strcmp(name, SN_des_cbc)) { - return EVP_des_cbc(); - } else if (0 == strcmp(name, SN_des_ede3_cbc)) { - return EVP_des_ede3_cbc(); - } else if (0 == strcmp(name, SN_aes_128_cbc)) { - return EVP_aes_128_cbc(); - } else if (0 == strcmp(name, SN_aes_192_cbc)) { - return EVP_aes_192_cbc(); - } else if (0 == strcmp(name, SN_aes_256_cbc)) { - return EVP_aes_256_cbc(); - } else { - return NULL; - } +static const EVP_CIPHER *cipher_by_name(const char *name) { + /* This is similar to the (deprecated) function |EVP_get_cipherbyname|. Note + * the PEM code assumes that ciphers have at least 8 bytes of IV, at most 20 + * bytes of overhead and generally behave like CBC mode. */ + if (0 == strcmp(name, SN_des_cbc)) { + return EVP_des_cbc(); + } else if (0 == strcmp(name, SN_des_ede3_cbc)) { + return EVP_des_ede3_cbc(); + } else if (0 == strcmp(name, SN_aes_128_cbc)) { + return EVP_aes_128_cbc(); + } else if (0 == strcmp(name, SN_aes_192_cbc)) { + return EVP_aes_192_cbc(); + } else if (0 == strcmp(name, SN_aes_256_cbc)) { + return EVP_aes_256_cbc(); + } else { + return NULL; + } } int PEM_bytes_read_bio(unsigned char **pdata, long *plen, char **pnm, const char *name, BIO *bp, pem_password_cb *cb, - void *u) -{ - EVP_CIPHER_INFO cipher; - char *nm = NULL, *header = NULL; - unsigned char *data = NULL; - long len; - int ret = 0; - - for (;;) { - if (!PEM_read_bio(bp, &nm, &header, &data, &len)) { - uint32_t error = ERR_peek_error(); - if (ERR_GET_LIB(error) == ERR_LIB_PEM && - ERR_GET_REASON(error) == PEM_R_NO_START_LINE) { - ERR_add_error_data(2, "Expecting: ", name); - } - return 0; - } - if (check_pem(nm, name)) - break; - OPENSSL_free(nm); - OPENSSL_free(header); - OPENSSL_free(data); - } - if (!PEM_get_EVP_CIPHER_INFO(header, &cipher)) - goto err; - if (!PEM_do_header(&cipher, data, &len, cb, u)) - goto err; - - *pdata = data; - *plen = len; - - if (pnm) - *pnm = nm; - - ret = 1; - - err: - if (!ret || !pnm) - OPENSSL_free(nm); + void *u) { + EVP_CIPHER_INFO cipher; + char *nm = NULL, *header = NULL; + unsigned char *data = NULL; + long len; + int ret = 0; + + for (;;) { + if (!PEM_read_bio(bp, &nm, &header, &data, &len)) { + uint32_t error = ERR_peek_error(); + if (ERR_GET_LIB(error) == ERR_LIB_PEM && + ERR_GET_REASON(error) == PEM_R_NO_START_LINE) { + ERR_add_error_data(2, "Expecting: ", name); + } + return 0; + } + if (check_pem(nm, name)) { + break; + } + OPENSSL_free(nm); OPENSSL_free(header); - if (!ret) - OPENSSL_free(data); - return ret; + OPENSSL_free(data); + } + if (!PEM_get_EVP_CIPHER_INFO(header, &cipher)) { + goto err; + } + if (!PEM_do_header(&cipher, data, &len, cb, u)) { + goto err; + } + + *pdata = data; + *plen = len; + + if (pnm) { + *pnm = nm; + } + + ret = 1; + +err: + if (!ret || !pnm) { + OPENSSL_free(nm); + } + OPENSSL_free(header); + if (!ret) { + OPENSSL_free(data); + } + return ret; } -int PEM_ASN1_write(i2d_of_void *i2d, const char *name, FILE *fp, - void *x, const EVP_CIPHER *enc, unsigned char *kstr, - int klen, pem_password_cb *callback, void *u) -{ - BIO *b = BIO_new_fp(fp, BIO_NOCLOSE); - if (b == NULL) { - OPENSSL_PUT_ERROR(PEM, ERR_R_BUF_LIB); - return 0; - } - int ret = PEM_ASN1_write_bio(i2d, name, b, x, enc, kstr, klen, callback, u); - BIO_free(b); - return ret; +int PEM_ASN1_write(i2d_of_void *i2d, const char *name, FILE *fp, void *x, + const EVP_CIPHER *enc, unsigned char *kstr, int klen, + pem_password_cb *callback, void *u) { + BIO *b = BIO_new_fp(fp, BIO_NOCLOSE); + if (b == NULL) { + OPENSSL_PUT_ERROR(PEM, ERR_R_BUF_LIB); + return 0; + } + int ret = PEM_ASN1_write_bio(i2d, name, b, x, enc, kstr, klen, callback, u); + BIO_free(b); + return ret; } -int PEM_ASN1_write_bio(i2d_of_void *i2d, const char *name, BIO *bp, - void *x, const EVP_CIPHER *enc, unsigned char *kstr, - int klen, pem_password_cb *callback, void *u) -{ - EVP_CIPHER_CTX ctx; - int dsize = 0, i, j, ret = 0; - unsigned char *p, *data = NULL; - const char *objstr = NULL; - char buf[PEM_BUFSIZE]; - unsigned char key[EVP_MAX_KEY_LENGTH]; - unsigned char iv[EVP_MAX_IV_LENGTH]; - - if (enc != NULL) { - objstr = OBJ_nid2sn(EVP_CIPHER_nid(enc)); - if (objstr == NULL || - cipher_by_name(objstr) == NULL || - EVP_CIPHER_iv_length(enc) < 8) { - OPENSSL_PUT_ERROR(PEM, PEM_R_UNSUPPORTED_CIPHER); - goto err; - } - } - - if ((dsize = i2d(x, NULL)) < 0) { - OPENSSL_PUT_ERROR(PEM, ERR_R_ASN1_LIB); - dsize = 0; +int PEM_ASN1_write_bio(i2d_of_void *i2d, const char *name, BIO *bp, void *x, + const EVP_CIPHER *enc, unsigned char *kstr, int klen, + pem_password_cb *callback, void *u) { + EVP_CIPHER_CTX ctx; + int dsize = 0, i, j, ret = 0; + unsigned char *p, *data = NULL; + const char *objstr = NULL; + char buf[PEM_BUFSIZE]; + unsigned char key[EVP_MAX_KEY_LENGTH]; + unsigned char iv[EVP_MAX_IV_LENGTH]; + + if (enc != NULL) { + objstr = OBJ_nid2sn(EVP_CIPHER_nid(enc)); + if (objstr == NULL || cipher_by_name(objstr) == NULL || + EVP_CIPHER_iv_length(enc) < 8) { + OPENSSL_PUT_ERROR(PEM, PEM_R_UNSUPPORTED_CIPHER); + goto err; + } + } + + if ((dsize = i2d(x, NULL)) < 0) { + OPENSSL_PUT_ERROR(PEM, ERR_R_ASN1_LIB); + dsize = 0; + goto err; + } + /* dzise + 8 bytes are needed */ + /* actually it needs the cipher block size extra... */ + data = (unsigned char *)OPENSSL_malloc((unsigned int)dsize + 20); + if (data == NULL) { + OPENSSL_PUT_ERROR(PEM, ERR_R_MALLOC_FAILURE); + goto err; + } + p = data; + i = i2d(x, &p); + + if (enc != NULL) { + const unsigned iv_len = EVP_CIPHER_iv_length(enc); + + if (kstr == NULL) { + klen = 0; + if (!callback) { + callback = PEM_def_callback; + } + klen = (*callback)(buf, PEM_BUFSIZE, 1, u); + if (klen <= 0) { + OPENSSL_PUT_ERROR(PEM, PEM_R_READ_KEY); goto err; + } + kstr = (unsigned char *)buf; } - /* dzise + 8 bytes are needed */ - /* actually it needs the cipher block size extra... */ - data = (unsigned char *)OPENSSL_malloc((unsigned int)dsize + 20); - if (data == NULL) { - OPENSSL_PUT_ERROR(PEM, ERR_R_MALLOC_FAILURE); - goto err; + assert(iv_len <= (int)sizeof(iv)); + if (!RAND_bytes(iv, iv_len)) { /* Generate a salt */ + goto err; + } + /* + * The 'iv' is used as the iv and as a salt. It is NOT taken from + * the BytesToKey function + */ + if (!EVP_BytesToKey(enc, EVP_md5(), iv, kstr, klen, 1, key, NULL)) { + goto err; } - p = data; - i = i2d(x, &p); - - if (enc != NULL) { - const unsigned iv_len = EVP_CIPHER_iv_length(enc); - - if (kstr == NULL) { - klen = 0; - if (!callback) - callback = PEM_def_callback; - klen = (*callback) (buf, PEM_BUFSIZE, 1, u); - if (klen <= 0) { - OPENSSL_PUT_ERROR(PEM, PEM_R_READ_KEY); - goto err; - } - kstr = (unsigned char *)buf; - } - assert(iv_len <= (int)sizeof(iv)); - if (!RAND_bytes(iv, iv_len)) /* Generate a salt */ - goto err; - /* - * The 'iv' is used as the iv and as a salt. It is NOT taken from - * the BytesToKey function - */ - if (!EVP_BytesToKey(enc, EVP_md5(), iv, kstr, klen, 1, key, NULL)) - goto err; - if (kstr == (unsigned char *)buf) - OPENSSL_cleanse(buf, PEM_BUFSIZE); + if (kstr == (unsigned char *)buf) { + OPENSSL_cleanse(buf, PEM_BUFSIZE); + } - assert(strlen(objstr) + 23 + 2 * iv_len + 13 <= sizeof buf); + assert(strlen(objstr) + 23 + 2 * iv_len + 13 <= sizeof buf); - buf[0] = '\0'; - PEM_proc_type(buf, PEM_TYPE_ENCRYPTED); - PEM_dek_info(buf, objstr, iv_len, (char *)iv); - /* k=strlen(buf); */ - - EVP_CIPHER_CTX_init(&ctx); - ret = 1; - if (!EVP_EncryptInit_ex(&ctx, enc, NULL, key, iv) - || !EVP_EncryptUpdate(&ctx, data, &j, data, i) - || !EVP_EncryptFinal_ex(&ctx, &(data[j]), &i)) - ret = 0; - else - i += j; - EVP_CIPHER_CTX_cleanup(&ctx); - if (ret == 0) - goto err; + buf[0] = '\0'; + PEM_proc_type(buf, PEM_TYPE_ENCRYPTED); + PEM_dek_info(buf, objstr, iv_len, (char *)iv); + /* k=strlen(buf); */ + + EVP_CIPHER_CTX_init(&ctx); + ret = 1; + if (!EVP_EncryptInit_ex(&ctx, enc, NULL, key, iv) || + !EVP_EncryptUpdate(&ctx, data, &j, data, i) || + !EVP_EncryptFinal_ex(&ctx, &(data[j]), &i)) { + ret = 0; } else { - ret = 1; - buf[0] = '\0'; + i += j; } - i = PEM_write_bio(bp, name, buf, data, i); - if (i <= 0) - ret = 0; - err: - OPENSSL_cleanse(key, sizeof(key)); - OPENSSL_cleanse(iv, sizeof(iv)); - OPENSSL_cleanse((char *)&ctx, sizeof(ctx)); - OPENSSL_cleanse(buf, PEM_BUFSIZE); - OPENSSL_free(data); - return (ret); + EVP_CIPHER_CTX_cleanup(&ctx); + if (ret == 0) { + goto err; + } + } else { + ret = 1; + buf[0] = '\0'; + } + i = PEM_write_bio(bp, name, buf, data, i); + if (i <= 0) { + ret = 0; + } +err: + OPENSSL_cleanse(key, sizeof(key)); + OPENSSL_cleanse(iv, sizeof(iv)); + OPENSSL_cleanse((char *)&ctx, sizeof(ctx)); + OPENSSL_cleanse(buf, PEM_BUFSIZE); + OPENSSL_free(data); + return (ret); } int PEM_do_header(EVP_CIPHER_INFO *cipher, unsigned char *data, long *plen, - pem_password_cb *callback, void *u) -{ - int i = 0, j, o, klen; - long len; - EVP_CIPHER_CTX ctx; - unsigned char key[EVP_MAX_KEY_LENGTH]; - char buf[PEM_BUFSIZE]; + pem_password_cb *callback, void *u) { + int i = 0, j, o, klen; + long len; + EVP_CIPHER_CTX ctx; + unsigned char key[EVP_MAX_KEY_LENGTH]; + char buf[PEM_BUFSIZE]; - len = *plen; + len = *plen; - if (cipher->cipher == NULL) - return (1); + if (cipher->cipher == NULL) { + return (1); + } + + klen = 0; + if (!callback) { + callback = PEM_def_callback; + } + klen = callback(buf, PEM_BUFSIZE, 0, u); + if (klen <= 0) { + OPENSSL_PUT_ERROR(PEM, PEM_R_BAD_PASSWORD_READ); + return (0); + } - klen = 0; - if (!callback) - callback = PEM_def_callback; - klen = callback(buf, PEM_BUFSIZE, 0, u); - if (klen <= 0) { - OPENSSL_PUT_ERROR(PEM, PEM_R_BAD_PASSWORD_READ); - return (0); - } + if (!EVP_BytesToKey(cipher->cipher, EVP_md5(), &(cipher->iv[0]), + (unsigned char *)buf, klen, 1, key, NULL)) { + return 0; + } + + j = (int)len; + EVP_CIPHER_CTX_init(&ctx); + o = EVP_DecryptInit_ex(&ctx, cipher->cipher, NULL, key, &(cipher->iv[0])); + if (o) { + o = EVP_DecryptUpdate(&ctx, data, &i, data, j); + } + if (o) { + o = EVP_DecryptFinal_ex(&ctx, &(data[i]), &j); + } + EVP_CIPHER_CTX_cleanup(&ctx); + OPENSSL_cleanse((char *)buf, sizeof(buf)); + OPENSSL_cleanse((char *)key, sizeof(key)); + if (!o) { + OPENSSL_PUT_ERROR(PEM, PEM_R_BAD_DECRYPT); + return (0); + } + j += i; + *plen = j; + return (1); +} - if (!EVP_BytesToKey(cipher->cipher, EVP_md5(), &(cipher->iv[0]), - (unsigned char *)buf, klen, 1, key, NULL)) - return 0; +int PEM_get_EVP_CIPHER_INFO(char *header, EVP_CIPHER_INFO *cipher) { + const EVP_CIPHER *enc = NULL; + char *p, c; + char **header_pp = &header; - j = (int)len; - EVP_CIPHER_CTX_init(&ctx); - o = EVP_DecryptInit_ex(&ctx, cipher->cipher, NULL, key, &(cipher->iv[0])); - if (o) - o = EVP_DecryptUpdate(&ctx, data, &i, data, j); - if (o) - o = EVP_DecryptFinal_ex(&ctx, &(data[i]), &j); - EVP_CIPHER_CTX_cleanup(&ctx); - OPENSSL_cleanse((char *)buf, sizeof(buf)); - OPENSSL_cleanse((char *)key, sizeof(key)); - if (!o) { - OPENSSL_PUT_ERROR(PEM, PEM_R_BAD_DECRYPT); - return (0); - } - j += i; - *plen = j; + cipher->cipher = NULL; + OPENSSL_memset(cipher->iv, 0, sizeof(cipher->iv)); + if ((header == NULL) || (*header == '\0') || (*header == '\n')) { return (1); -} - -int PEM_get_EVP_CIPHER_INFO(char *header, EVP_CIPHER_INFO *cipher) -{ - const EVP_CIPHER *enc = NULL; - char *p, c; - char **header_pp = &header; - - cipher->cipher = NULL; - OPENSSL_memset(cipher->iv, 0, sizeof(cipher->iv)); - if ((header == NULL) || (*header == '\0') || (*header == '\n')) - return (1); - if (strncmp(header, "Proc-Type: ", 11) != 0) { - OPENSSL_PUT_ERROR(PEM, PEM_R_NOT_PROC_TYPE); - return (0); - } - header += 11; - if (*header != '4') - return (0); - header++; - if (*header != ',') - return (0); - header++; - if (strncmp(header, "ENCRYPTED", 9) != 0) { - OPENSSL_PUT_ERROR(PEM, PEM_R_NOT_ENCRYPTED); - return (0); - } - for (; (*header != '\n') && (*header != '\0'); header++) ; - if (*header == '\0') { - OPENSSL_PUT_ERROR(PEM, PEM_R_SHORT_HEADER); - return (0); - } - header++; - if (strncmp(header, "DEK-Info: ", 10) != 0) { - OPENSSL_PUT_ERROR(PEM, PEM_R_NOT_DEK_INFO); - return (0); - } - header += 10; + } + if (strncmp(header, "Proc-Type: ", 11) != 0) { + OPENSSL_PUT_ERROR(PEM, PEM_R_NOT_PROC_TYPE); + return (0); + } + header += 11; + if (*header != '4') { + return (0); + } + header++; + if (*header != ',') { + return (0); + } + header++; + if (strncmp(header, "ENCRYPTED", 9) != 0) { + OPENSSL_PUT_ERROR(PEM, PEM_R_NOT_ENCRYPTED); + return (0); + } + for (; (*header != '\n') && (*header != '\0'); header++) { + ; + } + if (*header == '\0') { + OPENSSL_PUT_ERROR(PEM, PEM_R_SHORT_HEADER); + return (0); + } + header++; + if (strncmp(header, "DEK-Info: ", 10) != 0) { + OPENSSL_PUT_ERROR(PEM, PEM_R_NOT_DEK_INFO); + return (0); + } + header += 10; - p = header; - for (;;) { - c = *header; - if (!(((c >= 'A') && (c <= 'Z')) || (c == '-') || - ((c >= '0') && (c <= '9')))) - break; - header++; + p = header; + for (;;) { + c = *header; + if (!(((c >= 'A') && (c <= 'Z')) || (c == '-') || + ((c >= '0') && (c <= '9')))) { + break; } - *header = '\0'; - cipher->cipher = enc = cipher_by_name(p); - *header = c; header++; + } + *header = '\0'; + cipher->cipher = enc = cipher_by_name(p); + *header = c; + header++; + + if (enc == NULL) { + OPENSSL_PUT_ERROR(PEM, PEM_R_UNSUPPORTED_ENCRYPTION); + return (0); + } + // The IV parameter must be at least 8 bytes long to be used as the salt in + // the KDF. (This should not happen given |cipher_by_name|.) + if (EVP_CIPHER_iv_length(enc) < 8) { + assert(0); + OPENSSL_PUT_ERROR(PEM, PEM_R_UNSUPPORTED_ENCRYPTION); + return 0; + } + if (!load_iv(header_pp, &(cipher->iv[0]), EVP_CIPHER_iv_length(enc))) { + return (0); + } - if (enc == NULL) { - OPENSSL_PUT_ERROR(PEM, PEM_R_UNSUPPORTED_ENCRYPTION); - return (0); - } - // The IV parameter must be at least 8 bytes long to be used as the salt in - // the KDF. (This should not happen given |cipher_by_name|.) - if (EVP_CIPHER_iv_length(enc) < 8) { - assert(0); - OPENSSL_PUT_ERROR(PEM, PEM_R_UNSUPPORTED_ENCRYPTION); - return 0; - } - if (!load_iv(header_pp, &(cipher->iv[0]), EVP_CIPHER_iv_length(enc))) - return (0); - - return (1); + return (1); } -static int load_iv(char **fromp, unsigned char *to, int num) -{ - int v, i; - char *from; - - from = *fromp; - for (i = 0; i < num; i++) - to[i] = 0; - num *= 2; - for (i = 0; i < num; i++) { - if ((*from >= '0') && (*from <= '9')) - v = *from - '0'; - else if ((*from >= 'A') && (*from <= 'F')) - v = *from - 'A' + 10; - else if ((*from >= 'a') && (*from <= 'f')) - v = *from - 'a' + 10; - else { - OPENSSL_PUT_ERROR(PEM, PEM_R_BAD_IV_CHARS); - return (0); - } - from++; - to[i / 2] |= v << (long)((!(i & 1)) * 4); +static int load_iv(char **fromp, unsigned char *to, int num) { + int v, i; + char *from; + + from = *fromp; + for (i = 0; i < num; i++) { + to[i] = 0; + } + num *= 2; + for (i = 0; i < num; i++) { + if ((*from >= '0') && (*from <= '9')) { + v = *from - '0'; + } else if ((*from >= 'A') && (*from <= 'F')) { + v = *from - 'A' + 10; + } else if ((*from >= 'a') && (*from <= 'f')) { + v = *from - 'a' + 10; + } else { + OPENSSL_PUT_ERROR(PEM, PEM_R_BAD_IV_CHARS); + return (0); } + from++; + to[i / 2] |= v << (long)((!(i & 1)) * 4); + } - *fromp = from; - return (1); + *fromp = from; + return (1); } int PEM_write(FILE *fp, const char *name, const char *header, - const unsigned char *data, long len) -{ - BIO *b = BIO_new_fp(fp, BIO_NOCLOSE); - if (b == NULL) { - OPENSSL_PUT_ERROR(PEM, ERR_R_BUF_LIB); - return 0; - } - int ret = PEM_write_bio(b, name, header, data, len); - BIO_free(b); - return (ret); + const unsigned char *data, long len) { + BIO *b = BIO_new_fp(fp, BIO_NOCLOSE); + if (b == NULL) { + OPENSSL_PUT_ERROR(PEM, ERR_R_BUF_LIB); + return 0; + } + int ret = PEM_write_bio(b, name, header, data, len); + BIO_free(b); + return (ret); } int PEM_write_bio(BIO *bp, const char *name, const char *header, - const unsigned char *data, long len) -{ - int nlen, n, i, j, outl; - unsigned char *buf = NULL; - EVP_ENCODE_CTX ctx; - int reason = ERR_R_BUF_LIB; - - EVP_EncodeInit(&ctx); - nlen = strlen(name); - - if ((BIO_write(bp, "-----BEGIN ", 11) != 11) || - (BIO_write(bp, name, nlen) != nlen) || - (BIO_write(bp, "-----\n", 6) != 6)) - goto err; - - i = strlen(header); - if (i > 0) { - if ((BIO_write(bp, header, i) != i) || (BIO_write(bp, "\n", 1) != 1)) - goto err; - } - - buf = OPENSSL_malloc(PEM_BUFSIZE * 8); - if (buf == NULL) { - reason = ERR_R_MALLOC_FAILURE; - goto err; - } - - i = j = 0; - while (len > 0) { - n = (int)((len > (PEM_BUFSIZE * 5)) ? (PEM_BUFSIZE * 5) : len); - EVP_EncodeUpdate(&ctx, buf, &outl, &(data[j]), n); - if ((outl) && (BIO_write(bp, (char *)buf, outl) != outl)) - goto err; - i += outl; - len -= n; - j += n; - } - EVP_EncodeFinal(&ctx, buf, &outl); - if ((outl > 0) && (BIO_write(bp, (char *)buf, outl) != outl)) - goto err; + const unsigned char *data, long len) { + int nlen, n, i, j, outl; + unsigned char *buf = NULL; + EVP_ENCODE_CTX ctx; + int reason = ERR_R_BUF_LIB; + + EVP_EncodeInit(&ctx); + nlen = strlen(name); + + if ((BIO_write(bp, "-----BEGIN ", 11) != 11) || + (BIO_write(bp, name, nlen) != nlen) || + (BIO_write(bp, "-----\n", 6) != 6)) { + goto err; + } + + i = strlen(header); + if (i > 0) { + if ((BIO_write(bp, header, i) != i) || (BIO_write(bp, "\n", 1) != 1)) { + goto err; + } + } + + buf = OPENSSL_malloc(PEM_BUFSIZE * 8); + if (buf == NULL) { + reason = ERR_R_MALLOC_FAILURE; + goto err; + } + + i = j = 0; + while (len > 0) { + n = (int)((len > (PEM_BUFSIZE * 5)) ? (PEM_BUFSIZE * 5) : len); + EVP_EncodeUpdate(&ctx, buf, &outl, &(data[j]), n); + if ((outl) && (BIO_write(bp, (char *)buf, outl) != outl)) { + goto err; + } + i += outl; + len -= n; + j += n; + } + EVP_EncodeFinal(&ctx, buf, &outl); + if ((outl > 0) && (BIO_write(bp, (char *)buf, outl) != outl)) { + goto err; + } + OPENSSL_free(buf); + buf = NULL; + if ((BIO_write(bp, "-----END ", 9) != 9) || + (BIO_write(bp, name, nlen) != nlen) || + (BIO_write(bp, "-----\n", 6) != 6)) { + goto err; + } + return (i + outl); +err: + if (buf) { OPENSSL_free(buf); - buf = NULL; - if ((BIO_write(bp, "-----END ", 9) != 9) || - (BIO_write(bp, name, nlen) != nlen) || - (BIO_write(bp, "-----\n", 6) != 6)) - goto err; - return (i + outl); - err: - if (buf) { - OPENSSL_free(buf); - } - OPENSSL_PUT_ERROR(PEM, reason); - return (0); + } + OPENSSL_PUT_ERROR(PEM, reason); + return (0); } int PEM_read(FILE *fp, char **name, char **header, unsigned char **data, - long *len) -{ - BIO *b = BIO_new_fp(fp, BIO_NOCLOSE); - if (b == NULL) { - OPENSSL_PUT_ERROR(PEM, ERR_R_BUF_LIB); - return 0; - } - int ret = PEM_read_bio(b, name, header, data, len); - BIO_free(b); - return (ret); + long *len) { + BIO *b = BIO_new_fp(fp, BIO_NOCLOSE); + if (b == NULL) { + OPENSSL_PUT_ERROR(PEM, ERR_R_BUF_LIB); + return 0; + } + int ret = PEM_read_bio(b, name, header, data, len); + BIO_free(b); + return (ret); } int PEM_read_bio(BIO *bp, char **name, char **header, unsigned char **data, - long *len) -{ - EVP_ENCODE_CTX ctx; - int end = 0, i, k, bl = 0, hl = 0, nohead = 0; - char buf[256]; - BUF_MEM *nameB; - BUF_MEM *headerB; - BUF_MEM *dataB, *tmpB; - - nameB = BUF_MEM_new(); - headerB = BUF_MEM_new(); - dataB = BUF_MEM_new(); - if ((nameB == NULL) || (headerB == NULL) || (dataB == NULL)) { - BUF_MEM_free(nameB); - BUF_MEM_free(headerB); - BUF_MEM_free(dataB); - OPENSSL_PUT_ERROR(PEM, ERR_R_MALLOC_FAILURE); - return (0); - } - - buf[254] = '\0'; - for (;;) { - i = BIO_gets(bp, buf, 254); + long *len) { + EVP_ENCODE_CTX ctx; + int end = 0, i, k, bl = 0, hl = 0, nohead = 0; + char buf[256]; + BUF_MEM *nameB; + BUF_MEM *headerB; + BUF_MEM *dataB, *tmpB; + + nameB = BUF_MEM_new(); + headerB = BUF_MEM_new(); + dataB = BUF_MEM_new(); + if ((nameB == NULL) || (headerB == NULL) || (dataB == NULL)) { + BUF_MEM_free(nameB); + BUF_MEM_free(headerB); + BUF_MEM_free(dataB); + OPENSSL_PUT_ERROR(PEM, ERR_R_MALLOC_FAILURE); + return (0); + } - if (i <= 0) { - OPENSSL_PUT_ERROR(PEM, PEM_R_NO_START_LINE); - goto err; - } + buf[254] = '\0'; + for (;;) { + i = BIO_gets(bp, buf, 254); - while ((i >= 0) && (buf[i] <= ' ')) - i--; - buf[++i] = '\n'; - buf[++i] = '\0'; + if (i <= 0) { + OPENSSL_PUT_ERROR(PEM, PEM_R_NO_START_LINE); + goto err; + } - if (strncmp(buf, "-----BEGIN ", 11) == 0) { - i = strlen(&(buf[11])); - - if (strncmp(&(buf[11 + i - 6]), "-----\n", 6) != 0) - continue; - if (!BUF_MEM_grow(nameB, i + 9)) { - OPENSSL_PUT_ERROR(PEM, ERR_R_MALLOC_FAILURE); - goto err; - } - OPENSSL_memcpy(nameB->data, &(buf[11]), i - 6); - nameB->data[i - 6] = '\0'; - break; - } + while ((i >= 0) && (buf[i] <= ' ')) { + i--; } - hl = 0; - if (!BUF_MEM_grow(headerB, 256)) { + buf[++i] = '\n'; + buf[++i] = '\0'; + + if (strncmp(buf, "-----BEGIN ", 11) == 0) { + i = strlen(&(buf[11])); + + if (strncmp(&(buf[11 + i - 6]), "-----\n", 6) != 0) { + continue; + } + if (!BUF_MEM_grow(nameB, i + 9)) { OPENSSL_PUT_ERROR(PEM, ERR_R_MALLOC_FAILURE); goto err; - } - headerB->data[0] = '\0'; + } + OPENSSL_memcpy(nameB->data, &(buf[11]), i - 6); + nameB->data[i - 6] = '\0'; + break; + } + } + hl = 0; + if (!BUF_MEM_grow(headerB, 256)) { + OPENSSL_PUT_ERROR(PEM, ERR_R_MALLOC_FAILURE); + goto err; + } + headerB->data[0] = '\0'; + for (;;) { + i = BIO_gets(bp, buf, 254); + if (i <= 0) { + break; + } + + while ((i >= 0) && (buf[i] <= ' ')) { + i--; + } + buf[++i] = '\n'; + buf[++i] = '\0'; + + if (buf[0] == '\n') { + break; + } + if (!BUF_MEM_grow(headerB, hl + i + 9)) { + OPENSSL_PUT_ERROR(PEM, ERR_R_MALLOC_FAILURE); + goto err; + } + if (strncmp(buf, "-----END ", 9) == 0) { + nohead = 1; + break; + } + OPENSSL_memcpy(&(headerB->data[hl]), buf, i); + headerB->data[hl + i] = '\0'; + hl += i; + } + + bl = 0; + if (!BUF_MEM_grow(dataB, 1024)) { + OPENSSL_PUT_ERROR(PEM, ERR_R_MALLOC_FAILURE); + goto err; + } + dataB->data[0] = '\0'; + if (!nohead) { for (;;) { - i = BIO_gets(bp, buf, 254); - if (i <= 0) - break; - - while ((i >= 0) && (buf[i] <= ' ')) - i--; - buf[++i] = '\n'; - buf[++i] = '\0'; - - if (buf[0] == '\n') - break; - if (!BUF_MEM_grow(headerB, hl + i + 9)) { - OPENSSL_PUT_ERROR(PEM, ERR_R_MALLOC_FAILURE); - goto err; - } - if (strncmp(buf, "-----END ", 9) == 0) { - nohead = 1; - break; - } - OPENSSL_memcpy(&(headerB->data[hl]), buf, i); - headerB->data[hl + i] = '\0'; - hl += i; - } - - bl = 0; - if (!BUF_MEM_grow(dataB, 1024)) { + i = BIO_gets(bp, buf, 254); + if (i <= 0) { + break; + } + + while ((i >= 0) && (buf[i] <= ' ')) { + i--; + } + buf[++i] = '\n'; + buf[++i] = '\0'; + + if (i != 65) { + end = 1; + } + if (strncmp(buf, "-----END ", 9) == 0) { + break; + } + if (i > 65) { + break; + } + if (!BUF_MEM_grow_clean(dataB, i + bl + 9)) { OPENSSL_PUT_ERROR(PEM, ERR_R_MALLOC_FAILURE); goto err; - } - dataB->data[0] = '\0'; - if (!nohead) { - for (;;) { - i = BIO_gets(bp, buf, 254); - if (i <= 0) - break; - - while ((i >= 0) && (buf[i] <= ' ')) - i--; - buf[++i] = '\n'; - buf[++i] = '\0'; - - if (i != 65) - end = 1; - if (strncmp(buf, "-----END ", 9) == 0) - break; - if (i > 65) - break; - if (!BUF_MEM_grow_clean(dataB, i + bl + 9)) { - OPENSSL_PUT_ERROR(PEM, ERR_R_MALLOC_FAILURE); - goto err; - } - OPENSSL_memcpy(&(dataB->data[bl]), buf, i); - dataB->data[bl + i] = '\0'; - bl += i; - if (end) { - buf[0] = '\0'; - i = BIO_gets(bp, buf, 254); - if (i <= 0) - break; - - while ((i >= 0) && (buf[i] <= ' ')) - i--; - buf[++i] = '\n'; - buf[++i] = '\0'; - - break; - } + } + OPENSSL_memcpy(&(dataB->data[bl]), buf, i); + dataB->data[bl + i] = '\0'; + bl += i; + if (end) { + buf[0] = '\0'; + i = BIO_gets(bp, buf, 254); + if (i <= 0) { + break; } - } else { - tmpB = headerB; - headerB = dataB; - dataB = tmpB; - bl = hl; - } - i = strlen(nameB->data); - if ((strncmp(buf, "-----END ", 9) != 0) || - (strncmp(nameB->data, &(buf[9]), i) != 0) || - (strncmp(&(buf[9 + i]), "-----\n", 6) != 0)) { - OPENSSL_PUT_ERROR(PEM, PEM_R_BAD_END_LINE); - goto err; - } - EVP_DecodeInit(&ctx); - i = EVP_DecodeUpdate(&ctx, - (unsigned char *)dataB->data, &bl, - (unsigned char *)dataB->data, bl); - if (i < 0) { - OPENSSL_PUT_ERROR(PEM, PEM_R_BAD_BASE64_DECODE); - goto err; - } - i = EVP_DecodeFinal(&ctx, (unsigned char *)&(dataB->data[bl]), &k); - if (i < 0) { - OPENSSL_PUT_ERROR(PEM, PEM_R_BAD_BASE64_DECODE); - goto err; - } - bl += k; + while ((i >= 0) && (buf[i] <= ' ')) { + i--; + } + buf[++i] = '\n'; + buf[++i] = '\0'; - if (bl == 0) - goto err; - *name = nameB->data; - *header = headerB->data; - *data = (unsigned char *)dataB->data; - *len = bl; - OPENSSL_free(nameB); - OPENSSL_free(headerB); - OPENSSL_free(dataB); - return (1); - err: - BUF_MEM_free(nameB); - BUF_MEM_free(headerB); - BUF_MEM_free(dataB); - return (0); + break; + } + } + } else { + tmpB = headerB; + headerB = dataB; + dataB = tmpB; + bl = hl; + } + i = strlen(nameB->data); + if ((strncmp(buf, "-----END ", 9) != 0) || + (strncmp(nameB->data, &(buf[9]), i) != 0) || + (strncmp(&(buf[9 + i]), "-----\n", 6) != 0)) { + OPENSSL_PUT_ERROR(PEM, PEM_R_BAD_END_LINE); + goto err; + } + + EVP_DecodeInit(&ctx); + i = EVP_DecodeUpdate(&ctx, (unsigned char *)dataB->data, &bl, + (unsigned char *)dataB->data, bl); + if (i < 0) { + OPENSSL_PUT_ERROR(PEM, PEM_R_BAD_BASE64_DECODE); + goto err; + } + i = EVP_DecodeFinal(&ctx, (unsigned char *)&(dataB->data[bl]), &k); + if (i < 0) { + OPENSSL_PUT_ERROR(PEM, PEM_R_BAD_BASE64_DECODE); + goto err; + } + bl += k; + + if (bl == 0) { + goto err; + } + *name = nameB->data; + *header = headerB->data; + *data = (unsigned char *)dataB->data; + *len = bl; + OPENSSL_free(nameB); + OPENSSL_free(headerB); + OPENSSL_free(dataB); + return (1); +err: + BUF_MEM_free(nameB); + BUF_MEM_free(headerB); + BUF_MEM_free(dataB); + return (0); } -int PEM_def_callback(char *buf, int size, int rwflag, void *userdata) -{ - if (!buf || !userdata || size < 0) { - return 0; - } - size_t len = strlen((char *)userdata); - if (len >= (size_t)size) { - return 0; - } - OPENSSL_strlcpy(buf, userdata, (size_t)size); - return len; +int PEM_def_callback(char *buf, int size, int rwflag, void *userdata) { + if (!buf || !userdata || size < 0) { + return 0; + } + size_t len = strlen((char *)userdata); + if (len >= (size_t)size) { + return 0; + } + OPENSSL_strlcpy(buf, userdata, (size_t)size); + return len; } diff --git a/crypto/pem/pem_oth.c b/crypto/pem/pem_oth.c index 797f8223d6..7cb4e08c10 100644 --- a/crypto/pem/pem_oth.c +++ b/crypto/pem/pem_oth.c @@ -60,8 +60,8 @@ #include #include -#include #include +#include #include #include #include @@ -69,19 +69,20 @@ /* Handle 'other' PEMs: not private keys */ void *PEM_ASN1_read_bio(d2i_of_void *d2i, const char *name, BIO *bp, void **x, - pem_password_cb *cb, void *u) -{ - const unsigned char *p = NULL; - unsigned char *data = NULL; - long len; - char *ret = NULL; + pem_password_cb *cb, void *u) { + const unsigned char *p = NULL; + unsigned char *data = NULL; + long len; + char *ret = NULL; - if (!PEM_bytes_read_bio(&data, &len, NULL, name, bp, cb, u)) - return NULL; - p = data; - ret = d2i(x, &p, len); - if (ret == NULL) - OPENSSL_PUT_ERROR(PEM, ERR_R_ASN1_LIB); - OPENSSL_free(data); - return ret; + if (!PEM_bytes_read_bio(&data, &len, NULL, name, bp, cb, u)) { + return NULL; + } + p = data; + ret = d2i(x, &p, len); + if (ret == NULL) { + OPENSSL_PUT_ERROR(PEM, ERR_R_ASN1_LIB); + } + OPENSSL_free(data); + return ret; } diff --git a/crypto/pem/pem_pk8.c b/crypto/pem/pem_pk8.c index 8a1f040926..53b270333f 100644 --- a/crypto/pem/pem_pk8.c +++ b/crypto/pem/pem_pk8.c @@ -64,12 +64,12 @@ #include #include -static int do_pk8pkey(BIO *bp, EVP_PKEY *x, int isder, - int nid, const EVP_CIPHER *enc, - char *kstr, int klen, pem_password_cb *cb, void *u); -static int do_pk8pkey_fp(FILE *bp, EVP_PKEY *x, int isder, - int nid, const EVP_CIPHER *enc, - char *kstr, int klen, pem_password_cb *cb, void *u); +static int do_pk8pkey(BIO *bp, EVP_PKEY *x, int isder, int nid, + const EVP_CIPHER *enc, char *kstr, int klen, + pem_password_cb *cb, void *u); +static int do_pk8pkey_fp(FILE *bp, EVP_PKEY *x, int isder, int nid, + const EVP_CIPHER *enc, char *kstr, int klen, + pem_password_cb *cb, void *u); /* * These functions write a private key in PKCS#8 format: it is a "drop in" @@ -78,173 +78,166 @@ static int do_pk8pkey_fp(FILE *bp, EVP_PKEY *x, int isder, * uses PKCS#5 v1.5 PBE algorithms whereas the others use PKCS#5 v2.0. */ -int PEM_write_bio_PKCS8PrivateKey_nid(BIO *bp, EVP_PKEY *x, int nid, - char *kstr, int klen, - pem_password_cb *cb, void *u) -{ - return do_pk8pkey(bp, x, 0, nid, NULL, kstr, klen, cb, u); +int PEM_write_bio_PKCS8PrivateKey_nid(BIO *bp, EVP_PKEY *x, int nid, char *kstr, + int klen, pem_password_cb *cb, void *u) { + return do_pk8pkey(bp, x, 0, nid, NULL, kstr, klen, cb, u); } int PEM_write_bio_PKCS8PrivateKey(BIO *bp, EVP_PKEY *x, const EVP_CIPHER *enc, - char *kstr, int klen, - pem_password_cb *cb, void *u) -{ - return do_pk8pkey(bp, x, 0, -1, enc, kstr, klen, cb, u); + char *kstr, int klen, pem_password_cb *cb, + void *u) { + return do_pk8pkey(bp, x, 0, -1, enc, kstr, klen, cb, u); } int i2d_PKCS8PrivateKey_bio(BIO *bp, EVP_PKEY *x, const EVP_CIPHER *enc, - char *kstr, int klen, - pem_password_cb *cb, void *u) -{ - return do_pk8pkey(bp, x, 1, -1, enc, kstr, klen, cb, u); + char *kstr, int klen, pem_password_cb *cb, + void *u) { + return do_pk8pkey(bp, x, 1, -1, enc, kstr, klen, cb, u); } -int i2d_PKCS8PrivateKey_nid_bio(BIO *bp, EVP_PKEY *x, int nid, - char *kstr, int klen, - pem_password_cb *cb, void *u) -{ - return do_pk8pkey(bp, x, 1, nid, NULL, kstr, klen, cb, u); +int i2d_PKCS8PrivateKey_nid_bio(BIO *bp, EVP_PKEY *x, int nid, char *kstr, + int klen, pem_password_cb *cb, void *u) { + return do_pk8pkey(bp, x, 1, nid, NULL, kstr, klen, cb, u); } static int do_pk8pkey(BIO *bp, EVP_PKEY *x, int isder, int nid, const EVP_CIPHER *enc, char *kstr, int klen, - pem_password_cb *cb, void *u) -{ - X509_SIG *p8; - PKCS8_PRIV_KEY_INFO *p8inf; - char buf[PEM_BUFSIZE]; - int ret; - if (!(p8inf = EVP_PKEY2PKCS8(x))) { - OPENSSL_PUT_ERROR(PEM, PEM_R_ERROR_CONVERTING_PRIVATE_KEY); + pem_password_cb *cb, void *u) { + X509_SIG *p8; + PKCS8_PRIV_KEY_INFO *p8inf; + char buf[PEM_BUFSIZE]; + int ret; + if (!(p8inf = EVP_PKEY2PKCS8(x))) { + OPENSSL_PUT_ERROR(PEM, PEM_R_ERROR_CONVERTING_PRIVATE_KEY); + return 0; + } + if (enc || (nid != -1)) { + if (!kstr) { + klen = 0; + if (!cb) { + cb = PEM_def_callback; + } + klen = cb(buf, PEM_BUFSIZE, 1, u); + if (klen <= 0) { + OPENSSL_PUT_ERROR(PEM, PEM_R_READ_KEY); + PKCS8_PRIV_KEY_INFO_free(p8inf); return 0; + } + + kstr = buf; } - if (enc || (nid != -1)) { - if (!kstr) { - klen = 0; - if (!cb) - cb = PEM_def_callback; - klen = cb(buf, PEM_BUFSIZE, 1, u); - if (klen <= 0) { - OPENSSL_PUT_ERROR(PEM, PEM_R_READ_KEY); - PKCS8_PRIV_KEY_INFO_free(p8inf); - return 0; - } - - kstr = buf; - } - p8 = PKCS8_encrypt(nid, enc, kstr, klen, NULL, 0, 0, p8inf); - if (kstr == buf) - OPENSSL_cleanse(buf, klen); - PKCS8_PRIV_KEY_INFO_free(p8inf); - if (isder) - ret = i2d_PKCS8_bio(bp, p8); - else - ret = PEM_write_bio_PKCS8(bp, p8); - X509_SIG_free(p8); - return ret; + p8 = PKCS8_encrypt(nid, enc, kstr, klen, NULL, 0, 0, p8inf); + if (kstr == buf) { + OPENSSL_cleanse(buf, klen); + } + PKCS8_PRIV_KEY_INFO_free(p8inf); + if (isder) { + ret = i2d_PKCS8_bio(bp, p8); } else { - if (isder) - ret = i2d_PKCS8_PRIV_KEY_INFO_bio(bp, p8inf); - else - ret = PEM_write_bio_PKCS8_PRIV_KEY_INFO(bp, p8inf); - PKCS8_PRIV_KEY_INFO_free(p8inf); - return ret; + ret = PEM_write_bio_PKCS8(bp, p8); + } + X509_SIG_free(p8); + return ret; + } else { + if (isder) { + ret = i2d_PKCS8_PRIV_KEY_INFO_bio(bp, p8inf); + } else { + ret = PEM_write_bio_PKCS8_PRIV_KEY_INFO(bp, p8inf); } + PKCS8_PRIV_KEY_INFO_free(p8inf); + return ret; + } } EVP_PKEY *d2i_PKCS8PrivateKey_bio(BIO *bp, EVP_PKEY **x, pem_password_cb *cb, - void *u) -{ - PKCS8_PRIV_KEY_INFO *p8inf = NULL; - X509_SIG *p8 = NULL; - int klen; - EVP_PKEY *ret; - char psbuf[PEM_BUFSIZE]; - p8 = d2i_PKCS8_bio(bp, NULL); - if (!p8) - return NULL; - - klen = 0; - if (!cb) - cb = PEM_def_callback; - klen = cb(psbuf, PEM_BUFSIZE, 0, u); - if (klen <= 0) { - OPENSSL_PUT_ERROR(PEM, PEM_R_BAD_PASSWORD_READ); - X509_SIG_free(p8); - return NULL; - } - p8inf = PKCS8_decrypt(p8, psbuf, klen); + void *u) { + PKCS8_PRIV_KEY_INFO *p8inf = NULL; + X509_SIG *p8 = NULL; + int klen; + EVP_PKEY *ret; + char psbuf[PEM_BUFSIZE]; + p8 = d2i_PKCS8_bio(bp, NULL); + if (!p8) { + return NULL; + } + + klen = 0; + if (!cb) { + cb = PEM_def_callback; + } + klen = cb(psbuf, PEM_BUFSIZE, 0, u); + if (klen <= 0) { + OPENSSL_PUT_ERROR(PEM, PEM_R_BAD_PASSWORD_READ); X509_SIG_free(p8); - OPENSSL_cleanse(psbuf, klen); - if (!p8inf) - return NULL; - ret = EVP_PKCS82PKEY(p8inf); - PKCS8_PRIV_KEY_INFO_free(p8inf); - if (!ret) - return NULL; - if (x) { - if (*x) - EVP_PKEY_free(*x); - *x = ret; + return NULL; + } + p8inf = PKCS8_decrypt(p8, psbuf, klen); + X509_SIG_free(p8); + OPENSSL_cleanse(psbuf, klen); + if (!p8inf) { + return NULL; + } + ret = EVP_PKCS82PKEY(p8inf); + PKCS8_PRIV_KEY_INFO_free(p8inf); + if (!ret) { + return NULL; + } + if (x) { + if (*x) { + EVP_PKEY_free(*x); } - return ret; + *x = ret; + } + return ret; } int i2d_PKCS8PrivateKey_fp(FILE *fp, EVP_PKEY *x, const EVP_CIPHER *enc, - char *kstr, int klen, pem_password_cb *cb, void *u) -{ - return do_pk8pkey_fp(fp, x, 1, -1, enc, kstr, klen, cb, u); + char *kstr, int klen, pem_password_cb *cb, void *u) { + return do_pk8pkey_fp(fp, x, 1, -1, enc, kstr, klen, cb, u); } -int i2d_PKCS8PrivateKey_nid_fp(FILE *fp, EVP_PKEY *x, int nid, - char *kstr, int klen, - pem_password_cb *cb, void *u) -{ - return do_pk8pkey_fp(fp, x, 1, nid, NULL, kstr, klen, cb, u); +int i2d_PKCS8PrivateKey_nid_fp(FILE *fp, EVP_PKEY *x, int nid, char *kstr, + int klen, pem_password_cb *cb, void *u) { + return do_pk8pkey_fp(fp, x, 1, nid, NULL, kstr, klen, cb, u); } -int PEM_write_PKCS8PrivateKey_nid(FILE *fp, EVP_PKEY *x, int nid, - char *kstr, int klen, - pem_password_cb *cb, void *u) -{ - return do_pk8pkey_fp(fp, x, 0, nid, NULL, kstr, klen, cb, u); +int PEM_write_PKCS8PrivateKey_nid(FILE *fp, EVP_PKEY *x, int nid, char *kstr, + int klen, pem_password_cb *cb, void *u) { + return do_pk8pkey_fp(fp, x, 0, nid, NULL, kstr, klen, cb, u); } int PEM_write_PKCS8PrivateKey(FILE *fp, EVP_PKEY *x, const EVP_CIPHER *enc, char *kstr, int klen, pem_password_cb *cb, - void *u) -{ - return do_pk8pkey_fp(fp, x, 0, -1, enc, kstr, klen, cb, u); + void *u) { + return do_pk8pkey_fp(fp, x, 0, -1, enc, kstr, klen, cb, u); } static int do_pk8pkey_fp(FILE *fp, EVP_PKEY *x, int isder, int nid, const EVP_CIPHER *enc, char *kstr, int klen, - pem_password_cb *cb, void *u) -{ - BIO *bp; - int ret; - if (!(bp = BIO_new_fp(fp, BIO_NOCLOSE))) { - OPENSSL_PUT_ERROR(PEM, ERR_R_BUF_LIB); - return (0); - } - ret = do_pk8pkey(bp, x, isder, nid, enc, kstr, klen, cb, u); - BIO_free(bp); - return ret; + pem_password_cb *cb, void *u) { + BIO *bp; + int ret; + if (!(bp = BIO_new_fp(fp, BIO_NOCLOSE))) { + OPENSSL_PUT_ERROR(PEM, ERR_R_BUF_LIB); + return (0); + } + ret = do_pk8pkey(bp, x, isder, nid, enc, kstr, klen, cb, u); + BIO_free(bp); + return ret; } EVP_PKEY *d2i_PKCS8PrivateKey_fp(FILE *fp, EVP_PKEY **x, pem_password_cb *cb, - void *u) -{ - BIO *bp; - EVP_PKEY *ret; - if (!(bp = BIO_new_fp(fp, BIO_NOCLOSE))) { - OPENSSL_PUT_ERROR(PEM, ERR_R_BUF_LIB); - return NULL; - } - ret = d2i_PKCS8PrivateKey_bio(bp, x, cb, u); - BIO_free(bp); - return ret; + void *u) { + BIO *bp; + EVP_PKEY *ret; + if (!(bp = BIO_new_fp(fp, BIO_NOCLOSE))) { + OPENSSL_PUT_ERROR(PEM, ERR_R_BUF_LIB); + return NULL; + } + ret = d2i_PKCS8PrivateKey_bio(bp, x, cb, u); + BIO_free(bp); + return ret; } @@ -252,4 +245,4 @@ IMPLEMENT_PEM_rw(PKCS8, X509_SIG, PEM_STRING_PKCS8, X509_SIG) IMPLEMENT_PEM_rw(PKCS8_PRIV_KEY_INFO, PKCS8_PRIV_KEY_INFO, PEM_STRING_PKCS8INF, - PKCS8_PRIV_KEY_INFO) + PKCS8_PRIV_KEY_INFO) diff --git a/crypto/pem/pem_pkey.c b/crypto/pem/pem_pkey.c index f75486d928..b612304696 100644 --- a/crypto/pem/pem_pkey.c +++ b/crypto/pem/pem_pkey.c @@ -69,110 +69,114 @@ #include EVP_PKEY *PEM_read_bio_PrivateKey(BIO *bp, EVP_PKEY **x, pem_password_cb *cb, - void *u) -{ - char *nm = NULL; - const unsigned char *p = NULL; - unsigned char *data = NULL; - long len; - EVP_PKEY *ret = NULL; + void *u) { + char *nm = NULL; + const unsigned char *p = NULL; + unsigned char *data = NULL; + long len; + EVP_PKEY *ret = NULL; - if (!PEM_bytes_read_bio(&data, &len, &nm, PEM_STRING_EVP_PKEY, bp, cb, u)) - return NULL; - p = data; + if (!PEM_bytes_read_bio(&data, &len, &nm, PEM_STRING_EVP_PKEY, bp, cb, u)) { + return NULL; + } + p = data; - if (strcmp(nm, PEM_STRING_PKCS8INF) == 0) { - PKCS8_PRIV_KEY_INFO *p8inf; - p8inf = d2i_PKCS8_PRIV_KEY_INFO(NULL, &p, len); - if (!p8inf) - goto p8err; - ret = EVP_PKCS82PKEY(p8inf); - if (x) { - if (*x) - EVP_PKEY_free((EVP_PKEY *)*x); - *x = ret; - } - PKCS8_PRIV_KEY_INFO_free(p8inf); - } else if (strcmp(nm, PEM_STRING_PKCS8) == 0) { - PKCS8_PRIV_KEY_INFO *p8inf; - X509_SIG *p8; - int klen; - char psbuf[PEM_BUFSIZE]; - p8 = d2i_X509_SIG(NULL, &p, len); - if (!p8) - goto p8err; + if (strcmp(nm, PEM_STRING_PKCS8INF) == 0) { + PKCS8_PRIV_KEY_INFO *p8inf; + p8inf = d2i_PKCS8_PRIV_KEY_INFO(NULL, &p, len); + if (!p8inf) { + goto p8err; + } + ret = EVP_PKCS82PKEY(p8inf); + if (x) { + if (*x) { + EVP_PKEY_free((EVP_PKEY *)*x); + } + *x = ret; + } + PKCS8_PRIV_KEY_INFO_free(p8inf); + } else if (strcmp(nm, PEM_STRING_PKCS8) == 0) { + PKCS8_PRIV_KEY_INFO *p8inf; + X509_SIG *p8; + int klen; + char psbuf[PEM_BUFSIZE]; + p8 = d2i_X509_SIG(NULL, &p, len); + if (!p8) { + goto p8err; + } - klen = 0; - if (!cb) - cb = PEM_def_callback; - klen = cb(psbuf, PEM_BUFSIZE, 0, u); - if (klen <= 0) { - OPENSSL_PUT_ERROR(PEM, PEM_R_BAD_PASSWORD_READ); - X509_SIG_free(p8); - goto err; - } - p8inf = PKCS8_decrypt(p8, psbuf, klen); - X509_SIG_free(p8); - OPENSSL_cleanse(psbuf, klen); - if (!p8inf) - goto p8err; - ret = EVP_PKCS82PKEY(p8inf); - if (x) { - if (*x) - EVP_PKEY_free((EVP_PKEY *)*x); - *x = ret; - } - PKCS8_PRIV_KEY_INFO_free(p8inf); - } else if (strcmp(nm, PEM_STRING_RSA) == 0) { - /* TODO(davidben): d2i_PrivateKey parses PKCS#8 along with the - * standalone format. This and the cases below probably should not - * accept PKCS#8. */ - ret = d2i_PrivateKey(EVP_PKEY_RSA, x, &p, len); - } else if (strcmp(nm, PEM_STRING_EC) == 0) { - ret = d2i_PrivateKey(EVP_PKEY_EC, x, &p, len); - } else if (strcmp(nm, PEM_STRING_DSA) == 0) { - ret = d2i_PrivateKey(EVP_PKEY_DSA, x, &p, len); + klen = 0; + if (!cb) { + cb = PEM_def_callback; + } + klen = cb(psbuf, PEM_BUFSIZE, 0, u); + if (klen <= 0) { + OPENSSL_PUT_ERROR(PEM, PEM_R_BAD_PASSWORD_READ); + X509_SIG_free(p8); + goto err; } - p8err: - if (ret == NULL) - OPENSSL_PUT_ERROR(PEM, ERR_R_ASN1_LIB); + p8inf = PKCS8_decrypt(p8, psbuf, klen); + X509_SIG_free(p8); + OPENSSL_cleanse(psbuf, klen); + if (!p8inf) { + goto p8err; + } + ret = EVP_PKCS82PKEY(p8inf); + if (x) { + if (*x) { + EVP_PKEY_free((EVP_PKEY *)*x); + } + *x = ret; + } + PKCS8_PRIV_KEY_INFO_free(p8inf); + } else if (strcmp(nm, PEM_STRING_RSA) == 0) { + /* TODO(davidben): d2i_PrivateKey parses PKCS#8 along with the + * standalone format. This and the cases below probably should not + * accept PKCS#8. */ + ret = d2i_PrivateKey(EVP_PKEY_RSA, x, &p, len); + } else if (strcmp(nm, PEM_STRING_EC) == 0) { + ret = d2i_PrivateKey(EVP_PKEY_EC, x, &p, len); + } else if (strcmp(nm, PEM_STRING_DSA) == 0) { + ret = d2i_PrivateKey(EVP_PKEY_DSA, x, &p, len); + } +p8err: + if (ret == NULL) { + OPENSSL_PUT_ERROR(PEM, ERR_R_ASN1_LIB); + } - err: - OPENSSL_free(nm); - OPENSSL_free(data); - return (ret); +err: + OPENSSL_free(nm); + OPENSSL_free(data); + return (ret); } int PEM_write_bio_PrivateKey(BIO *bp, EVP_PKEY *x, const EVP_CIPHER *enc, - unsigned char *kstr, int klen, - pem_password_cb *cb, void *u) -{ - return PEM_write_bio_PKCS8PrivateKey(bp, x, enc, (char *)kstr, klen, cb, u); + unsigned char *kstr, int klen, pem_password_cb *cb, + void *u) { + return PEM_write_bio_PKCS8PrivateKey(bp, x, enc, (char *)kstr, klen, cb, u); } EVP_PKEY *PEM_read_PrivateKey(FILE *fp, EVP_PKEY **x, pem_password_cb *cb, - void *u) -{ - BIO *b = BIO_new_fp(fp, BIO_NOCLOSE); - if (b == NULL) { - OPENSSL_PUT_ERROR(PEM, ERR_R_BUF_LIB); - return NULL; - } - EVP_PKEY *ret = PEM_read_bio_PrivateKey(b, x, cb, u); - BIO_free(b); - return ret; + void *u) { + BIO *b = BIO_new_fp(fp, BIO_NOCLOSE); + if (b == NULL) { + OPENSSL_PUT_ERROR(PEM, ERR_R_BUF_LIB); + return NULL; + } + EVP_PKEY *ret = PEM_read_bio_PrivateKey(b, x, cb, u); + BIO_free(b); + return ret; } int PEM_write_PrivateKey(FILE *fp, EVP_PKEY *x, const EVP_CIPHER *enc, - unsigned char *kstr, int klen, - pem_password_cb *cb, void *u) -{ - BIO *b = BIO_new_fp(fp, BIO_NOCLOSE); - if (b == NULL) { - OPENSSL_PUT_ERROR(PEM, ERR_R_BUF_LIB); - return 0; - } - int ret = PEM_write_bio_PrivateKey(b, x, enc, kstr, klen, cb, u); - BIO_free(b); - return ret; + unsigned char *kstr, int klen, pem_password_cb *cb, + void *u) { + BIO *b = BIO_new_fp(fp, BIO_NOCLOSE); + if (b == NULL) { + OPENSSL_PUT_ERROR(PEM, ERR_R_BUF_LIB); + return 0; + } + int ret = PEM_write_bio_PrivateKey(b, x, enc, kstr, klen, cb, u); + BIO_free(b); + return ret; } diff --git a/crypto/stack/stack.c b/crypto/stack/stack.c index 6da6e3b232..6412e07bd1 100644 --- a/crypto/stack/stack.c +++ b/crypto/stack/stack.c @@ -131,7 +131,7 @@ void sk_free(_STACK *sk) { OPENSSL_free(sk); } -void sk_pop_free_ex(_STACK *sk, void (*call_free_func)(stack_free_func, void *), +void sk_pop_free_ex(_STACK *sk, stack_call_free_func call_free_func, stack_free_func free_func) { if (sk == NULL) { return; @@ -234,8 +234,7 @@ void *sk_delete_ptr(_STACK *sk, const void *p) { } int sk_find(const _STACK *sk, size_t *out_index, const void *p, - int (*call_cmp_func)(stack_cmp_func, const void **, - const void **)) { + stack_call_cmp_func call_cmp_func) { if (sk == NULL) { return 0; } @@ -355,24 +354,43 @@ _STACK *sk_dup(const _STACK *sk) { return NULL; } -void sk_sort(_STACK *sk) { +#if defined(_MSC_VER) +struct sort_compare_ctx { + stack_call_cmp_func call_cmp_func; + stack_cmp_func cmp_func; +}; + +static int sort_compare(void *ctx_v, const void *a, const void *b) { + struct sort_compare_ctx *ctx = ctx_v; + return ctx->call_cmp_func(ctx->cmp_func, a, b); +} +#endif + +void sk_sort(_STACK *sk, stack_call_cmp_func call_cmp_func) { if (sk == NULL || sk->comp == NULL || sk->sorted) { return; } - // sk->comp is a function that takes pointers to pointers to elements, but - // qsort take a comparison function that just takes pointers to elements. - // However, since we're passing an array of pointers to qsort, we can just - // cast the comparison function and everything works. - // - // TODO(davidben): This is undefined behavior, but the call is in libc so, - // e.g., CFI does not notice. Unfortunately, |qsort| is missing a void* - // parameter in its callback and |qsort_s| / |qsort_r| are a mess of - // incompatibility. if (sk->num >= 2) { +#if defined(_MSC_VER) + // MSVC's |qsort_s| is different from the C11 one. + // https://docs.microsoft.com/en-us/cpp/c-runtime-library/reference/qsort-s?view=msvc-170 + struct sort_compare_ctx ctx = {call_cmp_func, sk->comp}; + qsort_s(sk->data, sk->num, sizeof(void *), sort_compare, &ctx); +#else + // sk->comp is a function that takes pointers to pointers to elements, but + // qsort take a comparison function that just takes pointers to elements. + // However, since we're passing an array of pointers to qsort, we can just + // cast the comparison function and everything works. + // + // TODO(davidben): This is undefined behavior, but the call is in libc so, + // e.g., CFI does not notice. |qsort| is missing a void* parameter in its + // callback, while no one defines |qsort_r| or |qsort_s| consistently. See + // https://stackoverflow.com/a/39561369 int (*comp_func)(const void *, const void *) = (int (*)(const void *, const void *))(sk->comp); qsort(sk->data, sk->num, sizeof(void *), comp_func); +#endif } sk->sorted = 1; } @@ -395,10 +413,9 @@ stack_cmp_func sk_set_cmp_func(_STACK *sk, stack_cmp_func comp) { return old; } -_STACK *sk_deep_copy(const _STACK *sk, - void *(*call_copy_func)(stack_copy_func, void *), +_STACK *sk_deep_copy(const _STACK *sk, stack_call_copy_func call_copy_func, stack_copy_func copy_func, - void (*call_free_func)(stack_free_func, void *), + stack_call_free_func call_free_func, stack_free_func free_func) { _STACK *ret = sk_dup(sk); if (ret == NULL) { diff --git a/crypto/thread_pthread.c b/crypto/thread_pthread.c index 7a94157b10..acec90590a 100644 --- a/crypto/thread_pthread.c +++ b/crypto/thread_pthread.c @@ -26,10 +26,8 @@ OPENSSL_STATIC_ASSERT(sizeof(CRYPTO_MUTEX) >= sizeof(pthread_rwlock_t), CRYPTO_MUTEX_is_too_small) -#if defined(__GNUC__) || defined(__clang__) OPENSSL_STATIC_ASSERT(alignof(CRYPTO_MUTEX) >= alignof(pthread_rwlock_t), CRYPTO_MUTEX_has_insufficient_alignment) -#endif void CRYPTO_MUTEX_init(CRYPTO_MUTEX *lock) { if (pthread_rwlock_init((pthread_rwlock_t *) lock, NULL) != 0) { diff --git a/crypto/thread_win.c b/crypto/thread_win.c index e3da17719b..261f03d61c 100644 --- a/crypto/thread_win.c +++ b/crypto/thread_win.c @@ -29,10 +29,8 @@ OPENSSL_MSVC_PRAGMA(warning(pop)) OPENSSL_STATIC_ASSERT(sizeof(CRYPTO_MUTEX) >= sizeof(SRWLOCK), CRYPTO_MUTEX_is_too_small) -#if defined(__GNUC__) || defined(__clang__) OPENSSL_STATIC_ASSERT(alignof(CRYPTO_MUTEX) >= alignof(SRWLOCK), CRYPTO_MUTEX_has_insufficient_alignment) -#endif static BOOL CALLBACK call_once_init(INIT_ONCE *once, void *arg, void **out) { void (**init)(void) = (void (**)(void))arg; diff --git a/crypto/trust_token/internal.h b/crypto/trust_token/internal.h index 0aa19363f1..31ecc49b5c 100644 --- a/crypto/trust_token/internal.h +++ b/crypto/trust_token/internal.h @@ -93,6 +93,9 @@ DEFINE_STACK_OF(TRUST_TOKEN_PRETOKEN) // functions for |TRUST_TOKENS_experiment_v1|'s PMBTokens construction which // uses P-384. int pmbtoken_exp1_generate_key(CBB *out_private, CBB *out_public); +int pmbtoken_exp1_derive_key_from_secret(CBB *out_private, CBB *out_public, + const uint8_t *secret, + size_t secret_len); int pmbtoken_exp1_client_key_from_bytes(TRUST_TOKEN_CLIENT_KEY *key, const uint8_t *in, size_t len); int pmbtoken_exp1_issuer_key_from_bytes(TRUST_TOKEN_ISSUER_KEY *key, @@ -118,6 +121,9 @@ OPENSSL_EXPORT int pmbtoken_exp1_get_h_for_testing(uint8_t out[97]); // functions for |TRUST_TOKENS_experiment_v2|'s PMBTokens construction which // uses P-384. int pmbtoken_exp2_generate_key(CBB *out_private, CBB *out_public); +int pmbtoken_exp2_derive_key_from_secret(CBB *out_private, CBB *out_public, + const uint8_t *secret, + size_t secret_len); int pmbtoken_exp2_client_key_from_bytes(TRUST_TOKEN_CLIENT_KEY *key, const uint8_t *in, size_t len); int pmbtoken_exp2_issuer_key_from_bytes(TRUST_TOKEN_ISSUER_KEY *key, @@ -153,6 +159,8 @@ OPENSSL_EXPORT int pmbtoken_exp2_get_h_for_testing(uint8_t out[97]); // functions for |TRUST_TOKENS_experiment_v2|'s VOPRF construction which uses // P-384. int voprf_exp2_generate_key(CBB *out_private, CBB *out_public); +int voprf_exp2_derive_key_from_secret(CBB *out_private, CBB *out_public, + const uint8_t *secret, size_t secret_len); int voprf_exp2_client_key_from_bytes(TRUST_TOKEN_CLIENT_KEY *key, const uint8_t *in, size_t len); int voprf_exp2_issuer_key_from_bytes(TRUST_TOKEN_ISSUER_KEY *key, @@ -179,6 +187,12 @@ struct trust_token_method_st { // zero on failure. int (*generate_key)(CBB *out_private, CBB *out_public); + // derive_key_from_secret deterministically derives a keypair based on + // |secret| and writes their serialized forms into |out_private| and + // |out_public|. It returns one on success and zero on failure. + int (*derive_key_from_secret)(CBB *out_private, CBB *out_public, + const uint8_t *secret, size_t secret_len); + // client_key_from_bytes decodes a client key from |in| and sets |key| // to the resulting key. It returns one on success and zero // on failure. diff --git a/crypto/trust_token/pmbtoken.c b/crypto/trust_token/pmbtoken.c index a6549b9c5f..68d8909b91 100644 --- a/crypto/trust_token/pmbtoken.c +++ b/crypto/trust_token/pmbtoken.c @@ -37,6 +37,8 @@ typedef int (*hash_s_func_t)(const EC_GROUP *group, EC_RAW_POINT *out, const uint8_t s[TRUST_TOKEN_NONCE_SIZE]); typedef int (*hash_c_func_t)(const EC_GROUP *group, EC_SCALAR *out, uint8_t *buf, size_t len); +typedef int (*hash_to_scalar_func_t)(const EC_GROUP *group, EC_SCALAR *out, + uint8_t *buf, size_t len); typedef struct { const EC_GROUP *group; @@ -52,6 +54,9 @@ typedef struct { // hash_c implements the H_c operation in PMBTokens. It returns one on success // and zero on error. hash_c_func_t hash_c; + // hash_to_scalar implements the HashToScalar operation for PMBTokens. It + // returns one on success and zero on error. + hash_to_scalar_func_t hash_to_scalar; int prefix_point : 1; } PMBTOKEN_METHOD; @@ -60,7 +65,9 @@ static const uint8_t kDefaultAdditionalData[32] = {0}; static int pmbtoken_init_method(PMBTOKEN_METHOD *method, int curve_nid, const uint8_t *h_bytes, size_t h_len, hash_t_func_t hash_t, hash_s_func_t hash_s, - hash_c_func_t hash_c, int prefix_point) { + hash_c_func_t hash_c, + hash_to_scalar_func_t hash_to_scalar, + int prefix_point) { method->group = EC_GROUP_new_by_curve_name(curve_nid); if (method->group == NULL) { return 0; @@ -69,6 +76,7 @@ static int pmbtoken_init_method(PMBTOKEN_METHOD *method, int curve_nid, method->hash_t = hash_t; method->hash_s = hash_s; method->hash_c = hash_c; + method->hash_to_scalar = hash_to_scalar; method->prefix_point = prefix_point; EC_AFFINE h; @@ -85,21 +93,32 @@ static int pmbtoken_init_method(PMBTOKEN_METHOD *method, int curve_nid, return 1; } -// generate_keypair generates a keypair for the PMBTokens construction. -// |out_x| and |out_y| are set to the secret half of the keypair, while -// |*out_pub| is set to the public half of the keypair. It returns one on -// success and zero on failure. -static int generate_keypair(const PMBTOKEN_METHOD *method, EC_SCALAR *out_x, - EC_SCALAR *out_y, EC_RAW_POINT *out_pub) { - if (!ec_random_nonzero_scalar(method->group, out_x, kDefaultAdditionalData) || - !ec_random_nonzero_scalar(method->group, out_y, kDefaultAdditionalData) || - !ec_point_mul_scalar_precomp(method->group, out_pub, &method->g_precomp, - out_x, &method->h_precomp, out_y, NULL, - NULL)) { - OPENSSL_PUT_ERROR(TRUST_TOKEN, ERR_R_MALLOC_FAILURE); - return 0; +static int derive_scalar_from_secret(const PMBTOKEN_METHOD *method, + EC_SCALAR *out, const uint8_t *secret, + size_t secret_len, uint8_t scalar_id) { + static const uint8_t kKeygenLabel[] = "TrustTokenPMBTokenKeyGen"; + + int ok = 0; + CBB cbb; + CBB_zero(&cbb); + uint8_t *buf = NULL; + size_t len; + if (!CBB_init(&cbb, 0) || + !CBB_add_bytes(&cbb, kKeygenLabel, sizeof(kKeygenLabel)) || + !CBB_add_u8(&cbb, scalar_id) || + !CBB_add_bytes(&cbb, secret, secret_len) || + !CBB_finish(&cbb, &buf, &len) || + !method->hash_to_scalar(method->group, out, buf, len)) { + OPENSSL_PUT_ERROR(TRUST_TOKEN, TRUST_TOKEN_R_KEYGEN_FAILURE); + goto err; } - return 1; + + ok = 1; + +err: + CBB_cleanup(&cbb); + OPENSSL_free(buf); + return ok; } static int point_to_cbb(CBB *out, const EC_GROUP *group, @@ -165,19 +184,24 @@ static int mul_public_3(const EC_GROUP *group, EC_RAW_POINT *out, scalars, 3); } -static int pmbtoken_generate_key(const PMBTOKEN_METHOD *method, - CBB *out_private, CBB *out_public) { +static int pmbtoken_compute_keys(const PMBTOKEN_METHOD *method, + CBB *out_private, CBB *out_public, + const EC_SCALAR *x0, const EC_SCALAR *y0, + const EC_SCALAR *x1, const EC_SCALAR *y1, + const EC_SCALAR *xs, const EC_SCALAR *ys) { const EC_GROUP *group = method->group; EC_RAW_POINT pub[3]; - EC_SCALAR x0, y0, x1, y1, xs, ys; - if (!generate_keypair(method, &x0, &y0, &pub[0]) || - !generate_keypair(method, &x1, &y1, &pub[1]) || - !generate_keypair(method, &xs, &ys, &pub[2])) { + if (!ec_point_mul_scalar_precomp(group, &pub[0], &method->g_precomp, + x0, &method->h_precomp, y0, NULL, NULL) || + !ec_point_mul_scalar_precomp(group, &pub[1], &method->g_precomp, + x1, &method->h_precomp, y1, NULL, NULL) || + !ec_point_mul_scalar_precomp(method->group, &pub[2], &method->g_precomp, + xs, &method->h_precomp, ys, NULL, NULL)) { OPENSSL_PUT_ERROR(TRUST_TOKEN, TRUST_TOKEN_R_KEYGEN_FAILURE); return 0; } - const EC_SCALAR *scalars[] = {&x0, &y0, &x1, &y1, &xs, &ys}; + const EC_SCALAR *scalars[] = {x0, y0, x1, y1, xs, ys}; size_t scalar_len = BN_num_bytes(&group->order); for (size_t i = 0; i < OPENSSL_ARRAY_SIZE(scalars); i++) { uint8_t *buf; @@ -206,6 +230,42 @@ static int pmbtoken_generate_key(const PMBTOKEN_METHOD *method, return 1; } +static int pmbtoken_generate_key(const PMBTOKEN_METHOD *method, + CBB *out_private, CBB *out_public) { + EC_SCALAR x0, y0, x1, y1, xs, ys; + if (!ec_random_nonzero_scalar(method->group, &x0, kDefaultAdditionalData) || + !ec_random_nonzero_scalar(method->group, &y0, kDefaultAdditionalData) || + !ec_random_nonzero_scalar(method->group, &x1, kDefaultAdditionalData) || + !ec_random_nonzero_scalar(method->group, &y1, kDefaultAdditionalData) || + !ec_random_nonzero_scalar(method->group, &xs, kDefaultAdditionalData) || + !ec_random_nonzero_scalar(method->group, &ys, kDefaultAdditionalData)) { + OPENSSL_PUT_ERROR(TRUST_TOKEN, TRUST_TOKEN_R_KEYGEN_FAILURE); + return 0; + } + + return pmbtoken_compute_keys(method, out_private, out_public, &x0, &y0, &x1, + &y1, &xs, &ys); +} + +static int pmbtoken_derive_key_from_secret(const PMBTOKEN_METHOD *method, + CBB *out_private, CBB *out_public, + const uint8_t *secret, + size_t secret_len) { + EC_SCALAR x0, y0, x1, y1, xs, ys; + if (!derive_scalar_from_secret(method, &x0, secret, secret_len, 0) || + !derive_scalar_from_secret(method, &y0, secret, secret_len, 1) || + !derive_scalar_from_secret(method, &x1, secret, secret_len, 2) || + !derive_scalar_from_secret(method, &y1, secret, secret_len, 3) || + !derive_scalar_from_secret(method, &xs, secret, secret_len, 4) || + !derive_scalar_from_secret(method, &ys, secret, secret_len, 5)) { + OPENSSL_PUT_ERROR(TRUST_TOKEN, TRUST_TOKEN_R_KEYGEN_FAILURE); + return 0; + } + + return pmbtoken_compute_keys(method, out_private, out_public, &x0, &y0, &x1, + &y1, &xs, &ys); +} + static int pmbtoken_client_key_from_bytes(const PMBTOKEN_METHOD *method, TRUST_TOKEN_CLIENT_KEY *key, const uint8_t *in, size_t len) { @@ -1140,6 +1200,13 @@ static int pmbtoken_exp1_hash_c(const EC_GROUP *group, EC_SCALAR *out, group, out, kHashCLabel, sizeof(kHashCLabel), buf, len); } +static int pmbtoken_exp1_hash_to_scalar(const EC_GROUP *group, EC_SCALAR *out, + uint8_t *buf, size_t len) { + const uint8_t kHashLabel[] = "PMBTokens Experiment V1 HashToScalar"; + return ec_hash_to_scalar_p384_xmd_sha512_draft07( + group, out, kHashLabel, sizeof(kHashLabel), buf, len); +} + static int pmbtoken_exp1_ok = 0; static PMBTOKEN_METHOD pmbtoken_exp1_method; static CRYPTO_once_t pmbtoken_exp1_method_once = CRYPTO_ONCE_INIT; @@ -1159,10 +1226,10 @@ static void pmbtoken_exp1_init_method_impl(void) { 0x87, 0xc3, 0x95, 0xd0, 0x13, 0xb7, 0x0b, 0x5c, 0xc7, }; - pmbtoken_exp1_ok = - pmbtoken_init_method(&pmbtoken_exp1_method, NID_secp384r1, kH, sizeof(kH), - pmbtoken_exp1_hash_t, pmbtoken_exp1_hash_s, - pmbtoken_exp1_hash_c, 1); + pmbtoken_exp1_ok = pmbtoken_init_method( + &pmbtoken_exp1_method, NID_secp384r1, kH, sizeof(kH), + pmbtoken_exp1_hash_t, pmbtoken_exp1_hash_s, pmbtoken_exp1_hash_c, + pmbtoken_exp1_hash_to_scalar, 1); } static int pmbtoken_exp1_init_method(void) { @@ -1182,6 +1249,17 @@ int pmbtoken_exp1_generate_key(CBB *out_private, CBB *out_public) { return pmbtoken_generate_key(&pmbtoken_exp1_method, out_private, out_public); } +int pmbtoken_exp1_derive_key_from_secret(CBB *out_private, CBB *out_public, + const uint8_t *secret, + size_t secret_len) { + if (!pmbtoken_exp1_init_method()) { + return 0; + } + + return pmbtoken_derive_key_from_secret(&pmbtoken_exp1_method, out_private, + out_public, secret, secret_len); +} + int pmbtoken_exp1_client_key_from_bytes(TRUST_TOKEN_CLIENT_KEY *key, const uint8_t *in, size_t len) { if (!pmbtoken_exp1_init_method()) { @@ -1290,6 +1368,13 @@ static int pmbtoken_exp2_hash_c(const EC_GROUP *group, EC_SCALAR *out, group, out, kHashCLabel, sizeof(kHashCLabel), buf, len); } +static int pmbtoken_exp2_hash_to_scalar(const EC_GROUP *group, EC_SCALAR *out, + uint8_t *buf, size_t len) { + const uint8_t kHashLabel[] = "PMBTokens Experiment V2 HashToScalar"; + return ec_hash_to_scalar_p384_xmd_sha512_draft07( + group, out, kHashLabel, sizeof(kHashLabel), buf, len); +} + static int pmbtoken_exp2_ok = 0; static PMBTOKEN_METHOD pmbtoken_exp2_method; static CRYPTO_once_t pmbtoken_exp2_method_once = CRYPTO_ONCE_INIT; @@ -1309,10 +1394,10 @@ static void pmbtoken_exp2_init_method_impl(void) { 0x25, 0x62, 0xbf, 0x59, 0xb2, 0xd2, 0x3d, 0x71, 0xff }; - pmbtoken_exp2_ok = - pmbtoken_init_method(&pmbtoken_exp2_method, NID_secp384r1, kH, sizeof(kH), - pmbtoken_exp2_hash_t, pmbtoken_exp2_hash_s, - pmbtoken_exp2_hash_c, 0); + pmbtoken_exp2_ok = pmbtoken_init_method( + &pmbtoken_exp2_method, NID_secp384r1, kH, sizeof(kH), + pmbtoken_exp2_hash_t, pmbtoken_exp2_hash_s, pmbtoken_exp2_hash_c, + pmbtoken_exp2_hash_to_scalar, 0); } static int pmbtoken_exp2_init_method(void) { @@ -1332,6 +1417,18 @@ int pmbtoken_exp2_generate_key(CBB *out_private, CBB *out_public) { return pmbtoken_generate_key(&pmbtoken_exp2_method, out_private, out_public); } + +int pmbtoken_exp2_derive_key_from_secret(CBB *out_private, CBB *out_public, + const uint8_t *secret, + size_t secret_len) { + if (!pmbtoken_exp2_init_method()) { + return 0; + } + + return pmbtoken_derive_key_from_secret(&pmbtoken_exp2_method, out_private, + out_public, secret, secret_len); +} + int pmbtoken_exp2_client_key_from_bytes(TRUST_TOKEN_CLIENT_KEY *key, const uint8_t *in, size_t len) { if (!pmbtoken_exp2_init_method()) { diff --git a/crypto/trust_token/trust_token.c b/crypto/trust_token/trust_token.c index 3334fba877..5afb487c07 100644 --- a/crypto/trust_token/trust_token.c +++ b/crypto/trust_token/trust_token.c @@ -30,6 +30,7 @@ const TRUST_TOKEN_METHOD *TRUST_TOKEN_experiment_v1(void) { static const TRUST_TOKEN_METHOD kMethod = { pmbtoken_exp1_generate_key, + pmbtoken_exp1_derive_key_from_secret, pmbtoken_exp1_client_key_from_bytes, pmbtoken_exp1_issuer_key_from_bytes, pmbtoken_exp1_blind, @@ -46,6 +47,7 @@ const TRUST_TOKEN_METHOD *TRUST_TOKEN_experiment_v1(void) { const TRUST_TOKEN_METHOD *TRUST_TOKEN_experiment_v2_voprf(void) { static const TRUST_TOKEN_METHOD kMethod = { voprf_exp2_generate_key, + voprf_exp2_derive_key_from_secret, voprf_exp2_client_key_from_bytes, voprf_exp2_issuer_key_from_bytes, voprf_exp2_blind, @@ -62,6 +64,7 @@ const TRUST_TOKEN_METHOD *TRUST_TOKEN_experiment_v2_voprf(void) { const TRUST_TOKEN_METHOD *TRUST_TOKEN_experiment_v2_pmb(void) { static const TRUST_TOKEN_METHOD kMethod = { pmbtoken_exp2_generate_key, + pmbtoken_exp2_derive_key_from_secret, pmbtoken_exp2_client_key_from_bytes, pmbtoken_exp2_issuer_key_from_bytes, pmbtoken_exp2_blind, @@ -140,6 +143,43 @@ int TRUST_TOKEN_generate_key(const TRUST_TOKEN_METHOD *method, return ret; } +int TRUST_TOKEN_derive_key_from_secret( + const TRUST_TOKEN_METHOD *method, uint8_t *out_priv_key, + size_t *out_priv_key_len, size_t max_priv_key_len, uint8_t *out_pub_key, + size_t *out_pub_key_len, size_t max_pub_key_len, uint32_t id, + const uint8_t *secret, size_t secret_len) { + // Prepend the key ID in front of the PMBTokens format. + int ret = 0; + CBB priv_cbb, pub_cbb; + CBB_zero(&priv_cbb); + CBB_zero(&pub_cbb); + if (!CBB_init_fixed(&priv_cbb, out_priv_key, max_priv_key_len) || + !CBB_init_fixed(&pub_cbb, out_pub_key, max_pub_key_len) || + !CBB_add_u32(&priv_cbb, id) || + !CBB_add_u32(&pub_cbb, id)) { + OPENSSL_PUT_ERROR(TRUST_TOKEN, TRUST_TOKEN_R_BUFFER_TOO_SMALL); + goto err; + } + + if (!method->derive_key_from_secret(&priv_cbb, &pub_cbb, secret, + secret_len)) { + goto err; + } + + if (!CBB_finish(&priv_cbb, NULL, out_priv_key_len) || + !CBB_finish(&pub_cbb, NULL, out_pub_key_len)) { + OPENSSL_PUT_ERROR(TRUST_TOKEN, TRUST_TOKEN_R_BUFFER_TOO_SMALL); + goto err; + } + + ret = 1; + +err: + CBB_cleanup(&priv_cbb); + CBB_cleanup(&pub_cbb); + return ret; +} + TRUST_TOKEN_CLIENT *TRUST_TOKEN_CLIENT_new(const TRUST_TOKEN_METHOD *method, size_t max_batchsize) { if (max_batchsize > 0xffff) { diff --git a/crypto/trust_token/trust_token_test.cc b/crypto/trust_token/trust_token_test.cc index f9f183d941..7f55146e38 100644 --- a/crypto/trust_token/trust_token_test.cc +++ b/crypto/trust_token/trust_token_test.cc @@ -54,6 +54,73 @@ TEST(TrustTokenTest, KeyGenExp1) { TRUST_TOKEN_MAX_PUBLIC_KEY_SIZE, 0x0001)); ASSERT_EQ(292u, priv_key_len); ASSERT_EQ(301u, pub_key_len); + + const uint8_t kKeygenSecret[] = "SEED"; + ASSERT_TRUE(TRUST_TOKEN_derive_key_from_secret( + TRUST_TOKEN_experiment_v1(), priv_key, &priv_key_len, + TRUST_TOKEN_MAX_PRIVATE_KEY_SIZE, pub_key, &pub_key_len, + TRUST_TOKEN_MAX_PUBLIC_KEY_SIZE, 0x0001, kKeygenSecret, + sizeof(kKeygenSecret) - 1)); + + const uint8_t kExpectedPriv[] = { + 0x00, 0x00, 0x00, 0x01, 0x98, 0xaa, 0x32, 0xfc, 0x5f, 0x83, 0x35, 0xea, + 0x57, 0x4f, 0x9e, 0x61, 0x48, 0x6e, 0x89, 0x9d, 0x3d, 0xaa, 0x38, 0x5d, + 0xd0, 0x06, 0x96, 0x62, 0xe8, 0x0b, 0xd6, 0x5f, 0x12, 0xa4, 0xcc, 0xa9, + 0xb5, 0x20, 0x1b, 0x13, 0x8c, 0x1c, 0xaf, 0x36, 0x1b, 0xab, 0x0c, 0xc6, + 0xac, 0x38, 0xae, 0x96, 0x3d, 0x14, 0x9d, 0xb8, 0x8d, 0xf4, 0x7f, 0xe2, + 0x7d, 0xeb, 0x17, 0xc2, 0xbc, 0x63, 0x42, 0x93, 0x94, 0xe4, 0x97, 0xbf, + 0x97, 0xea, 0x02, 0x40, 0xac, 0xb6, 0xa5, 0x03, 0x4c, 0x6b, 0x4c, 0xb8, + 0x8c, 0xf4, 0x66, 0x1b, 0x4e, 0x02, 0x45, 0xf9, 0xcd, 0xb6, 0x0f, 0x59, + 0x09, 0x21, 0x03, 0x7e, 0x92, 0x1f, 0x3f, 0x40, 0x83, 0x50, 0xe3, 0xdc, + 0x9e, 0x6f, 0x65, 0xc5, 0xbd, 0x2c, 0x7d, 0xab, 0x74, 0x49, 0xc8, 0xa2, + 0x3c, 0xab, 0xcb, 0x4d, 0x63, 0x73, 0x81, 0x2b, 0xb2, 0x1e, 0x00, 0x8f, + 0x00, 0xb8, 0xd8, 0xb4, 0x5d, 0xc4, 0x3f, 0x3d, 0xa8, 0x4f, 0x4c, 0x72, + 0x0e, 0x20, 0x17, 0x4b, 0xac, 0x14, 0x8f, 0xb2, 0xa5, 0x20, 0x41, 0x2b, + 0xf7, 0x62, 0x25, 0x6a, 0xd6, 0x41, 0x26, 0x62, 0x10, 0xc1, 0xbc, 0x42, + 0xac, 0x54, 0x1b, 0x75, 0x05, 0xd6, 0x53, 0xb1, 0x7b, 0x84, 0x6a, 0x7b, + 0x5b, 0x2a, 0x34, 0x6e, 0x43, 0x4b, 0x43, 0xcc, 0x6c, 0xdb, 0x1d, 0x02, + 0x34, 0x7f, 0xd1, 0xe8, 0xfd, 0x42, 0x2c, 0xd9, 0x14, 0xdb, 0xd6, 0xf4, + 0xad, 0xb5, 0xe4, 0xac, 0xdd, 0x7e, 0xb5, 0x4c, 0x3f, 0x59, 0x24, 0xfa, + 0x04, 0xd9, 0xb6, 0xd2, 0xb7, 0x7d, 0xf1, 0xfa, 0x13, 0xc0, 0x4d, 0xd5, + 0xca, 0x3a, 0x4e, 0xa8, 0xdd, 0xa9, 0xfc, 0xcb, 0x06, 0xb2, 0xde, 0x4b, + 0x2a, 0x86, 0xbb, 0x0d, 0x41, 0xb6, 0x3d, 0xfb, 0x49, 0xc8, 0xdf, 0x9a, + 0x48, 0xe5, 0x68, 0x8a, 0xfc, 0x86, 0x9c, 0x79, 0x5a, 0x79, 0xc1, 0x09, + 0x33, 0x53, 0xdc, 0x3d, 0xe9, 0x93, 0x7c, 0x5b, 0x72, 0xf7, 0xa0, 0x8a, + 0x1f, 0x07, 0x6c, 0x38, 0x3c, 0x99, 0x0b, 0xe4, 0x4e, 0xa4, 0xbd, 0x41, + 0x1f, 0x83, 0xa6, 0xd3 + }; + ASSERT_EQ(Bytes(kExpectedPriv, sizeof(kExpectedPriv)), + Bytes(priv_key, priv_key_len)); + + const uint8_t kExpectedPub[] = { + 0x00, 0x00, 0x00, 0x01, 0x00, 0x61, 0x04, 0x5e, 0x06, 0x6b, 0x7b, 0xfd, + 0x54, 0x01, 0xe0, 0xd2, 0xb5, 0x12, 0xce, 0x48, 0x16, 0x66, 0xb2, 0xdf, + 0xfd, 0xa8, 0x38, 0x7c, 0x1f, 0x45, 0x1a, 0xb8, 0x21, 0x52, 0x17, 0x25, + 0xbb, 0x0b, 0x00, 0xd4, 0xa1, 0xbc, 0x28, 0xd9, 0x08, 0x36, 0x98, 0xb2, + 0x17, 0xd3, 0xb5, 0xad, 0xb6, 0x4e, 0x03, 0x5f, 0xd3, 0x66, 0x2c, 0x58, + 0x1c, 0xcc, 0xc6, 0x23, 0xa4, 0xf9, 0xa2, 0x7e, 0xb0, 0xe4, 0xd3, 0x95, + 0x41, 0x6f, 0xba, 0x23, 0x4a, 0x82, 0x93, 0x29, 0x73, 0x75, 0x38, 0x85, + 0x64, 0x9c, 0xaa, 0x12, 0x6d, 0x7d, 0xcd, 0x52, 0x02, 0x91, 0x9f, 0xa9, + 0xee, 0x4b, 0xfd, 0x68, 0x97, 0x40, 0xdc, 0x00, 0x61, 0x04, 0x14, 0x16, + 0x39, 0xf9, 0x63, 0x66, 0x94, 0x03, 0xfa, 0x0b, 0xbf, 0xca, 0x5a, 0x39, + 0x9f, 0x27, 0x5b, 0x3f, 0x69, 0x7a, 0xc9, 0xf7, 0x25, 0x7c, 0x84, 0x9e, + 0x1d, 0x61, 0x5a, 0x24, 0x53, 0xf2, 0x4a, 0x9d, 0xe9, 0x05, 0x53, 0xfd, + 0x12, 0x01, 0x2d, 0x9a, 0x69, 0x50, 0x74, 0x82, 0xa3, 0x45, 0x73, 0xdc, + 0x34, 0x36, 0x31, 0x44, 0x07, 0x0c, 0xda, 0x13, 0xbe, 0x94, 0x37, 0x65, + 0xa0, 0xab, 0x16, 0x52, 0x90, 0xe5, 0x8a, 0x03, 0xe5, 0x98, 0x79, 0x14, + 0x79, 0xd5, 0x17, 0xee, 0xd4, 0xb8, 0xda, 0x77, 0x76, 0x03, 0x20, 0x2a, + 0x7e, 0x3b, 0x76, 0x0b, 0x23, 0xb7, 0x72, 0x77, 0xb2, 0xeb, 0x00, 0x61, + 0x04, 0x68, 0x18, 0x4d, 0x23, 0x23, 0xf4, 0x45, 0xb8, 0x81, 0x0d, 0xa4, + 0x5d, 0x0b, 0x9e, 0x08, 0xfb, 0x45, 0xfb, 0x96, 0x29, 0x43, 0x2f, 0xab, + 0x93, 0x04, 0x4c, 0x04, 0xb6, 0x5e, 0x27, 0xf5, 0x39, 0x66, 0x94, 0x15, + 0x1d, 0xb1, 0x1c, 0x7c, 0x27, 0x6f, 0xa5, 0x19, 0x0c, 0x30, 0x12, 0xcc, + 0x77, 0x7f, 0x10, 0xa9, 0x7c, 0xe4, 0x08, 0x77, 0x3c, 0xd3, 0x6f, 0xa4, + 0xf4, 0xaf, 0xf1, 0x9d, 0x14, 0x1d, 0xd0, 0x02, 0x33, 0x50, 0x55, 0x00, + 0x6a, 0x47, 0x96, 0xe1, 0x8b, 0x4e, 0x44, 0x41, 0xad, 0xb3, 0xea, 0x0d, + 0x0d, 0xd5, 0x73, 0x8e, 0x62, 0x67, 0x8a, 0xb4, 0xe7, 0x5d, 0x17, 0xa9, + 0x24}; + ASSERT_EQ(Bytes(kExpectedPub, sizeof(kExpectedPub)), + Bytes(pub_key, pub_key_len)); } TEST(TrustTokenTest, KeyGenExp2VOPRF) { @@ -66,6 +133,37 @@ TEST(TrustTokenTest, KeyGenExp2VOPRF) { TRUST_TOKEN_MAX_PUBLIC_KEY_SIZE, 0x0001)); ASSERT_EQ(52u, priv_key_len); ASSERT_EQ(101u, pub_key_len); + + const uint8_t kKeygenSecret[] = "SEED"; + ASSERT_TRUE(TRUST_TOKEN_derive_key_from_secret( + TRUST_TOKEN_experiment_v2_voprf(), priv_key, &priv_key_len, + TRUST_TOKEN_MAX_PRIVATE_KEY_SIZE, pub_key, &pub_key_len, + TRUST_TOKEN_MAX_PUBLIC_KEY_SIZE, 0x0001, kKeygenSecret, + sizeof(kKeygenSecret) - 1)); + + const uint8_t kExpectedPriv[] = { + 0x00, 0x00, 0x00, 0x01, 0x0b, 0xe2, 0xc4, 0x73, 0x92, 0xe7, 0xf8, + 0x3e, 0xba, 0xab, 0x85, 0xa7, 0x77, 0xd7, 0x0a, 0x02, 0xc5, 0x36, + 0xfe, 0x62, 0xa3, 0xca, 0x01, 0x75, 0xc7, 0x62, 0x19, 0xc7, 0xf0, + 0x30, 0xc5, 0x14, 0x60, 0x13, 0x97, 0x4f, 0x63, 0x05, 0x37, 0x92, + 0x7b, 0x76, 0x8e, 0x9f, 0xd0, 0x1a, 0x74, 0x44 + }; + ASSERT_EQ(Bytes(kExpectedPriv, sizeof(kExpectedPriv)), + Bytes(priv_key, priv_key_len)); + + const uint8_t kExpectedPub[] = { + 0x00, 0x00, 0x00, 0x01, 0x04, 0x2c, 0x9c, 0x11, 0xc1, 0xe5, 0x52, 0x59, + 0x0b, 0x6d, 0x88, 0x8b, 0x6e, 0x28, 0xe8, 0xc5, 0xa3, 0xbe, 0x48, 0x18, + 0xf7, 0x1d, 0x31, 0xcf, 0xa2, 0x6e, 0x2a, 0xd6, 0xcb, 0x83, 0x26, 0x04, + 0xbd, 0x93, 0x67, 0xe4, 0x53, 0xf6, 0x11, 0x7d, 0x45, 0xe9, 0xfe, 0x27, + 0x33, 0x90, 0xdb, 0x1b, 0xfc, 0x9b, 0x31, 0x4d, 0x39, 0x1f, 0x1f, 0x8c, + 0x43, 0x06, 0x70, 0x2c, 0x84, 0xdc, 0x23, 0x18, 0xc7, 0x6a, 0x58, 0xcf, + 0x9e, 0xc1, 0xfa, 0xf2, 0x30, 0xdd, 0xad, 0x62, 0x24, 0xde, 0x11, 0xc1, + 0xba, 0x8d, 0xc3, 0x4f, 0xfb, 0xe5, 0xa5, 0xd4, 0x37, 0xba, 0x3b, 0x70, + 0xc0, 0xc3, 0xef, 0x20, 0x43 + }; + ASSERT_EQ(Bytes(kExpectedPub, sizeof(kExpectedPub)), + Bytes(pub_key, pub_key_len)); } TEST(TrustTokenTest, KeyGenExp2PMB) { @@ -78,6 +176,73 @@ TEST(TrustTokenTest, KeyGenExp2PMB) { TRUST_TOKEN_MAX_PUBLIC_KEY_SIZE, 0x0001)); ASSERT_EQ(292u, priv_key_len); ASSERT_EQ(295u, pub_key_len); + + const uint8_t kKeygenSecret[] = "SEED"; + ASSERT_TRUE(TRUST_TOKEN_derive_key_from_secret( + TRUST_TOKEN_experiment_v2_pmb(), priv_key, &priv_key_len, + TRUST_TOKEN_MAX_PRIVATE_KEY_SIZE, pub_key, &pub_key_len, + TRUST_TOKEN_MAX_PUBLIC_KEY_SIZE, 0x0001, kKeygenSecret, + sizeof(kKeygenSecret) - 1)); + + const uint8_t kExpectedPriv[] = { + 0x00, 0x00, 0x00, 0x01, 0x1b, 0x74, 0xdc, 0xf0, 0xa9, 0xa7, 0x6c, 0xfb, + 0x41, 0xef, 0xfa, 0x65, 0x52, 0xc9, 0x86, 0x4e, 0xfb, 0x16, 0x9d, 0xea, + 0x62, 0x3f, 0x47, 0xab, 0x1f, 0x1b, 0x05, 0xf2, 0x4f, 0x05, 0xfe, 0x64, + 0xb7, 0xe8, 0xcd, 0x2a, 0x10, 0xfa, 0xa2, 0x48, 0x3f, 0x0e, 0x8b, 0x94, + 0x39, 0xf1, 0xe7, 0x53, 0xe9, 0x50, 0x29, 0xe2, 0xb7, 0x0e, 0xc0, 0x94, + 0xa9, 0xd3, 0xef, 0x64, 0x10, 0x1d, 0x08, 0xd0, 0x60, 0xcb, 0x6d, 0x97, + 0x68, 0xc7, 0x04, 0x92, 0x07, 0xb2, 0x22, 0x83, 0xf7, 0xd9, 0x9b, 0x2c, + 0xf2, 0x52, 0x34, 0x0c, 0x42, 0x31, 0x47, 0x41, 0x19, 0xb9, 0xee, 0xfc, + 0x46, 0xbd, 0x14, 0xce, 0x42, 0xd7, 0x43, 0xc8, 0x32, 0x3b, 0x24, 0xed, + 0xdc, 0x69, 0xa3, 0x8e, 0x29, 0x01, 0xbe, 0xae, 0x24, 0x39, 0x14, 0xa7, + 0x52, 0xe5, 0xd5, 0xff, 0x9a, 0xc4, 0x15, 0x79, 0x29, 0x4c, 0x9b, 0x4e, + 0xfc, 0x61, 0xf2, 0x12, 0x6f, 0x4f, 0xd3, 0x96, 0x28, 0xb0, 0x79, 0xf0, + 0x4e, 0x6e, 0x7d, 0x56, 0x19, 0x1b, 0xc2, 0xd7, 0xf9, 0x3a, 0x58, 0x06, + 0xe5, 0xec, 0xa4, 0x33, 0x14, 0x1c, 0x78, 0x0c, 0x83, 0x94, 0x34, 0x22, + 0x5a, 0x8e, 0x2e, 0xa1, 0x72, 0x4a, 0x03, 0x35, 0xfe, 0x46, 0x92, 0x41, + 0x6b, 0xe6, 0x4b, 0x3f, 0xf0, 0xe7, 0x0b, 0xb5, 0xf3, 0x66, 0x6c, 0xc6, + 0x14, 0xcf, 0xce, 0x32, 0x0a, 0x2c, 0x28, 0xba, 0x4e, 0xb9, 0x75, 0x4a, + 0xa9, 0x2d, 0xb0, 0x8c, 0xd0, 0x62, 0x52, 0x29, 0x1f, 0x12, 0xfd, 0xfb, + 0xd3, 0x2a, 0x36, 0x0f, 0x89, 0x32, 0x86, 0x25, 0x56, 0xb9, 0xe7, 0x3c, + 0xeb, 0xb4, 0x84, 0x41, 0x2b, 0xa8, 0xf3, 0xa5, 0x3d, 0xfe, 0x56, 0x94, + 0x5b, 0x74, 0xb3, 0x5b, 0x27, 0x3f, 0xe7, 0xcf, 0xe4, 0xf8, 0x15, 0x95, + 0x2a, 0xd2, 0x5f, 0x92, 0xb4, 0x6a, 0x89, 0xa5, 0x54, 0xbd, 0x27, 0x5e, + 0xeb, 0x43, 0x07, 0x9b, 0x2b, 0x8b, 0x22, 0x59, 0x13, 0x4b, 0x9c, 0x56, + 0xd8, 0x63, 0xd9, 0xe6, 0x85, 0x15, 0x2c, 0x82, 0x52, 0x40, 0x8f, 0xb1, + 0xe7, 0x56, 0x07, 0x98 + }; + ASSERT_EQ(Bytes(kExpectedPriv, sizeof(kExpectedPriv)), + Bytes(priv_key, priv_key_len)); + + const uint8_t kExpectedPub[] = { + 0x00, 0x00, 0x00, 0x01, 0x04, 0x48, 0xb1, 0x2d, 0xdd, 0x03, 0x32, 0xeb, + 0x93, 0x31, 0x3d, 0x59, 0x74, 0xf0, 0xcf, 0xaa, 0xa5, 0x39, 0x5f, 0x53, + 0xc4, 0x94, 0x98, 0xbe, 0x8f, 0x22, 0xd7, 0x30, 0xde, 0x1e, 0xb4, 0xf3, + 0x32, 0x23, 0x90, 0x0b, 0xa6, 0x37, 0x4a, 0x4b, 0x44, 0xb3, 0x26, 0x52, + 0x93, 0x7b, 0x4b, 0xa4, 0x79, 0xe8, 0x77, 0x6a, 0x19, 0x81, 0x2a, 0xdd, + 0x91, 0xfb, 0x90, 0x8b, 0x24, 0xb5, 0xbe, 0x20, 0x2e, 0xe8, 0xbc, 0xd3, + 0x83, 0x6c, 0xa8, 0xc5, 0xa1, 0x9a, 0x5b, 0x5e, 0x60, 0xda, 0x45, 0x2e, + 0x31, 0x7f, 0x54, 0x0e, 0x14, 0x40, 0xd2, 0x4d, 0x40, 0x2e, 0x21, 0x79, + 0xfc, 0x77, 0xdd, 0xc7, 0x2d, 0x04, 0xfe, 0xc6, 0xe3, 0xcf, 0x99, 0xef, + 0x88, 0xab, 0x76, 0x86, 0x16, 0x14, 0xed, 0x72, 0x35, 0xa7, 0x05, 0x13, + 0x9f, 0x2c, 0x53, 0xd5, 0xdf, 0x66, 0x75, 0x2e, 0x68, 0xdc, 0xd4, 0xc4, + 0x00, 0x36, 0x08, 0x6d, 0xb7, 0x15, 0xf7, 0xe5, 0x32, 0x59, 0x81, 0x16, + 0x57, 0xaa, 0x72, 0x06, 0xf0, 0xad, 0xd1, 0x85, 0xa0, 0x04, 0xd4, 0x11, + 0x95, 0x1d, 0xac, 0x0b, 0x25, 0xbe, 0x59, 0xa2, 0xb3, 0x30, 0xee, 0x97, + 0x07, 0x2a, 0x51, 0x15, 0xc1, 0x8d, 0xa8, 0xa6, 0x57, 0x9a, 0x4e, 0xbf, + 0xd7, 0x2d, 0x35, 0x07, 0x6b, 0xd6, 0xc9, 0x3c, 0xe4, 0xcf, 0x0b, 0x14, + 0x3e, 0x10, 0x51, 0x77, 0xd6, 0x84, 0x04, 0xbe, 0xd1, 0xd5, 0xa8, 0xf3, + 0x9d, 0x1d, 0x4f, 0xc1, 0xc9, 0xf1, 0x0c, 0x6d, 0xb6, 0xcb, 0xe2, 0x05, + 0x0b, 0x9c, 0x7a, 0x3a, 0x9a, 0x99, 0xe9, 0xa1, 0x93, 0xdc, 0x72, 0x2e, + 0xef, 0xf3, 0x8d, 0xb9, 0x7b, 0xb0, 0x19, 0x24, 0x95, 0x0d, 0x68, 0xa7, + 0xe0, 0xaa, 0x0b, 0xb1, 0xd1, 0xcc, 0x52, 0x14, 0xf9, 0x6c, 0x91, 0x59, + 0xe4, 0xe1, 0x9b, 0xf9, 0x12, 0x39, 0xb1, 0x79, 0xbb, 0x21, 0x92, 0x00, + 0xa4, 0x89, 0xf5, 0xbd, 0xd7, 0x89, 0x27, 0x40, 0xdc, 0xb1, 0x09, 0x38, + 0x63, 0x91, 0x8c, 0xa5, 0x27, 0x27, 0x97, 0x39, 0x35, 0xfa, 0x1a, 0x8a, + 0xa7, 0xe5, 0xc4, 0xd8, 0xbf, 0xe7, 0xbe + }; + ASSERT_EQ(Bytes(kExpectedPub, sizeof(kExpectedPub)), + Bytes(pub_key, pub_key_len)); } // Test that H in |TRUST_TOKEN_experiment_v1| was computed correctly. diff --git a/crypto/trust_token/voprf.c b/crypto/trust_token/voprf.c index f93ee9cd1e..cedee1e803 100644 --- a/crypto/trust_token/voprf.c +++ b/crypto/trust_token/voprf.c @@ -110,20 +110,18 @@ static int scalar_from_cbs(CBS *cbs, const EC_GROUP *group, EC_SCALAR *out) { return 1; } -static int voprf_generate_key(const VOPRF_METHOD *method, CBB *out_private, - CBB *out_public) { +static int voprf_calculate_key(const VOPRF_METHOD *method, CBB *out_private, + CBB *out_public, const EC_SCALAR *priv) { const EC_GROUP *group = method->group; EC_RAW_POINT pub; - EC_SCALAR priv; EC_AFFINE pub_affine; - if (!ec_random_nonzero_scalar(group, &priv, kDefaultAdditionalData) || - !ec_point_mul_scalar_base(group, &pub, &priv) || + if (!ec_point_mul_scalar_base(group, &pub, priv) || !ec_jacobian_to_affine(group, &pub_affine, &pub)) { OPENSSL_PUT_ERROR(TRUST_TOKEN, TRUST_TOKEN_R_KEYGEN_FAILURE); return 0; } - if (!scalar_to_cbb(out_private, group, &priv) || + if (!scalar_to_cbb(out_private, group, priv) || !cbb_add_point(out_public, group, &pub_affine)) { OPENSSL_PUT_ERROR(TRUST_TOKEN, TRUST_TOKEN_R_BUFFER_TOO_SMALL); return 0; @@ -132,6 +130,46 @@ static int voprf_generate_key(const VOPRF_METHOD *method, CBB *out_private, return 1; } + +static int voprf_generate_key(const VOPRF_METHOD *method, CBB *out_private, + CBB *out_public) { + EC_SCALAR priv; + if (!ec_random_nonzero_scalar(method->group, &priv, kDefaultAdditionalData)) { + OPENSSL_PUT_ERROR(TRUST_TOKEN, TRUST_TOKEN_R_KEYGEN_FAILURE); + return 0; + } + return voprf_calculate_key(method, out_private, out_public, &priv); +} + +static int voprf_derive_key_from_secret(const VOPRF_METHOD *method, + CBB *out_private, CBB *out_public, + const uint8_t *secret, + size_t secret_len) { + static const uint8_t kKeygenLabel[] = "TrustTokenVOPRFKeyGen"; + + EC_SCALAR priv; + int ok = 0; + CBB cbb; + CBB_zero(&cbb); + uint8_t *buf = NULL; + size_t len; + if (!CBB_init(&cbb, 0) || + !CBB_add_bytes(&cbb, kKeygenLabel, sizeof(kKeygenLabel)) || + !CBB_add_bytes(&cbb, secret, secret_len) || + !CBB_finish(&cbb, &buf, &len) || + !method->hash_to_scalar(method->group, &priv, buf, len)) { + OPENSSL_PUT_ERROR(TRUST_TOKEN, TRUST_TOKEN_R_KEYGEN_FAILURE); + goto err; + } + + ok = voprf_calculate_key(method, out_private, out_public, &priv); + +err: + CBB_cleanup(&cbb); + OPENSSL_free(buf); + return ok; +} + static int voprf_client_key_from_bytes(const VOPRF_METHOD *method, TRUST_TOKEN_CLIENT_KEY *key, const uint8_t *in, size_t len) { @@ -711,6 +749,17 @@ int voprf_exp2_generate_key(CBB *out_private, CBB *out_public) { return voprf_generate_key(&voprf_exp2_method, out_private, out_public); } +int voprf_exp2_derive_key_from_secret(CBB *out_private, CBB *out_public, + const uint8_t *secret, + size_t secret_len) { + if (!voprf_exp2_init_method()) { + return 0; + } + + return voprf_derive_key_from_secret(&voprf_exp2_method, out_private, + out_public, secret, secret_len); +} + int voprf_exp2_client_key_from_bytes(TRUST_TOKEN_CLIENT_KEY *key, const uint8_t *in, size_t len) { if (!voprf_exp2_init_method()) { diff --git a/crypto/x509/a_digest.c b/crypto/x509/a_digest.c index b88d6ac79c..adc6313c46 100644 --- a/crypto/x509/a_digest.c +++ b/crypto/x509/a_digest.c @@ -62,35 +62,34 @@ #include int ASN1_digest(i2d_of_void *i2d, const EVP_MD *type, char *data, - unsigned char *md, unsigned int *len) -{ - int i, ret; - unsigned char *str, *p; + unsigned char *md, unsigned int *len) { + int i, ret; + unsigned char *str, *p; - i = i2d(data, NULL); - if ((str = (unsigned char *)OPENSSL_malloc(i)) == NULL) { - OPENSSL_PUT_ERROR(X509, ERR_R_MALLOC_FAILURE); - return (0); - } - p = str; - i2d(data, &p); + i = i2d(data, NULL); + if ((str = (unsigned char *)OPENSSL_malloc(i)) == NULL) { + OPENSSL_PUT_ERROR(X509, ERR_R_MALLOC_FAILURE); + return (0); + } + p = str; + i2d(data, &p); - ret = EVP_Digest(str, i, md, len, type, NULL); - OPENSSL_free(str); - return ret; + ret = EVP_Digest(str, i, md, len, type, NULL); + OPENSSL_free(str); + return ret; } int ASN1_item_digest(const ASN1_ITEM *it, const EVP_MD *type, void *asn, - unsigned char *md, unsigned int *len) -{ - int i, ret; - unsigned char *str = NULL; + unsigned char *md, unsigned int *len) { + int i, ret; + unsigned char *str = NULL; - i = ASN1_item_i2d(asn, &str, it); - if (!str) - return (0); + i = ASN1_item_i2d(asn, &str, it); + if (!str) { + return (0); + } - ret = EVP_Digest(str, i, md, len, type, NULL); - OPENSSL_free(str); - return ret; + ret = EVP_Digest(str, i, md, len, type, NULL); + OPENSSL_free(str); + return ret; } diff --git a/crypto/x509/a_sign.c b/crypto/x509/a_sign.c index 6c7f7136da..815d1439a6 100644 --- a/crypto/x509/a_sign.c +++ b/crypto/x509/a_sign.c @@ -64,65 +64,64 @@ #include "internal.h" -int ASN1_item_sign(const ASN1_ITEM *it, X509_ALGOR *algor1, - X509_ALGOR *algor2, ASN1_BIT_STRING *signature, void *asn, - EVP_PKEY *pkey, const EVP_MD *type) -{ - EVP_MD_CTX ctx; - EVP_MD_CTX_init(&ctx); - if (!EVP_DigestSignInit(&ctx, NULL, type, NULL, pkey)) { - EVP_MD_CTX_cleanup(&ctx); - return 0; - } - return ASN1_item_sign_ctx(it, algor1, algor2, signature, asn, &ctx); +int ASN1_item_sign(const ASN1_ITEM *it, X509_ALGOR *algor1, X509_ALGOR *algor2, + ASN1_BIT_STRING *signature, void *asn, EVP_PKEY *pkey, + const EVP_MD *type) { + EVP_MD_CTX ctx; + EVP_MD_CTX_init(&ctx); + if (!EVP_DigestSignInit(&ctx, NULL, type, NULL, pkey)) { + EVP_MD_CTX_cleanup(&ctx); + return 0; + } + return ASN1_item_sign_ctx(it, algor1, algor2, signature, asn, &ctx); } -int ASN1_item_sign_ctx(const ASN1_ITEM *it, - X509_ALGOR *algor1, X509_ALGOR *algor2, - ASN1_BIT_STRING *signature, void *asn, EVP_MD_CTX *ctx) -{ - EVP_PKEY *pkey; - unsigned char *buf_in = NULL, *buf_out = NULL; - size_t inl = 0, outl = 0; +int ASN1_item_sign_ctx(const ASN1_ITEM *it, X509_ALGOR *algor1, + X509_ALGOR *algor2, ASN1_BIT_STRING *signature, + void *asn, EVP_MD_CTX *ctx) { + EVP_PKEY *pkey; + unsigned char *buf_in = NULL, *buf_out = NULL; + size_t inl = 0, outl = 0; - pkey = EVP_PKEY_CTX_get0_pkey(ctx->pctx); + pkey = EVP_PKEY_CTX_get0_pkey(ctx->pctx); - /* Write out the requested copies of the AlgorithmIdentifier. */ - if (algor1 && !x509_digest_sign_algorithm(ctx, algor1)) { - goto err; - } - if (algor2 && !x509_digest_sign_algorithm(ctx, algor2)) { - goto err; - } + /* Write out the requested copies of the AlgorithmIdentifier. */ + if (algor1 && !x509_digest_sign_algorithm(ctx, algor1)) { + goto err; + } + if (algor2 && !x509_digest_sign_algorithm(ctx, algor2)) { + goto err; + } - inl = ASN1_item_i2d(asn, &buf_in, it); - outl = EVP_PKEY_size(pkey); - buf_out = OPENSSL_malloc((unsigned int)outl); - if ((buf_in == NULL) || (buf_out == NULL)) { - outl = 0; - OPENSSL_PUT_ERROR(X509, ERR_R_MALLOC_FAILURE); - goto err; - } + inl = ASN1_item_i2d(asn, &buf_in, it); + outl = EVP_PKEY_size(pkey); + buf_out = OPENSSL_malloc((unsigned int)outl); + if ((buf_in == NULL) || (buf_out == NULL)) { + outl = 0; + OPENSSL_PUT_ERROR(X509, ERR_R_MALLOC_FAILURE); + goto err; + } - if (!EVP_DigestSign(ctx, buf_out, &outl, buf_in, inl)) { - outl = 0; - OPENSSL_PUT_ERROR(X509, ERR_R_EVP_LIB); - goto err; - } - if (signature->data != NULL) - OPENSSL_free(signature->data); - signature->data = buf_out; - buf_out = NULL; - signature->length = outl; - /* - * In the interests of compatibility, I'll make sure that the bit string - * has a 'not-used bits' value of 0 - */ - signature->flags &= ~(ASN1_STRING_FLAG_BITS_LEFT | 0x07); - signature->flags |= ASN1_STRING_FLAG_BITS_LEFT; - err: - EVP_MD_CTX_cleanup(ctx); - OPENSSL_free(buf_in); - OPENSSL_free(buf_out); - return (outl); + if (!EVP_DigestSign(ctx, buf_out, &outl, buf_in, inl)) { + outl = 0; + OPENSSL_PUT_ERROR(X509, ERR_R_EVP_LIB); + goto err; + } + if (signature->data != NULL) { + OPENSSL_free(signature->data); + } + signature->data = buf_out; + buf_out = NULL; + signature->length = outl; + /* + * In the interests of compatibility, I'll make sure that the bit string + * has a 'not-used bits' value of 0 + */ + signature->flags &= ~(ASN1_STRING_FLAG_BITS_LEFT | 0x07); + signature->flags |= ASN1_STRING_FLAG_BITS_LEFT; +err: + EVP_MD_CTX_cleanup(ctx); + OPENSSL_free(buf_in); + OPENSSL_free(buf_out); + return (outl); } diff --git a/crypto/x509/a_verify.c b/crypto/x509/a_verify.c index ec671c0351..d9bb235497 100644 --- a/crypto/x509/a_verify.c +++ b/crypto/x509/a_verify.c @@ -57,8 +57,8 @@ #include #include -#include #include +#include #include #include @@ -72,47 +72,47 @@ int ASN1_item_verify(const ASN1_ITEM *it, const X509_ALGOR *a, const ASN1_BIT_STRING *signature, void *asn, EVP_PKEY *pkey) { - if (!pkey) { - OPENSSL_PUT_ERROR(X509, ERR_R_PASSED_NULL_PARAMETER); - return 0; - } + if (!pkey) { + OPENSSL_PUT_ERROR(X509, ERR_R_PASSED_NULL_PARAMETER); + return 0; + } - size_t sig_len; - if (signature->type == V_ASN1_BIT_STRING) { - if (!ASN1_BIT_STRING_num_bytes(signature, &sig_len)) { - OPENSSL_PUT_ERROR(X509, X509_R_INVALID_BIT_STRING_BITS_LEFT); - return 0; - } - } else { - sig_len = (size_t)ASN1_STRING_length(signature); + size_t sig_len; + if (signature->type == V_ASN1_BIT_STRING) { + if (!ASN1_BIT_STRING_num_bytes(signature, &sig_len)) { + OPENSSL_PUT_ERROR(X509, X509_R_INVALID_BIT_STRING_BITS_LEFT); + return 0; } + } else { + sig_len = (size_t)ASN1_STRING_length(signature); + } - EVP_MD_CTX ctx; - uint8_t *buf_in = NULL; - int ret = 0, inl = 0; - EVP_MD_CTX_init(&ctx); + EVP_MD_CTX ctx; + uint8_t *buf_in = NULL; + int ret = 0, inl = 0; + EVP_MD_CTX_init(&ctx); - if (!x509_digest_verify_init(&ctx, a, pkey)) { - goto err; - } + if (!x509_digest_verify_init(&ctx, a, pkey)) { + goto err; + } - inl = ASN1_item_i2d(asn, &buf_in, it); + inl = ASN1_item_i2d(asn, &buf_in, it); - if (buf_in == NULL) { - OPENSSL_PUT_ERROR(X509, ERR_R_MALLOC_FAILURE); - goto err; - } + if (buf_in == NULL) { + OPENSSL_PUT_ERROR(X509, ERR_R_MALLOC_FAILURE); + goto err; + } - if (!EVP_DigestVerify(&ctx, ASN1_STRING_get0_data(signature), sig_len, - buf_in, inl)) { - OPENSSL_PUT_ERROR(X509, ERR_R_EVP_LIB); - goto err; - } + if (!EVP_DigestVerify(&ctx, ASN1_STRING_get0_data(signature), sig_len, buf_in, + inl)) { + OPENSSL_PUT_ERROR(X509, ERR_R_EVP_LIB); + goto err; + } - ret = 1; + ret = 1; err: - OPENSSL_free(buf_in); - EVP_MD_CTX_cleanup(&ctx); - return ret; + OPENSSL_free(buf_in); + EVP_MD_CTX_cleanup(&ctx); + return ret; } diff --git a/crypto/x509/algorithm.c b/crypto/x509/algorithm.c index 13f46b2800..e3adfb555e 100644 --- a/crypto/x509/algorithm.c +++ b/crypto/x509/algorithm.c @@ -107,8 +107,7 @@ int x509_digest_sign_algorithm(EVP_MD_CTX *ctx, X509_ALGOR *algor) { const int digest_nid = EVP_MD_type(digest); int sign_nid; if (!x509_digest_nid_ok(digest_nid) || - !OBJ_find_sigid_by_algs(&sign_nid, digest_nid, - EVP_PKEY_id(pkey))) { + !OBJ_find_sigid_by_algs(&sign_nid, digest_nid, EVP_PKEY_id(pkey))) { OPENSSL_PUT_ERROR(ASN1, ASN1_R_DIGEST_AND_KEY_TYPE_NOT_SUPPORTED); return 0; } diff --git a/crypto/x509/asn1_gen.c b/crypto/x509/asn1_gen.c index cd8185bfed..e56da9af6a 100644 --- a/crypto/x509/asn1_gen.c +++ b/crypto/x509/asn1_gen.c @@ -73,55 +73,56 @@ * errors from the ASN.1 module for OpenSSL compatibility. */ -#define ASN1_GEN_FLAG 0x10000 -#define ASN1_GEN_FLAG_IMP (ASN1_GEN_FLAG|1) -#define ASN1_GEN_FLAG_EXP (ASN1_GEN_FLAG|2) -#define ASN1_GEN_FLAG_TAG (ASN1_GEN_FLAG|3) -#define ASN1_GEN_FLAG_BITWRAP (ASN1_GEN_FLAG|4) -#define ASN1_GEN_FLAG_OCTWRAP (ASN1_GEN_FLAG|5) -#define ASN1_GEN_FLAG_SEQWRAP (ASN1_GEN_FLAG|6) -#define ASN1_GEN_FLAG_SETWRAP (ASN1_GEN_FLAG|7) -#define ASN1_GEN_FLAG_FORMAT (ASN1_GEN_FLAG|8) - -#define ASN1_GEN_STR(str,val) {str, sizeof(str) - 1, val} - -#define ASN1_FLAG_EXP_MAX 20 +#define ASN1_GEN_FLAG 0x10000 +#define ASN1_GEN_FLAG_IMP (ASN1_GEN_FLAG | 1) +#define ASN1_GEN_FLAG_EXP (ASN1_GEN_FLAG | 2) +#define ASN1_GEN_FLAG_TAG (ASN1_GEN_FLAG | 3) +#define ASN1_GEN_FLAG_BITWRAP (ASN1_GEN_FLAG | 4) +#define ASN1_GEN_FLAG_OCTWRAP (ASN1_GEN_FLAG | 5) +#define ASN1_GEN_FLAG_SEQWRAP (ASN1_GEN_FLAG | 6) +#define ASN1_GEN_FLAG_SETWRAP (ASN1_GEN_FLAG | 7) +#define ASN1_GEN_FLAG_FORMAT (ASN1_GEN_FLAG | 8) + +#define ASN1_GEN_STR(str, val) \ + { str, sizeof(str) - 1, val } + +#define ASN1_FLAG_EXP_MAX 20 /* Maximum number of nested sequences */ -#define ASN1_GEN_SEQ_MAX_DEPTH 50 +#define ASN1_GEN_SEQ_MAX_DEPTH 50 /* Input formats */ /* ASCII: default */ -#define ASN1_GEN_FORMAT_ASCII 1 +#define ASN1_GEN_FORMAT_ASCII 1 /* UTF8 */ -#define ASN1_GEN_FORMAT_UTF8 2 +#define ASN1_GEN_FORMAT_UTF8 2 /* Hex */ -#define ASN1_GEN_FORMAT_HEX 3 +#define ASN1_GEN_FORMAT_HEX 3 /* List of bits */ #define ASN1_GEN_FORMAT_BITLIST 4 struct tag_name_st { - const char *strnam; - int len; - int tag; + const char *strnam; + int len; + int tag; }; typedef struct { - int exp_tag; - int exp_class; - int exp_constructed; - int exp_pad; - long exp_len; + int exp_tag; + int exp_class; + int exp_constructed; + int exp_pad; + long exp_len; } tag_exp_type; typedef struct { - int imp_tag; - int imp_class; - int utype; - int format; - const char *str; - tag_exp_type exp_list[ASN1_FLAG_EXP_MAX]; - int exp_count; + int imp_tag; + int imp_class; + int utype; + int format; + const char *str; + tag_exp_type exp_list[ASN1_FLAG_EXP_MAX]; + int exp_count; } tag_exp_arg; static ASN1_TYPE *generate_v3(const char *str, X509V3_CTX *cnf, int depth, @@ -130,591 +131,609 @@ static int bitstr_cb(const char *elem, int len, void *bitstr); static int asn1_cb(const char *elem, int len, void *bitstr); static int append_exp(tag_exp_arg *arg, int exp_tag, int exp_class, int exp_constructed, int exp_pad, int imp_ok); -static int parse_tagging(const char *vstart, int vlen, int *ptag, - int *pclass); +static int parse_tagging(const char *vstart, int vlen, int *ptag, int *pclass); static ASN1_TYPE *asn1_multi(int utype, const char *section, X509V3_CTX *cnf, int depth, int *perr); static ASN1_TYPE *asn1_str2type(const char *str, int format, int utype); static int asn1_str2tag(const char *tagstr, int len); -ASN1_TYPE *ASN1_generate_v3(const char *str, X509V3_CTX *cnf) -{ - int err = 0; - ASN1_TYPE *ret = generate_v3(str, cnf, 0, &err); - if (err) - OPENSSL_PUT_ERROR(ASN1, err); - return ret; +ASN1_TYPE *ASN1_generate_v3(const char *str, X509V3_CTX *cnf) { + int err = 0; + ASN1_TYPE *ret = generate_v3(str, cnf, 0, &err); + if (err) { + OPENSSL_PUT_ERROR(ASN1, err); + } + return ret; } static ASN1_TYPE *generate_v3(const char *str, X509V3_CTX *cnf, int depth, - int *perr) -{ - ASN1_TYPE *ret; - tag_exp_arg asn1_tags; - tag_exp_type *etmp; - - int i, len; - - unsigned char *orig_der = NULL, *new_der = NULL; - const unsigned char *cpy_start; - unsigned char *p; - const unsigned char *cp; - int cpy_len; - long hdr_len = 0; - int hdr_constructed = 0, hdr_tag, hdr_class; - int r; - - asn1_tags.imp_tag = -1; - asn1_tags.imp_class = -1; - asn1_tags.format = ASN1_GEN_FORMAT_ASCII; - asn1_tags.exp_count = 0; - if (CONF_parse_list(str, ',', 1, asn1_cb, &asn1_tags) != 0) { - *perr = ASN1_R_UNKNOWN_TAG; - return NULL; + int *perr) { + ASN1_TYPE *ret; + tag_exp_arg asn1_tags; + tag_exp_type *etmp; + + int i, len; + + unsigned char *orig_der = NULL, *new_der = NULL; + const unsigned char *cpy_start; + unsigned char *p; + const unsigned char *cp; + int cpy_len; + long hdr_len = 0; + int hdr_constructed = 0, hdr_tag, hdr_class; + int r; + + asn1_tags.imp_tag = -1; + asn1_tags.imp_class = -1; + asn1_tags.format = ASN1_GEN_FORMAT_ASCII; + asn1_tags.exp_count = 0; + if (CONF_parse_list(str, ',', 1, asn1_cb, &asn1_tags) != 0) { + *perr = ASN1_R_UNKNOWN_TAG; + return NULL; + } + + if ((asn1_tags.utype == V_ASN1_SEQUENCE) || (asn1_tags.utype == V_ASN1_SET)) { + if (!cnf) { + *perr = ASN1_R_SEQUENCE_OR_SET_NEEDS_CONFIG; + return NULL; } + if (depth >= ASN1_GEN_SEQ_MAX_DEPTH) { + *perr = ASN1_R_ILLEGAL_NESTED_TAGGING; + return NULL; + } + ret = asn1_multi(asn1_tags.utype, asn1_tags.str, cnf, depth, perr); + } else { + ret = asn1_str2type(asn1_tags.str, asn1_tags.format, asn1_tags.utype); + } - if ((asn1_tags.utype == V_ASN1_SEQUENCE) - || (asn1_tags.utype == V_ASN1_SET)) { - if (!cnf) { - *perr = ASN1_R_SEQUENCE_OR_SET_NEEDS_CONFIG; - return NULL; - } - if (depth >= ASN1_GEN_SEQ_MAX_DEPTH) { - *perr = ASN1_R_ILLEGAL_NESTED_TAGGING; - return NULL; - } - ret = asn1_multi(asn1_tags.utype, asn1_tags.str, cnf, depth, perr); - } else - ret = asn1_str2type(asn1_tags.str, asn1_tags.format, asn1_tags.utype); - - if (!ret) - return NULL; - - /* If no tagging return base type */ - if ((asn1_tags.imp_tag == -1) && (asn1_tags.exp_count == 0)) - return ret; - - /* Generate the encoding */ - cpy_len = i2d_ASN1_TYPE(ret, &orig_der); - ASN1_TYPE_free(ret); - ret = NULL; - /* Set point to start copying for modified encoding */ - cpy_start = orig_der; - - /* Do we need IMPLICIT tagging? */ - if (asn1_tags.imp_tag != -1) { - /* If IMPLICIT we will replace the underlying tag */ - /* Skip existing tag+len */ - r = ASN1_get_object(&cpy_start, &hdr_len, &hdr_tag, &hdr_class, - cpy_len); - if (r & 0x80) - goto err; - /* Update copy length */ - cpy_len -= cpy_start - orig_der; - /* - * For IMPLICIT tagging the length should match the original length - * and constructed flag should be consistent. - */ - hdr_constructed = r & V_ASN1_CONSTRUCTED; - /* - * Work out new length with IMPLICIT tag: ignore constructed because - * it will mess up if indefinite length - */ - len = ASN1_object_size(0, hdr_len, asn1_tags.imp_tag); - } else - len = cpy_len; - - /* Work out length in any EXPLICIT, starting from end */ - - for (i = 0, etmp = asn1_tags.exp_list + asn1_tags.exp_count - 1; - i < asn1_tags.exp_count; i++, etmp--) { - /* Content length: number of content octets + any padding */ - len += etmp->exp_pad; - etmp->exp_len = len; - /* Total object length: length including new header */ - len = ASN1_object_size(0, len, etmp->exp_tag); + if (!ret) { + return NULL; + } + + /* If no tagging return base type */ + if ((asn1_tags.imp_tag == -1) && (asn1_tags.exp_count == 0)) { + return ret; + } + + /* Generate the encoding */ + cpy_len = i2d_ASN1_TYPE(ret, &orig_der); + ASN1_TYPE_free(ret); + ret = NULL; + /* Set point to start copying for modified encoding */ + cpy_start = orig_der; + + /* Do we need IMPLICIT tagging? */ + if (asn1_tags.imp_tag != -1) { + /* If IMPLICIT we will replace the underlying tag */ + /* Skip existing tag+len */ + r = ASN1_get_object(&cpy_start, &hdr_len, &hdr_tag, &hdr_class, cpy_len); + if (r & 0x80) { + goto err; } + /* Update copy length */ + cpy_len -= cpy_start - orig_der; + /* + * For IMPLICIT tagging the length should match the original length + * and constructed flag should be consistent. + */ + hdr_constructed = r & V_ASN1_CONSTRUCTED; + /* + * Work out new length with IMPLICIT tag: ignore constructed because + * it will mess up if indefinite length + */ + len = ASN1_object_size(0, hdr_len, asn1_tags.imp_tag); + } else { + len = cpy_len; + } - /* Allocate buffer for new encoding */ + /* Work out length in any EXPLICIT, starting from end */ - new_der = OPENSSL_malloc(len); - if (!new_der) - goto err; + for (i = 0, etmp = asn1_tags.exp_list + asn1_tags.exp_count - 1; + i < asn1_tags.exp_count; i++, etmp--) { + /* Content length: number of content octets + any padding */ + len += etmp->exp_pad; + etmp->exp_len = len; + /* Total object length: length including new header */ + len = ASN1_object_size(0, len, etmp->exp_tag); + } - /* Generate tagged encoding */ + /* Allocate buffer for new encoding */ - p = new_der; + new_der = OPENSSL_malloc(len); + if (!new_der) { + goto err; + } - /* Output explicit tags first */ + /* Generate tagged encoding */ - for (i = 0, etmp = asn1_tags.exp_list; i < asn1_tags.exp_count; - i++, etmp++) { - ASN1_put_object(&p, etmp->exp_constructed, etmp->exp_len, - etmp->exp_tag, etmp->exp_class); - if (etmp->exp_pad) - *p++ = 0; - } + p = new_der; - /* If IMPLICIT, output tag */ + /* Output explicit tags first */ - if (asn1_tags.imp_tag != -1) { - if (asn1_tags.imp_class == V_ASN1_UNIVERSAL - && (asn1_tags.imp_tag == V_ASN1_SEQUENCE - || asn1_tags.imp_tag == V_ASN1_SET)) - hdr_constructed = V_ASN1_CONSTRUCTED; - ASN1_put_object(&p, hdr_constructed, hdr_len, - asn1_tags.imp_tag, asn1_tags.imp_class); + for (i = 0, etmp = asn1_tags.exp_list; i < asn1_tags.exp_count; i++, etmp++) { + ASN1_put_object(&p, etmp->exp_constructed, etmp->exp_len, etmp->exp_tag, + etmp->exp_class); + if (etmp->exp_pad) { + *p++ = 0; } + } - /* Copy across original encoding */ - OPENSSL_memcpy(p, cpy_start, cpy_len); + /* If IMPLICIT, output tag */ - cp = new_der; + if (asn1_tags.imp_tag != -1) { + if (asn1_tags.imp_class == V_ASN1_UNIVERSAL && + (asn1_tags.imp_tag == V_ASN1_SEQUENCE || + asn1_tags.imp_tag == V_ASN1_SET)) { + hdr_constructed = V_ASN1_CONSTRUCTED; + } + ASN1_put_object(&p, hdr_constructed, hdr_len, asn1_tags.imp_tag, + asn1_tags.imp_class); + } - /* Obtain new ASN1_TYPE structure */ - ret = d2i_ASN1_TYPE(NULL, &cp, len); + /* Copy across original encoding */ + OPENSSL_memcpy(p, cpy_start, cpy_len); - err: - if (orig_der) - OPENSSL_free(orig_der); - if (new_der) - OPENSSL_free(new_der); + cp = new_der; - return ret; + /* Obtain new ASN1_TYPE structure */ + ret = d2i_ASN1_TYPE(NULL, &cp, len); +err: + if (orig_der) { + OPENSSL_free(orig_der); + } + if (new_der) { + OPENSSL_free(new_der); + } + + return ret; } -static int asn1_cb(const char *elem, int len, void *bitstr) -{ - tag_exp_arg *arg = bitstr; - int i; - int utype; - int vlen = 0; - const char *p, *vstart = NULL; +static int asn1_cb(const char *elem, int len, void *bitstr) { + tag_exp_arg *arg = bitstr; + int i; + int utype; + int vlen = 0; + const char *p, *vstart = NULL; - int tmp_tag, tmp_class; + int tmp_tag, tmp_class; - if (elem == NULL) - return -1; - - for (i = 0, p = elem; i < len; p++, i++) { - /* Look for the ':' in name value pairs */ - if (*p == ':') { - vstart = p + 1; - vlen = len - (vstart - elem); - len = p - elem; - break; - } + if (elem == NULL) { + return -1; + } + + for (i = 0, p = elem; i < len; p++, i++) { + /* Look for the ':' in name value pairs */ + if (*p == ':') { + vstart = p + 1; + vlen = len - (vstart - elem); + len = p - elem; + break; } + } - utype = asn1_str2tag(elem, len); + utype = asn1_str2tag(elem, len); - if (utype == -1) { - OPENSSL_PUT_ERROR(ASN1, ASN1_R_UNKNOWN_TAG); - ERR_add_error_data(2, "tag=", elem); - return -1; - } - - /* If this is not a modifier mark end of string and exit */ - if (!(utype & ASN1_GEN_FLAG)) { - arg->utype = utype; - arg->str = vstart; - /* If no value and not end of string, error */ - if (!vstart && elem[len]) { - OPENSSL_PUT_ERROR(ASN1, ASN1_R_MISSING_VALUE); - return -1; - } - return 0; + if (utype == -1) { + OPENSSL_PUT_ERROR(ASN1, ASN1_R_UNKNOWN_TAG); + ERR_add_error_data(2, "tag=", elem); + return -1; + } + + /* If this is not a modifier mark end of string and exit */ + if (!(utype & ASN1_GEN_FLAG)) { + arg->utype = utype; + arg->str = vstart; + /* If no value and not end of string, error */ + if (!vstart && elem[len]) { + OPENSSL_PUT_ERROR(ASN1, ASN1_R_MISSING_VALUE); + return -1; } + return 0; + } - switch (utype) { - + switch (utype) { case ASN1_GEN_FLAG_IMP: - /* Check for illegal multiple IMPLICIT tagging */ - if (arg->imp_tag != -1) { - OPENSSL_PUT_ERROR(ASN1, ASN1_R_ILLEGAL_NESTED_TAGGING); - return -1; - } - if (!parse_tagging(vstart, vlen, &arg->imp_tag, &arg->imp_class)) - return -1; - break; + /* Check for illegal multiple IMPLICIT tagging */ + if (arg->imp_tag != -1) { + OPENSSL_PUT_ERROR(ASN1, ASN1_R_ILLEGAL_NESTED_TAGGING); + return -1; + } + if (!parse_tagging(vstart, vlen, &arg->imp_tag, &arg->imp_class)) { + return -1; + } + break; case ASN1_GEN_FLAG_EXP: - if (!parse_tagging(vstart, vlen, &tmp_tag, &tmp_class)) - return -1; - if (!append_exp(arg, tmp_tag, tmp_class, 1, 0, 0)) - return -1; - break; + if (!parse_tagging(vstart, vlen, &tmp_tag, &tmp_class)) { + return -1; + } + if (!append_exp(arg, tmp_tag, tmp_class, 1, 0, 0)) { + return -1; + } + break; case ASN1_GEN_FLAG_SEQWRAP: - if (!append_exp(arg, V_ASN1_SEQUENCE, V_ASN1_UNIVERSAL, 1, 0, 1)) - return -1; - break; + if (!append_exp(arg, V_ASN1_SEQUENCE, V_ASN1_UNIVERSAL, 1, 0, 1)) { + return -1; + } + break; case ASN1_GEN_FLAG_SETWRAP: - if (!append_exp(arg, V_ASN1_SET, V_ASN1_UNIVERSAL, 1, 0, 1)) - return -1; - break; + if (!append_exp(arg, V_ASN1_SET, V_ASN1_UNIVERSAL, 1, 0, 1)) { + return -1; + } + break; case ASN1_GEN_FLAG_BITWRAP: - if (!append_exp(arg, V_ASN1_BIT_STRING, V_ASN1_UNIVERSAL, 0, 1, 1)) - return -1; - break; + if (!append_exp(arg, V_ASN1_BIT_STRING, V_ASN1_UNIVERSAL, 0, 1, 1)) { + return -1; + } + break; case ASN1_GEN_FLAG_OCTWRAP: - if (!append_exp(arg, V_ASN1_OCTET_STRING, V_ASN1_UNIVERSAL, 0, 0, 1)) - return -1; - break; + if (!append_exp(arg, V_ASN1_OCTET_STRING, V_ASN1_UNIVERSAL, 0, 0, 1)) { + return -1; + } + break; case ASN1_GEN_FLAG_FORMAT: - if (!vstart) { - OPENSSL_PUT_ERROR(ASN1, ASN1_R_UNKNOWN_FORMAT); - return -1; - } - if (!strncmp(vstart, "ASCII", 5)) - arg->format = ASN1_GEN_FORMAT_ASCII; - else if (!strncmp(vstart, "UTF8", 4)) - arg->format = ASN1_GEN_FORMAT_UTF8; - else if (!strncmp(vstart, "HEX", 3)) - arg->format = ASN1_GEN_FORMAT_HEX; - else if (!strncmp(vstart, "BITLIST", 7)) - arg->format = ASN1_GEN_FORMAT_BITLIST; - else { - OPENSSL_PUT_ERROR(ASN1, ASN1_R_UNKNOWN_FORMAT); - return -1; - } - break; + if (!vstart) { + OPENSSL_PUT_ERROR(ASN1, ASN1_R_UNKNOWN_FORMAT); + return -1; + } + if (!strncmp(vstart, "ASCII", 5)) { + arg->format = ASN1_GEN_FORMAT_ASCII; + } else if (!strncmp(vstart, "UTF8", 4)) { + arg->format = ASN1_GEN_FORMAT_UTF8; + } else if (!strncmp(vstart, "HEX", 3)) { + arg->format = ASN1_GEN_FORMAT_HEX; + } else if (!strncmp(vstart, "BITLIST", 7)) { + arg->format = ASN1_GEN_FORMAT_BITLIST; + } else { + OPENSSL_PUT_ERROR(ASN1, ASN1_R_UNKNOWN_FORMAT); + return -1; + } + break; + } - } + return 1; +} - return 1; +static int parse_tagging(const char *vstart, int vlen, int *ptag, int *pclass) { + char erch[2]; + long tag_num; + char *eptr; + if (!vstart) { + return 0; + } + tag_num = strtoul(vstart, &eptr, 10); + /* Check we haven't gone past max length: should be impossible */ + if (eptr && *eptr && (eptr > vstart + vlen)) { + return 0; + } + if (tag_num < 0) { + OPENSSL_PUT_ERROR(ASN1, ASN1_R_INVALID_NUMBER); + return 0; + } + *ptag = tag_num; + /* If we have non numeric characters, parse them */ + if (eptr) { + vlen -= eptr - vstart; + } else { + vlen = 0; + } + if (vlen) { + switch (*eptr) { + case 'U': + *pclass = V_ASN1_UNIVERSAL; + break; -} + case 'A': + *pclass = V_ASN1_APPLICATION; + break; -static int parse_tagging(const char *vstart, int vlen, int *ptag, int *pclass) -{ - char erch[2]; - long tag_num; - char *eptr; - if (!vstart) - return 0; - tag_num = strtoul(vstart, &eptr, 10); - /* Check we haven't gone past max length: should be impossible */ - if (eptr && *eptr && (eptr > vstart + vlen)) - return 0; - if (tag_num < 0) { - OPENSSL_PUT_ERROR(ASN1, ASN1_R_INVALID_NUMBER); - return 0; - } - *ptag = tag_num; - /* If we have non numeric characters, parse them */ - if (eptr) - vlen -= eptr - vstart; - else - vlen = 0; - if (vlen) { - switch (*eptr) { - - case 'U': - *pclass = V_ASN1_UNIVERSAL; - break; - - case 'A': - *pclass = V_ASN1_APPLICATION; - break; - - case 'P': - *pclass = V_ASN1_PRIVATE; - break; - - case 'C': - *pclass = V_ASN1_CONTEXT_SPECIFIC; - break; - - default: - erch[0] = *eptr; - erch[1] = 0; - OPENSSL_PUT_ERROR(ASN1, ASN1_R_INVALID_MODIFIER); - ERR_add_error_data(2, "Char=", erch); - return 0; - break; + case 'P': + *pclass = V_ASN1_PRIVATE; + break; - } - } else + case 'C': *pclass = V_ASN1_CONTEXT_SPECIFIC; + break; - return 1; + default: + erch[0] = *eptr; + erch[1] = 0; + OPENSSL_PUT_ERROR(ASN1, ASN1_R_INVALID_MODIFIER); + ERR_add_error_data(2, "Char=", erch); + return 0; + break; + } + } else { + *pclass = V_ASN1_CONTEXT_SPECIFIC; + } + return 1; } /* Handle multiple types: SET and SEQUENCE */ static ASN1_TYPE *asn1_multi(int utype, const char *section, X509V3_CTX *cnf, - int depth, int *perr) -{ - ASN1_TYPE *ret = NULL; - STACK_OF(ASN1_TYPE) *sk = NULL; - STACK_OF(CONF_VALUE) *sect = NULL; - unsigned char *der = NULL; - int derlen; - size_t i; - sk = sk_ASN1_TYPE_new_null(); - if (!sk) + int depth, int *perr) { + ASN1_TYPE *ret = NULL; + STACK_OF(ASN1_TYPE) *sk = NULL; + STACK_OF(CONF_VALUE) *sect = NULL; + unsigned char *der = NULL; + int derlen; + size_t i; + sk = sk_ASN1_TYPE_new_null(); + if (!sk) { + goto bad; + } + if (section) { + if (!cnf) { + goto bad; + } + sect = X509V3_get_section(cnf, (char *)section); + if (!sect) { + goto bad; + } + for (i = 0; i < sk_CONF_VALUE_num(sect); i++) { + ASN1_TYPE *typ = generate_v3(sk_CONF_VALUE_value(sect, i)->value, cnf, + depth + 1, perr); + if (!typ) { goto bad; - if (section) { - if (!cnf) - goto bad; - sect = X509V3_get_section(cnf, (char *)section); - if (!sect) - goto bad; - for (i = 0; i < sk_CONF_VALUE_num(sect); i++) { - ASN1_TYPE *typ = - generate_v3(sk_CONF_VALUE_value(sect, i)->value, cnf, - depth + 1, perr); - if (!typ) - goto bad; - if (!sk_ASN1_TYPE_push(sk, typ)) - goto bad; - } + } + if (!sk_ASN1_TYPE_push(sk, typ)) { + goto bad; + } } + } - /* - * Now we has a STACK of the components, convert to the correct form - */ + /* + * Now we has a STACK of the components, convert to the correct form + */ - if (utype == V_ASN1_SET) - derlen = i2d_ASN1_SET_ANY(sk, &der); - else - derlen = i2d_ASN1_SEQUENCE_ANY(sk, &der); + if (utype == V_ASN1_SET) { + derlen = i2d_ASN1_SET_ANY(sk, &der); + } else { + derlen = i2d_ASN1_SEQUENCE_ANY(sk, &der); + } - if (derlen < 0) - goto bad; + if (derlen < 0) { + goto bad; + } - if (!(ret = ASN1_TYPE_new())) - goto bad; + if (!(ret = ASN1_TYPE_new())) { + goto bad; + } - if (!(ret->value.asn1_string = ASN1_STRING_type_new(utype))) - goto bad; + if (!(ret->value.asn1_string = ASN1_STRING_type_new(utype))) { + goto bad; + } - ret->type = utype; + ret->type = utype; - ret->value.asn1_string->data = der; - ret->value.asn1_string->length = derlen; + ret->value.asn1_string->data = der; + ret->value.asn1_string->length = derlen; - der = NULL; + der = NULL; - bad: +bad: - if (der) - OPENSSL_free(der); + if (der) { + OPENSSL_free(der); + } - if (sk) - sk_ASN1_TYPE_pop_free(sk, ASN1_TYPE_free); - if (sect) - X509V3_section_free(cnf, sect); + if (sk) { + sk_ASN1_TYPE_pop_free(sk, ASN1_TYPE_free); + } + if (sect) { + X509V3_section_free(cnf, sect); + } - return ret; + return ret; } static int append_exp(tag_exp_arg *arg, int exp_tag, int exp_class, - int exp_constructed, int exp_pad, int imp_ok) -{ - tag_exp_type *exp_tmp; - /* Can only have IMPLICIT if permitted */ - if ((arg->imp_tag != -1) && !imp_ok) { - OPENSSL_PUT_ERROR(ASN1, ASN1_R_ILLEGAL_IMPLICIT_TAG); - return 0; - } - - if (arg->exp_count == ASN1_FLAG_EXP_MAX) { - OPENSSL_PUT_ERROR(ASN1, ASN1_R_DEPTH_EXCEEDED); - return 0; - } - - exp_tmp = &arg->exp_list[arg->exp_count++]; - - /* - * If IMPLICIT set tag to implicit value then reset implicit tag since it - * has been used. - */ - if (arg->imp_tag != -1) { - exp_tmp->exp_tag = arg->imp_tag; - exp_tmp->exp_class = arg->imp_class; - arg->imp_tag = -1; - arg->imp_class = -1; - } else { - exp_tmp->exp_tag = exp_tag; - exp_tmp->exp_class = exp_class; - } - exp_tmp->exp_constructed = exp_constructed; - exp_tmp->exp_pad = exp_pad; - - return 1; + int exp_constructed, int exp_pad, int imp_ok) { + tag_exp_type *exp_tmp; + /* Can only have IMPLICIT if permitted */ + if ((arg->imp_tag != -1) && !imp_ok) { + OPENSSL_PUT_ERROR(ASN1, ASN1_R_ILLEGAL_IMPLICIT_TAG); + return 0; + } + + if (arg->exp_count == ASN1_FLAG_EXP_MAX) { + OPENSSL_PUT_ERROR(ASN1, ASN1_R_DEPTH_EXCEEDED); + return 0; + } + + exp_tmp = &arg->exp_list[arg->exp_count++]; + + /* + * If IMPLICIT set tag to implicit value then reset implicit tag since it + * has been used. + */ + if (arg->imp_tag != -1) { + exp_tmp->exp_tag = arg->imp_tag; + exp_tmp->exp_class = arg->imp_class; + arg->imp_tag = -1; + arg->imp_class = -1; + } else { + exp_tmp->exp_tag = exp_tag; + exp_tmp->exp_class = exp_class; + } + exp_tmp->exp_constructed = exp_constructed; + exp_tmp->exp_pad = exp_pad; + + return 1; } -static int asn1_str2tag(const char *tagstr, int len) -{ - unsigned int i; - static const struct tag_name_st *tntmp, tnst[] = { - ASN1_GEN_STR("BOOL", V_ASN1_BOOLEAN), - ASN1_GEN_STR("BOOLEAN", V_ASN1_BOOLEAN), - ASN1_GEN_STR("NULL", V_ASN1_NULL), - ASN1_GEN_STR("INT", V_ASN1_INTEGER), - ASN1_GEN_STR("INTEGER", V_ASN1_INTEGER), - ASN1_GEN_STR("ENUM", V_ASN1_ENUMERATED), - ASN1_GEN_STR("ENUMERATED", V_ASN1_ENUMERATED), - ASN1_GEN_STR("OID", V_ASN1_OBJECT), - ASN1_GEN_STR("OBJECT", V_ASN1_OBJECT), - ASN1_GEN_STR("UTCTIME", V_ASN1_UTCTIME), - ASN1_GEN_STR("UTC", V_ASN1_UTCTIME), - ASN1_GEN_STR("GENERALIZEDTIME", V_ASN1_GENERALIZEDTIME), - ASN1_GEN_STR("GENTIME", V_ASN1_GENERALIZEDTIME), - ASN1_GEN_STR("OCT", V_ASN1_OCTET_STRING), - ASN1_GEN_STR("OCTETSTRING", V_ASN1_OCTET_STRING), - ASN1_GEN_STR("BITSTR", V_ASN1_BIT_STRING), - ASN1_GEN_STR("BITSTRING", V_ASN1_BIT_STRING), - ASN1_GEN_STR("UNIVERSALSTRING", V_ASN1_UNIVERSALSTRING), - ASN1_GEN_STR("UNIV", V_ASN1_UNIVERSALSTRING), - ASN1_GEN_STR("IA5", V_ASN1_IA5STRING), - ASN1_GEN_STR("IA5STRING", V_ASN1_IA5STRING), - ASN1_GEN_STR("UTF8", V_ASN1_UTF8STRING), - ASN1_GEN_STR("UTF8String", V_ASN1_UTF8STRING), - ASN1_GEN_STR("BMP", V_ASN1_BMPSTRING), - ASN1_GEN_STR("BMPSTRING", V_ASN1_BMPSTRING), - ASN1_GEN_STR("VISIBLESTRING", V_ASN1_VISIBLESTRING), - ASN1_GEN_STR("VISIBLE", V_ASN1_VISIBLESTRING), - ASN1_GEN_STR("PRINTABLESTRING", V_ASN1_PRINTABLESTRING), - ASN1_GEN_STR("PRINTABLE", V_ASN1_PRINTABLESTRING), - ASN1_GEN_STR("T61", V_ASN1_T61STRING), - ASN1_GEN_STR("T61STRING", V_ASN1_T61STRING), - ASN1_GEN_STR("TELETEXSTRING", V_ASN1_T61STRING), - ASN1_GEN_STR("GeneralString", V_ASN1_GENERALSTRING), - ASN1_GEN_STR("GENSTR", V_ASN1_GENERALSTRING), - ASN1_GEN_STR("NUMERIC", V_ASN1_NUMERICSTRING), - ASN1_GEN_STR("NUMERICSTRING", V_ASN1_NUMERICSTRING), - - /* Special cases */ - ASN1_GEN_STR("SEQUENCE", V_ASN1_SEQUENCE), - ASN1_GEN_STR("SEQ", V_ASN1_SEQUENCE), - ASN1_GEN_STR("SET", V_ASN1_SET), - /* type modifiers */ - /* Explicit tag */ - ASN1_GEN_STR("EXP", ASN1_GEN_FLAG_EXP), - ASN1_GEN_STR("EXPLICIT", ASN1_GEN_FLAG_EXP), - /* Implicit tag */ - ASN1_GEN_STR("IMP", ASN1_GEN_FLAG_IMP), - ASN1_GEN_STR("IMPLICIT", ASN1_GEN_FLAG_IMP), - /* OCTET STRING wrapper */ - ASN1_GEN_STR("OCTWRAP", ASN1_GEN_FLAG_OCTWRAP), - /* SEQUENCE wrapper */ - ASN1_GEN_STR("SEQWRAP", ASN1_GEN_FLAG_SEQWRAP), - /* SET wrapper */ - ASN1_GEN_STR("SETWRAP", ASN1_GEN_FLAG_SETWRAP), - /* BIT STRING wrapper */ - ASN1_GEN_STR("BITWRAP", ASN1_GEN_FLAG_BITWRAP), - ASN1_GEN_STR("FORM", ASN1_GEN_FLAG_FORMAT), - ASN1_GEN_STR("FORMAT", ASN1_GEN_FLAG_FORMAT), - }; - - if (len == -1) - len = strlen(tagstr); - - tntmp = tnst; - for (i = 0; i < sizeof(tnst) / sizeof(struct tag_name_st); i++, tntmp++) { - if ((len == tntmp->len) && !strncmp(tntmp->strnam, tagstr, len)) - return tntmp->tag; +static int asn1_str2tag(const char *tagstr, int len) { + unsigned int i; + static const struct tag_name_st *tntmp, + tnst[] = { + ASN1_GEN_STR("BOOL", V_ASN1_BOOLEAN), + ASN1_GEN_STR("BOOLEAN", V_ASN1_BOOLEAN), + ASN1_GEN_STR("NULL", V_ASN1_NULL), + ASN1_GEN_STR("INT", V_ASN1_INTEGER), + ASN1_GEN_STR("INTEGER", V_ASN1_INTEGER), + ASN1_GEN_STR("ENUM", V_ASN1_ENUMERATED), + ASN1_GEN_STR("ENUMERATED", V_ASN1_ENUMERATED), + ASN1_GEN_STR("OID", V_ASN1_OBJECT), + ASN1_GEN_STR("OBJECT", V_ASN1_OBJECT), + ASN1_GEN_STR("UTCTIME", V_ASN1_UTCTIME), + ASN1_GEN_STR("UTC", V_ASN1_UTCTIME), + ASN1_GEN_STR("GENERALIZEDTIME", V_ASN1_GENERALIZEDTIME), + ASN1_GEN_STR("GENTIME", V_ASN1_GENERALIZEDTIME), + ASN1_GEN_STR("OCT", V_ASN1_OCTET_STRING), + ASN1_GEN_STR("OCTETSTRING", V_ASN1_OCTET_STRING), + ASN1_GEN_STR("BITSTR", V_ASN1_BIT_STRING), + ASN1_GEN_STR("BITSTRING", V_ASN1_BIT_STRING), + ASN1_GEN_STR("UNIVERSALSTRING", V_ASN1_UNIVERSALSTRING), + ASN1_GEN_STR("UNIV", V_ASN1_UNIVERSALSTRING), + ASN1_GEN_STR("IA5", V_ASN1_IA5STRING), + ASN1_GEN_STR("IA5STRING", V_ASN1_IA5STRING), + ASN1_GEN_STR("UTF8", V_ASN1_UTF8STRING), + ASN1_GEN_STR("UTF8String", V_ASN1_UTF8STRING), + ASN1_GEN_STR("BMP", V_ASN1_BMPSTRING), + ASN1_GEN_STR("BMPSTRING", V_ASN1_BMPSTRING), + ASN1_GEN_STR("VISIBLESTRING", V_ASN1_VISIBLESTRING), + ASN1_GEN_STR("VISIBLE", V_ASN1_VISIBLESTRING), + ASN1_GEN_STR("PRINTABLESTRING", V_ASN1_PRINTABLESTRING), + ASN1_GEN_STR("PRINTABLE", V_ASN1_PRINTABLESTRING), + ASN1_GEN_STR("T61", V_ASN1_T61STRING), + ASN1_GEN_STR("T61STRING", V_ASN1_T61STRING), + ASN1_GEN_STR("TELETEXSTRING", V_ASN1_T61STRING), + ASN1_GEN_STR("GeneralString", V_ASN1_GENERALSTRING), + ASN1_GEN_STR("GENSTR", V_ASN1_GENERALSTRING), + ASN1_GEN_STR("NUMERIC", V_ASN1_NUMERICSTRING), + ASN1_GEN_STR("NUMERICSTRING", V_ASN1_NUMERICSTRING), + + /* Special cases */ + ASN1_GEN_STR("SEQUENCE", V_ASN1_SEQUENCE), + ASN1_GEN_STR("SEQ", V_ASN1_SEQUENCE), + ASN1_GEN_STR("SET", V_ASN1_SET), + /* type modifiers */ + /* Explicit tag */ + ASN1_GEN_STR("EXP", ASN1_GEN_FLAG_EXP), + ASN1_GEN_STR("EXPLICIT", ASN1_GEN_FLAG_EXP), + /* Implicit tag */ + ASN1_GEN_STR("IMP", ASN1_GEN_FLAG_IMP), + ASN1_GEN_STR("IMPLICIT", ASN1_GEN_FLAG_IMP), + /* OCTET STRING wrapper */ + ASN1_GEN_STR("OCTWRAP", ASN1_GEN_FLAG_OCTWRAP), + /* SEQUENCE wrapper */ + ASN1_GEN_STR("SEQWRAP", ASN1_GEN_FLAG_SEQWRAP), + /* SET wrapper */ + ASN1_GEN_STR("SETWRAP", ASN1_GEN_FLAG_SETWRAP), + /* BIT STRING wrapper */ + ASN1_GEN_STR("BITWRAP", ASN1_GEN_FLAG_BITWRAP), + ASN1_GEN_STR("FORM", ASN1_GEN_FLAG_FORMAT), + ASN1_GEN_STR("FORMAT", ASN1_GEN_FLAG_FORMAT), + }; + + if (len == -1) { + len = strlen(tagstr); + } + + tntmp = tnst; + for (i = 0; i < sizeof(tnst) / sizeof(struct tag_name_st); i++, tntmp++) { + if ((len == tntmp->len) && !strncmp(tntmp->strnam, tagstr, len)) { + return tntmp->tag; } + } - return -1; + return -1; } -static ASN1_TYPE *asn1_str2type(const char *str, int format, int utype) -{ - ASN1_TYPE *atmp = NULL; - - CONF_VALUE vtmp; +static ASN1_TYPE *asn1_str2type(const char *str, int format, int utype) { + ASN1_TYPE *atmp = NULL; - unsigned char *rdata; - long rdlen; + CONF_VALUE vtmp; - int no_unused = 1; + unsigned char *rdata; + long rdlen; - if (!(atmp = ASN1_TYPE_new())) { - OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE); - return NULL; - } + int no_unused = 1; - if (!str) - str = ""; + if (!(atmp = ASN1_TYPE_new())) { + OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE); + return NULL; + } - switch (utype) { + if (!str) { + str = ""; + } + switch (utype) { case V_ASN1_NULL: - if (str && *str) { - OPENSSL_PUT_ERROR(ASN1, ASN1_R_ILLEGAL_NULL_VALUE); - goto bad_form; - } - break; + if (str && *str) { + OPENSSL_PUT_ERROR(ASN1, ASN1_R_ILLEGAL_NULL_VALUE); + goto bad_form; + } + break; case V_ASN1_BOOLEAN: - if (format != ASN1_GEN_FORMAT_ASCII) { - OPENSSL_PUT_ERROR(ASN1, ASN1_R_NOT_ASCII_FORMAT); - goto bad_form; - } - vtmp.name = NULL; - vtmp.section = NULL; - vtmp.value = (char *)str; - if (!X509V3_get_value_bool(&vtmp, &atmp->value.boolean)) { - OPENSSL_PUT_ERROR(ASN1, ASN1_R_ILLEGAL_BOOLEAN); - goto bad_str; - } - break; + if (format != ASN1_GEN_FORMAT_ASCII) { + OPENSSL_PUT_ERROR(ASN1, ASN1_R_NOT_ASCII_FORMAT); + goto bad_form; + } + vtmp.name = NULL; + vtmp.section = NULL; + vtmp.value = (char *)str; + if (!X509V3_get_value_bool(&vtmp, &atmp->value.boolean)) { + OPENSSL_PUT_ERROR(ASN1, ASN1_R_ILLEGAL_BOOLEAN); + goto bad_str; + } + break; case V_ASN1_INTEGER: case V_ASN1_ENUMERATED: - if (format != ASN1_GEN_FORMAT_ASCII) { - OPENSSL_PUT_ERROR(ASN1, ASN1_R_INTEGER_NOT_ASCII_FORMAT); - goto bad_form; - } - if (!(atmp->value.integer = s2i_ASN1_INTEGER(NULL, (char *)str))) { - OPENSSL_PUT_ERROR(ASN1, ASN1_R_ILLEGAL_INTEGER); - goto bad_str; - } - break; + if (format != ASN1_GEN_FORMAT_ASCII) { + OPENSSL_PUT_ERROR(ASN1, ASN1_R_INTEGER_NOT_ASCII_FORMAT); + goto bad_form; + } + if (!(atmp->value.integer = s2i_ASN1_INTEGER(NULL, (char *)str))) { + OPENSSL_PUT_ERROR(ASN1, ASN1_R_ILLEGAL_INTEGER); + goto bad_str; + } + break; case V_ASN1_OBJECT: - if (format != ASN1_GEN_FORMAT_ASCII) { - OPENSSL_PUT_ERROR(ASN1, ASN1_R_OBJECT_NOT_ASCII_FORMAT); - goto bad_form; - } - if (!(atmp->value.object = OBJ_txt2obj(str, 0))) { - OPENSSL_PUT_ERROR(ASN1, ASN1_R_ILLEGAL_OBJECT); - goto bad_str; - } - break; + if (format != ASN1_GEN_FORMAT_ASCII) { + OPENSSL_PUT_ERROR(ASN1, ASN1_R_OBJECT_NOT_ASCII_FORMAT); + goto bad_form; + } + if (!(atmp->value.object = OBJ_txt2obj(str, 0))) { + OPENSSL_PUT_ERROR(ASN1, ASN1_R_ILLEGAL_OBJECT); + goto bad_str; + } + break; case V_ASN1_UTCTIME: case V_ASN1_GENERALIZEDTIME: - if (format != ASN1_GEN_FORMAT_ASCII) { - OPENSSL_PUT_ERROR(ASN1, ASN1_R_TIME_NOT_ASCII_FORMAT); - goto bad_form; - } - if (!(atmp->value.asn1_string = ASN1_STRING_new())) { - OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE); - goto bad_str; - } - if (!ASN1_STRING_set(atmp->value.asn1_string, str, -1)) { - OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE); - goto bad_str; - } - atmp->value.asn1_string->type = utype; - if (!ASN1_TIME_check(atmp->value.asn1_string)) { - OPENSSL_PUT_ERROR(ASN1, ASN1_R_ILLEGAL_TIME_VALUE); - goto bad_str; - } + if (format != ASN1_GEN_FORMAT_ASCII) { + OPENSSL_PUT_ERROR(ASN1, ASN1_R_TIME_NOT_ASCII_FORMAT); + goto bad_form; + } + if (!(atmp->value.asn1_string = ASN1_STRING_new())) { + OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE); + goto bad_str; + } + if (!ASN1_STRING_set(atmp->value.asn1_string, str, -1)) { + OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE); + goto bad_str; + } + atmp->value.asn1_string->type = utype; + if (!ASN1_TIME_check(atmp->value.asn1_string)) { + OPENSSL_PUT_ERROR(ASN1, ASN1_R_ILLEGAL_TIME_VALUE); + goto bad_str; + } - break; + break; case V_ASN1_BMPSTRING: case V_ASN1_PRINTABLESTRING: @@ -726,101 +745,98 @@ static ASN1_TYPE *asn1_str2type(const char *str, int format, int utype) case V_ASN1_GENERALSTRING: case V_ASN1_NUMERICSTRING: - if (format == ASN1_GEN_FORMAT_ASCII) - format = MBSTRING_ASC; - else if (format == ASN1_GEN_FORMAT_UTF8) - format = MBSTRING_UTF8; - else { - OPENSSL_PUT_ERROR(ASN1, ASN1_R_ILLEGAL_FORMAT); - goto bad_form; - } - - if (ASN1_mbstring_copy(&atmp->value.asn1_string, (unsigned char *)str, - -1, format, ASN1_tag2bit(utype)) <= 0) { - OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE); - goto bad_str; - } + if (format == ASN1_GEN_FORMAT_ASCII) { + format = MBSTRING_ASC; + } else if (format == ASN1_GEN_FORMAT_UTF8) { + format = MBSTRING_UTF8; + } else { + OPENSSL_PUT_ERROR(ASN1, ASN1_R_ILLEGAL_FORMAT); + goto bad_form; + } + + if (ASN1_mbstring_copy(&atmp->value.asn1_string, (unsigned char *)str, -1, + format, ASN1_tag2bit(utype)) <= 0) { + OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE); + goto bad_str; + } - break; + break; case V_ASN1_BIT_STRING: case V_ASN1_OCTET_STRING: - if (!(atmp->value.asn1_string = ASN1_STRING_new())) { - OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE); - goto bad_form; - } + if (!(atmp->value.asn1_string = ASN1_STRING_new())) { + OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE); + goto bad_form; + } - if (format == ASN1_GEN_FORMAT_HEX) { - - if (!(rdata = x509v3_hex_to_bytes((char *)str, &rdlen))) { - OPENSSL_PUT_ERROR(ASN1, ASN1_R_ILLEGAL_HEX); - goto bad_str; - } - - atmp->value.asn1_string->data = rdata; - atmp->value.asn1_string->length = rdlen; - atmp->value.asn1_string->type = utype; - - } else if (format == ASN1_GEN_FORMAT_ASCII) - ASN1_STRING_set(atmp->value.asn1_string, str, -1); - else if ((format == ASN1_GEN_FORMAT_BITLIST) - && (utype == V_ASN1_BIT_STRING)) { - if (!CONF_parse_list - (str, ',', 1, bitstr_cb, atmp->value.bit_string)) { - OPENSSL_PUT_ERROR(ASN1, ASN1_R_LIST_ERROR); - goto bad_str; - } - no_unused = 0; - - } else { - OPENSSL_PUT_ERROR(ASN1, ASN1_R_ILLEGAL_BITSTRING_FORMAT); - goto bad_form; + if (format == ASN1_GEN_FORMAT_HEX) { + if (!(rdata = x509v3_hex_to_bytes((char *)str, &rdlen))) { + OPENSSL_PUT_ERROR(ASN1, ASN1_R_ILLEGAL_HEX); + goto bad_str; } - if ((utype == V_ASN1_BIT_STRING) && no_unused) { - atmp->value.asn1_string->flags - &= ~(ASN1_STRING_FLAG_BITS_LEFT | 0x07); - atmp->value.asn1_string->flags |= ASN1_STRING_FLAG_BITS_LEFT; + atmp->value.asn1_string->data = rdata; + atmp->value.asn1_string->length = rdlen; + atmp->value.asn1_string->type = utype; + + } else if (format == ASN1_GEN_FORMAT_ASCII) { + ASN1_STRING_set(atmp->value.asn1_string, str, -1); + } else if ((format == ASN1_GEN_FORMAT_BITLIST) && + (utype == V_ASN1_BIT_STRING)) { + if (!CONF_parse_list(str, ',', 1, bitstr_cb, atmp->value.bit_string)) { + OPENSSL_PUT_ERROR(ASN1, ASN1_R_LIST_ERROR); + goto bad_str; } + no_unused = 0; - break; + } else { + OPENSSL_PUT_ERROR(ASN1, ASN1_R_ILLEGAL_BITSTRING_FORMAT); + goto bad_form; + } - default: - OPENSSL_PUT_ERROR(ASN1, ASN1_R_UNSUPPORTED_TYPE); - goto bad_str; - break; - } + if ((utype == V_ASN1_BIT_STRING) && no_unused) { + atmp->value.asn1_string->flags &= ~(ASN1_STRING_FLAG_BITS_LEFT | 0x07); + atmp->value.asn1_string->flags |= ASN1_STRING_FLAG_BITS_LEFT; + } - atmp->type = utype; - return atmp; + break; - bad_str: - ERR_add_error_data(2, "string=", str); - bad_form: + default: + OPENSSL_PUT_ERROR(ASN1, ASN1_R_UNSUPPORTED_TYPE); + goto bad_str; + break; + } - ASN1_TYPE_free(atmp); - return NULL; + atmp->type = utype; + return atmp; +bad_str: + ERR_add_error_data(2, "string=", str); +bad_form: + + ASN1_TYPE_free(atmp); + return NULL; } -static int bitstr_cb(const char *elem, int len, void *bitstr) -{ - long bitnum; - char *eptr; - if (!elem) - return 0; - bitnum = strtoul(elem, &eptr, 10); - if (eptr && *eptr && (eptr != elem + len)) - return 0; - if (bitnum < 0) { - OPENSSL_PUT_ERROR(ASN1, ASN1_R_INVALID_NUMBER); - return 0; - } - if (!ASN1_BIT_STRING_set_bit(bitstr, bitnum, 1)) { - OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE); - return 0; - } - return 1; +static int bitstr_cb(const char *elem, int len, void *bitstr) { + long bitnum; + char *eptr; + if (!elem) { + return 0; + } + bitnum = strtoul(elem, &eptr, 10); + if (eptr && *eptr && (eptr != elem + len)) { + return 0; + } + if (bitnum < 0) { + OPENSSL_PUT_ERROR(ASN1, ASN1_R_INVALID_NUMBER); + return 0; + } + if (!ASN1_BIT_STRING_set_bit(bitstr, bitnum, 1)) { + OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE); + return 0; + } + return 1; } diff --git a/crypto/x509/by_dir.c b/crypto/x509/by_dir.c index 2f1694468a..e5e72b3e4f 100644 --- a/crypto/x509/by_dir.c +++ b/crypto/x509/by_dir.c @@ -71,19 +71,19 @@ #include "internal.h" typedef struct lookup_dir_hashes_st { - unsigned long hash; - int suffix; + unsigned long hash; + int suffix; } BY_DIR_HASH; typedef struct lookup_dir_entry_st { - char *dir; - int dir_type; - STACK_OF(BY_DIR_HASH) *hashes; + char *dir; + int dir_type; + STACK_OF(BY_DIR_HASH) *hashes; } BY_DIR_ENTRY; typedef struct lookup_dir_st { - BUF_MEM *buffer; - STACK_OF(BY_DIR_ENTRY) *dirs; + BUF_MEM *buffer; + STACK_OF(BY_DIR_ENTRY) *dirs; } BY_DIR; DEFINE_STACK_OF(BY_DIR_HASH) @@ -98,369 +98,372 @@ static int get_cert_by_subject(X509_LOOKUP *xl, int type, X509_NAME *name, X509_OBJECT *ret); static X509_LOOKUP_METHOD x509_dir_lookup = { "Load certs from files in a directory", - new_dir, /* new */ - free_dir, /* free */ - NULL, /* init */ - NULL, /* shutdown */ - dir_ctrl, /* ctrl */ - get_cert_by_subject, /* get_by_subject */ - NULL, /* get_by_issuer_serial */ - NULL, /* get_by_fingerprint */ - NULL, /* get_by_alias */ + new_dir, /* new */ + free_dir, /* free */ + NULL, /* init */ + NULL, /* shutdown */ + dir_ctrl, /* ctrl */ + get_cert_by_subject, /* get_by_subject */ + NULL, /* get_by_issuer_serial */ + NULL, /* get_by_fingerprint */ + NULL, /* get_by_alias */ }; -X509_LOOKUP_METHOD *X509_LOOKUP_hash_dir(void) -{ - return (&x509_dir_lookup); -} +X509_LOOKUP_METHOD *X509_LOOKUP_hash_dir(void) { return (&x509_dir_lookup); } static int dir_ctrl(X509_LOOKUP *ctx, int cmd, const char *argp, long argl, - char **retp) -{ - int ret = 0; - BY_DIR *ld; - char *dir = NULL; + char **retp) { + int ret = 0; + BY_DIR *ld; + char *dir = NULL; - ld = (BY_DIR *)ctx->method_data; + ld = (BY_DIR *)ctx->method_data; - switch (cmd) { + switch (cmd) { case X509_L_ADD_DIR: - if (argl == X509_FILETYPE_DEFAULT) { - dir = (char *)getenv(X509_get_default_cert_dir_env()); - if (dir) - ret = add_cert_dir(ld, dir, X509_FILETYPE_PEM); - else - ret = add_cert_dir(ld, X509_get_default_cert_dir(), - X509_FILETYPE_PEM); - if (!ret) { - OPENSSL_PUT_ERROR(X509, X509_R_LOADING_CERT_DIR); - } - } else - ret = add_cert_dir(ld, argp, (int)argl); - break; - } - return (ret); + if (argl == X509_FILETYPE_DEFAULT) { + dir = (char *)getenv(X509_get_default_cert_dir_env()); + if (dir) { + ret = add_cert_dir(ld, dir, X509_FILETYPE_PEM); + } else { + ret = + add_cert_dir(ld, X509_get_default_cert_dir(), X509_FILETYPE_PEM); + } + if (!ret) { + OPENSSL_PUT_ERROR(X509, X509_R_LOADING_CERT_DIR); + } + } else { + ret = add_cert_dir(ld, argp, (int)argl); + } + break; + } + return (ret); } -static int new_dir(X509_LOOKUP *lu) -{ - BY_DIR *a; +static int new_dir(X509_LOOKUP *lu) { + BY_DIR *a; - if ((a = (BY_DIR *)OPENSSL_malloc(sizeof(BY_DIR))) == NULL) - return (0); - if ((a->buffer = BUF_MEM_new()) == NULL) { - OPENSSL_free(a); - return (0); - } - a->dirs = NULL; - lu->method_data = (char *)a; - return (1); + if ((a = (BY_DIR *)OPENSSL_malloc(sizeof(BY_DIR))) == NULL) { + return (0); + } + if ((a->buffer = BUF_MEM_new()) == NULL) { + OPENSSL_free(a); + return (0); + } + a->dirs = NULL; + lu->method_data = (char *)a; + return (1); } -static void by_dir_hash_free(BY_DIR_HASH *hash) -{ - OPENSSL_free(hash); -} +static void by_dir_hash_free(BY_DIR_HASH *hash) { OPENSSL_free(hash); } -static int by_dir_hash_cmp(const BY_DIR_HASH **a, const BY_DIR_HASH **b) -{ - if ((*a)->hash > (*b)->hash) - return 1; - if ((*a)->hash < (*b)->hash) - return -1; - return 0; +static int by_dir_hash_cmp(const BY_DIR_HASH **a, const BY_DIR_HASH **b) { + if ((*a)->hash > (*b)->hash) { + return 1; + } + if ((*a)->hash < (*b)->hash) { + return -1; + } + return 0; } -static void by_dir_entry_free(BY_DIR_ENTRY *ent) -{ - if (ent->dir) - OPENSSL_free(ent->dir); - if (ent->hashes) - sk_BY_DIR_HASH_pop_free(ent->hashes, by_dir_hash_free); - OPENSSL_free(ent); +static void by_dir_entry_free(BY_DIR_ENTRY *ent) { + if (ent->dir) { + OPENSSL_free(ent->dir); + } + if (ent->hashes) { + sk_BY_DIR_HASH_pop_free(ent->hashes, by_dir_hash_free); + } + OPENSSL_free(ent); } -static void free_dir(X509_LOOKUP *lu) -{ - BY_DIR *a; - - a = (BY_DIR *)lu->method_data; - if (a->dirs != NULL) - sk_BY_DIR_ENTRY_pop_free(a->dirs, by_dir_entry_free); - if (a->buffer != NULL) - BUF_MEM_free(a->buffer); - OPENSSL_free(a); +static void free_dir(X509_LOOKUP *lu) { + BY_DIR *a; + + a = (BY_DIR *)lu->method_data; + if (a->dirs != NULL) { + sk_BY_DIR_ENTRY_pop_free(a->dirs, by_dir_entry_free); + } + if (a->buffer != NULL) { + BUF_MEM_free(a->buffer); + } + OPENSSL_free(a); } -static int add_cert_dir(BY_DIR *ctx, const char *dir, int type) -{ - size_t j, len; - const char *s, *ss, *p; +static int add_cert_dir(BY_DIR *ctx, const char *dir, int type) { + size_t j, len; + const char *s, *ss, *p; - if (dir == NULL || !*dir) { - OPENSSL_PUT_ERROR(X509, X509_R_INVALID_DIRECTORY); + if (dir == NULL || !*dir) { + OPENSSL_PUT_ERROR(X509, X509_R_INVALID_DIRECTORY); + return 0; + } + + s = dir; + p = s; + do { + if ((*p == ':') || (*p == '\0')) { + BY_DIR_ENTRY *ent; + ss = s; + s = p + 1; + len = p - ss; + if (len == 0) { + continue; + } + for (j = 0; j < sk_BY_DIR_ENTRY_num(ctx->dirs); j++) { + ent = sk_BY_DIR_ENTRY_value(ctx->dirs, j); + if (strlen(ent->dir) == len && strncmp(ent->dir, ss, len) == 0) { + break; + } + } + if (j < sk_BY_DIR_ENTRY_num(ctx->dirs)) { + continue; + } + if (ctx->dirs == NULL) { + ctx->dirs = sk_BY_DIR_ENTRY_new_null(); + if (!ctx->dirs) { + OPENSSL_PUT_ERROR(X509, ERR_R_MALLOC_FAILURE); + return 0; + } + } + ent = OPENSSL_malloc(sizeof(BY_DIR_ENTRY)); + if (!ent) { + return 0; + } + ent->dir_type = type; + ent->hashes = sk_BY_DIR_HASH_new(by_dir_hash_cmp); + ent->dir = OPENSSL_malloc(len + 1); + if (!ent->dir || !ent->hashes) { + by_dir_entry_free(ent); return 0; + } + OPENSSL_strlcpy(ent->dir, ss, len + 1); + if (!sk_BY_DIR_ENTRY_push(ctx->dirs, ent)) { + by_dir_entry_free(ent); + return 0; + } } - - s = dir; - p = s; - do { - if ((*p == ':') || (*p == '\0')) { - BY_DIR_ENTRY *ent; - ss = s; - s = p + 1; - len = p - ss; - if (len == 0) - continue; - for (j = 0; j < sk_BY_DIR_ENTRY_num(ctx->dirs); j++) { - ent = sk_BY_DIR_ENTRY_value(ctx->dirs, j); - if (strlen(ent->dir) == len && - strncmp(ent->dir, ss, len) == 0) - break; - } - if (j < sk_BY_DIR_ENTRY_num(ctx->dirs)) - continue; - if (ctx->dirs == NULL) { - ctx->dirs = sk_BY_DIR_ENTRY_new_null(); - if (!ctx->dirs) { - OPENSSL_PUT_ERROR(X509, ERR_R_MALLOC_FAILURE); - return 0; - } - } - ent = OPENSSL_malloc(sizeof(BY_DIR_ENTRY)); - if (!ent) - return 0; - ent->dir_type = type; - ent->hashes = sk_BY_DIR_HASH_new(by_dir_hash_cmp); - ent->dir = OPENSSL_malloc(len + 1); - if (!ent->dir || !ent->hashes) { - by_dir_entry_free(ent); - return 0; - } - OPENSSL_strlcpy(ent->dir, ss, len + 1); - if (!sk_BY_DIR_ENTRY_push(ctx->dirs, ent)) { - by_dir_entry_free(ent); - return 0; - } - } - } while (*p++ != '\0'); - return 1; + } while (*p++ != '\0'); + return 1; } /* * g_ent_hashes_lock protects the |hashes| member of all |BY_DIR_ENTRY| * objects. */ -static struct CRYPTO_STATIC_MUTEX g_ent_hashes_lock = - CRYPTO_STATIC_MUTEX_INIT; +static struct CRYPTO_STATIC_MUTEX g_ent_hashes_lock = CRYPTO_STATIC_MUTEX_INIT; static int get_cert_by_subject(X509_LOOKUP *xl, int type, X509_NAME *name, - X509_OBJECT *ret) -{ - BY_DIR *ctx; - union { - struct { - X509 st_x509; - X509_CINF st_x509_cinf; - } x509; - struct { - X509_CRL st_crl; - X509_CRL_INFO st_crl_info; - } crl; - } data; - int ok = 0; - size_t i; - int j, k; - unsigned long h; - unsigned long hash_array[2]; - int hash_index; - BUF_MEM *b = NULL; - X509_OBJECT stmp, *tmp; - const char *postfix = ""; - - if (name == NULL) - return (0); - - stmp.type = type; - if (type == X509_LU_X509) { - data.x509.st_x509.cert_info = &data.x509.st_x509_cinf; - data.x509.st_x509_cinf.subject = name; - stmp.data.x509 = &data.x509.st_x509; - postfix = ""; - } else if (type == X509_LU_CRL) { - data.crl.st_crl.crl = &data.crl.st_crl_info; - data.crl.st_crl_info.issuer = name; - stmp.data.crl = &data.crl.st_crl; - postfix = "r"; - } else { - OPENSSL_PUT_ERROR(X509, X509_R_WRONG_LOOKUP_TYPE); - goto finish; - } - - if ((b = BUF_MEM_new()) == NULL) { - OPENSSL_PUT_ERROR(X509, ERR_R_BUF_LIB); + X509_OBJECT *ret) { + BY_DIR *ctx; + union { + struct { + X509 st_x509; + X509_CINF st_x509_cinf; + } x509; + struct { + X509_CRL st_crl; + X509_CRL_INFO st_crl_info; + } crl; + } data; + int ok = 0; + size_t i; + int j, k; + unsigned long h; + unsigned long hash_array[2]; + int hash_index; + BUF_MEM *b = NULL; + X509_OBJECT stmp, *tmp; + const char *postfix = ""; + + if (name == NULL) { + return (0); + } + + stmp.type = type; + if (type == X509_LU_X509) { + data.x509.st_x509.cert_info = &data.x509.st_x509_cinf; + data.x509.st_x509_cinf.subject = name; + stmp.data.x509 = &data.x509.st_x509; + postfix = ""; + } else if (type == X509_LU_CRL) { + data.crl.st_crl.crl = &data.crl.st_crl_info; + data.crl.st_crl_info.issuer = name; + stmp.data.crl = &data.crl.st_crl; + postfix = "r"; + } else { + OPENSSL_PUT_ERROR(X509, X509_R_WRONG_LOOKUP_TYPE); + goto finish; + } + + if ((b = BUF_MEM_new()) == NULL) { + OPENSSL_PUT_ERROR(X509, ERR_R_BUF_LIB); + goto finish; + } + + ctx = (BY_DIR *)xl->method_data; + + hash_array[0] = X509_NAME_hash(name); + hash_array[1] = X509_NAME_hash_old(name); + for (hash_index = 0; hash_index < 2; ++hash_index) { + h = hash_array[hash_index]; + for (i = 0; i < sk_BY_DIR_ENTRY_num(ctx->dirs); i++) { + BY_DIR_ENTRY *ent; + size_t idx; + BY_DIR_HASH htmp, *hent; + ent = sk_BY_DIR_ENTRY_value(ctx->dirs, i); + j = strlen(ent->dir) + 1 + 8 + 6 + 1 + 1; + if (!BUF_MEM_grow(b, j)) { + OPENSSL_PUT_ERROR(X509, ERR_R_MALLOC_FAILURE); goto finish; - } - - ctx = (BY_DIR *)xl->method_data; - - hash_array[0] = X509_NAME_hash(name); - hash_array[1] = X509_NAME_hash_old(name); - for (hash_index = 0; hash_index < 2; ++hash_index) { - h = hash_array[hash_index]; - for (i = 0; i < sk_BY_DIR_ENTRY_num(ctx->dirs); i++) { - BY_DIR_ENTRY *ent; - size_t idx; - BY_DIR_HASH htmp, *hent; - ent = sk_BY_DIR_ENTRY_value(ctx->dirs, i); - j = strlen(ent->dir) + 1 + 8 + 6 + 1 + 1; - if (!BUF_MEM_grow(b, j)) { - OPENSSL_PUT_ERROR(X509, ERR_R_MALLOC_FAILURE); - goto finish; - } - if (type == X509_LU_CRL && ent->hashes) { - htmp.hash = h; - CRYPTO_STATIC_MUTEX_lock_read(&g_ent_hashes_lock); - if (sk_BY_DIR_HASH_find(ent->hashes, &idx, &htmp)) { - hent = sk_BY_DIR_HASH_value(ent->hashes, idx); - k = hent->suffix; - } else { - hent = NULL; - k = 0; - } - CRYPTO_STATIC_MUTEX_unlock_read(&g_ent_hashes_lock); - } else { - k = 0; - hent = NULL; - } - for (;;) { - char c = '/'; + } + if (type == X509_LU_CRL && ent->hashes) { + htmp.hash = h; + CRYPTO_STATIC_MUTEX_lock_read(&g_ent_hashes_lock); + if (sk_BY_DIR_HASH_find(ent->hashes, &idx, &htmp)) { + hent = sk_BY_DIR_HASH_value(ent->hashes, idx); + k = hent->suffix; + } else { + hent = NULL; + k = 0; + } + CRYPTO_STATIC_MUTEX_unlock_read(&g_ent_hashes_lock); + } else { + k = 0; + hent = NULL; + } + for (;;) { + char c = '/'; #ifdef OPENSSL_SYS_VMS - c = ent->dir[strlen(ent->dir) - 1]; - if (c != ':' && c != '>' && c != ']') { - /* - * If no separator is present, we assume the directory - * specifier is a logical name, and add a colon. We - * really should use better VMS routines for merging - * things like this, but this will do for now... -- - * Richard Levitte - */ - c = ':'; - } else { - c = '\0'; - } + c = ent->dir[strlen(ent->dir) - 1]; + if (c != ':' && c != '>' && c != ']') { + /* + * If no separator is present, we assume the directory + * specifier is a logical name, and add a colon. We + * really should use better VMS routines for merging + * things like this, but this will do for now... -- + * Richard Levitte + */ + c = ':'; + } else { + c = '\0'; + } #endif - if (c == '\0') { - /* - * This is special. When c == '\0', no directory - * separator should be added. - */ - BIO_snprintf(b->data, b->max, - "%s%08lx.%s%d", ent->dir, h, postfix, k); - } else { - BIO_snprintf(b->data, b->max, - "%s%c%08lx.%s%d", ent->dir, c, h, - postfix, k); - } + if (c == '\0') { + /* + * This is special. When c == '\0', no directory + * separator should be added. + */ + BIO_snprintf(b->data, b->max, "%s%08lx.%s%d", ent->dir, h, postfix, + k); + } else { + BIO_snprintf(b->data, b->max, "%s%c%08lx.%s%d", ent->dir, c, h, + postfix, k); + } #ifndef OPENSSL_NO_POSIX_IO -# if defined(_WIN32) && !defined(stat) -# define stat _stat -# endif - { - struct stat st; - if (stat(b->data, &st) < 0) - break; - } +#if defined(_WIN32) && !defined(stat) +#define stat _stat +#endif + { + struct stat st; + if (stat(b->data, &st) < 0) { + break; + } + } #endif - /* found one. */ - if (type == X509_LU_X509) { - if ((X509_load_cert_file(xl, b->data, - ent->dir_type)) == 0) - break; - } else if (type == X509_LU_CRL) { - if ((X509_load_crl_file(xl, b->data, ent->dir_type)) == 0) - break; - } - /* else case will caught higher up */ - k++; - } - - /* - * we have added it to the cache so now pull it out again - */ - CRYPTO_MUTEX_lock_write(&xl->store_ctx->objs_lock); - tmp = NULL; - sk_X509_OBJECT_sort(xl->store_ctx->objs); - if (sk_X509_OBJECT_find(xl->store_ctx->objs, &idx, &stmp)) { - tmp = sk_X509_OBJECT_value(xl->store_ctx->objs, idx); - } - CRYPTO_MUTEX_unlock_write(&xl->store_ctx->objs_lock); - - /* - * If a CRL, update the last file suffix added for this - */ - - if (type == X509_LU_CRL) { - CRYPTO_STATIC_MUTEX_lock_write(&g_ent_hashes_lock); - /* - * Look for entry again in case another thread added an entry - * first. - */ - if (!hent) { - htmp.hash = h; - sk_BY_DIR_HASH_sort(ent->hashes); - if (sk_BY_DIR_HASH_find(ent->hashes, &idx, &htmp)) - hent = sk_BY_DIR_HASH_value(ent->hashes, idx); - } - if (!hent) { - hent = OPENSSL_malloc(sizeof(BY_DIR_HASH)); - if (hent == NULL) { - CRYPTO_STATIC_MUTEX_unlock_write(&g_ent_hashes_lock); - ok = 0; - goto finish; - } - hent->hash = h; - hent->suffix = k; - if (!sk_BY_DIR_HASH_push(ent->hashes, hent)) { - CRYPTO_STATIC_MUTEX_unlock_write(&g_ent_hashes_lock); - OPENSSL_free(hent); - ok = 0; - goto finish; - } - sk_BY_DIR_HASH_sort(ent->hashes); - } else if (hent->suffix < k) - hent->suffix = k; - - CRYPTO_STATIC_MUTEX_unlock_write(&g_ent_hashes_lock); - } - - if (tmp != NULL) { - ok = 1; - ret->type = tmp->type; - OPENSSL_memcpy(&ret->data, &tmp->data, sizeof(ret->data)); - - /* - * Clear any errors that might have been raised processing empty - * or malformed files. - */ - ERR_clear_error(); - - /* - * If we were going to up the reference count, we would need - * to do it on a perl 'type' basis - */ - /* - * CRYPTO_add(&tmp->data.x509->references,1, - * CRYPTO_LOCK_X509); - */ - goto finish; - } + /* found one. */ + if (type == X509_LU_X509) { + if ((X509_load_cert_file(xl, b->data, ent->dir_type)) == 0) { + break; + } + } else if (type == X509_LU_CRL) { + if ((X509_load_crl_file(xl, b->data, ent->dir_type)) == 0) { + break; + } } + /* else case will caught higher up */ + k++; + } + + /* + * we have added it to the cache so now pull it out again + */ + CRYPTO_MUTEX_lock_write(&xl->store_ctx->objs_lock); + tmp = NULL; + sk_X509_OBJECT_sort(xl->store_ctx->objs); + if (sk_X509_OBJECT_find(xl->store_ctx->objs, &idx, &stmp)) { + tmp = sk_X509_OBJECT_value(xl->store_ctx->objs, idx); + } + CRYPTO_MUTEX_unlock_write(&xl->store_ctx->objs_lock); + + /* + * If a CRL, update the last file suffix added for this + */ + + if (type == X509_LU_CRL) { + CRYPTO_STATIC_MUTEX_lock_write(&g_ent_hashes_lock); + /* + * Look for entry again in case another thread added an entry + * first. + */ + if (!hent) { + htmp.hash = h; + sk_BY_DIR_HASH_sort(ent->hashes); + if (sk_BY_DIR_HASH_find(ent->hashes, &idx, &htmp)) { + hent = sk_BY_DIR_HASH_value(ent->hashes, idx); + } + } + if (!hent) { + hent = OPENSSL_malloc(sizeof(BY_DIR_HASH)); + if (hent == NULL) { + CRYPTO_STATIC_MUTEX_unlock_write(&g_ent_hashes_lock); + ok = 0; + goto finish; + } + hent->hash = h; + hent->suffix = k; + if (!sk_BY_DIR_HASH_push(ent->hashes, hent)) { + CRYPTO_STATIC_MUTEX_unlock_write(&g_ent_hashes_lock); + OPENSSL_free(hent); + ok = 0; + goto finish; + } + sk_BY_DIR_HASH_sort(ent->hashes); + } else if (hent->suffix < k) { + hent->suffix = k; + } + + CRYPTO_STATIC_MUTEX_unlock_write(&g_ent_hashes_lock); + } + + if (tmp != NULL) { + ok = 1; + ret->type = tmp->type; + OPENSSL_memcpy(&ret->data, &tmp->data, sizeof(ret->data)); + + /* + * Clear any errors that might have been raised processing empty + * or malformed files. + */ + ERR_clear_error(); + + /* + * If we were going to up the reference count, we would need + * to do it on a perl 'type' basis + */ + /* + * CRYPTO_add(&tmp->data.x509->references,1, + * CRYPTO_LOCK_X509); + */ + goto finish; + } } - finish: - if (b != NULL) - BUF_MEM_free(b); - return (ok); + } +finish: + if (b != NULL) { + BUF_MEM_free(b); + } + return (ok); } #endif // OPENSSL_TRUSTY diff --git a/crypto/x509/by_file.c b/crypto/x509/by_file.c index 0714b4fc11..d45c96fda7 100644 --- a/crypto/x509/by_file.c +++ b/crypto/x509/by_file.c @@ -65,230 +65,230 @@ #ifndef OPENSSL_NO_STDIO -static int by_file_ctrl(X509_LOOKUP *ctx, int cmd, const char *argc, - long argl, char **ret); +static int by_file_ctrl(X509_LOOKUP *ctx, int cmd, const char *argc, long argl, + char **ret); static X509_LOOKUP_METHOD x509_file_lookup = { "Load file into cache", - NULL, /* new */ - NULL, /* free */ - NULL, /* init */ - NULL, /* shutdown */ - by_file_ctrl, /* ctrl */ - NULL, /* get_by_subject */ - NULL, /* get_by_issuer_serial */ - NULL, /* get_by_fingerprint */ - NULL, /* get_by_alias */ + NULL, /* new */ + NULL, /* free */ + NULL, /* init */ + NULL, /* shutdown */ + by_file_ctrl, /* ctrl */ + NULL, /* get_by_subject */ + NULL, /* get_by_issuer_serial */ + NULL, /* get_by_fingerprint */ + NULL, /* get_by_alias */ }; -X509_LOOKUP_METHOD *X509_LOOKUP_file(void) -{ - return (&x509_file_lookup); -} +X509_LOOKUP_METHOD *X509_LOOKUP_file(void) { return (&x509_file_lookup); } -static int by_file_ctrl(X509_LOOKUP *ctx, int cmd, const char *argp, - long argl, char **ret) -{ - int ok = 0; - const char *file; +static int by_file_ctrl(X509_LOOKUP *ctx, int cmd, const char *argp, long argl, + char **ret) { + int ok = 0; + const char *file; - switch (cmd) { + switch (cmd) { case X509_L_FILE_LOAD: - if (argl == X509_FILETYPE_DEFAULT) { - file = getenv(X509_get_default_cert_file_env()); - if (file) - ok = (X509_load_cert_crl_file(ctx, file, - X509_FILETYPE_PEM) != 0); + if (argl == X509_FILETYPE_DEFAULT) { + file = getenv(X509_get_default_cert_file_env()); + if (file) { + ok = (X509_load_cert_crl_file(ctx, file, X509_FILETYPE_PEM) != 0); + } - else - ok = (X509_load_cert_crl_file - (ctx, X509_get_default_cert_file(), - X509_FILETYPE_PEM) != 0); + else { + ok = (X509_load_cert_crl_file(ctx, X509_get_default_cert_file(), + X509_FILETYPE_PEM) != 0); + } - if (!ok) { - OPENSSL_PUT_ERROR(X509, X509_R_LOADING_DEFAULTS); - } + if (!ok) { + OPENSSL_PUT_ERROR(X509, X509_R_LOADING_DEFAULTS); + } + } else { + if (argl == X509_FILETYPE_PEM) { + ok = (X509_load_cert_crl_file(ctx, argp, X509_FILETYPE_PEM) != 0); } else { - if (argl == X509_FILETYPE_PEM) - ok = (X509_load_cert_crl_file(ctx, argp, - X509_FILETYPE_PEM) != 0); - else - ok = (X509_load_cert_file(ctx, argp, (int)argl) != 0); + ok = (X509_load_cert_file(ctx, argp, (int)argl) != 0); } - break; - } - return (ok); + } + break; + } + return (ok); } -int X509_load_cert_file(X509_LOOKUP *ctx, const char *file, int type) -{ - int ret = 0; - BIO *in = NULL; - int i, count = 0; - X509 *x = NULL; +int X509_load_cert_file(X509_LOOKUP *ctx, const char *file, int type) { + int ret = 0; + BIO *in = NULL; + int i, count = 0; + X509 *x = NULL; - in = BIO_new(BIO_s_file()); + in = BIO_new(BIO_s_file()); - if ((in == NULL) || (BIO_read_filename(in, file) <= 0)) { - OPENSSL_PUT_ERROR(X509, ERR_R_SYS_LIB); - goto err; - } + if ((in == NULL) || (BIO_read_filename(in, file) <= 0)) { + OPENSSL_PUT_ERROR(X509, ERR_R_SYS_LIB); + goto err; + } - if (type == X509_FILETYPE_PEM) { - for (;;) { - x = PEM_read_bio_X509_AUX(in, NULL, NULL, NULL); - if (x == NULL) { - uint32_t error = ERR_peek_last_error(); - if (ERR_GET_LIB(error) == ERR_LIB_PEM && - ERR_GET_REASON(error) == PEM_R_NO_START_LINE && - count > 0) { - ERR_clear_error(); - break; - } - OPENSSL_PUT_ERROR(X509, ERR_R_PEM_LIB); - goto err; - } - i = X509_STORE_add_cert(ctx->store_ctx, x); - if (!i) - goto err; - count++; - X509_free(x); - x = NULL; + if (type == X509_FILETYPE_PEM) { + for (;;) { + x = PEM_read_bio_X509_AUX(in, NULL, NULL, NULL); + if (x == NULL) { + uint32_t error = ERR_peek_last_error(); + if (ERR_GET_LIB(error) == ERR_LIB_PEM && + ERR_GET_REASON(error) == PEM_R_NO_START_LINE && count > 0) { + ERR_clear_error(); + break; } - ret = count; - } else if (type == X509_FILETYPE_ASN1) { - x = d2i_X509_bio(in, NULL); - if (x == NULL) { - OPENSSL_PUT_ERROR(X509, ERR_R_ASN1_LIB); - goto err; - } - i = X509_STORE_add_cert(ctx->store_ctx, x); - if (!i) - goto err; - ret = i; - } else { - OPENSSL_PUT_ERROR(X509, X509_R_BAD_X509_FILETYPE); + OPENSSL_PUT_ERROR(X509, ERR_R_PEM_LIB); goto err; + } + i = X509_STORE_add_cert(ctx->store_ctx, x); + if (!i) { + goto err; + } + count++; + X509_free(x); + x = NULL; } - - if (ret == 0) { - OPENSSL_PUT_ERROR(X509, X509_R_NO_CERTIFICATE_FOUND); + ret = count; + } else if (type == X509_FILETYPE_ASN1) { + x = d2i_X509_bio(in, NULL); + if (x == NULL) { + OPENSSL_PUT_ERROR(X509, ERR_R_ASN1_LIB); + goto err; } + i = X509_STORE_add_cert(ctx->store_ctx, x); + if (!i) { + goto err; + } + ret = i; + } else { + OPENSSL_PUT_ERROR(X509, X509_R_BAD_X509_FILETYPE); + goto err; + } + + if (ret == 0) { + OPENSSL_PUT_ERROR(X509, X509_R_NO_CERTIFICATE_FOUND); + } - err: - if (x != NULL) - X509_free(x); - if (in != NULL) - BIO_free(in); - return (ret); +err: + if (x != NULL) { + X509_free(x); + } + if (in != NULL) { + BIO_free(in); + } + return (ret); } -int X509_load_crl_file(X509_LOOKUP *ctx, const char *file, int type) -{ - int ret = 0; - BIO *in = NULL; - int i, count = 0; - X509_CRL *x = NULL; +int X509_load_crl_file(X509_LOOKUP *ctx, const char *file, int type) { + int ret = 0; + BIO *in = NULL; + int i, count = 0; + X509_CRL *x = NULL; - in = BIO_new(BIO_s_file()); + in = BIO_new(BIO_s_file()); - if ((in == NULL) || (BIO_read_filename(in, file) <= 0)) { - OPENSSL_PUT_ERROR(X509, ERR_R_SYS_LIB); - goto err; - } + if ((in == NULL) || (BIO_read_filename(in, file) <= 0)) { + OPENSSL_PUT_ERROR(X509, ERR_R_SYS_LIB); + goto err; + } - if (type == X509_FILETYPE_PEM) { - for (;;) { - x = PEM_read_bio_X509_CRL(in, NULL, NULL, NULL); - if (x == NULL) { - uint32_t error = ERR_peek_last_error(); - if (ERR_GET_LIB(error) == ERR_LIB_PEM && - ERR_GET_REASON(error) == PEM_R_NO_START_LINE && - count > 0) { - ERR_clear_error(); - break; - } - OPENSSL_PUT_ERROR(X509, ERR_R_PEM_LIB); - goto err; - } - i = X509_STORE_add_crl(ctx->store_ctx, x); - if (!i) - goto err; - count++; - X509_CRL_free(x); - x = NULL; + if (type == X509_FILETYPE_PEM) { + for (;;) { + x = PEM_read_bio_X509_CRL(in, NULL, NULL, NULL); + if (x == NULL) { + uint32_t error = ERR_peek_last_error(); + if (ERR_GET_LIB(error) == ERR_LIB_PEM && + ERR_GET_REASON(error) == PEM_R_NO_START_LINE && count > 0) { + ERR_clear_error(); + break; } - ret = count; - } else if (type == X509_FILETYPE_ASN1) { - x = d2i_X509_CRL_bio(in, NULL); - if (x == NULL) { - OPENSSL_PUT_ERROR(X509, ERR_R_ASN1_LIB); - goto err; - } - i = X509_STORE_add_crl(ctx->store_ctx, x); - if (!i) - goto err; - ret = i; - } else { - OPENSSL_PUT_ERROR(X509, X509_R_BAD_X509_FILETYPE); + OPENSSL_PUT_ERROR(X509, ERR_R_PEM_LIB); goto err; + } + i = X509_STORE_add_crl(ctx->store_ctx, x); + if (!i) { + goto err; + } + count++; + X509_CRL_free(x); + x = NULL; } - - if (ret == 0) { - OPENSSL_PUT_ERROR(X509, X509_R_NO_CRL_FOUND); + ret = count; + } else if (type == X509_FILETYPE_ASN1) { + x = d2i_X509_CRL_bio(in, NULL); + if (x == NULL) { + OPENSSL_PUT_ERROR(X509, ERR_R_ASN1_LIB); + goto err; } + i = X509_STORE_add_crl(ctx->store_ctx, x); + if (!i) { + goto err; + } + ret = i; + } else { + OPENSSL_PUT_ERROR(X509, X509_R_BAD_X509_FILETYPE); + goto err; + } + + if (ret == 0) { + OPENSSL_PUT_ERROR(X509, X509_R_NO_CRL_FOUND); + } - err: - if (x != NULL) - X509_CRL_free(x); - if (in != NULL) - BIO_free(in); - return (ret); +err: + if (x != NULL) { + X509_CRL_free(x); + } + if (in != NULL) { + BIO_free(in); + } + return (ret); } -int X509_load_cert_crl_file(X509_LOOKUP *ctx, const char *file, int type) -{ - STACK_OF(X509_INFO) *inf; - X509_INFO *itmp; - BIO *in; - size_t i; - int count = 0; +int X509_load_cert_crl_file(X509_LOOKUP *ctx, const char *file, int type) { + STACK_OF(X509_INFO) *inf; + X509_INFO *itmp; + BIO *in; + size_t i; + int count = 0; - if (type != X509_FILETYPE_PEM) - return X509_load_cert_file(ctx, file, type); - in = BIO_new_file(file, "r"); - if (!in) { - OPENSSL_PUT_ERROR(X509, ERR_R_SYS_LIB); - return 0; - } - inf = PEM_X509_INFO_read_bio(in, NULL, NULL, NULL); - BIO_free(in); - if (!inf) { - OPENSSL_PUT_ERROR(X509, ERR_R_PEM_LIB); - return 0; + if (type != X509_FILETYPE_PEM) { + return X509_load_cert_file(ctx, file, type); + } + in = BIO_new_file(file, "r"); + if (!in) { + OPENSSL_PUT_ERROR(X509, ERR_R_SYS_LIB); + return 0; + } + inf = PEM_X509_INFO_read_bio(in, NULL, NULL, NULL); + BIO_free(in); + if (!inf) { + OPENSSL_PUT_ERROR(X509, ERR_R_PEM_LIB); + return 0; + } + for (i = 0; i < sk_X509_INFO_num(inf); i++) { + itmp = sk_X509_INFO_value(inf, i); + if (itmp->x509) { + if (!X509_STORE_add_cert(ctx->store_ctx, itmp->x509)) { + goto err; + } + count++; } - for (i = 0; i < sk_X509_INFO_num(inf); i++) { - itmp = sk_X509_INFO_value(inf, i); - if (itmp->x509) { - if (!X509_STORE_add_cert(ctx->store_ctx, itmp->x509)) { - goto err; - } - count++; - } - if (itmp->crl) { - if (!X509_STORE_add_crl(ctx->store_ctx, itmp->crl)) { - goto err; - } - count++; - } + if (itmp->crl) { + if (!X509_STORE_add_crl(ctx->store_ctx, itmp->crl)) { + goto err; + } + count++; } + } - if (count == 0) { - OPENSSL_PUT_ERROR(X509, X509_R_NO_CERTIFICATE_OR_CRL_FOUND); - } + if (count == 0) { + OPENSSL_PUT_ERROR(X509, X509_R_NO_CERTIFICATE_OR_CRL_FOUND); + } err: - sk_X509_INFO_pop_free(inf, X509_INFO_free); - return count; + sk_X509_INFO_pop_free(inf, X509_INFO_free); + return count; } -#endif /* OPENSSL_NO_STDIO */ +#endif /* OPENSSL_NO_STDIO */ diff --git a/crypto/x509/i2d_pr.c b/crypto/x509/i2d_pr.c index c3fb8a8a63..456ab8bfb3 100644 --- a/crypto/x509/i2d_pr.c +++ b/crypto/x509/i2d_pr.c @@ -56,28 +56,27 @@ * [including the GNU Public Licence.] */ #include +#include #include #include #include #include -#include -int i2d_PrivateKey(const EVP_PKEY *a, uint8_t **pp) -{ - switch (EVP_PKEY_id(a)) { +int i2d_PrivateKey(const EVP_PKEY *a, uint8_t **pp) { + switch (EVP_PKEY_id(a)) { case EVP_PKEY_RSA: - return i2d_RSAPrivateKey(a->pkey.rsa, pp); + return i2d_RSAPrivateKey(a->pkey.rsa, pp); case EVP_PKEY_EC: - return i2d_ECPrivateKey(a->pkey.ec, pp); + return i2d_ECPrivateKey(a->pkey.ec, pp); case EVP_PKEY_DSA: - return i2d_DSAPrivateKey(a->pkey.dsa, pp); + return i2d_DSAPrivateKey(a->pkey.dsa, pp); default: - /* - * Although this file is in crypto/x509 for layering reasons, it emits - * an error code from ASN1 for OpenSSL compatibility. - */ - OPENSSL_PUT_ERROR(ASN1, ASN1_R_UNSUPPORTED_PUBLIC_KEY_TYPE); - return -1; - } + /* + * Although this file is in crypto/x509 for layering reasons, it emits + * an error code from ASN1 for OpenSSL compatibility. + */ + OPENSSL_PUT_ERROR(ASN1, ASN1_R_UNSUPPORTED_PUBLIC_KEY_TYPE); + return -1; + } } diff --git a/crypto/x509/internal.h b/crypto/x509/internal.h index 78275aeb51..0f77fa083e 100644 --- a/crypto/x509/internal.h +++ b/crypto/x509/internal.h @@ -409,7 +409,7 @@ int x509_digest_verify_init(EVP_MD_CTX *ctx, const X509_ALGOR *sigalg, #if defined(__cplusplus) -} /* extern C */ +} /* extern C */ #endif -#endif /* OPENSSL_HEADER_X509_INTERNAL_H */ +#endif /* OPENSSL_HEADER_X509_INTERNAL_H */ diff --git a/crypto/x509/name_print.c b/crypto/x509/name_print.c index b5523c0f1d..9ca3a9908d 100644 --- a/crypto/x509/name_print.c +++ b/crypto/x509/name_print.c @@ -64,183 +64,190 @@ #include -static int maybe_write(BIO *out, const void *buf, int len) -{ - /* If |out| is NULL, ignore the output but report the length. */ - return out == NULL || BIO_write(out, buf, len) == len; +static int maybe_write(BIO *out, const void *buf, int len) { + /* If |out| is NULL, ignore the output but report the length. */ + return out == NULL || BIO_write(out, buf, len) == len; } /* do_indent prints |indent| spaces to |out|. */ -static int do_indent(BIO *out, int indent) -{ - for (int i = 0; i < indent; i++) { - if (!maybe_write(out, " ", 1)) { - return 0; - } +static int do_indent(BIO *out, int indent) { + for (int i = 0; i < indent; i++) { + if (!maybe_write(out, " ", 1)) { + return 0; } - return 1; + } + return 1; } -#define FN_WIDTH_LN 25 -#define FN_WIDTH_SN 10 +#define FN_WIDTH_LN 25 +#define FN_WIDTH_SN 10 static int do_name_ex(BIO *out, const X509_NAME *n, int indent, - unsigned long flags) -{ - int i, prev = -1, orflags, cnt; - int fn_opt, fn_nid; - ASN1_OBJECT *fn; - ASN1_STRING *val; - X509_NAME_ENTRY *ent; - char objtmp[80]; - const char *objbuf; - int outlen, len; - const char *sep_dn, *sep_mv, *sep_eq; - int sep_dn_len, sep_mv_len, sep_eq_len; - if (indent < 0) - indent = 0; - outlen = indent; - if (!do_indent(out, indent)) - return -1; - switch (flags & XN_FLAG_SEP_MASK) { + unsigned long flags) { + int i, prev = -1, orflags, cnt; + int fn_opt, fn_nid; + ASN1_OBJECT *fn; + ASN1_STRING *val; + X509_NAME_ENTRY *ent; + char objtmp[80]; + const char *objbuf; + int outlen, len; + const char *sep_dn, *sep_mv, *sep_eq; + int sep_dn_len, sep_mv_len, sep_eq_len; + if (indent < 0) { + indent = 0; + } + outlen = indent; + if (!do_indent(out, indent)) { + return -1; + } + switch (flags & XN_FLAG_SEP_MASK) { case XN_FLAG_SEP_MULTILINE: - sep_dn = "\n"; - sep_dn_len = 1; - sep_mv = " + "; - sep_mv_len = 3; - break; + sep_dn = "\n"; + sep_dn_len = 1; + sep_mv = " + "; + sep_mv_len = 3; + break; case XN_FLAG_SEP_COMMA_PLUS: - sep_dn = ","; - sep_dn_len = 1; - sep_mv = "+"; - sep_mv_len = 1; - indent = 0; - break; + sep_dn = ","; + sep_dn_len = 1; + sep_mv = "+"; + sep_mv_len = 1; + indent = 0; + break; case XN_FLAG_SEP_CPLUS_SPC: - sep_dn = ", "; - sep_dn_len = 2; - sep_mv = " + "; - sep_mv_len = 3; - indent = 0; - break; + sep_dn = ", "; + sep_dn_len = 2; + sep_mv = " + "; + sep_mv_len = 3; + indent = 0; + break; case XN_FLAG_SEP_SPLUS_SPC: - sep_dn = "; "; - sep_dn_len = 2; - sep_mv = " + "; - sep_mv_len = 3; - indent = 0; - break; + sep_dn = "; "; + sep_dn_len = 2; + sep_mv = " + "; + sep_mv_len = 3; + indent = 0; + break; default: + return -1; + } + + if (flags & XN_FLAG_SPC_EQ) { + sep_eq = " = "; + sep_eq_len = 3; + } else { + sep_eq = "="; + sep_eq_len = 1; + } + + fn_opt = flags & XN_FLAG_FN_MASK; + + cnt = X509_NAME_entry_count(n); + for (i = 0; i < cnt; i++) { + if (flags & XN_FLAG_DN_REV) { + ent = X509_NAME_get_entry(n, cnt - i - 1); + } else { + ent = X509_NAME_get_entry(n, i); + } + if (prev != -1) { + if (prev == X509_NAME_ENTRY_set(ent)) { + if (!maybe_write(out, sep_mv, sep_mv_len)) { + return -1; + } + outlen += sep_mv_len; + } else { + if (!maybe_write(out, sep_dn, sep_dn_len)) { + return -1; + } + outlen += sep_dn_len; + if (!do_indent(out, indent)) { + return -1; + } + outlen += indent; + } + } + prev = X509_NAME_ENTRY_set(ent); + fn = X509_NAME_ENTRY_get_object(ent); + val = X509_NAME_ENTRY_get_data(ent); + fn_nid = OBJ_obj2nid(fn); + if (fn_opt != XN_FLAG_FN_NONE) { + int objlen, fld_len; + if ((fn_opt == XN_FLAG_FN_OID) || (fn_nid == NID_undef)) { + OBJ_obj2txt(objtmp, sizeof objtmp, fn, 1); + fld_len = 0; /* XXX: what should this be? */ + objbuf = objtmp; + } else { + if (fn_opt == XN_FLAG_FN_SN) { + fld_len = FN_WIDTH_SN; + objbuf = OBJ_nid2sn(fn_nid); + } else if (fn_opt == XN_FLAG_FN_LN) { + fld_len = FN_WIDTH_LN; + objbuf = OBJ_nid2ln(fn_nid); + } else { + fld_len = 0; /* XXX: what should this be? */ + objbuf = ""; + } + } + objlen = strlen(objbuf); + if (!maybe_write(out, objbuf, objlen)) { + return -1; + } + if ((objlen < fld_len) && (flags & XN_FLAG_FN_ALIGN)) { + if (!do_indent(out, fld_len - objlen)) { + return -1; + } + outlen += fld_len - objlen; + } + if (!maybe_write(out, sep_eq, sep_eq_len)) { return -1; + } + outlen += objlen + sep_eq_len; } - - if (flags & XN_FLAG_SPC_EQ) { - sep_eq = " = "; - sep_eq_len = 3; + /* + * If the field name is unknown then fix up the DER dump flag. We + * might want to limit this further so it will DER dump on anything + * other than a few 'standard' fields. + */ + if ((fn_nid == NID_undef) && (flags & XN_FLAG_DUMP_UNKNOWN_FIELDS)) { + orflags = ASN1_STRFLGS_DUMP_ALL; } else { - sep_eq = "="; - sep_eq_len = 1; + orflags = 0; } - fn_opt = flags & XN_FLAG_FN_MASK; - - cnt = X509_NAME_entry_count(n); - for (i = 0; i < cnt; i++) { - if (flags & XN_FLAG_DN_REV) - ent = X509_NAME_get_entry(n, cnt - i - 1); - else - ent = X509_NAME_get_entry(n, i); - if (prev != -1) { - if (prev == X509_NAME_ENTRY_set(ent)) { - if (!maybe_write(out, sep_mv, sep_mv_len)) - return -1; - outlen += sep_mv_len; - } else { - if (!maybe_write(out, sep_dn, sep_dn_len)) - return -1; - outlen += sep_dn_len; - if (!do_indent(out, indent)) - return -1; - outlen += indent; - } - } - prev = X509_NAME_ENTRY_set(ent); - fn = X509_NAME_ENTRY_get_object(ent); - val = X509_NAME_ENTRY_get_data(ent); - fn_nid = OBJ_obj2nid(fn); - if (fn_opt != XN_FLAG_FN_NONE) { - int objlen, fld_len; - if ((fn_opt == XN_FLAG_FN_OID) || (fn_nid == NID_undef)) { - OBJ_obj2txt(objtmp, sizeof objtmp, fn, 1); - fld_len = 0; /* XXX: what should this be? */ - objbuf = objtmp; - } else { - if (fn_opt == XN_FLAG_FN_SN) { - fld_len = FN_WIDTH_SN; - objbuf = OBJ_nid2sn(fn_nid); - } else if (fn_opt == XN_FLAG_FN_LN) { - fld_len = FN_WIDTH_LN; - objbuf = OBJ_nid2ln(fn_nid); - } else { - fld_len = 0; /* XXX: what should this be? */ - objbuf = ""; - } - } - objlen = strlen(objbuf); - if (!maybe_write(out, objbuf, objlen)) - return -1; - if ((objlen < fld_len) && (flags & XN_FLAG_FN_ALIGN)) { - if (!do_indent(out, fld_len - objlen)) - return -1; - outlen += fld_len - objlen; - } - if (!maybe_write(out, sep_eq, sep_eq_len)) - return -1; - outlen += objlen + sep_eq_len; - } - /* - * If the field name is unknown then fix up the DER dump flag. We - * might want to limit this further so it will DER dump on anything - * other than a few 'standard' fields. - */ - if ((fn_nid == NID_undef) && (flags & XN_FLAG_DUMP_UNKNOWN_FIELDS)) - orflags = ASN1_STRFLGS_DUMP_ALL; - else - orflags = 0; - - len = ASN1_STRING_print_ex(out, val, flags | orflags); - if (len < 0) - return -1; - outlen += len; + len = ASN1_STRING_print_ex(out, val, flags | orflags); + if (len < 0) { + return -1; } - return outlen; + outlen += len; + } + return outlen; } int X509_NAME_print_ex(BIO *out, const X509_NAME *nm, int indent, - unsigned long flags) -{ - if (flags == XN_FLAG_COMPAT) - return X509_NAME_print(out, nm, indent); - return do_name_ex(out, nm, indent, flags); + unsigned long flags) { + if (flags == XN_FLAG_COMPAT) { + return X509_NAME_print(out, nm, indent); + } + return do_name_ex(out, nm, indent, flags); } int X509_NAME_print_ex_fp(FILE *fp, const X509_NAME *nm, int indent, - unsigned long flags) -{ - BIO *bio = NULL; - if (fp != NULL) { - /* If |fp| is NULL, this function returns the number of bytes without - * writing. */ - bio = BIO_new_fp(fp, BIO_NOCLOSE); - if (bio == NULL) { - return -1; - } + unsigned long flags) { + BIO *bio = NULL; + if (fp != NULL) { + /* If |fp| is NULL, this function returns the number of bytes without + * writing. */ + bio = BIO_new_fp(fp, BIO_NOCLOSE); + if (bio == NULL) { + return -1; } - int ret = X509_NAME_print_ex(bio, nm, indent, flags); - BIO_free(bio); - return ret; + } + int ret = X509_NAME_print_ex(bio, nm, indent, flags); + BIO_free(bio); + return ret; } diff --git a/crypto/x509/rsa_pss.c b/crypto/x509/rsa_pss.c index 21a6bea9fa..8c503442e9 100644 --- a/crypto/x509/rsa_pss.c +++ b/crypto/x509/rsa_pss.c @@ -9,7 +9,7 @@ * are met: * * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. + * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in @@ -60,8 +60,8 @@ #include #include #include -#include #include +#include #include #include "internal.h" @@ -77,10 +77,10 @@ static int rsa_pss_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it, } ASN1_SEQUENCE_cb(RSA_PSS_PARAMS, rsa_pss_cb) = { - ASN1_EXP_OPT(RSA_PSS_PARAMS, hashAlgorithm, X509_ALGOR,0), - ASN1_EXP_OPT(RSA_PSS_PARAMS, maskGenAlgorithm, X509_ALGOR,1), - ASN1_EXP_OPT(RSA_PSS_PARAMS, saltLength, ASN1_INTEGER,2), - ASN1_EXP_OPT(RSA_PSS_PARAMS, trailerField, ASN1_INTEGER,3), + ASN1_EXP_OPT(RSA_PSS_PARAMS, hashAlgorithm, X509_ALGOR, 0), + ASN1_EXP_OPT(RSA_PSS_PARAMS, maskGenAlgorithm, X509_ALGOR, 1), + ASN1_EXP_OPT(RSA_PSS_PARAMS, saltLength, ASN1_INTEGER, 2), + ASN1_EXP_OPT(RSA_PSS_PARAMS, trailerField, ASN1_INTEGER, 3), } ASN1_SEQUENCE_END_cb(RSA_PSS_PARAMS, RSA_PSS_PARAMS) IMPLEMENT_ASN1_FUNCTIONS(RSA_PSS_PARAMS) @@ -183,8 +183,7 @@ static const EVP_MD *rsa_mgf1_to_md(const X509_ALGOR *alg, return EVP_sha1(); } /* Check mask and lookup mask hash algorithm */ - if (OBJ_obj2nid(alg->algorithm) != NID_mgf1 || - maskHash == NULL) { + if (OBJ_obj2nid(alg->algorithm) != NID_mgf1 || maskHash == NULL) { OPENSSL_PUT_ERROR(X509, X509_R_INVALID_PSS_PARAMETERS); return NULL; } @@ -230,8 +229,7 @@ int x509_rsa_ctx_to_pss(EVP_MD_CTX *ctx, X509_ALGOR *algor) { if (saltlen != 20) { pss->saltLength = ASN1_INTEGER_new(); - if (!pss->saltLength || - !ASN1_INTEGER_set(pss->saltLength, saltlen)) { + if (!pss->saltLength || !ASN1_INTEGER_set(pss->saltLength, saltlen)) { goto err; } } @@ -325,8 +323,7 @@ int x509_print_rsa_pss_params(BIO *bp, const X509_ALGOR *sigalg, int indent, goto err; } - if (BIO_puts(bp, "\n") <= 0 || - !BIO_indent(bp, indent, 128) || + if (BIO_puts(bp, "\n") <= 0 || !BIO_indent(bp, indent, 128) || BIO_puts(bp, "Hash Algorithm: ") <= 0) { goto err; } @@ -339,8 +336,7 @@ int x509_print_rsa_pss_params(BIO *bp, const X509_ALGOR *sigalg, int indent, goto err; } - if (BIO_puts(bp, "\n") <= 0 || - !BIO_indent(bp, indent, 128) || + if (BIO_puts(bp, "\n") <= 0 || !BIO_indent(bp, indent, 128) || BIO_puts(bp, "Mask Algorithm: ") <= 0) { goto err; } @@ -363,8 +359,7 @@ int x509_print_rsa_pss_params(BIO *bp, const X509_ALGOR *sigalg, int indent, } BIO_puts(bp, "\n"); - if (!BIO_indent(bp, indent, 128) || - BIO_puts(bp, "Salt Length: 0x") <= 0) { + if (!BIO_indent(bp, indent, 128) || BIO_puts(bp, "Salt Length: 0x") <= 0) { goto err; } @@ -377,8 +372,7 @@ int x509_print_rsa_pss_params(BIO *bp, const X509_ALGOR *sigalg, int indent, } BIO_puts(bp, "\n"); - if (!BIO_indent(bp, indent, 128) || - BIO_puts(bp, "Trailer Field: 0x") <= 0) { + if (!BIO_indent(bp, indent, 128) || BIO_puts(bp, "Trailer Field: 0x") <= 0) { goto err; } diff --git a/crypto/x509/t_crl.c b/crypto/x509/t_crl.c index 2aee83d6ca..1957e3175b 100644 --- a/crypto/x509/t_crl.c +++ b/crypto/x509/t_crl.c @@ -63,86 +63,83 @@ #include #include -int X509_CRL_print_fp(FILE *fp, X509_CRL *x) -{ - BIO *b = BIO_new_fp(fp, BIO_NOCLOSE); - if (b == NULL) { - OPENSSL_PUT_ERROR(X509, ERR_R_BUF_LIB); - return 0; - } - int ret = X509_CRL_print(b, x); - BIO_free(b); - return ret; +int X509_CRL_print_fp(FILE *fp, X509_CRL *x) { + BIO *b = BIO_new_fp(fp, BIO_NOCLOSE); + if (b == NULL) { + OPENSSL_PUT_ERROR(X509, ERR_R_BUF_LIB); + return 0; + } + int ret = X509_CRL_print(b, x); + BIO_free(b); + return ret; } -int X509_CRL_print(BIO *out, X509_CRL *x) -{ - long version = X509_CRL_get_version(x); - assert(X509_CRL_VERSION_1 <= version && version <= X509_CRL_VERSION_2); - const X509_ALGOR *sig_alg; - const ASN1_BIT_STRING *signature; - X509_CRL_get0_signature(x, &signature, &sig_alg); - if (BIO_printf(out, "Certificate Revocation List (CRL):\n") <= 0 || - BIO_printf(out, "%8sVersion %ld (0x%lx)\n", "", version + 1, - (unsigned long)version) <= 0 || - // Note this and the other |X509_signature_print| call both print the - // outer signature algorithm, rather than printing the inner and outer - // ones separately. This matches OpenSSL, though it was probably a bug. - !X509_signature_print(out, sig_alg, NULL)) { - return 0; - } +int X509_CRL_print(BIO *out, X509_CRL *x) { + long version = X509_CRL_get_version(x); + assert(X509_CRL_VERSION_1 <= version && version <= X509_CRL_VERSION_2); + const X509_ALGOR *sig_alg; + const ASN1_BIT_STRING *signature; + X509_CRL_get0_signature(x, &signature, &sig_alg); + if (BIO_printf(out, "Certificate Revocation List (CRL):\n") <= 0 || + BIO_printf(out, "%8sVersion %ld (0x%lx)\n", "", version + 1, + (unsigned long)version) <= 0 || + // Note this and the other |X509_signature_print| call both print the + // outer signature algorithm, rather than printing the inner and outer + // ones separately. This matches OpenSSL, though it was probably a bug. + !X509_signature_print(out, sig_alg, NULL)) { + return 0; + } - char *issuer = X509_NAME_oneline(X509_CRL_get_issuer(x), NULL, 0); - int ok = issuer != NULL && - BIO_printf(out, "%8sIssuer: %s\n", "", issuer) > 0; - OPENSSL_free(issuer); - if (!ok) { - return 0; - } + char *issuer = X509_NAME_oneline(X509_CRL_get_issuer(x), NULL, 0); + int ok = issuer != NULL && BIO_printf(out, "%8sIssuer: %s\n", "", issuer) > 0; + OPENSSL_free(issuer); + if (!ok) { + return 0; + } - if (BIO_printf(out, "%8sLast Update: ", "") <= 0 || - !ASN1_TIME_print(out, X509_CRL_get0_lastUpdate(x)) || - BIO_printf(out, "\n%8sNext Update: ", "") <= 0) { - return 0; + if (BIO_printf(out, "%8sLast Update: ", "") <= 0 || + !ASN1_TIME_print(out, X509_CRL_get0_lastUpdate(x)) || + BIO_printf(out, "\n%8sNext Update: ", "") <= 0) { + return 0; + } + if (X509_CRL_get0_nextUpdate(x)) { + if (!ASN1_TIME_print(out, X509_CRL_get0_nextUpdate(x))) { + return 0; } - if (X509_CRL_get0_nextUpdate(x)) { - if (!ASN1_TIME_print(out, X509_CRL_get0_nextUpdate(x))) { - return 0; - } - } else { - if (BIO_printf(out, "NONE") <= 0) { - return 0; - } + } else { + if (BIO_printf(out, "NONE") <= 0) { + return 0; } + } - if (BIO_printf(out, "\n") <= 0 || - !X509V3_extensions_print(out, "CRL extensions", - X509_CRL_get0_extensions(x), 0, 8)) { - return 0; - } + if (BIO_printf(out, "\n") <= 0 || + !X509V3_extensions_print(out, "CRL extensions", + X509_CRL_get0_extensions(x), 0, 8)) { + return 0; + } - const STACK_OF(X509_REVOKED) *rev = X509_CRL_get_REVOKED(x); - if (sk_X509_REVOKED_num(rev) > 0) { - if (BIO_printf(out, "Revoked Certificates:\n") <= 0) { - return 0; - } - } else { - if (BIO_printf(out, "No Revoked Certificates.\n") <= 0) { - return 0; - } + const STACK_OF(X509_REVOKED) *rev = X509_CRL_get_REVOKED(x); + if (sk_X509_REVOKED_num(rev) > 0) { + if (BIO_printf(out, "Revoked Certificates:\n") <= 0) { + return 0; + } + } else { + if (BIO_printf(out, "No Revoked Certificates.\n") <= 0) { + return 0; } + } - for (size_t i = 0; i < sk_X509_REVOKED_num(rev); i++) { - const X509_REVOKED *r = sk_X509_REVOKED_value(rev, i); - if (BIO_printf(out, " Serial Number: ") <= 0 || - i2a_ASN1_INTEGER(out, X509_REVOKED_get0_serialNumber(r)) <= 0 || - BIO_printf(out, "\n Revocation Date: ") <= 0 || - !ASN1_TIME_print(out, X509_REVOKED_get0_revocationDate(r)) || - BIO_printf(out, "\n") <= 0 || - !X509V3_extensions_print(out, "CRL entry extensions", - X509_REVOKED_get0_extensions(r), 0, 8)) { - } + for (size_t i = 0; i < sk_X509_REVOKED_num(rev); i++) { + const X509_REVOKED *r = sk_X509_REVOKED_value(rev, i); + if (BIO_printf(out, " Serial Number: ") <= 0 || + i2a_ASN1_INTEGER(out, X509_REVOKED_get0_serialNumber(r)) <= 0 || + BIO_printf(out, "\n Revocation Date: ") <= 0 || + !ASN1_TIME_print(out, X509_REVOKED_get0_revocationDate(r)) || + BIO_printf(out, "\n") <= 0 || + !X509V3_extensions_print(out, "CRL entry extensions", + X509_REVOKED_get0_extensions(r), 0, 8)) { } + } - return X509_signature_print(out, sig_alg, signature); + return X509_signature_print(out, sig_alg, signature); } diff --git a/crypto/x509/t_req.c b/crypto/x509/t_req.c index 9e3ce26251..b9090b9253 100644 --- a/crypto/x509/t_req.c +++ b/crypto/x509/t_req.c @@ -82,7 +82,7 @@ int X509_REQ_print_ex(BIO *bio, X509_REQ *x, unsigned long nmflags, unsigned long cflag) { long l; EVP_PKEY *pkey; - STACK_OF(X509_ATTRIBUTE) * sk; + STACK_OF(X509_ATTRIBUTE) *sk; char mlch = ' '; int nmindent = 0; @@ -187,10 +187,8 @@ int X509_REQ_print_ex(BIO *bio, X509_REQ *x, unsigned long nmflags, goto err; } - if (type == V_ASN1_PRINTABLESTRING || - type == V_ASN1_UTF8STRING || - type == V_ASN1_IA5STRING || - type == V_ASN1_T61STRING) { + if (type == V_ASN1_PRINTABLESTRING || type == V_ASN1_UTF8STRING || + type == V_ASN1_IA5STRING || type == V_ASN1_T61STRING) { if (BIO_write(bio, (char *)bs->data, bs->length) != bs->length) { goto err; } diff --git a/crypto/x509/t_x509.c b/crypto/x509/t_x509.c index 955d1cdb7f..63cb444e1d 100644 --- a/crypto/x509/t_x509.c +++ b/crypto/x509/t_x509.c @@ -70,295 +70,328 @@ int X509_print_ex_fp(FILE *fp, X509 *x, unsigned long nmflag, - unsigned long cflag) -{ - BIO *b = BIO_new_fp(fp, BIO_NOCLOSE); - if (b == NULL) { - OPENSSL_PUT_ERROR(X509, ERR_R_BUF_LIB); - return 0; - } - int ret = X509_print_ex(b, x, nmflag, cflag); - BIO_free(b); - return ret; + unsigned long cflag) { + BIO *b = BIO_new_fp(fp, BIO_NOCLOSE); + if (b == NULL) { + OPENSSL_PUT_ERROR(X509, ERR_R_BUF_LIB); + return 0; + } + int ret = X509_print_ex(b, x, nmflag, cflag); + BIO_free(b); + return ret; } -int X509_print_fp(FILE *fp, X509 *x) -{ - return X509_print_ex_fp(fp, x, XN_FLAG_COMPAT, X509_FLAG_COMPAT); +int X509_print_fp(FILE *fp, X509 *x) { + return X509_print_ex_fp(fp, x, XN_FLAG_COMPAT, X509_FLAG_COMPAT); } -int X509_print(BIO *bp, X509 *x) -{ - return X509_print_ex(bp, x, XN_FLAG_COMPAT, X509_FLAG_COMPAT); +int X509_print(BIO *bp, X509 *x) { + return X509_print_ex(bp, x, XN_FLAG_COMPAT, X509_FLAG_COMPAT); } int X509_print_ex(BIO *bp, X509 *x, unsigned long nmflags, - unsigned long cflag) -{ - long l; - int ret = 0, i; - char *m = NULL, mlch = ' '; - int nmindent = 0; - X509_CINF *ci; - EVP_PKEY *pkey = NULL; - const char *neg; - - if ((nmflags & XN_FLAG_SEP_MASK) == XN_FLAG_SEP_MULTILINE) { - mlch = '\n'; - nmindent = 12; + unsigned long cflag) { + long l; + int ret = 0, i; + char *m = NULL, mlch = ' '; + int nmindent = 0; + X509_CINF *ci; + EVP_PKEY *pkey = NULL; + const char *neg; + + if ((nmflags & XN_FLAG_SEP_MASK) == XN_FLAG_SEP_MULTILINE) { + mlch = '\n'; + nmindent = 12; + } + + if (nmflags == X509_FLAG_COMPAT) { + nmindent = 16; + } + + ci = x->cert_info; + if (!(cflag & X509_FLAG_NO_HEADER)) { + if (BIO_write(bp, "Certificate:\n", 13) <= 0) { + goto err; } - - if (nmflags == X509_FLAG_COMPAT) - nmindent = 16; - - ci = x->cert_info; - if (!(cflag & X509_FLAG_NO_HEADER)) { - if (BIO_write(bp, "Certificate:\n", 13) <= 0) - goto err; - if (BIO_write(bp, " Data:\n", 10) <= 0) - goto err; + if (BIO_write(bp, " Data:\n", 10) <= 0) { + goto err; } - if (!(cflag & X509_FLAG_NO_VERSION)) { - l = X509_get_version(x); - assert(X509_VERSION_1 <= l && l <= X509_VERSION_3); - if (BIO_printf(bp, "%8sVersion: %ld (0x%lx)\n", "", l + 1, - (unsigned long)l) <= 0) { - goto err; - } + } + if (!(cflag & X509_FLAG_NO_VERSION)) { + l = X509_get_version(x); + assert(X509_VERSION_1 <= l && l <= X509_VERSION_3); + if (BIO_printf(bp, "%8sVersion: %ld (0x%lx)\n", "", l + 1, + (unsigned long)l) <= 0) { + goto err; + } + } + if (!(cflag & X509_FLAG_NO_SERIAL)) { + if (BIO_write(bp, " Serial Number:", 22) <= 0) { + goto err; } - if (!(cflag & X509_FLAG_NO_SERIAL)) { - if (BIO_write(bp, " Serial Number:", 22) <= 0) { - goto err; - } - const ASN1_INTEGER *serial = X509_get0_serialNumber(x); - uint64_t serial_u64; - if (ASN1_INTEGER_get_uint64(&serial_u64, serial)) { - assert(serial->type != V_ASN1_NEG_INTEGER); - if (BIO_printf(bp, " %" PRIu64 " (0x%" PRIx64 ")\n", serial_u64, - serial_u64) <= 0) { - goto err; - } - } else { - ERR_clear_error(); /* Clear |ASN1_INTEGER_get_uint64|'s error. */ - neg = (serial->type == V_ASN1_NEG_INTEGER) ? " (Negative)" : ""; - if (BIO_printf(bp, "\n%12s%s", "", neg) <= 0) { - goto err; - } - - for (i = 0; i < serial->length; i++) { - if (BIO_printf(bp, "%02x%c", serial->data[i], - ((i + 1 == serial->length) ? '\n' : ':')) <= 0) { - goto err; - } - } + const ASN1_INTEGER *serial = X509_get0_serialNumber(x); + uint64_t serial_u64; + if (ASN1_INTEGER_get_uint64(&serial_u64, serial)) { + assert(serial->type != V_ASN1_NEG_INTEGER); + if (BIO_printf(bp, " %" PRIu64 " (0x%" PRIx64 ")\n", serial_u64, + serial_u64) <= 0) { + goto err; + } + } else { + ERR_clear_error(); /* Clear |ASN1_INTEGER_get_uint64|'s error. */ + neg = (serial->type == V_ASN1_NEG_INTEGER) ? " (Negative)" : ""; + if (BIO_printf(bp, "\n%12s%s", "", neg) <= 0) { + goto err; + } + + for (i = 0; i < serial->length; i++) { + if (BIO_printf(bp, "%02x%c", serial->data[i], + ((i + 1 == serial->length) ? '\n' : ':')) <= 0) { + goto err; } + } } + } - if (!(cflag & X509_FLAG_NO_SIGNAME)) { - if (X509_signature_print(bp, ci->signature, NULL) <= 0) - goto err; + if (!(cflag & X509_FLAG_NO_SIGNAME)) { + if (X509_signature_print(bp, ci->signature, NULL) <= 0) { + goto err; } + } - if (!(cflag & X509_FLAG_NO_ISSUER)) { - if (BIO_printf(bp, " Issuer:%c", mlch) <= 0) - goto err; - if (X509_NAME_print_ex(bp, X509_get_issuer_name(x), nmindent, nmflags) - < 0) - goto err; - if (BIO_write(bp, "\n", 1) <= 0) - goto err; + if (!(cflag & X509_FLAG_NO_ISSUER)) { + if (BIO_printf(bp, " Issuer:%c", mlch) <= 0) { + goto err; } - if (!(cflag & X509_FLAG_NO_VALIDITY)) { - if (BIO_write(bp, " Validity\n", 17) <= 0) - goto err; - if (BIO_write(bp, " Not Before: ", 24) <= 0) - goto err; - if (!ASN1_TIME_print(bp, X509_get_notBefore(x))) - goto err; - if (BIO_write(bp, "\n Not After : ", 25) <= 0) - goto err; - if (!ASN1_TIME_print(bp, X509_get_notAfter(x))) - goto err; - if (BIO_write(bp, "\n", 1) <= 0) - goto err; + if (X509_NAME_print_ex(bp, X509_get_issuer_name(x), nmindent, nmflags) < + 0) { + goto err; } - if (!(cflag & X509_FLAG_NO_SUBJECT)) { - if (BIO_printf(bp, " Subject:%c", mlch) <= 0) - goto err; - if (X509_NAME_print_ex - (bp, X509_get_subject_name(x), nmindent, nmflags) < 0) - goto err; - if (BIO_write(bp, "\n", 1) <= 0) - goto err; + if (BIO_write(bp, "\n", 1) <= 0) { + goto err; } - if (!(cflag & X509_FLAG_NO_PUBKEY)) { - if (BIO_write(bp, " Subject Public Key Info:\n", 33) <= 0) - goto err; - if (BIO_printf(bp, "%12sPublic Key Algorithm: ", "") <= 0) - goto err; - if (i2a_ASN1_OBJECT(bp, ci->key->algor->algorithm) <= 0) - goto err; - if (BIO_puts(bp, "\n") <= 0) - goto err; - - pkey = X509_get_pubkey(x); - if (pkey == NULL) { - BIO_printf(bp, "%12sUnable to load Public Key\n", ""); - ERR_print_errors(bp); - } else { - EVP_PKEY_print_public(bp, pkey, 16, NULL); - EVP_PKEY_free(pkey); - } + } + if (!(cflag & X509_FLAG_NO_VALIDITY)) { + if (BIO_write(bp, " Validity\n", 17) <= 0) { + goto err; } - - if (!(cflag & X509_FLAG_NO_IDS)) { - if (ci->issuerUID) { - if (BIO_printf(bp, "%8sIssuer Unique ID: ", "") <= 0) - goto err; - if (!X509_signature_dump(bp, ci->issuerUID, 12)) - goto err; - } - if (ci->subjectUID) { - if (BIO_printf(bp, "%8sSubject Unique ID: ", "") <= 0) - goto err; - if (!X509_signature_dump(bp, ci->subjectUID, 12)) - goto err; - } + if (BIO_write(bp, " Not Before: ", 24) <= 0) { + goto err; } - - if (!(cflag & X509_FLAG_NO_EXTENSIONS)) - X509V3_extensions_print(bp, "X509v3 extensions", - ci->extensions, cflag, 8); - - if (!(cflag & X509_FLAG_NO_SIGDUMP)) { - if (X509_signature_print(bp, x->sig_alg, x->signature) <= 0) - goto err; + if (!ASN1_TIME_print(bp, X509_get_notBefore(x))) { + goto err; } - if (!(cflag & X509_FLAG_NO_AUX)) { - if (!X509_CERT_AUX_print(bp, x->aux, 0)) - goto err; + if (BIO_write(bp, "\n Not After : ", 25) <= 0) { + goto err; + } + if (!ASN1_TIME_print(bp, X509_get_notAfter(x))) { + goto err; + } + if (BIO_write(bp, "\n", 1) <= 0) { + goto err; + } + } + if (!(cflag & X509_FLAG_NO_SUBJECT)) { + if (BIO_printf(bp, " Subject:%c", mlch) <= 0) { + goto err; + } + if (X509_NAME_print_ex(bp, X509_get_subject_name(x), nmindent, nmflags) < + 0) { + goto err; + } + if (BIO_write(bp, "\n", 1) <= 0) { + goto err; + } + } + if (!(cflag & X509_FLAG_NO_PUBKEY)) { + if (BIO_write(bp, " Subject Public Key Info:\n", 33) <= 0) { + goto err; + } + if (BIO_printf(bp, "%12sPublic Key Algorithm: ", "") <= 0) { + goto err; + } + if (i2a_ASN1_OBJECT(bp, ci->key->algor->algorithm) <= 0) { + goto err; + } + if (BIO_puts(bp, "\n") <= 0) { + goto err; } - ret = 1; - err: - if (m != NULL) - OPENSSL_free(m); - return (ret); -} -int X509_ocspid_print(BIO *bp, X509 *x) -{ - unsigned char *der = NULL; - unsigned char *dertmp; - int derlen; - int i; - unsigned char SHA1md[SHA_DIGEST_LENGTH]; - - /* - * display the hash of the subject as it would appear in OCSP requests - */ - if (BIO_printf(bp, " Subject OCSP hash: ") <= 0) - goto err; - derlen = i2d_X509_NAME(x->cert_info->subject, NULL); - if ((der = dertmp = (unsigned char *)OPENSSL_malloc(derlen)) == NULL) - goto err; - i2d_X509_NAME(x->cert_info->subject, &dertmp); + pkey = X509_get_pubkey(x); + if (pkey == NULL) { + BIO_printf(bp, "%12sUnable to load Public Key\n", ""); + ERR_print_errors(bp); + } else { + EVP_PKEY_print_public(bp, pkey, 16, NULL); + EVP_PKEY_free(pkey); + } + } - if (!EVP_Digest(der, derlen, SHA1md, NULL, EVP_sha1(), NULL)) + if (!(cflag & X509_FLAG_NO_IDS)) { + if (ci->issuerUID) { + if (BIO_printf(bp, "%8sIssuer Unique ID: ", "") <= 0) { goto err; - for (i = 0; i < SHA_DIGEST_LENGTH; i++) { - if (BIO_printf(bp, "%02X", SHA1md[i]) <= 0) - goto err; + } + if (!X509_signature_dump(bp, ci->issuerUID, 12)) { + goto err; + } } - OPENSSL_free(der); - der = NULL; - - /* - * display the hash of the public key as it would appear in OCSP requests - */ - if (BIO_printf(bp, "\n Public key OCSP hash: ") <= 0) + if (ci->subjectUID) { + if (BIO_printf(bp, "%8sSubject Unique ID: ", "") <= 0) { goto err; - - if (!EVP_Digest(x->cert_info->key->public_key->data, - x->cert_info->key->public_key->length, - SHA1md, NULL, EVP_sha1(), NULL)) + } + if (!X509_signature_dump(bp, ci->subjectUID, 12)) { goto err; - for (i = 0; i < SHA_DIGEST_LENGTH; i++) { - if (BIO_printf(bp, "%02X", SHA1md[i]) <= 0) - goto err; + } } - BIO_printf(bp, "\n"); + } + + if (!(cflag & X509_FLAG_NO_EXTENSIONS)) { + X509V3_extensions_print(bp, "X509v3 extensions", ci->extensions, cflag, 8); + } - return (1); - err: - if (der != NULL) - OPENSSL_free(der); - return (0); + if (!(cflag & X509_FLAG_NO_SIGDUMP)) { + if (X509_signature_print(bp, x->sig_alg, x->signature) <= 0) { + goto err; + } + } + if (!(cflag & X509_FLAG_NO_AUX)) { + if (!X509_CERT_AUX_print(bp, x->aux, 0)) { + goto err; + } + } + ret = 1; +err: + if (m != NULL) { + OPENSSL_free(m); + } + return (ret); } -int X509_signature_print(BIO *bp, const X509_ALGOR *sigalg, - const ASN1_STRING *sig) -{ - if (BIO_puts(bp, " Signature Algorithm: ") <= 0) - return 0; - if (i2a_ASN1_OBJECT(bp, sigalg->algorithm) <= 0) - return 0; - - /* RSA-PSS signatures have parameters to print. */ - int sig_nid = OBJ_obj2nid(sigalg->algorithm); - if (sig_nid == NID_rsassaPss && - !x509_print_rsa_pss_params(bp, sigalg, 9, 0)) { - return 0; +int X509_ocspid_print(BIO *bp, X509 *x) { + unsigned char *der = NULL; + unsigned char *dertmp; + int derlen; + int i; + unsigned char SHA1md[SHA_DIGEST_LENGTH]; + + /* + * display the hash of the subject as it would appear in OCSP requests + */ + if (BIO_printf(bp, " Subject OCSP hash: ") <= 0) { + goto err; + } + derlen = i2d_X509_NAME(x->cert_info->subject, NULL); + if ((der = dertmp = (unsigned char *)OPENSSL_malloc(derlen)) == NULL) { + goto err; + } + i2d_X509_NAME(x->cert_info->subject, &dertmp); + + if (!EVP_Digest(der, derlen, SHA1md, NULL, EVP_sha1(), NULL)) { + goto err; + } + for (i = 0; i < SHA_DIGEST_LENGTH; i++) { + if (BIO_printf(bp, "%02X", SHA1md[i]) <= 0) { + goto err; + } + } + OPENSSL_free(der); + der = NULL; + + /* + * display the hash of the public key as it would appear in OCSP requests + */ + if (BIO_printf(bp, "\n Public key OCSP hash: ") <= 0) { + goto err; + } + + if (!EVP_Digest(x->cert_info->key->public_key->data, + x->cert_info->key->public_key->length, SHA1md, NULL, + EVP_sha1(), NULL)) { + goto err; + } + for (i = 0; i < SHA_DIGEST_LENGTH; i++) { + if (BIO_printf(bp, "%02X", SHA1md[i]) <= 0) { + goto err; } + } + BIO_printf(bp, "\n"); - if (sig) - return X509_signature_dump(bp, sig, 9); - else if (BIO_puts(bp, "\n") <= 0) - return 0; - return 1; + return (1); +err: + if (der != NULL) { + OPENSSL_free(der); + } + return (0); } -int X509_NAME_print(BIO *bp, const X509_NAME *name, int obase) -{ - char *s, *c, *b; - int ret = 0, i; - - b = X509_NAME_oneline(name, NULL, 0); - if (!b) - return 0; - if (!*b) { - OPENSSL_free(b); - return 1; - } - s = b + 1; /* skip the first slash */ - - c = s; - for (;;) { - if (((*s == '/') && - ((s[1] >= 'A') && (s[1] <= 'Z') && ((s[2] == '=') || - ((s[2] >= 'A') - && (s[2] <= 'Z') - && (s[3] == '=')) - ))) || (*s == '\0')) { - i = s - c; - if (BIO_write(bp, c, i) != i) - goto err; - c = s + 1; /* skip following slash */ - if (*s != '\0') { - if (BIO_write(bp, ", ", 2) != 2) - goto err; - } +int X509_signature_print(BIO *bp, const X509_ALGOR *sigalg, + const ASN1_STRING *sig) { + if (BIO_puts(bp, " Signature Algorithm: ") <= 0) { + return 0; + } + if (i2a_ASN1_OBJECT(bp, sigalg->algorithm) <= 0) { + return 0; + } + + /* RSA-PSS signatures have parameters to print. */ + int sig_nid = OBJ_obj2nid(sigalg->algorithm); + if (sig_nid == NID_rsassaPss && + !x509_print_rsa_pss_params(bp, sigalg, 9, 0)) { + return 0; + } + + if (sig) { + return X509_signature_dump(bp, sig, 9); + } else if (BIO_puts(bp, "\n") <= 0) { + return 0; + } + return 1; +} + +int X509_NAME_print(BIO *bp, const X509_NAME *name, int obase) { + char *s, *c, *b; + int ret = 0, i; + + b = X509_NAME_oneline(name, NULL, 0); + if (!b) { + return 0; + } + if (!*b) { + OPENSSL_free(b); + return 1; + } + s = b + 1; /* skip the first slash */ + + c = s; + for (;;) { + if (((*s == '/') && ((s[1] >= 'A') && (s[1] <= 'Z') && + ((s[2] == '=') || ((s[2] >= 'A') && (s[2] <= 'Z') && + (s[3] == '='))))) || + (*s == '\0')) { + i = s - c; + if (BIO_write(bp, c, i) != i) { + goto err; + } + c = s + 1; /* skip following slash */ + if (*s != '\0') { + if (BIO_write(bp, ", ", 2) != 2) { + goto err; } - if (*s == '\0') - break; - s++; + } } - - ret = 1; - if (0) { - err: - OPENSSL_PUT_ERROR(X509, ERR_R_BUF_LIB); + if (*s == '\0') { + break; } - OPENSSL_free(b); - return (ret); + s++; + } + + ret = 1; + if (0) { + err: + OPENSSL_PUT_ERROR(X509, ERR_R_BUF_LIB); + } + OPENSSL_free(b); + return (ret); } diff --git a/crypto/x509/t_x509a.c b/crypto/x509/t_x509a.c index 4c7b2128fd..f8495e32b2 100644 --- a/crypto/x509/t_x509a.c +++ b/crypto/x509/t_x509a.c @@ -65,52 +65,57 @@ /* X509_CERT_AUX and string set routines */ -int X509_CERT_AUX_print(BIO *out, X509_CERT_AUX *aux, int indent) -{ - char oidstr[80], first; - size_t i; - int j; - if (!aux) - return 1; - if (aux->trust) { - first = 1; - BIO_printf(out, "%*sTrusted Uses:\n%*s", indent, "", indent + 2, ""); - for (i = 0; i < sk_ASN1_OBJECT_num(aux->trust); i++) { - if (!first) - BIO_puts(out, ", "); - else - first = 0; - OBJ_obj2txt(oidstr, sizeof oidstr, - sk_ASN1_OBJECT_value(aux->trust, i), 0); - BIO_puts(out, oidstr); - } - BIO_puts(out, "\n"); - } else - BIO_printf(out, "%*sNo Trusted Uses.\n", indent, ""); - if (aux->reject) { - first = 1; - BIO_printf(out, "%*sRejected Uses:\n%*s", indent, "", indent + 2, ""); - for (i = 0; i < sk_ASN1_OBJECT_num(aux->reject); i++) { - if (!first) - BIO_puts(out, ", "); - else - first = 0; - OBJ_obj2txt(oidstr, sizeof oidstr, - sk_ASN1_OBJECT_value(aux->reject, i), 0); - BIO_puts(out, oidstr); - } - BIO_puts(out, "\n"); - } else - BIO_printf(out, "%*sNo Rejected Uses.\n", indent, ""); - if (aux->alias) { - BIO_printf(out, "%*sAlias: %.*s\n", indent, "", aux->alias->length, - aux->alias->data); +int X509_CERT_AUX_print(BIO *out, X509_CERT_AUX *aux, int indent) { + char oidstr[80], first; + size_t i; + int j; + if (!aux) { + return 1; + } + if (aux->trust) { + first = 1; + BIO_printf(out, "%*sTrusted Uses:\n%*s", indent, "", indent + 2, ""); + for (i = 0; i < sk_ASN1_OBJECT_num(aux->trust); i++) { + if (!first) { + BIO_puts(out, ", "); + } else { + first = 0; + } + OBJ_obj2txt(oidstr, sizeof oidstr, sk_ASN1_OBJECT_value(aux->trust, i), + 0); + BIO_puts(out, oidstr); } - if (aux->keyid) { - BIO_printf(out, "%*sKey Id: ", indent, ""); - for (j = 0; j < aux->keyid->length; j++) - BIO_printf(out, "%s%02X", j ? ":" : "", aux->keyid->data[j]); - BIO_write(out, "\n", 1); + BIO_puts(out, "\n"); + } else { + BIO_printf(out, "%*sNo Trusted Uses.\n", indent, ""); + } + if (aux->reject) { + first = 1; + BIO_printf(out, "%*sRejected Uses:\n%*s", indent, "", indent + 2, ""); + for (i = 0; i < sk_ASN1_OBJECT_num(aux->reject); i++) { + if (!first) { + BIO_puts(out, ", "); + } else { + first = 0; + } + OBJ_obj2txt(oidstr, sizeof oidstr, sk_ASN1_OBJECT_value(aux->reject, i), + 0); + BIO_puts(out, oidstr); } - return 1; + BIO_puts(out, "\n"); + } else { + BIO_printf(out, "%*sNo Rejected Uses.\n", indent, ""); + } + if (aux->alias) { + BIO_printf(out, "%*sAlias: %.*s\n", indent, "", aux->alias->length, + aux->alias->data); + } + if (aux->keyid) { + BIO_printf(out, "%*sKey Id: ", indent, ""); + for (j = 0; j < aux->keyid->length; j++) { + BIO_printf(out, "%s%02X", j ? ":" : "", aux->keyid->data[j]); + } + BIO_write(out, "\n", 1); + } + return 1; } diff --git a/crypto/x509/x509.c b/crypto/x509/x509.c index 9049a35d58..0ae368e6a9 100644 --- a/crypto/x509/x509.c +++ b/crypto/x509/x509.c @@ -73,8 +73,7 @@ int X509_signature_dump(BIO *bp, const ASN1_STRING *sig, int indent) { s = sig->data; for (i = 0; i < n; i++) { if ((i % 18) == 0) { - if (BIO_write(bp, "\n", 1) <= 0 || - BIO_indent(bp, indent, indent) <= 0) { + if (BIO_write(bp, "\n", 1) <= 0 || BIO_indent(bp, indent, indent) <= 0) { return 0; } } diff --git a/crypto/x509/x509_att.c b/crypto/x509/x509_att.c index e2a5121a80..3824a6e6eb 100644 --- a/crypto/x509/x509_att.c +++ b/crypto/x509/x509_att.c @@ -66,293 +66,306 @@ #include "internal.h" -int X509at_get_attr_count(const STACK_OF(X509_ATTRIBUTE) *x) -{ - return sk_X509_ATTRIBUTE_num(x); +int X509at_get_attr_count(const STACK_OF(X509_ATTRIBUTE) *x) { + return sk_X509_ATTRIBUTE_num(x); } int X509at_get_attr_by_NID(const STACK_OF(X509_ATTRIBUTE) *x, int nid, - int lastpos) -{ - const ASN1_OBJECT *obj = OBJ_nid2obj(nid); - if (obj == NULL) { - return -1; - } - return X509at_get_attr_by_OBJ(x, obj, lastpos); + int lastpos) { + const ASN1_OBJECT *obj = OBJ_nid2obj(nid); + if (obj == NULL) { + return -1; + } + return X509at_get_attr_by_OBJ(x, obj, lastpos); } int X509at_get_attr_by_OBJ(const STACK_OF(X509_ATTRIBUTE) *sk, - const ASN1_OBJECT *obj, int lastpos) -{ - int n; - X509_ATTRIBUTE *ex; + const ASN1_OBJECT *obj, int lastpos) { + int n; + X509_ATTRIBUTE *ex; - if (sk == NULL) - return (-1); - lastpos++; - if (lastpos < 0) - lastpos = 0; - n = sk_X509_ATTRIBUTE_num(sk); - for (; lastpos < n; lastpos++) { - ex = sk_X509_ATTRIBUTE_value(sk, lastpos); - if (OBJ_cmp(ex->object, obj) == 0) - return (lastpos); - } + if (sk == NULL) { return (-1); + } + lastpos++; + if (lastpos < 0) { + lastpos = 0; + } + n = sk_X509_ATTRIBUTE_num(sk); + for (; lastpos < n; lastpos++) { + ex = sk_X509_ATTRIBUTE_value(sk, lastpos); + if (OBJ_cmp(ex->object, obj) == 0) { + return (lastpos); + } + } + return (-1); } -X509_ATTRIBUTE *X509at_get_attr(const STACK_OF(X509_ATTRIBUTE) *x, int loc) -{ - if (x == NULL || loc < 0 || sk_X509_ATTRIBUTE_num(x) <= (size_t)loc) - return NULL; - else - return sk_X509_ATTRIBUTE_value(x, loc); +X509_ATTRIBUTE *X509at_get_attr(const STACK_OF(X509_ATTRIBUTE) *x, int loc) { + if (x == NULL || loc < 0 || sk_X509_ATTRIBUTE_num(x) <= (size_t)loc) { + return NULL; + } else { + return sk_X509_ATTRIBUTE_value(x, loc); + } } -X509_ATTRIBUTE *X509at_delete_attr(STACK_OF(X509_ATTRIBUTE) *x, int loc) -{ - X509_ATTRIBUTE *ret; +X509_ATTRIBUTE *X509at_delete_attr(STACK_OF(X509_ATTRIBUTE) *x, int loc) { + X509_ATTRIBUTE *ret; - if (x == NULL || loc < 0 || sk_X509_ATTRIBUTE_num(x) <= (size_t)loc) - return (NULL); - ret = sk_X509_ATTRIBUTE_delete(x, loc); - return (ret); + if (x == NULL || loc < 0 || sk_X509_ATTRIBUTE_num(x) <= (size_t)loc) { + return (NULL); + } + ret = sk_X509_ATTRIBUTE_delete(x, loc); + return (ret); } STACK_OF(X509_ATTRIBUTE) *X509at_add1_attr(STACK_OF(X509_ATTRIBUTE) **x, - X509_ATTRIBUTE *attr) -{ - X509_ATTRIBUTE *new_attr = NULL; - STACK_OF(X509_ATTRIBUTE) *sk = NULL; + X509_ATTRIBUTE *attr) { + X509_ATTRIBUTE *new_attr = NULL; + STACK_OF(X509_ATTRIBUTE) *sk = NULL; - if (x == NULL) { - OPENSSL_PUT_ERROR(X509, ERR_R_PASSED_NULL_PARAMETER); - goto err2; - } + if (x == NULL) { + OPENSSL_PUT_ERROR(X509, ERR_R_PASSED_NULL_PARAMETER); + goto err2; + } - if (*x == NULL) { - if ((sk = sk_X509_ATTRIBUTE_new_null()) == NULL) - goto err; - } else - sk = *x; + if (*x == NULL) { + if ((sk = sk_X509_ATTRIBUTE_new_null()) == NULL) { + goto err; + } + } else { + sk = *x; + } - if ((new_attr = X509_ATTRIBUTE_dup(attr)) == NULL) - goto err2; - if (!sk_X509_ATTRIBUTE_push(sk, new_attr)) - goto err; - if (*x == NULL) - *x = sk; - return (sk); - err: - OPENSSL_PUT_ERROR(X509, ERR_R_MALLOC_FAILURE); - err2: - if (new_attr != NULL) - X509_ATTRIBUTE_free(new_attr); - if (sk != NULL) - sk_X509_ATTRIBUTE_free(sk); - return (NULL); + if ((new_attr = X509_ATTRIBUTE_dup(attr)) == NULL) { + goto err2; + } + if (!sk_X509_ATTRIBUTE_push(sk, new_attr)) { + goto err; + } + if (*x == NULL) { + *x = sk; + } + return (sk); +err: + OPENSSL_PUT_ERROR(X509, ERR_R_MALLOC_FAILURE); +err2: + if (new_attr != NULL) { + X509_ATTRIBUTE_free(new_attr); + } + if (sk != NULL) { + sk_X509_ATTRIBUTE_free(sk); + } + return (NULL); } -STACK_OF(X509_ATTRIBUTE) *X509at_add1_attr_by_OBJ(STACK_OF(X509_ATTRIBUTE) - **x, const ASN1_OBJECT *obj, +STACK_OF(X509_ATTRIBUTE) *X509at_add1_attr_by_OBJ(STACK_OF(X509_ATTRIBUTE) **x, + const ASN1_OBJECT *obj, int type, const unsigned char *bytes, - int len) -{ - X509_ATTRIBUTE *attr; - STACK_OF(X509_ATTRIBUTE) *ret; - attr = X509_ATTRIBUTE_create_by_OBJ(NULL, obj, type, bytes, len); - if (!attr) - return 0; - ret = X509at_add1_attr(x, attr); - X509_ATTRIBUTE_free(attr); - return ret; + int len) { + X509_ATTRIBUTE *attr; + STACK_OF(X509_ATTRIBUTE) *ret; + attr = X509_ATTRIBUTE_create_by_OBJ(NULL, obj, type, bytes, len); + if (!attr) { + return 0; + } + ret = X509at_add1_attr(x, attr); + X509_ATTRIBUTE_free(attr); + return ret; } -STACK_OF(X509_ATTRIBUTE) *X509at_add1_attr_by_NID(STACK_OF(X509_ATTRIBUTE) - **x, int nid, int type, +STACK_OF(X509_ATTRIBUTE) *X509at_add1_attr_by_NID(STACK_OF(X509_ATTRIBUTE) **x, + int nid, int type, const unsigned char *bytes, - int len) -{ - X509_ATTRIBUTE *attr; - STACK_OF(X509_ATTRIBUTE) *ret; - attr = X509_ATTRIBUTE_create_by_NID(NULL, nid, type, bytes, len); - if (!attr) - return 0; - ret = X509at_add1_attr(x, attr); - X509_ATTRIBUTE_free(attr); - return ret; + int len) { + X509_ATTRIBUTE *attr; + STACK_OF(X509_ATTRIBUTE) *ret; + attr = X509_ATTRIBUTE_create_by_NID(NULL, nid, type, bytes, len); + if (!attr) { + return 0; + } + ret = X509at_add1_attr(x, attr); + X509_ATTRIBUTE_free(attr); + return ret; } -STACK_OF(X509_ATTRIBUTE) *X509at_add1_attr_by_txt(STACK_OF(X509_ATTRIBUTE) - **x, const char *attrname, +STACK_OF(X509_ATTRIBUTE) *X509at_add1_attr_by_txt(STACK_OF(X509_ATTRIBUTE) **x, + const char *attrname, int type, const unsigned char *bytes, - int len) -{ - X509_ATTRIBUTE *attr; - STACK_OF(X509_ATTRIBUTE) *ret; - attr = X509_ATTRIBUTE_create_by_txt(NULL, attrname, type, bytes, len); - if (!attr) - return 0; - ret = X509at_add1_attr(x, attr); - X509_ATTRIBUTE_free(attr); - return ret; + int len) { + X509_ATTRIBUTE *attr; + STACK_OF(X509_ATTRIBUTE) *ret; + attr = X509_ATTRIBUTE_create_by_txt(NULL, attrname, type, bytes, len); + if (!attr) { + return 0; + } + ret = X509at_add1_attr(x, attr); + X509_ATTRIBUTE_free(attr); + return ret; } X509_ATTRIBUTE *X509_ATTRIBUTE_create_by_NID(X509_ATTRIBUTE **attr, int nid, int attrtype, const void *data, - int len) -{ - const ASN1_OBJECT *obj; + int len) { + const ASN1_OBJECT *obj; - obj = OBJ_nid2obj(nid); - if (obj == NULL) { - OPENSSL_PUT_ERROR(X509, X509_R_UNKNOWN_NID); - return (NULL); - } - return X509_ATTRIBUTE_create_by_OBJ(attr, obj, attrtype, data, len); + obj = OBJ_nid2obj(nid); + if (obj == NULL) { + OPENSSL_PUT_ERROR(X509, X509_R_UNKNOWN_NID); + return (NULL); + } + return X509_ATTRIBUTE_create_by_OBJ(attr, obj, attrtype, data, len); } X509_ATTRIBUTE *X509_ATTRIBUTE_create_by_OBJ(X509_ATTRIBUTE **attr, const ASN1_OBJECT *obj, int attrtype, const void *data, - int len) -{ - X509_ATTRIBUTE *ret; + int len) { + X509_ATTRIBUTE *ret; - if ((attr == NULL) || (*attr == NULL)) { - if ((ret = X509_ATTRIBUTE_new()) == NULL) { - OPENSSL_PUT_ERROR(X509, ERR_R_MALLOC_FAILURE); - return (NULL); - } - } else - ret = *attr; + if ((attr == NULL) || (*attr == NULL)) { + if ((ret = X509_ATTRIBUTE_new()) == NULL) { + OPENSSL_PUT_ERROR(X509, ERR_R_MALLOC_FAILURE); + return (NULL); + } + } else { + ret = *attr; + } - if (!X509_ATTRIBUTE_set1_object(ret, obj)) - goto err; - if (!X509_ATTRIBUTE_set1_data(ret, attrtype, data, len)) - goto err; + if (!X509_ATTRIBUTE_set1_object(ret, obj)) { + goto err; + } + if (!X509_ATTRIBUTE_set1_data(ret, attrtype, data, len)) { + goto err; + } - if ((attr != NULL) && (*attr == NULL)) - *attr = ret; - return (ret); - err: - if ((attr == NULL) || (ret != *attr)) - X509_ATTRIBUTE_free(ret); - return (NULL); + if ((attr != NULL) && (*attr == NULL)) { + *attr = ret; + } + return (ret); +err: + if ((attr == NULL) || (ret != *attr)) { + X509_ATTRIBUTE_free(ret); + } + return (NULL); } X509_ATTRIBUTE *X509_ATTRIBUTE_create_by_txt(X509_ATTRIBUTE **attr, const char *attrname, int type, const unsigned char *bytes, - int len) -{ - ASN1_OBJECT *obj; - X509_ATTRIBUTE *nattr; + int len) { + ASN1_OBJECT *obj; + X509_ATTRIBUTE *nattr; - obj = OBJ_txt2obj(attrname, 0); - if (obj == NULL) { - OPENSSL_PUT_ERROR(X509, X509_R_INVALID_FIELD_NAME); - ERR_add_error_data(2, "name=", attrname); - return (NULL); - } - nattr = X509_ATTRIBUTE_create_by_OBJ(attr, obj, type, bytes, len); - ASN1_OBJECT_free(obj); - return nattr; + obj = OBJ_txt2obj(attrname, 0); + if (obj == NULL) { + OPENSSL_PUT_ERROR(X509, X509_R_INVALID_FIELD_NAME); + ERR_add_error_data(2, "name=", attrname); + return (NULL); + } + nattr = X509_ATTRIBUTE_create_by_OBJ(attr, obj, type, bytes, len); + ASN1_OBJECT_free(obj); + return nattr; } -int X509_ATTRIBUTE_set1_object(X509_ATTRIBUTE *attr, const ASN1_OBJECT *obj) -{ - if ((attr == NULL) || (obj == NULL)) - return (0); - ASN1_OBJECT_free(attr->object); - attr->object = OBJ_dup(obj); - return attr->object != NULL; +int X509_ATTRIBUTE_set1_object(X509_ATTRIBUTE *attr, const ASN1_OBJECT *obj) { + if ((attr == NULL) || (obj == NULL)) { + return (0); + } + ASN1_OBJECT_free(attr->object); + attr->object = OBJ_dup(obj); + return attr->object != NULL; } int X509_ATTRIBUTE_set1_data(X509_ATTRIBUTE *attr, int attrtype, - const void *data, int len) -{ - ASN1_TYPE *ttmp = NULL; - ASN1_STRING *stmp = NULL; - int atype = 0; - if (!attr) - return 0; - if (attrtype & MBSTRING_FLAG) { - stmp = ASN1_STRING_set_by_NID(NULL, data, len, attrtype, - OBJ_obj2nid(attr->object)); - if (!stmp) { - OPENSSL_PUT_ERROR(X509, ERR_R_ASN1_LIB); - return 0; - } - atype = stmp->type; - } else if (len != -1) { - if (!(stmp = ASN1_STRING_type_new(attrtype))) - goto err; - if (!ASN1_STRING_set(stmp, data, len)) - goto err; - atype = attrtype; + const void *data, int len) { + ASN1_TYPE *ttmp = NULL; + ASN1_STRING *stmp = NULL; + int atype = 0; + if (!attr) { + return 0; + } + if (attrtype & MBSTRING_FLAG) { + stmp = ASN1_STRING_set_by_NID(NULL, data, len, attrtype, + OBJ_obj2nid(attr->object)); + if (!stmp) { + OPENSSL_PUT_ERROR(X509, ERR_R_ASN1_LIB); + return 0; } - /* - * This is a bit naughty because the attribute should really have at - * least one value but some types use and zero length SET and require - * this. - */ - if (attrtype == 0) { - ASN1_STRING_free(stmp); - return 1; + atype = stmp->type; + } else if (len != -1) { + if (!(stmp = ASN1_STRING_type_new(attrtype))) { + goto err; } - if (!(ttmp = ASN1_TYPE_new())) - goto err; - if ((len == -1) && !(attrtype & MBSTRING_FLAG)) { - if (!ASN1_TYPE_set1(ttmp, attrtype, data)) - goto err; - } else { - ASN1_TYPE_set(ttmp, atype, stmp); - stmp = NULL; + if (!ASN1_STRING_set(stmp, data, len)) { + goto err; } - if (!sk_ASN1_TYPE_push(attr->set, ttmp)) - goto err; - return 1; - err: - OPENSSL_PUT_ERROR(X509, ERR_R_MALLOC_FAILURE); - ASN1_TYPE_free(ttmp); + atype = attrtype; + } + /* + * This is a bit naughty because the attribute should really have at + * least one value but some types use and zero length SET and require + * this. + */ + if (attrtype == 0) { ASN1_STRING_free(stmp); - return 0; + return 1; + } + if (!(ttmp = ASN1_TYPE_new())) { + goto err; + } + if ((len == -1) && !(attrtype & MBSTRING_FLAG)) { + if (!ASN1_TYPE_set1(ttmp, attrtype, data)) { + goto err; + } + } else { + ASN1_TYPE_set(ttmp, atype, stmp); + stmp = NULL; + } + if (!sk_ASN1_TYPE_push(attr->set, ttmp)) { + goto err; + } + return 1; +err: + OPENSSL_PUT_ERROR(X509, ERR_R_MALLOC_FAILURE); + ASN1_TYPE_free(ttmp); + ASN1_STRING_free(stmp); + return 0; } -int X509_ATTRIBUTE_count(const X509_ATTRIBUTE *attr) -{ - return sk_ASN1_TYPE_num(attr->set); +int X509_ATTRIBUTE_count(const X509_ATTRIBUTE *attr) { + return sk_ASN1_TYPE_num(attr->set); } -ASN1_OBJECT *X509_ATTRIBUTE_get0_object(X509_ATTRIBUTE *attr) -{ - if (attr == NULL) - return (NULL); - return (attr->object); +ASN1_OBJECT *X509_ATTRIBUTE_get0_object(X509_ATTRIBUTE *attr) { + if (attr == NULL) { + return (NULL); + } + return (attr->object); } -void *X509_ATTRIBUTE_get0_data(X509_ATTRIBUTE *attr, int idx, - int attrtype, void *unused) -{ - ASN1_TYPE *ttmp; - ttmp = X509_ATTRIBUTE_get0_type(attr, idx); - if (!ttmp) - return NULL; - if (attrtype != ASN1_TYPE_get(ttmp)) { - OPENSSL_PUT_ERROR(X509, X509_R_WRONG_TYPE); - return NULL; - } - return (void *)asn1_type_value_as_pointer(ttmp); +void *X509_ATTRIBUTE_get0_data(X509_ATTRIBUTE *attr, int idx, int attrtype, + void *unused) { + ASN1_TYPE *ttmp; + ttmp = X509_ATTRIBUTE_get0_type(attr, idx); + if (!ttmp) { + return NULL; + } + if (attrtype != ASN1_TYPE_get(ttmp)) { + OPENSSL_PUT_ERROR(X509, X509_R_WRONG_TYPE); + return NULL; + } + return (void *)asn1_type_value_as_pointer(ttmp); } -ASN1_TYPE *X509_ATTRIBUTE_get0_type(X509_ATTRIBUTE *attr, int idx) -{ - if (attr == NULL) - return NULL; - if (idx >= X509_ATTRIBUTE_count(attr)) - return NULL; - return sk_ASN1_TYPE_value(attr->set, idx); +ASN1_TYPE *X509_ATTRIBUTE_get0_type(X509_ATTRIBUTE *attr, int idx) { + if (attr == NULL) { + return NULL; + } + if (idx >= X509_ATTRIBUTE_count(attr)) { + return NULL; + } + return sk_ASN1_TYPE_value(attr->set, idx); } diff --git a/crypto/x509/x509_cmp.c b/crypto/x509/x509_cmp.c index 80590e23a8..788a073195 100644 --- a/crypto/x509/x509_cmp.c +++ b/crypto/x509/x509_cmp.c @@ -71,77 +71,65 @@ #include "internal.h" -int X509_issuer_and_serial_cmp(const X509 *a, const X509 *b) -{ - int i; - X509_CINF *ai, *bi; - - ai = a->cert_info; - bi = b->cert_info; - i = ASN1_INTEGER_cmp(ai->serialNumber, bi->serialNumber); - if (i) - return (i); - return (X509_NAME_cmp(ai->issuer, bi->issuer)); +int X509_issuer_and_serial_cmp(const X509 *a, const X509 *b) { + int i; + X509_CINF *ai, *bi; + + ai = a->cert_info; + bi = b->cert_info; + i = ASN1_INTEGER_cmp(ai->serialNumber, bi->serialNumber); + if (i) { + return (i); + } + return (X509_NAME_cmp(ai->issuer, bi->issuer)); } -int X509_issuer_name_cmp(const X509 *a, const X509 *b) -{ - return (X509_NAME_cmp(a->cert_info->issuer, b->cert_info->issuer)); +int X509_issuer_name_cmp(const X509 *a, const X509 *b) { + return (X509_NAME_cmp(a->cert_info->issuer, b->cert_info->issuer)); } -int X509_subject_name_cmp(const X509 *a, const X509 *b) -{ - return (X509_NAME_cmp(a->cert_info->subject, b->cert_info->subject)); +int X509_subject_name_cmp(const X509 *a, const X509 *b) { + return (X509_NAME_cmp(a->cert_info->subject, b->cert_info->subject)); } -int X509_CRL_cmp(const X509_CRL *a, const X509_CRL *b) -{ - return (X509_NAME_cmp(a->crl->issuer, b->crl->issuer)); +int X509_CRL_cmp(const X509_CRL *a, const X509_CRL *b) { + return (X509_NAME_cmp(a->crl->issuer, b->crl->issuer)); } -int X509_CRL_match(const X509_CRL *a, const X509_CRL *b) -{ - return OPENSSL_memcmp(a->crl_hash, b->crl_hash, SHA256_DIGEST_LENGTH); +int X509_CRL_match(const X509_CRL *a, const X509_CRL *b) { + return OPENSSL_memcmp(a->crl_hash, b->crl_hash, SHA256_DIGEST_LENGTH); } -X509_NAME *X509_get_issuer_name(const X509 *a) -{ - return (a->cert_info->issuer); +X509_NAME *X509_get_issuer_name(const X509 *a) { + return (a->cert_info->issuer); } -unsigned long X509_issuer_name_hash(X509 *x) -{ - return (X509_NAME_hash(x->cert_info->issuer)); +unsigned long X509_issuer_name_hash(X509 *x) { + return (X509_NAME_hash(x->cert_info->issuer)); } -unsigned long X509_issuer_name_hash_old(X509 *x) -{ - return (X509_NAME_hash_old(x->cert_info->issuer)); +unsigned long X509_issuer_name_hash_old(X509 *x) { + return (X509_NAME_hash_old(x->cert_info->issuer)); } -X509_NAME *X509_get_subject_name(const X509 *a) -{ - return (a->cert_info->subject); +X509_NAME *X509_get_subject_name(const X509 *a) { + return (a->cert_info->subject); } -ASN1_INTEGER *X509_get_serialNumber(X509 *a) -{ - return (a->cert_info->serialNumber); +ASN1_INTEGER *X509_get_serialNumber(X509 *a) { + return (a->cert_info->serialNumber); } -const ASN1_INTEGER *X509_get0_serialNumber(const X509 *x509) -{ - return x509->cert_info->serialNumber; +const ASN1_INTEGER *X509_get0_serialNumber(const X509 *x509) { + return x509->cert_info->serialNumber; } -unsigned long X509_subject_name_hash(X509 *x) -{ - return (X509_NAME_hash(x->cert_info->subject)); +unsigned long X509_subject_name_hash(X509 *x) { + return (X509_NAME_hash(x->cert_info->subject)); } -unsigned long X509_subject_name_hash_old(X509 *x) -{ - return (X509_NAME_hash_old(x->cert_info->subject)); +unsigned long X509_subject_name_hash_old(X509 *x) { + return (X509_NAME_hash_old(x->cert_info->subject)); } /* @@ -152,64 +140,63 @@ unsigned long X509_subject_name_hash_old(X509 *x) * certain cert information is cached. So this is the point where the * "depth-first" constification tree has to halt with an evil cast. */ -int X509_cmp(const X509 *a, const X509 *b) -{ - /* Fill in the |cert_hash| fields. - * - * TODO(davidben): This may fail, in which case the the hash will be all - * zeros. This produces a consistent comparison (failures are sticky), but - * not a good one. OpenSSL now returns -2, but this is not a consistent - * comparison and may cause misbehaving sorts by transitivity. For now, we - * retain the old OpenSSL behavior, which was to ignore the error. See - * https://crbug.com/boringssl/355. */ - x509v3_cache_extensions((X509 *)a); - x509v3_cache_extensions((X509 *)b); - - return OPENSSL_memcmp(a->cert_hash, b->cert_hash, SHA256_DIGEST_LENGTH); +int X509_cmp(const X509 *a, const X509 *b) { + /* Fill in the |cert_hash| fields. + * + * TODO(davidben): This may fail, in which case the the hash will be all + * zeros. This produces a consistent comparison (failures are sticky), but + * not a good one. OpenSSL now returns -2, but this is not a consistent + * comparison and may cause misbehaving sorts by transitivity. For now, we + * retain the old OpenSSL behavior, which was to ignore the error. See + * https://crbug.com/boringssl/355. */ + x509v3_cache_extensions((X509 *)a); + x509v3_cache_extensions((X509 *)b); + + return OPENSSL_memcmp(a->cert_hash, b->cert_hash, SHA256_DIGEST_LENGTH); } -int X509_NAME_cmp(const X509_NAME *a, const X509_NAME *b) -{ - int ret; +int X509_NAME_cmp(const X509_NAME *a, const X509_NAME *b) { + int ret; - /* Ensure canonical encoding is present and up to date */ + /* Ensure canonical encoding is present and up to date */ - if (!a->canon_enc || a->modified) { - ret = i2d_X509_NAME((X509_NAME *)a, NULL); - if (ret < 0) - return -2; + if (!a->canon_enc || a->modified) { + ret = i2d_X509_NAME((X509_NAME *)a, NULL); + if (ret < 0) { + return -2; } + } - if (!b->canon_enc || b->modified) { - ret = i2d_X509_NAME((X509_NAME *)b, NULL); - if (ret < 0) - return -2; + if (!b->canon_enc || b->modified) { + ret = i2d_X509_NAME((X509_NAME *)b, NULL); + if (ret < 0) { + return -2; } + } - ret = a->canon_enclen - b->canon_enclen; + ret = a->canon_enclen - b->canon_enclen; - if (ret) - return ret; - - return OPENSSL_memcmp(a->canon_enc, b->canon_enc, a->canon_enclen); + if (ret) { + return ret; + } + return OPENSSL_memcmp(a->canon_enc, b->canon_enc, a->canon_enclen); } -unsigned long X509_NAME_hash(X509_NAME *x) -{ - unsigned long ret = 0; - unsigned char md[SHA_DIGEST_LENGTH]; +unsigned long X509_NAME_hash(X509_NAME *x) { + unsigned long ret = 0; + unsigned char md[SHA_DIGEST_LENGTH]; - /* Make sure X509_NAME structure contains valid cached encoding */ - i2d_X509_NAME(x, NULL); - if (!EVP_Digest(x->canon_enc, x->canon_enclen, md, NULL, EVP_sha1(), - NULL)) - return 0; + /* Make sure X509_NAME structure contains valid cached encoding */ + i2d_X509_NAME(x, NULL); + if (!EVP_Digest(x->canon_enc, x->canon_enclen, md, NULL, EVP_sha1(), NULL)) { + return 0; + } - ret = (((unsigned long)md[0]) | ((unsigned long)md[1] << 8L) | - ((unsigned long)md[2] << 16L) | ((unsigned long)md[3] << 24L) - ) & 0xffffffffL; - return (ret); + ret = (((unsigned long)md[0]) | ((unsigned long)md[1] << 8L) | + ((unsigned long)md[2] << 16L) | ((unsigned long)md[3] << 24L)) & + 0xffffffffL; + return (ret); } /* @@ -217,106 +204,109 @@ unsigned long X509_NAME_hash(X509_NAME *x) * this is reasonably efficient. */ -unsigned long X509_NAME_hash_old(X509_NAME *x) -{ - EVP_MD_CTX md_ctx; - unsigned long ret = 0; - unsigned char md[16]; - - /* Make sure X509_NAME structure contains valid cached encoding */ - i2d_X509_NAME(x, NULL); - EVP_MD_CTX_init(&md_ctx); - /* EVP_MD_CTX_set_flags(&md_ctx, EVP_MD_CTX_FLAG_NON_FIPS_ALLOW); */ - if (EVP_DigestInit_ex(&md_ctx, EVP_md5(), NULL) - && EVP_DigestUpdate(&md_ctx, x->bytes->data, x->bytes->length) - && EVP_DigestFinal_ex(&md_ctx, md, NULL)) - ret = (((unsigned long)md[0]) | ((unsigned long)md[1] << 8L) | - ((unsigned long)md[2] << 16L) | ((unsigned long)md[3] << 24L) - ) & 0xffffffffL; - EVP_MD_CTX_cleanup(&md_ctx); - - return (ret); +unsigned long X509_NAME_hash_old(X509_NAME *x) { + EVP_MD_CTX md_ctx; + unsigned long ret = 0; + unsigned char md[16]; + + /* Make sure X509_NAME structure contains valid cached encoding */ + i2d_X509_NAME(x, NULL); + EVP_MD_CTX_init(&md_ctx); + /* EVP_MD_CTX_set_flags(&md_ctx, EVP_MD_CTX_FLAG_NON_FIPS_ALLOW); */ + if (EVP_DigestInit_ex(&md_ctx, EVP_md5(), NULL) && + EVP_DigestUpdate(&md_ctx, x->bytes->data, x->bytes->length) && + EVP_DigestFinal_ex(&md_ctx, md, NULL)) { + ret = (((unsigned long)md[0]) | ((unsigned long)md[1] << 8L) | + ((unsigned long)md[2] << 16L) | ((unsigned long)md[3] << 24L)) & + 0xffffffffL; + } + EVP_MD_CTX_cleanup(&md_ctx); + + return (ret); } /* Search a stack of X509 for a match */ X509 *X509_find_by_issuer_and_serial(STACK_OF(X509) *sk, X509_NAME *name, - ASN1_INTEGER *serial) -{ - size_t i; - X509_CINF cinf; - X509 x, *x509 = NULL; - - if (!sk) - return NULL; - - x.cert_info = &cinf; - cinf.serialNumber = serial; - cinf.issuer = name; - - for (i = 0; i < sk_X509_num(sk); i++) { - x509 = sk_X509_value(sk, i); - if (X509_issuer_and_serial_cmp(x509, &x) == 0) - return (x509); + ASN1_INTEGER *serial) { + size_t i; + X509_CINF cinf; + X509 x, *x509 = NULL; + + if (!sk) { + return NULL; + } + + x.cert_info = &cinf; + cinf.serialNumber = serial; + cinf.issuer = name; + + for (i = 0; i < sk_X509_num(sk); i++) { + x509 = sk_X509_value(sk, i); + if (X509_issuer_and_serial_cmp(x509, &x) == 0) { + return (x509); } - return (NULL); + } + return (NULL); } -X509 *X509_find_by_subject(STACK_OF(X509) *sk, X509_NAME *name) -{ - X509 *x509; - size_t i; +X509 *X509_find_by_subject(STACK_OF(X509) *sk, X509_NAME *name) { + X509 *x509; + size_t i; - for (i = 0; i < sk_X509_num(sk); i++) { - x509 = sk_X509_value(sk, i); - if (X509_NAME_cmp(X509_get_subject_name(x509), name) == 0) - return (x509); + for (i = 0; i < sk_X509_num(sk); i++) { + x509 = sk_X509_value(sk, i); + if (X509_NAME_cmp(X509_get_subject_name(x509), name) == 0) { + return (x509); } - return (NULL); + } + return (NULL); } -EVP_PKEY *X509_get_pubkey(X509 *x) -{ - if ((x == NULL) || (x->cert_info == NULL)) - return (NULL); - return (X509_PUBKEY_get(x->cert_info->key)); +EVP_PKEY *X509_get_pubkey(X509 *x) { + if ((x == NULL) || (x->cert_info == NULL)) { + return (NULL); + } + return (X509_PUBKEY_get(x->cert_info->key)); } -ASN1_BIT_STRING *X509_get0_pubkey_bitstr(const X509 *x) -{ - if (!x) - return NULL; - return x->cert_info->key->public_key; +ASN1_BIT_STRING *X509_get0_pubkey_bitstr(const X509 *x) { + if (!x) { + return NULL; + } + return x->cert_info->key->public_key; } -int X509_check_private_key(X509 *x, const EVP_PKEY *k) -{ - EVP_PKEY *xk; - int ret; +int X509_check_private_key(X509 *x, const EVP_PKEY *k) { + EVP_PKEY *xk; + int ret; - xk = X509_get_pubkey(x); + xk = X509_get_pubkey(x); - if (xk) - ret = EVP_PKEY_cmp(xk, k); - else - ret = -2; + if (xk) { + ret = EVP_PKEY_cmp(xk, k); + } else { + ret = -2; + } - switch (ret) { + switch (ret) { case 1: - break; + break; case 0: - OPENSSL_PUT_ERROR(X509, X509_R_KEY_VALUES_MISMATCH); - break; + OPENSSL_PUT_ERROR(X509, X509_R_KEY_VALUES_MISMATCH); + break; case -1: - OPENSSL_PUT_ERROR(X509, X509_R_KEY_TYPE_MISMATCH); - break; + OPENSSL_PUT_ERROR(X509, X509_R_KEY_TYPE_MISMATCH); + break; case -2: - OPENSSL_PUT_ERROR(X509, X509_R_UNKNOWN_KEY_TYPE); - } - if (xk) - EVP_PKEY_free(xk); - if (ret > 0) - return 1; - return 0; + OPENSSL_PUT_ERROR(X509, X509_R_UNKNOWN_KEY_TYPE); + } + if (xk) { + EVP_PKEY_free(xk); + } + if (ret > 0) { + return 1; + } + return 0; } /* @@ -325,112 +315,125 @@ int X509_check_private_key(X509 *x, const EVP_PKEY *k) * flags field which must contain the suite B verification flags. */ -static int check_suite_b(EVP_PKEY *pkey, int sign_nid, unsigned long *pflags) -{ - const EC_GROUP *grp = NULL; - int curve_nid; - if (pkey && pkey->type == EVP_PKEY_EC) - grp = EC_KEY_get0_group(pkey->pkey.ec); - if (!grp) - return X509_V_ERR_SUITE_B_INVALID_ALGORITHM; - curve_nid = EC_GROUP_get_curve_name(grp); - /* Check curve is consistent with LOS */ - if (curve_nid == NID_secp384r1) { /* P-384 */ - /* - * Check signature algorithm is consistent with curve. - */ - if (sign_nid != -1 && sign_nid != NID_ecdsa_with_SHA384) - return X509_V_ERR_SUITE_B_INVALID_SIGNATURE_ALGORITHM; - if (!(*pflags & X509_V_FLAG_SUITEB_192_LOS)) - return X509_V_ERR_SUITE_B_LOS_NOT_ALLOWED; - /* If we encounter P-384 we cannot use P-256 later */ - *pflags &= ~X509_V_FLAG_SUITEB_128_LOS_ONLY; - } else if (curve_nid == NID_X9_62_prime256v1) { /* P-256 */ - if (sign_nid != -1 && sign_nid != NID_ecdsa_with_SHA256) - return X509_V_ERR_SUITE_B_INVALID_SIGNATURE_ALGORITHM; - if (!(*pflags & X509_V_FLAG_SUITEB_128_LOS_ONLY)) - return X509_V_ERR_SUITE_B_LOS_NOT_ALLOWED; - } else - return X509_V_ERR_SUITE_B_INVALID_CURVE; +static int check_suite_b(EVP_PKEY *pkey, int sign_nid, unsigned long *pflags) { + const EC_GROUP *grp = NULL; + int curve_nid; + if (pkey && pkey->type == EVP_PKEY_EC) { + grp = EC_KEY_get0_group(pkey->pkey.ec); + } + if (!grp) { + return X509_V_ERR_SUITE_B_INVALID_ALGORITHM; + } + curve_nid = EC_GROUP_get_curve_name(grp); + /* Check curve is consistent with LOS */ + if (curve_nid == NID_secp384r1) { /* P-384 */ + /* + * Check signature algorithm is consistent with curve. + */ + if (sign_nid != -1 && sign_nid != NID_ecdsa_with_SHA384) { + return X509_V_ERR_SUITE_B_INVALID_SIGNATURE_ALGORITHM; + } + if (!(*pflags & X509_V_FLAG_SUITEB_192_LOS)) { + return X509_V_ERR_SUITE_B_LOS_NOT_ALLOWED; + } + /* If we encounter P-384 we cannot use P-256 later */ + *pflags &= ~X509_V_FLAG_SUITEB_128_LOS_ONLY; + } else if (curve_nid == NID_X9_62_prime256v1) { /* P-256 */ + if (sign_nid != -1 && sign_nid != NID_ecdsa_with_SHA256) { + return X509_V_ERR_SUITE_B_INVALID_SIGNATURE_ALGORITHM; + } + if (!(*pflags & X509_V_FLAG_SUITEB_128_LOS_ONLY)) { + return X509_V_ERR_SUITE_B_LOS_NOT_ALLOWED; + } + } else { + return X509_V_ERR_SUITE_B_INVALID_CURVE; + } - return X509_V_OK; + return X509_V_OK; } int X509_chain_check_suiteb(int *perror_depth, X509 *x, STACK_OF(X509) *chain, - unsigned long flags) -{ - int rv, sign_nid; - size_t i; - EVP_PKEY *pk = NULL; - unsigned long tflags; - if (!(flags & X509_V_FLAG_SUITEB_128_LOS)) - return X509_V_OK; - tflags = flags; - /* If no EE certificate passed in must be first in chain */ - if (x == NULL) { - x = sk_X509_value(chain, 0); - i = 1; - } else - i = 0; - + unsigned long flags) { + int rv, sign_nid; + size_t i; + EVP_PKEY *pk = NULL; + unsigned long tflags; + if (!(flags & X509_V_FLAG_SUITEB_128_LOS)) { + return X509_V_OK; + } + tflags = flags; + /* If no EE certificate passed in must be first in chain */ + if (x == NULL) { + x = sk_X509_value(chain, 0); + i = 1; + } else { + i = 0; + } + + if (X509_get_version(x) != X509_VERSION_3) { + rv = X509_V_ERR_SUITE_B_INVALID_VERSION; + /* Correct error depth */ + i = 0; + goto end; + } + + pk = X509_get_pubkey(x); + /* Check EE key only */ + rv = check_suite_b(pk, -1, &tflags); + if (rv != X509_V_OK) { + /* Correct error depth */ + i = 0; + goto end; + } + for (; i < sk_X509_num(chain); i++) { + sign_nid = X509_get_signature_nid(x); + x = sk_X509_value(chain, i); if (X509_get_version(x) != X509_VERSION_3) { - rv = X509_V_ERR_SUITE_B_INVALID_VERSION; - /* Correct error depth */ - i = 0; - goto end; + rv = X509_V_ERR_SUITE_B_INVALID_VERSION; + goto end; } - + EVP_PKEY_free(pk); pk = X509_get_pubkey(x); - /* Check EE key only */ - rv = check_suite_b(pk, -1, &tflags); + rv = check_suite_b(pk, sign_nid, &tflags); if (rv != X509_V_OK) { - /* Correct error depth */ - i = 0; - goto end; + goto end; } - for (; i < sk_X509_num(chain); i++) { - sign_nid = X509_get_signature_nid(x); - x = sk_X509_value(chain, i); - if (X509_get_version(x) != X509_VERSION_3) { - rv = X509_V_ERR_SUITE_B_INVALID_VERSION; - goto end; - } - EVP_PKEY_free(pk); - pk = X509_get_pubkey(x); - rv = check_suite_b(pk, sign_nid, &tflags); - if (rv != X509_V_OK) - goto end; + } + + /* Final check: root CA signature */ + rv = check_suite_b(pk, X509_get_signature_nid(x), &tflags); +end: + if (pk) { + EVP_PKEY_free(pk); + } + if (rv != X509_V_OK) { + /* Invalid signature or LOS errors are for previous cert */ + if ((rv == X509_V_ERR_SUITE_B_INVALID_SIGNATURE_ALGORITHM || + rv == X509_V_ERR_SUITE_B_LOS_NOT_ALLOWED) && + i) { + i--; } - - /* Final check: root CA signature */ - rv = check_suite_b(pk, X509_get_signature_nid(x), &tflags); - end: - if (pk) - EVP_PKEY_free(pk); - if (rv != X509_V_OK) { - /* Invalid signature or LOS errors are for previous cert */ - if ((rv == X509_V_ERR_SUITE_B_INVALID_SIGNATURE_ALGORITHM - || rv == X509_V_ERR_SUITE_B_LOS_NOT_ALLOWED) && i) - i--; - /* - * If we have LOS error and flags changed then we are signing P-384 - * with P-256. Use more meaninggul error. - */ - if (rv == X509_V_ERR_SUITE_B_LOS_NOT_ALLOWED && flags != tflags) - rv = X509_V_ERR_SUITE_B_CANNOT_SIGN_P_384_WITH_P_256; - if (perror_depth) - *perror_depth = i; + /* + * If we have LOS error and flags changed then we are signing P-384 + * with P-256. Use more meaninggul error. + */ + if (rv == X509_V_ERR_SUITE_B_LOS_NOT_ALLOWED && flags != tflags) { + rv = X509_V_ERR_SUITE_B_CANNOT_SIGN_P_384_WITH_P_256; + } + if (perror_depth) { + *perror_depth = i; } - return rv; + } + return rv; } -int X509_CRL_check_suiteb(X509_CRL *crl, EVP_PKEY *pk, unsigned long flags) -{ - int sign_nid; - if (!(flags & X509_V_FLAG_SUITEB_128_LOS)) - return X509_V_OK; - sign_nid = OBJ_obj2nid(crl->crl->sig_alg->algorithm); - return check_suite_b(pk, sign_nid, &flags); +int X509_CRL_check_suiteb(X509_CRL *crl, EVP_PKEY *pk, unsigned long flags) { + int sign_nid; + if (!(flags & X509_V_FLAG_SUITEB_128_LOS)) { + return X509_V_OK; + } + sign_nid = OBJ_obj2nid(crl->crl->sig_alg->algorithm); + return check_suite_b(pk, sign_nid, &flags); } /* @@ -438,13 +441,12 @@ int X509_CRL_check_suiteb(X509_CRL *crl, EVP_PKEY *pk, unsigned long flags) * count but it has the same effect by duping the STACK and upping the ref of * each X509 structure. */ -STACK_OF(X509) *X509_chain_up_ref(STACK_OF(X509) *chain) -{ - STACK_OF(X509) *ret; - size_t i; - ret = sk_X509_dup(chain); - for (i = 0; i < sk_X509_num(ret); i++) { - X509_up_ref(sk_X509_value(ret, i)); - } - return ret; +STACK_OF(X509) *X509_chain_up_ref(STACK_OF(X509) *chain) { + STACK_OF(X509) *ret; + size_t i; + ret = sk_X509_dup(chain); + for (i = 0; i < sk_X509_num(ret); i++) { + X509_up_ref(sk_X509_value(ret, i)); + } + return ret; } diff --git a/crypto/x509/x509_d2.c b/crypto/x509/x509_d2.c index 69ae54ed8a..7043123ac7 100644 --- a/crypto/x509/x509_d2.c +++ b/crypto/x509/x509_d2.c @@ -59,48 +59,53 @@ #include #ifndef OPENSSL_NO_STDIO -int X509_STORE_set_default_paths(X509_STORE *ctx) -{ - X509_LOOKUP *lookup; +int X509_STORE_set_default_paths(X509_STORE *ctx) { + X509_LOOKUP *lookup; - lookup = X509_STORE_add_lookup(ctx, X509_LOOKUP_file()); - if (lookup == NULL) - return (0); - X509_LOOKUP_load_file(lookup, NULL, X509_FILETYPE_DEFAULT); + lookup = X509_STORE_add_lookup(ctx, X509_LOOKUP_file()); + if (lookup == NULL) { + return (0); + } + X509_LOOKUP_load_file(lookup, NULL, X509_FILETYPE_DEFAULT); - lookup = X509_STORE_add_lookup(ctx, X509_LOOKUP_hash_dir()); - if (lookup == NULL) - return (0); - X509_LOOKUP_add_dir(lookup, NULL, X509_FILETYPE_DEFAULT); + lookup = X509_STORE_add_lookup(ctx, X509_LOOKUP_hash_dir()); + if (lookup == NULL) { + return (0); + } + X509_LOOKUP_add_dir(lookup, NULL, X509_FILETYPE_DEFAULT); - /* clear any errors */ - ERR_clear_error(); + /* clear any errors */ + ERR_clear_error(); - return (1); + return (1); } int X509_STORE_load_locations(X509_STORE *ctx, const char *file, - const char *path) -{ - X509_LOOKUP *lookup; + const char *path) { + X509_LOOKUP *lookup; - if (file != NULL) { - lookup = X509_STORE_add_lookup(ctx, X509_LOOKUP_file()); - if (lookup == NULL) - return (0); - if (X509_LOOKUP_load_file(lookup, file, X509_FILETYPE_PEM) != 1) - return (0); + if (file != NULL) { + lookup = X509_STORE_add_lookup(ctx, X509_LOOKUP_file()); + if (lookup == NULL) { + return (0); + } + if (X509_LOOKUP_load_file(lookup, file, X509_FILETYPE_PEM) != 1) { + return (0); + } + } + if (path != NULL) { + lookup = X509_STORE_add_lookup(ctx, X509_LOOKUP_hash_dir()); + if (lookup == NULL) { + return (0); } - if (path != NULL) { - lookup = X509_STORE_add_lookup(ctx, X509_LOOKUP_hash_dir()); - if (lookup == NULL) - return (0); - if (X509_LOOKUP_add_dir(lookup, path, X509_FILETYPE_PEM) != 1) - return (0); + if (X509_LOOKUP_add_dir(lookup, path, X509_FILETYPE_PEM) != 1) { + return (0); } - if ((path == NULL) && (file == NULL)) - return (0); - return (1); + } + if ((path == NULL) && (file == NULL)) { + return (0); + } + return (1); } #endif diff --git a/crypto/x509/x509_def.c b/crypto/x509/x509_def.c index d2bc3e5c15..71d2331967 100644 --- a/crypto/x509/x509_def.c +++ b/crypto/x509/x509_def.c @@ -65,39 +65,23 @@ #define OPENSSLDIR "/etc/ssl" #endif -#define X509_CERT_AREA OPENSSLDIR -#define X509_CERT_DIR OPENSSLDIR "/certs" -#define X509_CERT_FILE OPENSSLDIR "/cert.pem" -#define X509_PRIVATE_DIR OPENSSLDIR "/private" -#define X509_CERT_DIR_EVP "SSL_CERT_DIR" -#define X509_CERT_FILE_EVP "SSL_CERT_FILE" +#define X509_CERT_AREA OPENSSLDIR +#define X509_CERT_DIR OPENSSLDIR "/certs" +#define X509_CERT_FILE OPENSSLDIR "/cert.pem" +#define X509_PRIVATE_DIR OPENSSLDIR "/private" +#define X509_CERT_DIR_EVP "SSL_CERT_DIR" +#define X509_CERT_FILE_EVP "SSL_CERT_FILE" -const char *X509_get_default_private_dir(void) -{ - return (X509_PRIVATE_DIR); -} +const char *X509_get_default_private_dir(void) { return (X509_PRIVATE_DIR); } -const char *X509_get_default_cert_area(void) -{ - return (X509_CERT_AREA); -} +const char *X509_get_default_cert_area(void) { return (X509_CERT_AREA); } -const char *X509_get_default_cert_dir(void) -{ - return (X509_CERT_DIR); -} +const char *X509_get_default_cert_dir(void) { return (X509_CERT_DIR); } -const char *X509_get_default_cert_file(void) -{ - return (X509_CERT_FILE); -} +const char *X509_get_default_cert_file(void) { return (X509_CERT_FILE); } -const char *X509_get_default_cert_dir_env(void) -{ - return (X509_CERT_DIR_EVP); -} +const char *X509_get_default_cert_dir_env(void) { return (X509_CERT_DIR_EVP); } -const char *X509_get_default_cert_file_env(void) -{ - return (X509_CERT_FILE_EVP); +const char *X509_get_default_cert_file_env(void) { + return (X509_CERT_FILE_EVP); } diff --git a/crypto/x509/x509_ext.c b/crypto/x509/x509_ext.c index a08e2a85cb..17f4d171fe 100644 --- a/crypto/x509/x509_ext.c +++ b/crypto/x509/x509_ext.c @@ -64,149 +64,120 @@ #include "internal.h" -int X509_CRL_get_ext_count(const X509_CRL *x) -{ - return (X509v3_get_ext_count(x->crl->extensions)); +int X509_CRL_get_ext_count(const X509_CRL *x) { + return (X509v3_get_ext_count(x->crl->extensions)); } -int X509_CRL_get_ext_by_NID(const X509_CRL *x, int nid, int lastpos) -{ - return (X509v3_get_ext_by_NID(x->crl->extensions, nid, lastpos)); +int X509_CRL_get_ext_by_NID(const X509_CRL *x, int nid, int lastpos) { + return (X509v3_get_ext_by_NID(x->crl->extensions, nid, lastpos)); } int X509_CRL_get_ext_by_OBJ(const X509_CRL *x, const ASN1_OBJECT *obj, - int lastpos) -{ - return (X509v3_get_ext_by_OBJ(x->crl->extensions, obj, lastpos)); + int lastpos) { + return (X509v3_get_ext_by_OBJ(x->crl->extensions, obj, lastpos)); } -int X509_CRL_get_ext_by_critical(const X509_CRL *x, int crit, int lastpos) -{ - return (X509v3_get_ext_by_critical(x->crl->extensions, crit, lastpos)); +int X509_CRL_get_ext_by_critical(const X509_CRL *x, int crit, int lastpos) { + return (X509v3_get_ext_by_critical(x->crl->extensions, crit, lastpos)); } -X509_EXTENSION *X509_CRL_get_ext(const X509_CRL *x, int loc) -{ - return (X509v3_get_ext(x->crl->extensions, loc)); +X509_EXTENSION *X509_CRL_get_ext(const X509_CRL *x, int loc) { + return (X509v3_get_ext(x->crl->extensions, loc)); } -X509_EXTENSION *X509_CRL_delete_ext(X509_CRL *x, int loc) -{ - return (X509v3_delete_ext(x->crl->extensions, loc)); +X509_EXTENSION *X509_CRL_delete_ext(X509_CRL *x, int loc) { + return (X509v3_delete_ext(x->crl->extensions, loc)); } void *X509_CRL_get_ext_d2i(const X509_CRL *crl, int nid, int *out_critical, - int *out_idx) -{ - return X509V3_get_d2i(crl->crl->extensions, nid, out_critical, out_idx); + int *out_idx) { + return X509V3_get_d2i(crl->crl->extensions, nid, out_critical, out_idx); } int X509_CRL_add1_ext_i2d(X509_CRL *x, int nid, void *value, int crit, - unsigned long flags) -{ - return X509V3_add1_i2d(&x->crl->extensions, nid, value, crit, flags); + unsigned long flags) { + return X509V3_add1_i2d(&x->crl->extensions, nid, value, crit, flags); } -int X509_CRL_add_ext(X509_CRL *x, X509_EXTENSION *ex, int loc) -{ - return (X509v3_add_ext(&(x->crl->extensions), ex, loc) != NULL); +int X509_CRL_add_ext(X509_CRL *x, X509_EXTENSION *ex, int loc) { + return (X509v3_add_ext(&(x->crl->extensions), ex, loc) != NULL); } -int X509_get_ext_count(const X509 *x) -{ - return (X509v3_get_ext_count(x->cert_info->extensions)); +int X509_get_ext_count(const X509 *x) { + return (X509v3_get_ext_count(x->cert_info->extensions)); } -int X509_get_ext_by_NID(const X509 *x, int nid, int lastpos) -{ - return (X509v3_get_ext_by_NID(x->cert_info->extensions, nid, lastpos)); +int X509_get_ext_by_NID(const X509 *x, int nid, int lastpos) { + return (X509v3_get_ext_by_NID(x->cert_info->extensions, nid, lastpos)); } -int X509_get_ext_by_OBJ(const X509 *x, const ASN1_OBJECT *obj, int lastpos) -{ - return (X509v3_get_ext_by_OBJ(x->cert_info->extensions, obj, lastpos)); +int X509_get_ext_by_OBJ(const X509 *x, const ASN1_OBJECT *obj, int lastpos) { + return (X509v3_get_ext_by_OBJ(x->cert_info->extensions, obj, lastpos)); } -int X509_get_ext_by_critical(const X509 *x, int crit, int lastpos) -{ - return (X509v3_get_ext_by_critical - (x->cert_info->extensions, crit, lastpos)); +int X509_get_ext_by_critical(const X509 *x, int crit, int lastpos) { + return (X509v3_get_ext_by_critical(x->cert_info->extensions, crit, lastpos)); } -X509_EXTENSION *X509_get_ext(const X509 *x, int loc) -{ - return (X509v3_get_ext(x->cert_info->extensions, loc)); +X509_EXTENSION *X509_get_ext(const X509 *x, int loc) { + return (X509v3_get_ext(x->cert_info->extensions, loc)); } -X509_EXTENSION *X509_delete_ext(X509 *x, int loc) -{ - return (X509v3_delete_ext(x->cert_info->extensions, loc)); +X509_EXTENSION *X509_delete_ext(X509 *x, int loc) { + return (X509v3_delete_ext(x->cert_info->extensions, loc)); } -int X509_add_ext(X509 *x, X509_EXTENSION *ex, int loc) -{ - return (X509v3_add_ext(&(x->cert_info->extensions), ex, loc) != NULL); +int X509_add_ext(X509 *x, X509_EXTENSION *ex, int loc) { + return (X509v3_add_ext(&(x->cert_info->extensions), ex, loc) != NULL); } void *X509_get_ext_d2i(const X509 *x509, int nid, int *out_critical, - int *out_idx) -{ - return X509V3_get_d2i(x509->cert_info->extensions, nid, out_critical, - out_idx); + int *out_idx) { + return X509V3_get_d2i(x509->cert_info->extensions, nid, out_critical, + out_idx); } int X509_add1_ext_i2d(X509 *x, int nid, void *value, int crit, - unsigned long flags) -{ - return X509V3_add1_i2d(&x->cert_info->extensions, nid, value, crit, - flags); + unsigned long flags) { + return X509V3_add1_i2d(&x->cert_info->extensions, nid, value, crit, flags); } -int X509_REVOKED_get_ext_count(const X509_REVOKED *x) -{ - return (X509v3_get_ext_count(x->extensions)); +int X509_REVOKED_get_ext_count(const X509_REVOKED *x) { + return (X509v3_get_ext_count(x->extensions)); } -int X509_REVOKED_get_ext_by_NID(const X509_REVOKED *x, int nid, int lastpos) -{ - return (X509v3_get_ext_by_NID(x->extensions, nid, lastpos)); +int X509_REVOKED_get_ext_by_NID(const X509_REVOKED *x, int nid, int lastpos) { + return (X509v3_get_ext_by_NID(x->extensions, nid, lastpos)); } int X509_REVOKED_get_ext_by_OBJ(const X509_REVOKED *x, const ASN1_OBJECT *obj, - int lastpos) -{ - return (X509v3_get_ext_by_OBJ(x->extensions, obj, lastpos)); + int lastpos) { + return (X509v3_get_ext_by_OBJ(x->extensions, obj, lastpos)); } int X509_REVOKED_get_ext_by_critical(const X509_REVOKED *x, int crit, - int lastpos) -{ - return (X509v3_get_ext_by_critical(x->extensions, crit, lastpos)); + int lastpos) { + return (X509v3_get_ext_by_critical(x->extensions, crit, lastpos)); } -X509_EXTENSION *X509_REVOKED_get_ext(const X509_REVOKED *x, int loc) -{ - return (X509v3_get_ext(x->extensions, loc)); +X509_EXTENSION *X509_REVOKED_get_ext(const X509_REVOKED *x, int loc) { + return (X509v3_get_ext(x->extensions, loc)); } -X509_EXTENSION *X509_REVOKED_delete_ext(X509_REVOKED *x, int loc) -{ - return (X509v3_delete_ext(x->extensions, loc)); +X509_EXTENSION *X509_REVOKED_delete_ext(X509_REVOKED *x, int loc) { + return (X509v3_delete_ext(x->extensions, loc)); } -int X509_REVOKED_add_ext(X509_REVOKED *x, X509_EXTENSION *ex, int loc) -{ - return (X509v3_add_ext(&(x->extensions), ex, loc) != NULL); +int X509_REVOKED_add_ext(X509_REVOKED *x, X509_EXTENSION *ex, int loc) { + return (X509v3_add_ext(&(x->extensions), ex, loc) != NULL); } void *X509_REVOKED_get_ext_d2i(const X509_REVOKED *revoked, int nid, - int *out_critical, int *out_idx) -{ - return X509V3_get_d2i(revoked->extensions, nid, out_critical, out_idx); + int *out_critical, int *out_idx) { + return X509V3_get_d2i(revoked->extensions, nid, out_critical, out_idx); } int X509_REVOKED_add1_ext_i2d(X509_REVOKED *x, int nid, void *value, int crit, - unsigned long flags) -{ - return X509V3_add1_i2d(&x->extensions, nid, value, crit, flags); + unsigned long flags) { + return X509V3_add1_i2d(&x->extensions, nid, value, crit, flags); } diff --git a/crypto/x509/x509_lu.c b/crypto/x509/x509_lu.c index 4680e61bd0..09661fcc6b 100644 --- a/crypto/x509/x509_lu.c +++ b/crypto/x509/x509_lu.c @@ -66,540 +66,540 @@ #include "../internal.h" #include "internal.h" -X509_LOOKUP *X509_LOOKUP_new(X509_LOOKUP_METHOD *method) -{ - X509_LOOKUP *ret; - - ret = (X509_LOOKUP *)OPENSSL_malloc(sizeof(X509_LOOKUP)); - if (ret == NULL) - return NULL; - - ret->init = 0; - ret->skip = 0; - ret->method = method; - ret->method_data = NULL; - ret->store_ctx = NULL; - if ((method->new_item != NULL) && !method->new_item(ret)) { - OPENSSL_free(ret); - return NULL; - } - return ret; -} +X509_LOOKUP *X509_LOOKUP_new(X509_LOOKUP_METHOD *method) { + X509_LOOKUP *ret; -void X509_LOOKUP_free(X509_LOOKUP *ctx) -{ - if (ctx == NULL) - return; - if ((ctx->method != NULL) && (ctx->method->free != NULL)) - (*ctx->method->free) (ctx); - OPENSSL_free(ctx); -} - -int X509_LOOKUP_init(X509_LOOKUP *ctx) -{ - if (ctx->method == NULL) - return 0; - if (ctx->method->init != NULL) - return ctx->method->init(ctx); - else - return 1; + ret = (X509_LOOKUP *)OPENSSL_malloc(sizeof(X509_LOOKUP)); + if (ret == NULL) { + return NULL; + } + + ret->init = 0; + ret->skip = 0; + ret->method = method; + ret->method_data = NULL; + ret->store_ctx = NULL; + if ((method->new_item != NULL) && !method->new_item(ret)) { + OPENSSL_free(ret); + return NULL; + } + return ret; +} + +void X509_LOOKUP_free(X509_LOOKUP *ctx) { + if (ctx == NULL) { + return; + } + if ((ctx->method != NULL) && (ctx->method->free != NULL)) { + (*ctx->method->free)(ctx); + } + OPENSSL_free(ctx); +} + +int X509_LOOKUP_init(X509_LOOKUP *ctx) { + if (ctx->method == NULL) { + return 0; + } + if (ctx->method->init != NULL) { + return ctx->method->init(ctx); + } else { + return 1; + } } -int X509_LOOKUP_shutdown(X509_LOOKUP *ctx) -{ - if (ctx->method == NULL) - return 0; - if (ctx->method->shutdown != NULL) - return ctx->method->shutdown(ctx); - else - return 1; +int X509_LOOKUP_shutdown(X509_LOOKUP *ctx) { + if (ctx->method == NULL) { + return 0; + } + if (ctx->method->shutdown != NULL) { + return ctx->method->shutdown(ctx); + } else { + return 1; + } } int X509_LOOKUP_ctrl(X509_LOOKUP *ctx, int cmd, const char *argc, long argl, - char **ret) -{ - if (ctx->method == NULL) - return -1; - if (ctx->method->ctrl != NULL) - return ctx->method->ctrl(ctx, cmd, argc, argl, ret); - else - return 1; + char **ret) { + if (ctx->method == NULL) { + return -1; + } + if (ctx->method->ctrl != NULL) { + return ctx->method->ctrl(ctx, cmd, argc, argl, ret); + } else { + return 1; + } } int X509_LOOKUP_by_subject(X509_LOOKUP *ctx, int type, X509_NAME *name, - X509_OBJECT *ret) -{ - if ((ctx->method == NULL) || (ctx->method->get_by_subject == NULL)) - return 0; - if (ctx->skip) - return 0; - return ctx->method->get_by_subject(ctx, type, name, ret) > 0; + X509_OBJECT *ret) { + if ((ctx->method == NULL) || (ctx->method->get_by_subject == NULL)) { + return 0; + } + if (ctx->skip) { + return 0; + } + return ctx->method->get_by_subject(ctx, type, name, ret) > 0; } int X509_LOOKUP_by_issuer_serial(X509_LOOKUP *ctx, int type, X509_NAME *name, - ASN1_INTEGER *serial, X509_OBJECT *ret) -{ - if ((ctx->method == NULL) || (ctx->method->get_by_issuer_serial == NULL)) - return 0; - return ctx->method->get_by_issuer_serial(ctx, type, name, serial, ret) > 0; + ASN1_INTEGER *serial, X509_OBJECT *ret) { + if ((ctx->method == NULL) || (ctx->method->get_by_issuer_serial == NULL)) { + return 0; + } + return ctx->method->get_by_issuer_serial(ctx, type, name, serial, ret) > 0; } -int X509_LOOKUP_by_fingerprint(X509_LOOKUP *ctx, int type, - unsigned char *bytes, int len, - X509_OBJECT *ret) -{ - if ((ctx->method == NULL) || (ctx->method->get_by_fingerprint == NULL)) - return 0; - return ctx->method->get_by_fingerprint(ctx, type, bytes, len, ret) > 0; +int X509_LOOKUP_by_fingerprint(X509_LOOKUP *ctx, int type, unsigned char *bytes, + int len, X509_OBJECT *ret) { + if ((ctx->method == NULL) || (ctx->method->get_by_fingerprint == NULL)) { + return 0; + } + return ctx->method->get_by_fingerprint(ctx, type, bytes, len, ret) > 0; } int X509_LOOKUP_by_alias(X509_LOOKUP *ctx, int type, char *str, int len, - X509_OBJECT *ret) -{ - if ((ctx->method == NULL) || (ctx->method->get_by_alias == NULL)) - return 0; - return ctx->method->get_by_alias(ctx, type, str, len, ret) > 0; + X509_OBJECT *ret) { + if ((ctx->method == NULL) || (ctx->method->get_by_alias == NULL)) { + return 0; + } + return ctx->method->get_by_alias(ctx, type, str, len, ret) > 0; } -static int x509_object_cmp(const X509_OBJECT **a, const X509_OBJECT **b) -{ - int ret; +static int x509_object_cmp(const X509_OBJECT **a, const X509_OBJECT **b) { + int ret; - ret = ((*a)->type - (*b)->type); - if (ret) - return ret; - switch ((*a)->type) { + ret = ((*a)->type - (*b)->type); + if (ret) { + return ret; + } + switch ((*a)->type) { case X509_LU_X509: - ret = X509_subject_name_cmp((*a)->data.x509, (*b)->data.x509); - break; + ret = X509_subject_name_cmp((*a)->data.x509, (*b)->data.x509); + break; case X509_LU_CRL: - ret = X509_CRL_cmp((*a)->data.crl, (*b)->data.crl); - break; + ret = X509_CRL_cmp((*a)->data.crl, (*b)->data.crl); + break; default: - /* abort(); */ - return 0; - } - return ret; -} - -X509_STORE *X509_STORE_new(void) -{ - X509_STORE *ret; - - if ((ret = (X509_STORE *)OPENSSL_malloc(sizeof(X509_STORE))) == NULL) - return NULL; - OPENSSL_memset(ret, 0, sizeof(*ret)); - CRYPTO_MUTEX_init(&ret->objs_lock); - ret->objs = sk_X509_OBJECT_new(x509_object_cmp); - if (ret->objs == NULL) - goto err; - ret->cache = 1; - ret->get_cert_methods = sk_X509_LOOKUP_new_null(); - if (ret->get_cert_methods == NULL) - goto err; - ret->param = X509_VERIFY_PARAM_new(); - if (ret->param == NULL) - goto err; - - ret->references = 1; - return ret; - err: - if (ret) { - CRYPTO_MUTEX_cleanup(&ret->objs_lock); - if (ret->param) - X509_VERIFY_PARAM_free(ret->param); - if (ret->get_cert_methods) - sk_X509_LOOKUP_free(ret->get_cert_methods); - if (ret->objs) - sk_X509_OBJECT_free(ret->objs); - OPENSSL_free(ret); - } - return NULL; + /* abort(); */ + return 0; + } + return ret; } -int X509_STORE_up_ref(X509_STORE *store) -{ - CRYPTO_refcount_inc(&store->references); - return 1; -} +X509_STORE *X509_STORE_new(void) { + X509_STORE *ret; -static void cleanup(X509_OBJECT *a) -{ - if (a == NULL) { - return; - } - if (a->type == X509_LU_X509) { - X509_free(a->data.x509); - } else if (a->type == X509_LU_CRL) { - X509_CRL_free(a->data.crl); - } else { - /* abort(); */ + if ((ret = (X509_STORE *)OPENSSL_malloc(sizeof(X509_STORE))) == NULL) { + return NULL; + } + OPENSSL_memset(ret, 0, sizeof(*ret)); + CRYPTO_MUTEX_init(&ret->objs_lock); + ret->objs = sk_X509_OBJECT_new(x509_object_cmp); + if (ret->objs == NULL) { + goto err; + } + ret->cache = 1; + ret->get_cert_methods = sk_X509_LOOKUP_new_null(); + if (ret->get_cert_methods == NULL) { + goto err; + } + ret->param = X509_VERIFY_PARAM_new(); + if (ret->param == NULL) { + goto err; + } + + ret->references = 1; + return ret; +err: + if (ret) { + CRYPTO_MUTEX_cleanup(&ret->objs_lock); + if (ret->param) { + X509_VERIFY_PARAM_free(ret->param); } - - OPENSSL_free(a); -} - -void X509_STORE_free(X509_STORE *vfy) -{ - size_t j; - STACK_OF(X509_LOOKUP) *sk; - X509_LOOKUP *lu; - - if (vfy == NULL) - return; - - if (!CRYPTO_refcount_dec_and_test_zero(&vfy->references)) { - return; + if (ret->get_cert_methods) { + sk_X509_LOOKUP_free(ret->get_cert_methods); } - - CRYPTO_MUTEX_cleanup(&vfy->objs_lock); - - sk = vfy->get_cert_methods; - for (j = 0; j < sk_X509_LOOKUP_num(sk); j++) { - lu = sk_X509_LOOKUP_value(sk, j); - X509_LOOKUP_shutdown(lu); - X509_LOOKUP_free(lu); + if (ret->objs) { + sk_X509_OBJECT_free(ret->objs); } - sk_X509_LOOKUP_free(sk); - sk_X509_OBJECT_pop_free(vfy->objs, cleanup); - - if (vfy->param) - X509_VERIFY_PARAM_free(vfy->param); - OPENSSL_free(vfy); -} - -X509_LOOKUP *X509_STORE_add_lookup(X509_STORE *v, X509_LOOKUP_METHOD *m) -{ - size_t i; - STACK_OF(X509_LOOKUP) *sk; - X509_LOOKUP *lu; - - sk = v->get_cert_methods; - for (i = 0; i < sk_X509_LOOKUP_num(sk); i++) { - lu = sk_X509_LOOKUP_value(sk, i); - if (m == lu->method) { - return lu; - } + OPENSSL_free(ret); + } + return NULL; +} + +int X509_STORE_up_ref(X509_STORE *store) { + CRYPTO_refcount_inc(&store->references); + return 1; +} + +static void cleanup(X509_OBJECT *a) { + if (a == NULL) { + return; + } + if (a->type == X509_LU_X509) { + X509_free(a->data.x509); + } else if (a->type == X509_LU_CRL) { + X509_CRL_free(a->data.crl); + } else { + /* abort(); */ + } + + OPENSSL_free(a); +} + +void X509_STORE_free(X509_STORE *vfy) { + size_t j; + STACK_OF(X509_LOOKUP) *sk; + X509_LOOKUP *lu; + + if (vfy == NULL) { + return; + } + + if (!CRYPTO_refcount_dec_and_test_zero(&vfy->references)) { + return; + } + + CRYPTO_MUTEX_cleanup(&vfy->objs_lock); + + sk = vfy->get_cert_methods; + for (j = 0; j < sk_X509_LOOKUP_num(sk); j++) { + lu = sk_X509_LOOKUP_value(sk, j); + X509_LOOKUP_shutdown(lu); + X509_LOOKUP_free(lu); + } + sk_X509_LOOKUP_free(sk); + sk_X509_OBJECT_pop_free(vfy->objs, cleanup); + + if (vfy->param) { + X509_VERIFY_PARAM_free(vfy->param); + } + OPENSSL_free(vfy); +} + +X509_LOOKUP *X509_STORE_add_lookup(X509_STORE *v, X509_LOOKUP_METHOD *m) { + size_t i; + STACK_OF(X509_LOOKUP) *sk; + X509_LOOKUP *lu; + + sk = v->get_cert_methods; + for (i = 0; i < sk_X509_LOOKUP_num(sk); i++) { + lu = sk_X509_LOOKUP_value(sk, i); + if (m == lu->method) { + return lu; } - /* a new one */ - lu = X509_LOOKUP_new(m); - if (lu == NULL) - return NULL; - else { - lu->store_ctx = v; - if (sk_X509_LOOKUP_push(v->get_cert_methods, lu)) - return lu; - else { - X509_LOOKUP_free(lu); - return NULL; - } + } + /* a new one */ + lu = X509_LOOKUP_new(m); + if (lu == NULL) { + return NULL; + } else { + lu->store_ctx = v; + if (sk_X509_LOOKUP_push(v->get_cert_methods, lu)) { + return lu; + } else { + X509_LOOKUP_free(lu); + return NULL; } + } } int X509_STORE_get_by_subject(X509_STORE_CTX *vs, int type, X509_NAME *name, - X509_OBJECT *ret) -{ - X509_STORE *ctx = vs->ctx; - X509_LOOKUP *lu; - X509_OBJECT stmp, *tmp; - int i; - - CRYPTO_MUTEX_lock_write(&ctx->objs_lock); - tmp = X509_OBJECT_retrieve_by_subject(ctx->objs, type, name); - CRYPTO_MUTEX_unlock_write(&ctx->objs_lock); - - if (tmp == NULL || type == X509_LU_CRL) { - for (i = 0; i < (int)sk_X509_LOOKUP_num(ctx->get_cert_methods); i++) { - lu = sk_X509_LOOKUP_value(ctx->get_cert_methods, i); - if (X509_LOOKUP_by_subject(lu, type, name, &stmp)) { - tmp = &stmp; - break; - } - } - if (tmp == NULL) - return 0; + X509_OBJECT *ret) { + X509_STORE *ctx = vs->ctx; + X509_LOOKUP *lu; + X509_OBJECT stmp, *tmp; + int i; + + CRYPTO_MUTEX_lock_write(&ctx->objs_lock); + tmp = X509_OBJECT_retrieve_by_subject(ctx->objs, type, name); + CRYPTO_MUTEX_unlock_write(&ctx->objs_lock); + + if (tmp == NULL || type == X509_LU_CRL) { + for (i = 0; i < (int)sk_X509_LOOKUP_num(ctx->get_cert_methods); i++) { + lu = sk_X509_LOOKUP_value(ctx->get_cert_methods, i); + if (X509_LOOKUP_by_subject(lu, type, name, &stmp)) { + tmp = &stmp; + break; + } } + if (tmp == NULL) { + return 0; + } + } - /* - * if (ret->data.ptr != NULL) X509_OBJECT_free_contents(ret); - */ + /* + * if (ret->data.ptr != NULL) X509_OBJECT_free_contents(ret); + */ - ret->type = tmp->type; - ret->data.ptr = tmp->data.ptr; + ret->type = tmp->type; + ret->data.ptr = tmp->data.ptr; - X509_OBJECT_up_ref_count(ret); + X509_OBJECT_up_ref_count(ret); - return 1; + return 1; } -static int x509_store_add(X509_STORE *ctx, void *x, int is_crl) -{ - if (x == NULL) { - return 0; - } +static int x509_store_add(X509_STORE *ctx, void *x, int is_crl) { + if (x == NULL) { + return 0; + } - X509_OBJECT *const obj = (X509_OBJECT *)OPENSSL_malloc(sizeof(X509_OBJECT)); - if (obj == NULL) { - OPENSSL_PUT_ERROR(X509, ERR_R_MALLOC_FAILURE); - return 0; - } + X509_OBJECT *const obj = (X509_OBJECT *)OPENSSL_malloc(sizeof(X509_OBJECT)); + if (obj == NULL) { + OPENSSL_PUT_ERROR(X509, ERR_R_MALLOC_FAILURE); + return 0; + } - if (is_crl) { - obj->type = X509_LU_CRL; - obj->data.crl = (X509_CRL *)x; - } else { - obj->type = X509_LU_X509; - obj->data.x509 = (X509 *)x; - } - X509_OBJECT_up_ref_count(obj); + if (is_crl) { + obj->type = X509_LU_CRL; + obj->data.crl = (X509_CRL *)x; + } else { + obj->type = X509_LU_X509; + obj->data.x509 = (X509 *)x; + } + X509_OBJECT_up_ref_count(obj); - CRYPTO_MUTEX_lock_write(&ctx->objs_lock); + CRYPTO_MUTEX_lock_write(&ctx->objs_lock); - int ret = 1; - int added = 0; - /* Duplicates are silently ignored */ - if (!X509_OBJECT_retrieve_match(ctx->objs, obj)) { - ret = added = (sk_X509_OBJECT_push(ctx->objs, obj) != 0); - } + int ret = 1; + int added = 0; + /* Duplicates are silently ignored */ + if (!X509_OBJECT_retrieve_match(ctx->objs, obj)) { + ret = added = (sk_X509_OBJECT_push(ctx->objs, obj) != 0); + } - CRYPTO_MUTEX_unlock_write(&ctx->objs_lock); + CRYPTO_MUTEX_unlock_write(&ctx->objs_lock); - if (!added) { - X509_OBJECT_free_contents(obj); - OPENSSL_free(obj); - } + if (!added) { + X509_OBJECT_free_contents(obj); + OPENSSL_free(obj); + } - return ret; + return ret; } -int X509_STORE_add_cert(X509_STORE *ctx, X509 *x) -{ - return x509_store_add(ctx, x, /*is_crl=*/0); +int X509_STORE_add_cert(X509_STORE *ctx, X509 *x) { + return x509_store_add(ctx, x, /*is_crl=*/0); } -int X509_STORE_add_crl(X509_STORE *ctx, X509_CRL *x) -{ - return x509_store_add(ctx, x, /*is_crl=*/1); +int X509_STORE_add_crl(X509_STORE *ctx, X509_CRL *x) { + return x509_store_add(ctx, x, /*is_crl=*/1); } -int X509_OBJECT_up_ref_count(X509_OBJECT *a) -{ - switch (a->type) { +int X509_OBJECT_up_ref_count(X509_OBJECT *a) { + switch (a->type) { case X509_LU_X509: - X509_up_ref(a->data.x509); - break; + X509_up_ref(a->data.x509); + break; case X509_LU_CRL: - X509_CRL_up_ref(a->data.crl); - break; - } - return 1; + X509_CRL_up_ref(a->data.crl); + break; + } + return 1; } -void X509_OBJECT_free_contents(X509_OBJECT *a) -{ - switch (a->type) { +void X509_OBJECT_free_contents(X509_OBJECT *a) { + switch (a->type) { case X509_LU_X509: - X509_free(a->data.x509); - break; + X509_free(a->data.x509); + break; case X509_LU_CRL: - X509_CRL_free(a->data.crl); - break; - } + X509_CRL_free(a->data.crl); + break; + } } -int X509_OBJECT_get_type(const X509_OBJECT *a) -{ - return a->type; -} +int X509_OBJECT_get_type(const X509_OBJECT *a) { return a->type; } -X509 *X509_OBJECT_get0_X509(const X509_OBJECT *a) -{ - if (a == NULL || a->type != X509_LU_X509) { - return NULL; - } - return a->data.x509; +X509 *X509_OBJECT_get0_X509(const X509_OBJECT *a) { + if (a == NULL || a->type != X509_LU_X509) { + return NULL; + } + return a->data.x509; } static int x509_object_idx_cnt(STACK_OF(X509_OBJECT) *h, int type, - X509_NAME *name, int *pnmatch) -{ - X509_OBJECT stmp; - X509 x509_s; - X509_CINF cinf_s; - X509_CRL crl_s; - X509_CRL_INFO crl_info_s; - - stmp.type = type; - switch (type) { + X509_NAME *name, int *pnmatch) { + X509_OBJECT stmp; + X509 x509_s; + X509_CINF cinf_s; + X509_CRL crl_s; + X509_CRL_INFO crl_info_s; + + stmp.type = type; + switch (type) { case X509_LU_X509: - stmp.data.x509 = &x509_s; - x509_s.cert_info = &cinf_s; - cinf_s.subject = name; - break; + stmp.data.x509 = &x509_s; + x509_s.cert_info = &cinf_s; + cinf_s.subject = name; + break; case X509_LU_CRL: - stmp.data.crl = &crl_s; - crl_s.crl = &crl_info_s; - crl_info_s.issuer = name; - break; + stmp.data.crl = &crl_s; + crl_s.crl = &crl_info_s; + crl_info_s.issuer = name; + break; default: - /* abort(); */ - return -1; - } - - size_t idx; - sk_X509_OBJECT_sort(h); - if (!sk_X509_OBJECT_find(h, &idx, &stmp)) - return -1; - - if (pnmatch != NULL) { - int tidx; - const X509_OBJECT *tobj, *pstmp; - *pnmatch = 1; - pstmp = &stmp; - for (tidx = idx + 1; tidx < (int)sk_X509_OBJECT_num(h); tidx++) { - tobj = sk_X509_OBJECT_value(h, tidx); - if (x509_object_cmp(&tobj, &pstmp)) - break; - (*pnmatch)++; - } + /* abort(); */ + return -1; + } + + size_t idx; + sk_X509_OBJECT_sort(h); + if (!sk_X509_OBJECT_find(h, &idx, &stmp)) { + return -1; + } + + if (pnmatch != NULL) { + int tidx; + const X509_OBJECT *tobj, *pstmp; + *pnmatch = 1; + pstmp = &stmp; + for (tidx = idx + 1; tidx < (int)sk_X509_OBJECT_num(h); tidx++) { + tobj = sk_X509_OBJECT_value(h, tidx); + if (x509_object_cmp(&tobj, &pstmp)) { + break; + } + (*pnmatch)++; } + } - return idx; + return idx; } int X509_OBJECT_idx_by_subject(STACK_OF(X509_OBJECT) *h, int type, - X509_NAME *name) -{ - return x509_object_idx_cnt(h, type, name, NULL); -} - -X509_OBJECT *X509_OBJECT_retrieve_by_subject(STACK_OF(X509_OBJECT) *h, - int type, X509_NAME *name) -{ - int idx; - idx = X509_OBJECT_idx_by_subject(h, type, name); - if (idx == -1) - return NULL; - return sk_X509_OBJECT_value(h, idx); + X509_NAME *name) { + return x509_object_idx_cnt(h, type, name, NULL); } -STACK_OF(X509_OBJECT) *X509_STORE_get0_objects(X509_STORE *st) -{ - return st->objs; +X509_OBJECT *X509_OBJECT_retrieve_by_subject(STACK_OF(X509_OBJECT) *h, int type, + X509_NAME *name) { + int idx; + idx = X509_OBJECT_idx_by_subject(h, type, name); + if (idx == -1) { + return NULL; + } + return sk_X509_OBJECT_value(h, idx); } -STACK_OF (X509) * X509_STORE_get1_certs(X509_STORE_CTX *ctx, X509_NAME *nm) -{ - int i, idx, cnt; - STACK_OF(X509) *sk; - X509 *x; - X509_OBJECT *obj; - sk = sk_X509_new_null(); - if (sk == NULL) - return NULL; - CRYPTO_MUTEX_lock_write(&ctx->ctx->objs_lock); - idx = x509_object_idx_cnt(ctx->ctx->objs, X509_LU_X509, nm, &cnt); - if (idx < 0) { - /* - * Nothing found in cache: do lookup to possibly add new objects to - * cache - */ - X509_OBJECT xobj; - CRYPTO_MUTEX_unlock_write(&ctx->ctx->objs_lock); - if (!X509_STORE_get_by_subject(ctx, X509_LU_X509, nm, &xobj)) { - sk_X509_free(sk); - return NULL; - } - X509_OBJECT_free_contents(&xobj); - CRYPTO_MUTEX_lock_write(&ctx->ctx->objs_lock); - idx = x509_object_idx_cnt(ctx->ctx->objs, X509_LU_X509, nm, &cnt); - if (idx < 0) { - CRYPTO_MUTEX_unlock_write(&ctx->ctx->objs_lock); - sk_X509_free(sk); - return NULL; - } - } - for (i = 0; i < cnt; i++, idx++) { - obj = sk_X509_OBJECT_value(ctx->ctx->objs, idx); - x = obj->data.x509; - if (!sk_X509_push(sk, x)) { - CRYPTO_MUTEX_unlock_write(&ctx->ctx->objs_lock); - sk_X509_pop_free(sk, X509_free); - return NULL; - } - X509_up_ref(x); - } - CRYPTO_MUTEX_unlock_write(&ctx->ctx->objs_lock); - return sk; - +STACK_OF(X509_OBJECT) *X509_STORE_get0_objects(X509_STORE *st) { + return st->objs; } -STACK_OF (X509_CRL) * X509_STORE_get1_crls(X509_STORE_CTX *ctx, X509_NAME *nm) -{ - int i, idx, cnt; - STACK_OF(X509_CRL) *sk; - X509_CRL *x; - X509_OBJECT *obj, xobj; - sk = sk_X509_CRL_new_null(); - if (sk == NULL) - return NULL; - - /* Always do lookup to possibly add new CRLs to cache. */ - if (!X509_STORE_get_by_subject(ctx, X509_LU_CRL, nm, &xobj)) { - sk_X509_CRL_free(sk); - return NULL; +STACK_OF(X509) *X509_STORE_get1_certs(X509_STORE_CTX *ctx, X509_NAME *nm) { + int i, idx, cnt; + STACK_OF(X509) *sk; + X509 *x; + X509_OBJECT *obj; + sk = sk_X509_new_null(); + if (sk == NULL) { + return NULL; + } + CRYPTO_MUTEX_lock_write(&ctx->ctx->objs_lock); + idx = x509_object_idx_cnt(ctx->ctx->objs, X509_LU_X509, nm, &cnt); + if (idx < 0) { + /* + * Nothing found in cache: do lookup to possibly add new objects to + * cache + */ + X509_OBJECT xobj; + CRYPTO_MUTEX_unlock_write(&ctx->ctx->objs_lock); + if (!X509_STORE_get_by_subject(ctx, X509_LU_X509, nm, &xobj)) { + sk_X509_free(sk); + return NULL; } X509_OBJECT_free_contents(&xobj); CRYPTO_MUTEX_lock_write(&ctx->ctx->objs_lock); - idx = x509_object_idx_cnt(ctx->ctx->objs, X509_LU_CRL, nm, &cnt); + idx = x509_object_idx_cnt(ctx->ctx->objs, X509_LU_X509, nm, &cnt); if (idx < 0) { - CRYPTO_MUTEX_unlock_write(&ctx->ctx->objs_lock); - sk_X509_CRL_free(sk); - return NULL; + CRYPTO_MUTEX_unlock_write(&ctx->ctx->objs_lock); + sk_X509_free(sk); + return NULL; } - - for (i = 0; i < cnt; i++, idx++) { - obj = sk_X509_OBJECT_value(ctx->ctx->objs, idx); - x = obj->data.crl; - X509_CRL_up_ref(x); - if (!sk_X509_CRL_push(sk, x)) { - CRYPTO_MUTEX_unlock_write(&ctx->ctx->objs_lock); - X509_CRL_free(x); - sk_X509_CRL_pop_free(sk, X509_CRL_free); - return NULL; - } + } + for (i = 0; i < cnt; i++, idx++) { + obj = sk_X509_OBJECT_value(ctx->ctx->objs, idx); + x = obj->data.x509; + if (!sk_X509_push(sk, x)) { + CRYPTO_MUTEX_unlock_write(&ctx->ctx->objs_lock); + sk_X509_pop_free(sk, X509_free); + return NULL; } + X509_up_ref(x); + } + CRYPTO_MUTEX_unlock_write(&ctx->ctx->objs_lock); + return sk; +} + +STACK_OF(X509_CRL) *X509_STORE_get1_crls(X509_STORE_CTX *ctx, X509_NAME *nm) { + int i, idx, cnt; + STACK_OF(X509_CRL) *sk; + X509_CRL *x; + X509_OBJECT *obj, xobj; + sk = sk_X509_CRL_new_null(); + if (sk == NULL) { + return NULL; + } + + /* Always do lookup to possibly add new CRLs to cache. */ + if (!X509_STORE_get_by_subject(ctx, X509_LU_CRL, nm, &xobj)) { + sk_X509_CRL_free(sk); + return NULL; + } + X509_OBJECT_free_contents(&xobj); + CRYPTO_MUTEX_lock_write(&ctx->ctx->objs_lock); + idx = x509_object_idx_cnt(ctx->ctx->objs, X509_LU_CRL, nm, &cnt); + if (idx < 0) { CRYPTO_MUTEX_unlock_write(&ctx->ctx->objs_lock); - return sk; + sk_X509_CRL_free(sk); + return NULL; + } + + for (i = 0; i < cnt; i++, idx++) { + obj = sk_X509_OBJECT_value(ctx->ctx->objs, idx); + x = obj->data.crl; + X509_CRL_up_ref(x); + if (!sk_X509_CRL_push(sk, x)) { + CRYPTO_MUTEX_unlock_write(&ctx->ctx->objs_lock); + X509_CRL_free(x); + sk_X509_CRL_pop_free(sk, X509_CRL_free); + return NULL; + } + } + CRYPTO_MUTEX_unlock_write(&ctx->ctx->objs_lock); + return sk; } X509_OBJECT *X509_OBJECT_retrieve_match(STACK_OF(X509_OBJECT) *h, - X509_OBJECT *x) -{ - size_t idx, i; - X509_OBJECT *obj; - - sk_X509_OBJECT_sort(h); - if (!sk_X509_OBJECT_find(h, &idx, x)) { - return NULL; + X509_OBJECT *x) { + size_t idx, i; + X509_OBJECT *obj; + + sk_X509_OBJECT_sort(h); + if (!sk_X509_OBJECT_find(h, &idx, x)) { + return NULL; + } + if ((x->type != X509_LU_X509) && (x->type != X509_LU_CRL)) { + return sk_X509_OBJECT_value(h, idx); + } + for (i = idx; i < sk_X509_OBJECT_num(h); i++) { + obj = sk_X509_OBJECT_value(h, i); + if (x509_object_cmp((const X509_OBJECT **)&obj, (const X509_OBJECT **)&x)) { + return NULL; } - if ((x->type != X509_LU_X509) && (x->type != X509_LU_CRL)) - return sk_X509_OBJECT_value(h, idx); - for (i = idx; i < sk_X509_OBJECT_num(h); i++) { - obj = sk_X509_OBJECT_value(h, i); - if (x509_object_cmp - ((const X509_OBJECT **)&obj, (const X509_OBJECT **)&x)) - return NULL; - if (x->type == X509_LU_X509) { - if (!X509_cmp(obj->data.x509, x->data.x509)) - return obj; - } else if (x->type == X509_LU_CRL) { - if (!X509_CRL_match(obj->data.crl, x->data.crl)) - return obj; - } else - return obj; + if (x->type == X509_LU_X509) { + if (!X509_cmp(obj->data.x509, x->data.x509)) { + return obj; + } + } else if (x->type == X509_LU_CRL) { + if (!X509_CRL_match(obj->data.crl, x->data.crl)) { + return obj; + } + } else { + return obj; } - return NULL; + } + return NULL; } /* @@ -609,200 +609,170 @@ X509_OBJECT *X509_OBJECT_retrieve_match(STACK_OF(X509_OBJECT) *h, * examine the cache for all matches. Return values are: 1 lookup * successful. 0 certificate not found. -1 some other error. */ -int X509_STORE_CTX_get1_issuer(X509 **issuer, X509_STORE_CTX *ctx, X509 *x) -{ - X509_NAME *xn; - X509_OBJECT obj, *pobj; - int idx, ret; - size_t i; - xn = X509_get_issuer_name(x); - if (!X509_STORE_get_by_subject(ctx, X509_LU_X509, xn, &obj)) - return 0; - /* If certificate matches all OK */ - if (ctx->check_issued(ctx, x, obj.data.x509)) { - *issuer = obj.data.x509; - return 1; - } - X509_OBJECT_free_contents(&obj); - - /* Else find index of first cert accepted by 'check_issued' */ - ret = 0; - CRYPTO_MUTEX_lock_write(&ctx->ctx->objs_lock); - idx = X509_OBJECT_idx_by_subject(ctx->ctx->objs, X509_LU_X509, xn); - if (idx != -1) { /* should be true as we've had at least one - * match */ - /* Look through all matching certs for suitable issuer */ - for (i = idx; i < sk_X509_OBJECT_num(ctx->ctx->objs); i++) { - pobj = sk_X509_OBJECT_value(ctx->ctx->objs, i); - /* See if we've run past the matches */ - if (pobj->type != X509_LU_X509) - break; - if (X509_NAME_cmp(xn, X509_get_subject_name(pobj->data.x509))) - break; - if (ctx->check_issued(ctx, x, pobj->data.x509)) { - *issuer = pobj->data.x509; - X509_OBJECT_up_ref_count(pobj); - ret = 1; - break; - } - } +int X509_STORE_CTX_get1_issuer(X509 **issuer, X509_STORE_CTX *ctx, X509 *x) { + X509_NAME *xn; + X509_OBJECT obj, *pobj; + int idx, ret; + size_t i; + xn = X509_get_issuer_name(x); + if (!X509_STORE_get_by_subject(ctx, X509_LU_X509, xn, &obj)) { + return 0; + } + /* If certificate matches all OK */ + if (ctx->check_issued(ctx, x, obj.data.x509)) { + *issuer = obj.data.x509; + return 1; + } + X509_OBJECT_free_contents(&obj); + + /* Else find index of first cert accepted by 'check_issued' */ + ret = 0; + CRYPTO_MUTEX_lock_write(&ctx->ctx->objs_lock); + idx = X509_OBJECT_idx_by_subject(ctx->ctx->objs, X509_LU_X509, xn); + if (idx != -1) { /* should be true as we've had at least one + * match */ + /* Look through all matching certs for suitable issuer */ + for (i = idx; i < sk_X509_OBJECT_num(ctx->ctx->objs); i++) { + pobj = sk_X509_OBJECT_value(ctx->ctx->objs, i); + /* See if we've run past the matches */ + if (pobj->type != X509_LU_X509) { + break; + } + if (X509_NAME_cmp(xn, X509_get_subject_name(pobj->data.x509))) { + break; + } + if (ctx->check_issued(ctx, x, pobj->data.x509)) { + *issuer = pobj->data.x509; + X509_OBJECT_up_ref_count(pobj); + ret = 1; + break; + } } - CRYPTO_MUTEX_unlock_write(&ctx->ctx->objs_lock); - return ret; + } + CRYPTO_MUTEX_unlock_write(&ctx->ctx->objs_lock); + return ret; } -int X509_STORE_set_flags(X509_STORE *ctx, unsigned long flags) -{ - return X509_VERIFY_PARAM_set_flags(ctx->param, flags); +int X509_STORE_set_flags(X509_STORE *ctx, unsigned long flags) { + return X509_VERIFY_PARAM_set_flags(ctx->param, flags); } -int X509_STORE_set_depth(X509_STORE *ctx, int depth) -{ - X509_VERIFY_PARAM_set_depth(ctx->param, depth); - return 1; +int X509_STORE_set_depth(X509_STORE *ctx, int depth) { + X509_VERIFY_PARAM_set_depth(ctx->param, depth); + return 1; } -int X509_STORE_set_purpose(X509_STORE *ctx, int purpose) -{ - return X509_VERIFY_PARAM_set_purpose(ctx->param, purpose); +int X509_STORE_set_purpose(X509_STORE *ctx, int purpose) { + return X509_VERIFY_PARAM_set_purpose(ctx->param, purpose); } -int X509_STORE_set_trust(X509_STORE *ctx, int trust) -{ - return X509_VERIFY_PARAM_set_trust(ctx->param, trust); +int X509_STORE_set_trust(X509_STORE *ctx, int trust) { + return X509_VERIFY_PARAM_set_trust(ctx->param, trust); } -int X509_STORE_set1_param(X509_STORE *ctx, X509_VERIFY_PARAM *param) -{ - return X509_VERIFY_PARAM_set1(ctx->param, param); +int X509_STORE_set1_param(X509_STORE *ctx, X509_VERIFY_PARAM *param) { + return X509_VERIFY_PARAM_set1(ctx->param, param); } -X509_VERIFY_PARAM *X509_STORE_get0_param(X509_STORE *ctx) -{ - return ctx->param; -} +X509_VERIFY_PARAM *X509_STORE_get0_param(X509_STORE *ctx) { return ctx->param; } -void X509_STORE_set_verify(X509_STORE *ctx, X509_STORE_CTX_verify_fn verify) -{ - ctx->verify = verify; +void X509_STORE_set_verify(X509_STORE *ctx, X509_STORE_CTX_verify_fn verify) { + ctx->verify = verify; } -X509_STORE_CTX_verify_fn X509_STORE_get_verify(X509_STORE *ctx) -{ - return ctx->verify; +X509_STORE_CTX_verify_fn X509_STORE_get_verify(X509_STORE *ctx) { + return ctx->verify; } void X509_STORE_set_verify_cb(X509_STORE *ctx, - X509_STORE_CTX_verify_cb verify_cb) -{ - ctx->verify_cb = verify_cb; + X509_STORE_CTX_verify_cb verify_cb) { + ctx->verify_cb = verify_cb; } -X509_STORE_CTX_verify_cb X509_STORE_get_verify_cb(X509_STORE *ctx) -{ - return ctx->verify_cb; +X509_STORE_CTX_verify_cb X509_STORE_get_verify_cb(X509_STORE *ctx) { + return ctx->verify_cb; } void X509_STORE_set_get_issuer(X509_STORE *ctx, - X509_STORE_CTX_get_issuer_fn get_issuer) -{ - ctx->get_issuer = get_issuer; + X509_STORE_CTX_get_issuer_fn get_issuer) { + ctx->get_issuer = get_issuer; } -X509_STORE_CTX_get_issuer_fn X509_STORE_get_get_issuer(X509_STORE *ctx) -{ - return ctx->get_issuer; +X509_STORE_CTX_get_issuer_fn X509_STORE_get_get_issuer(X509_STORE *ctx) { + return ctx->get_issuer; } void X509_STORE_set_check_issued(X509_STORE *ctx, - X509_STORE_CTX_check_issued_fn check_issued) -{ - ctx->check_issued = check_issued; + X509_STORE_CTX_check_issued_fn check_issued) { + ctx->check_issued = check_issued; } -X509_STORE_CTX_check_issued_fn X509_STORE_get_check_issued(X509_STORE *ctx) -{ - return ctx->check_issued; +X509_STORE_CTX_check_issued_fn X509_STORE_get_check_issued(X509_STORE *ctx) { + return ctx->check_issued; } -void X509_STORE_set_check_revocation(X509_STORE *ctx, - X509_STORE_CTX_check_revocation_fn check_revocation) -{ - ctx->check_revocation = check_revocation; +void X509_STORE_set_check_revocation( + X509_STORE *ctx, X509_STORE_CTX_check_revocation_fn check_revocation) { + ctx->check_revocation = check_revocation; } -X509_STORE_CTX_check_revocation_fn X509_STORE_get_check_revocation(X509_STORE *ctx) -{ - return ctx->check_revocation; +X509_STORE_CTX_check_revocation_fn X509_STORE_get_check_revocation( + X509_STORE *ctx) { + return ctx->check_revocation; } void X509_STORE_set_get_crl(X509_STORE *ctx, - X509_STORE_CTX_get_crl_fn get_crl) -{ - ctx->get_crl = get_crl; + X509_STORE_CTX_get_crl_fn get_crl) { + ctx->get_crl = get_crl; } -X509_STORE_CTX_get_crl_fn X509_STORE_get_get_crl(X509_STORE *ctx) -{ - return ctx->get_crl; +X509_STORE_CTX_get_crl_fn X509_STORE_get_get_crl(X509_STORE *ctx) { + return ctx->get_crl; } void X509_STORE_set_check_crl(X509_STORE *ctx, - X509_STORE_CTX_check_crl_fn check_crl) -{ - ctx->check_crl = check_crl; + X509_STORE_CTX_check_crl_fn check_crl) { + ctx->check_crl = check_crl; } -X509_STORE_CTX_check_crl_fn X509_STORE_get_check_crl(X509_STORE *ctx) -{ - return ctx->check_crl; +X509_STORE_CTX_check_crl_fn X509_STORE_get_check_crl(X509_STORE *ctx) { + return ctx->check_crl; } void X509_STORE_set_cert_crl(X509_STORE *ctx, - X509_STORE_CTX_cert_crl_fn cert_crl) -{ - ctx->cert_crl = cert_crl; + X509_STORE_CTX_cert_crl_fn cert_crl) { + ctx->cert_crl = cert_crl; } -X509_STORE_CTX_cert_crl_fn X509_STORE_get_cert_crl(X509_STORE *ctx) -{ - return ctx->cert_crl; +X509_STORE_CTX_cert_crl_fn X509_STORE_get_cert_crl(X509_STORE *ctx) { + return ctx->cert_crl; } void X509_STORE_set_lookup_certs(X509_STORE *ctx, - X509_STORE_CTX_lookup_certs_fn lookup_certs) -{ - ctx->lookup_certs = lookup_certs; + X509_STORE_CTX_lookup_certs_fn lookup_certs) { + ctx->lookup_certs = lookup_certs; } -X509_STORE_CTX_lookup_certs_fn X509_STORE_get_lookup_certs(X509_STORE *ctx) -{ - return ctx->lookup_certs; +X509_STORE_CTX_lookup_certs_fn X509_STORE_get_lookup_certs(X509_STORE *ctx) { + return ctx->lookup_certs; } void X509_STORE_set_lookup_crls(X509_STORE *ctx, - X509_STORE_CTX_lookup_crls_fn lookup_crls) -{ - ctx->lookup_crls = lookup_crls; + X509_STORE_CTX_lookup_crls_fn lookup_crls) { + ctx->lookup_crls = lookup_crls; } -X509_STORE_CTX_lookup_crls_fn X509_STORE_get_lookup_crls(X509_STORE *ctx) -{ - return ctx->lookup_crls; +X509_STORE_CTX_lookup_crls_fn X509_STORE_get_lookup_crls(X509_STORE *ctx) { + return ctx->lookup_crls; } void X509_STORE_set_cleanup(X509_STORE *ctx, - X509_STORE_CTX_cleanup_fn ctx_cleanup) -{ - ctx->cleanup = ctx_cleanup; + X509_STORE_CTX_cleanup_fn ctx_cleanup) { + ctx->cleanup = ctx_cleanup; } -X509_STORE_CTX_cleanup_fn X509_STORE_get_cleanup(X509_STORE *ctx) -{ - return ctx->cleanup; +X509_STORE_CTX_cleanup_fn X509_STORE_get_cleanup(X509_STORE *ctx) { + return ctx->cleanup; } -X509_STORE *X509_STORE_CTX_get0_store(X509_STORE_CTX *ctx) -{ - return ctx->ctx; -} +X509_STORE *X509_STORE_CTX_get0_store(X509_STORE_CTX *ctx) { return ctx->ctx; } diff --git a/crypto/x509/x509_obj.c b/crypto/x509/x509_obj.c index df54f779ab..65463fa981 100644 --- a/crypto/x509/x509_obj.c +++ b/crypto/x509/x509_obj.c @@ -72,128 +72,140 @@ * anything enountered in practice. */ -#define NAME_ONELINE_MAX (1024 * 1024) - -char *X509_NAME_oneline(const X509_NAME *a, char *buf, int len) -{ - X509_NAME_ENTRY *ne; - size_t i; - int n, lold, l, l1, l2, num, j, type; - const char *s; - char *p; - unsigned char *q; - BUF_MEM *b = NULL; - static const char hex[17] = "0123456789ABCDEF"; - int gs_doit[4]; - char tmp_buf[80]; - - if (buf == NULL) { - if ((b = BUF_MEM_new()) == NULL) - goto err; - if (!BUF_MEM_grow(b, 200)) - goto err; - b->data[0] = '\0'; - len = 200; - } else if (len <= 0) { - return NULL; +#define NAME_ONELINE_MAX (1024 * 1024) + +char *X509_NAME_oneline(const X509_NAME *a, char *buf, int len) { + X509_NAME_ENTRY *ne; + size_t i; + int n, lold, l, l1, l2, num, j, type; + const char *s; + char *p; + unsigned char *q; + BUF_MEM *b = NULL; + static const char hex[17] = "0123456789ABCDEF"; + int gs_doit[4]; + char tmp_buf[80]; + + if (buf == NULL) { + if ((b = BUF_MEM_new()) == NULL) { + goto err; } - if (a == NULL) { - if (b) { - buf = b->data; - OPENSSL_free(b); - } - OPENSSL_strlcpy(buf, "NO X509_NAME", len); - return buf; + if (!BUF_MEM_grow(b, 200)) { + goto err; + } + b->data[0] = '\0'; + len = 200; + } else if (len <= 0) { + return NULL; + } + if (a == NULL) { + if (b) { + buf = b->data; + OPENSSL_free(b); } + OPENSSL_strlcpy(buf, "NO X509_NAME", len); + return buf; + } + + len--; /* space for '\0' */ + l = 0; + for (i = 0; i < sk_X509_NAME_ENTRY_num(a->entries); i++) { + ne = sk_X509_NAME_ENTRY_value(a->entries, i); + n = OBJ_obj2nid(ne->object); + if ((n == NID_undef) || ((s = OBJ_nid2sn(n)) == NULL)) { + i2t_ASN1_OBJECT(tmp_buf, sizeof(tmp_buf), ne->object); + s = tmp_buf; + } + l1 = strlen(s); - len--; /* space for '\0' */ - l = 0; - for (i = 0; i < sk_X509_NAME_ENTRY_num(a->entries); i++) { - ne = sk_X509_NAME_ENTRY_value(a->entries, i); - n = OBJ_obj2nid(ne->object); - if ((n == NID_undef) || ((s = OBJ_nid2sn(n)) == NULL)) { - i2t_ASN1_OBJECT(tmp_buf, sizeof(tmp_buf), ne->object); - s = tmp_buf; - } - l1 = strlen(s); + type = ne->value->type; + num = ne->value->length; + if (num > NAME_ONELINE_MAX) { + OPENSSL_PUT_ERROR(X509, X509_R_NAME_TOO_LONG); + goto end; + } + q = ne->value->data; - type = ne->value->type; - num = ne->value->length; - if (num > NAME_ONELINE_MAX) { - OPENSSL_PUT_ERROR(X509, X509_R_NAME_TOO_LONG); - goto end; - } - q = ne->value->data; - - if ((type == V_ASN1_GENERALSTRING) && ((num % 4) == 0)) { - gs_doit[0] = gs_doit[1] = gs_doit[2] = gs_doit[3] = 0; - for (j = 0; j < num; j++) - if (q[j] != 0) - gs_doit[j & 3] = 1; - - if (gs_doit[0] | gs_doit[1] | gs_doit[2]) - gs_doit[0] = gs_doit[1] = gs_doit[2] = gs_doit[3] = 1; - else { - gs_doit[0] = gs_doit[1] = gs_doit[2] = 0; - gs_doit[3] = 1; - } - } else - gs_doit[0] = gs_doit[1] = gs_doit[2] = gs_doit[3] = 1; - - for (l2 = j = 0; j < num; j++) { - if (!gs_doit[j & 3]) - continue; - l2++; - if ((q[j] < ' ') || (q[j] > '~')) - l2 += 3; + if ((type == V_ASN1_GENERALSTRING) && ((num % 4) == 0)) { + gs_doit[0] = gs_doit[1] = gs_doit[2] = gs_doit[3] = 0; + for (j = 0; j < num; j++) { + if (q[j] != 0) { + gs_doit[j & 3] = 1; } + } + + if (gs_doit[0] | gs_doit[1] | gs_doit[2]) { + gs_doit[0] = gs_doit[1] = gs_doit[2] = gs_doit[3] = 1; + } else { + gs_doit[0] = gs_doit[1] = gs_doit[2] = 0; + gs_doit[3] = 1; + } + } else { + gs_doit[0] = gs_doit[1] = gs_doit[2] = gs_doit[3] = 1; + } - lold = l; - l += 1 + l1 + 1 + l2; - if (l > NAME_ONELINE_MAX) { - OPENSSL_PUT_ERROR(X509, X509_R_NAME_TOO_LONG); - goto end; - } - if (b != NULL) { - if (!BUF_MEM_grow(b, l + 1)) - goto err; - p = &(b->data[lold]); - } else if (l > len) { - break; - } else - p = &(buf[lold]); - *(p++) = '/'; - OPENSSL_memcpy(p, s, (unsigned int)l1); - p += l1; - *(p++) = '='; - - q = ne->value->data; - - for (j = 0; j < num; j++) { - if (!gs_doit[j & 3]) - continue; - n = q[j]; - if ((n < ' ') || (n > '~')) { - *(p++) = '\\'; - *(p++) = 'x'; - *(p++) = hex[(n >> 4) & 0x0f]; - *(p++) = hex[n & 0x0f]; - } else - *(p++) = n; - } - *p = '\0'; + for (l2 = j = 0; j < num; j++) { + if (!gs_doit[j & 3]) { + continue; + } + l2++; + if ((q[j] < ' ') || (q[j] > '~')) { + l2 += 3; + } + } + + lold = l; + l += 1 + l1 + 1 + l2; + if (l > NAME_ONELINE_MAX) { + OPENSSL_PUT_ERROR(X509, X509_R_NAME_TOO_LONG); + goto end; } if (b != NULL) { - p = b->data; - OPENSSL_free(b); - } else - p = buf; - if (i == 0) - *p = '\0'; - return (p); - err: - OPENSSL_PUT_ERROR(X509, ERR_R_MALLOC_FAILURE); - end: - BUF_MEM_free(b); - return (NULL); + if (!BUF_MEM_grow(b, l + 1)) { + goto err; + } + p = &(b->data[lold]); + } else if (l > len) { + break; + } else { + p = &(buf[lold]); + } + *(p++) = '/'; + OPENSSL_memcpy(p, s, (unsigned int)l1); + p += l1; + *(p++) = '='; + + q = ne->value->data; + + for (j = 0; j < num; j++) { + if (!gs_doit[j & 3]) { + continue; + } + n = q[j]; + if ((n < ' ') || (n > '~')) { + *(p++) = '\\'; + *(p++) = 'x'; + *(p++) = hex[(n >> 4) & 0x0f]; + *(p++) = hex[n & 0x0f]; + } else { + *(p++) = n; + } + } + *p = '\0'; + } + if (b != NULL) { + p = b->data; + OPENSSL_free(b); + } else { + p = buf; + } + if (i == 0) { + *p = '\0'; + } + return (p); +err: + OPENSSL_PUT_ERROR(X509, ERR_R_MALLOC_FAILURE); +end: + BUF_MEM_free(b); + return (NULL); } diff --git a/crypto/x509/x509_req.c b/crypto/x509/x509_req.c index 5a69a5f9ac..778d5735da 100644 --- a/crypto/x509/x509_req.c +++ b/crypto/x509/x509_req.c @@ -68,84 +68,78 @@ #include "internal.h" -long X509_REQ_get_version(const X509_REQ *req) -{ - return ASN1_INTEGER_get(req->req_info->version); +long X509_REQ_get_version(const X509_REQ *req) { + return ASN1_INTEGER_get(req->req_info->version); } -X509_NAME *X509_REQ_get_subject_name(const X509_REQ *req) -{ - return req->req_info->subject; +X509_NAME *X509_REQ_get_subject_name(const X509_REQ *req) { + return req->req_info->subject; } -EVP_PKEY *X509_REQ_get_pubkey(X509_REQ *req) -{ - if ((req == NULL) || (req->req_info == NULL)) - return (NULL); - return (X509_PUBKEY_get(req->req_info->pubkey)); +EVP_PKEY *X509_REQ_get_pubkey(X509_REQ *req) { + if ((req == NULL) || (req->req_info == NULL)) { + return (NULL); + } + return (X509_PUBKEY_get(req->req_info->pubkey)); } -int X509_REQ_check_private_key(X509_REQ *x, EVP_PKEY *k) -{ - EVP_PKEY *xk = NULL; - int ok = 0; +int X509_REQ_check_private_key(X509_REQ *x, EVP_PKEY *k) { + EVP_PKEY *xk = NULL; + int ok = 0; - xk = X509_REQ_get_pubkey(x); - switch (EVP_PKEY_cmp(xk, k)) { + xk = X509_REQ_get_pubkey(x); + switch (EVP_PKEY_cmp(xk, k)) { case 1: - ok = 1; - break; + ok = 1; + break; case 0: - OPENSSL_PUT_ERROR(X509, X509_R_KEY_VALUES_MISMATCH); - break; + OPENSSL_PUT_ERROR(X509, X509_R_KEY_VALUES_MISMATCH); + break; case -1: - OPENSSL_PUT_ERROR(X509, X509_R_KEY_TYPE_MISMATCH); - break; + OPENSSL_PUT_ERROR(X509, X509_R_KEY_TYPE_MISMATCH); + break; case -2: - if (k->type == EVP_PKEY_EC) { - OPENSSL_PUT_ERROR(X509, ERR_R_EC_LIB); - break; - } - if (k->type == EVP_PKEY_DH) { - /* No idea */ - OPENSSL_PUT_ERROR(X509, X509_R_CANT_CHECK_DH_KEY); - break; - } - OPENSSL_PUT_ERROR(X509, X509_R_UNKNOWN_KEY_TYPE); - } + if (k->type == EVP_PKEY_EC) { + OPENSSL_PUT_ERROR(X509, ERR_R_EC_LIB); + break; + } + if (k->type == EVP_PKEY_DH) { + /* No idea */ + OPENSSL_PUT_ERROR(X509, X509_R_CANT_CHECK_DH_KEY); + break; + } + OPENSSL_PUT_ERROR(X509, X509_R_UNKNOWN_KEY_TYPE); + } - EVP_PKEY_free(xk); - return (ok); + EVP_PKEY_free(xk); + return (ok); } -int X509_REQ_extension_nid(int req_nid) -{ - return req_nid == NID_ext_req || req_nid == NID_ms_ext_req; +int X509_REQ_extension_nid(int req_nid) { + return req_nid == NID_ext_req || req_nid == NID_ms_ext_req; } -STACK_OF(X509_EXTENSION) *X509_REQ_get_extensions(X509_REQ *req) -{ - if (req == NULL || req->req_info == NULL) { - return NULL; - } +STACK_OF(X509_EXTENSION) *X509_REQ_get_extensions(X509_REQ *req) { + if (req == NULL || req->req_info == NULL) { + return NULL; + } - int idx = X509_REQ_get_attr_by_NID(req, NID_ext_req, -1); - if (idx == -1) { - idx = X509_REQ_get_attr_by_NID(req, NID_ms_ext_req, -1); - } - if (idx == -1) { - return NULL; - } + int idx = X509_REQ_get_attr_by_NID(req, NID_ext_req, -1); + if (idx == -1) { + idx = X509_REQ_get_attr_by_NID(req, NID_ms_ext_req, -1); + } + if (idx == -1) { + return NULL; + } - X509_ATTRIBUTE *attr = X509_REQ_get_attr(req, idx); - ASN1_TYPE *ext = X509_ATTRIBUTE_get0_type(attr, 0); - if (!ext || ext->type != V_ASN1_SEQUENCE) { - return NULL; - } - const unsigned char *p = ext->value.sequence->data; - return (STACK_OF(X509_EXTENSION) *) - ASN1_item_d2i(NULL, &p, ext->value.sequence->length, - ASN1_ITEM_rptr(X509_EXTENSIONS)); + X509_ATTRIBUTE *attr = X509_REQ_get_attr(req, idx); + ASN1_TYPE *ext = X509_ATTRIBUTE_get0_type(attr, 0); + if (!ext || ext->type != V_ASN1_SEQUENCE) { + return NULL; + } + const unsigned char *p = ext->value.sequence->data; + return (STACK_OF(X509_EXTENSION) *)ASN1_item_d2i( + NULL, &p, ext->value.sequence->length, ASN1_ITEM_rptr(X509_EXTENSIONS)); } /* @@ -154,109 +148,98 @@ STACK_OF(X509_EXTENSION) *X509_REQ_get_extensions(X509_REQ *req) */ int X509_REQ_add_extensions_nid(X509_REQ *req, - const STACK_OF(X509_EXTENSION) *exts, int nid) -{ - /* Generate encoding of extensions */ - unsigned char *ext = NULL; - int ext_len = ASN1_item_i2d((ASN1_VALUE *)exts, &ext, - ASN1_ITEM_rptr(X509_EXTENSIONS)); - if (ext_len <= 0) { - return 0; - } - int ret = X509_REQ_add1_attr_by_NID(req, nid, V_ASN1_SEQUENCE, ext, - ext_len); - OPENSSL_free(ext); - return ret; + const STACK_OF(X509_EXTENSION) *exts, int nid) { + /* Generate encoding of extensions */ + unsigned char *ext = NULL; + int ext_len = + ASN1_item_i2d((ASN1_VALUE *)exts, &ext, ASN1_ITEM_rptr(X509_EXTENSIONS)); + if (ext_len <= 0) { + return 0; + } + int ret = X509_REQ_add1_attr_by_NID(req, nid, V_ASN1_SEQUENCE, ext, ext_len); + OPENSSL_free(ext); + return ret; } /* This is the normal usage: use the "official" OID */ int X509_REQ_add_extensions(X509_REQ *req, - const STACK_OF(X509_EXTENSION) *exts) -{ - return X509_REQ_add_extensions_nid(req, exts, NID_ext_req); + const STACK_OF(X509_EXTENSION) *exts) { + return X509_REQ_add_extensions_nid(req, exts, NID_ext_req); } /* Request attribute functions */ -int X509_REQ_get_attr_count(const X509_REQ *req) -{ - return X509at_get_attr_count(req->req_info->attributes); +int X509_REQ_get_attr_count(const X509_REQ *req) { + return X509at_get_attr_count(req->req_info->attributes); } -int X509_REQ_get_attr_by_NID(const X509_REQ *req, int nid, int lastpos) -{ - return X509at_get_attr_by_NID(req->req_info->attributes, nid, lastpos); +int X509_REQ_get_attr_by_NID(const X509_REQ *req, int nid, int lastpos) { + return X509at_get_attr_by_NID(req->req_info->attributes, nid, lastpos); } int X509_REQ_get_attr_by_OBJ(const X509_REQ *req, const ASN1_OBJECT *obj, - int lastpos) -{ - return X509at_get_attr_by_OBJ(req->req_info->attributes, obj, lastpos); + int lastpos) { + return X509at_get_attr_by_OBJ(req->req_info->attributes, obj, lastpos); } -X509_ATTRIBUTE *X509_REQ_get_attr(const X509_REQ *req, int loc) -{ - return X509at_get_attr(req->req_info->attributes, loc); +X509_ATTRIBUTE *X509_REQ_get_attr(const X509_REQ *req, int loc) { + return X509at_get_attr(req->req_info->attributes, loc); } -X509_ATTRIBUTE *X509_REQ_delete_attr(X509_REQ *req, int loc) -{ - return X509at_delete_attr(req->req_info->attributes, loc); +X509_ATTRIBUTE *X509_REQ_delete_attr(X509_REQ *req, int loc) { + return X509at_delete_attr(req->req_info->attributes, loc); } -int X509_REQ_add1_attr(X509_REQ *req, X509_ATTRIBUTE *attr) -{ - if (X509at_add1_attr(&req->req_info->attributes, attr)) - return 1; - return 0; +int X509_REQ_add1_attr(X509_REQ *req, X509_ATTRIBUTE *attr) { + if (X509at_add1_attr(&req->req_info->attributes, attr)) { + return 1; + } + return 0; } -int X509_REQ_add1_attr_by_OBJ(X509_REQ *req, - const ASN1_OBJECT *obj, int attrtype, - const unsigned char *data, int len) -{ - if (X509at_add1_attr_by_OBJ(&req->req_info->attributes, obj, - attrtype, data, len)) - return 1; - return 0; +int X509_REQ_add1_attr_by_OBJ(X509_REQ *req, const ASN1_OBJECT *obj, + int attrtype, const unsigned char *data, + int len) { + if (X509at_add1_attr_by_OBJ(&req->req_info->attributes, obj, attrtype, data, + len)) { + return 1; + } + return 0; } -int X509_REQ_add1_attr_by_NID(X509_REQ *req, - int nid, int attrtype, - const unsigned char *data, int len) -{ - if (X509at_add1_attr_by_NID(&req->req_info->attributes, nid, - attrtype, data, len)) - return 1; - return 0; +int X509_REQ_add1_attr_by_NID(X509_REQ *req, int nid, int attrtype, + const unsigned char *data, int len) { + if (X509at_add1_attr_by_NID(&req->req_info->attributes, nid, attrtype, data, + len)) { + return 1; + } + return 0; } -int X509_REQ_add1_attr_by_txt(X509_REQ *req, - const char *attrname, int attrtype, - const unsigned char *data, int len) -{ - if (X509at_add1_attr_by_txt(&req->req_info->attributes, attrname, - attrtype, data, len)) - return 1; - return 0; +int X509_REQ_add1_attr_by_txt(X509_REQ *req, const char *attrname, int attrtype, + const unsigned char *data, int len) { + if (X509at_add1_attr_by_txt(&req->req_info->attributes, attrname, attrtype, + data, len)) { + return 1; + } + return 0; } void X509_REQ_get0_signature(const X509_REQ *req, const ASN1_BIT_STRING **psig, - const X509_ALGOR **palg) -{ - if (psig != NULL) - *psig = req->signature; - if (palg != NULL) - *palg = req->sig_alg; + const X509_ALGOR **palg) { + if (psig != NULL) { + *psig = req->signature; + } + if (palg != NULL) { + *palg = req->sig_alg; + } } -int X509_REQ_get_signature_nid(const X509_REQ *req) -{ - return OBJ_obj2nid(req->sig_alg->algorithm); +int X509_REQ_get_signature_nid(const X509_REQ *req) { + return OBJ_obj2nid(req->sig_alg->algorithm); } -int i2d_re_X509_REQ_tbs(X509_REQ *req, unsigned char **pp) -{ - req->req_info->enc.modified = 1; - return i2d_X509_REQ_INFO(req->req_info, pp); +int i2d_re_X509_REQ_tbs(X509_REQ *req, unsigned char **pp) { + req->req_info->enc.modified = 1; + return i2d_X509_REQ_INFO(req->req_info, pp); } diff --git a/crypto/x509/x509_set.c b/crypto/x509/x509_set.c index 6a58322569..99fbdc347e 100644 --- a/crypto/x509/x509_set.c +++ b/crypto/x509/x509_set.c @@ -63,188 +63,174 @@ #include "internal.h" -long X509_get_version(const X509 *x509) -{ - // The default version is v1(0). - if (x509->cert_info->version == NULL) { - return X509_VERSION_1; - } - return ASN1_INTEGER_get(x509->cert_info->version); -} - -int X509_set_version(X509 *x, long version) -{ - if (x == NULL) { - return 0; - } - - if (version < X509_VERSION_1 || version > X509_VERSION_3) { - OPENSSL_PUT_ERROR(X509, X509_R_INVALID_VERSION); - return 0; - } - - /* v1(0) is default and is represented by omitting the version. */ - if (version == X509_VERSION_1) { - ASN1_INTEGER_free(x->cert_info->version); - x->cert_info->version = NULL; - return 1; - } - +long X509_get_version(const X509 *x509) { + // The default version is v1(0). + if (x509->cert_info->version == NULL) { + return X509_VERSION_1; + } + return ASN1_INTEGER_get(x509->cert_info->version); +} + +int X509_set_version(X509 *x, long version) { + if (x == NULL) { + return 0; + } + + if (version < X509_VERSION_1 || version > X509_VERSION_3) { + OPENSSL_PUT_ERROR(X509, X509_R_INVALID_VERSION); + return 0; + } + + /* v1(0) is default and is represented by omitting the version. */ + if (version == X509_VERSION_1) { + ASN1_INTEGER_free(x->cert_info->version); + x->cert_info->version = NULL; + return 1; + } + + if (x->cert_info->version == NULL) { + x->cert_info->version = ASN1_INTEGER_new(); if (x->cert_info->version == NULL) { - x->cert_info->version = ASN1_INTEGER_new(); - if (x->cert_info->version == NULL) { - return 0; - } + return 0; } - return ASN1_INTEGER_set(x->cert_info->version, version); -} - -int X509_set_serialNumber(X509 *x, const ASN1_INTEGER *serial) -{ - ASN1_INTEGER *in; - - if (x == NULL) - return (0); - in = x->cert_info->serialNumber; - if (in != serial) { - in = ASN1_INTEGER_dup(serial); - if (in != NULL) { - ASN1_INTEGER_free(x->cert_info->serialNumber); - x->cert_info->serialNumber = in; - } + } + return ASN1_INTEGER_set(x->cert_info->version, version); +} + +int X509_set_serialNumber(X509 *x, const ASN1_INTEGER *serial) { + ASN1_INTEGER *in; + + if (x == NULL) { + return (0); + } + in = x->cert_info->serialNumber; + if (in != serial) { + in = ASN1_INTEGER_dup(serial); + if (in != NULL) { + ASN1_INTEGER_free(x->cert_info->serialNumber); + x->cert_info->serialNumber = in; } - return (in != NULL); + } + return (in != NULL); } -int X509_set_issuer_name(X509 *x, X509_NAME *name) -{ - if ((x == NULL) || (x->cert_info == NULL)) - return (0); - return (X509_NAME_set(&x->cert_info->issuer, name)); +int X509_set_issuer_name(X509 *x, X509_NAME *name) { + if ((x == NULL) || (x->cert_info == NULL)) { + return (0); + } + return (X509_NAME_set(&x->cert_info->issuer, name)); } -int X509_set_subject_name(X509 *x, X509_NAME *name) -{ - if ((x == NULL) || (x->cert_info == NULL)) - return (0); - return (X509_NAME_set(&x->cert_info->subject, name)); +int X509_set_subject_name(X509 *x, X509_NAME *name) { + if ((x == NULL) || (x->cert_info == NULL)) { + return (0); + } + return (X509_NAME_set(&x->cert_info->subject, name)); } -int X509_set1_notBefore(X509 *x, const ASN1_TIME *tm) -{ - ASN1_TIME *in; +int X509_set1_notBefore(X509 *x, const ASN1_TIME *tm) { + ASN1_TIME *in; - if ((x == NULL) || (x->cert_info->validity == NULL)) - return (0); - in = x->cert_info->validity->notBefore; - if (in != tm) { - in = ASN1_STRING_dup(tm); - if (in != NULL) { - ASN1_TIME_free(x->cert_info->validity->notBefore); - x->cert_info->validity->notBefore = in; - } + if ((x == NULL) || (x->cert_info->validity == NULL)) { + return (0); + } + in = x->cert_info->validity->notBefore; + if (in != tm) { + in = ASN1_STRING_dup(tm); + if (in != NULL) { + ASN1_TIME_free(x->cert_info->validity->notBefore); + x->cert_info->validity->notBefore = in; } - return (in != NULL); + } + return (in != NULL); } -int X509_set_notBefore(X509 *x, const ASN1_TIME *tm) -{ - return X509_set1_notBefore(x, tm); +int X509_set_notBefore(X509 *x, const ASN1_TIME *tm) { + return X509_set1_notBefore(x, tm); } -const ASN1_TIME *X509_get0_notBefore(const X509 *x) -{ - return x->cert_info->validity->notBefore; +const ASN1_TIME *X509_get0_notBefore(const X509 *x) { + return x->cert_info->validity->notBefore; } -ASN1_TIME *X509_getm_notBefore(X509 *x) -{ - // Note this function takes a const |X509| pointer in OpenSSL. We require - // non-const as this allows mutating |x|. If it comes up for compatibility, - // we can relax this. - return x->cert_info->validity->notBefore; +ASN1_TIME *X509_getm_notBefore(X509 *x) { + // Note this function takes a const |X509| pointer in OpenSSL. We require + // non-const as this allows mutating |x|. If it comes up for compatibility, + // we can relax this. + return x->cert_info->validity->notBefore; } -ASN1_TIME *X509_get_notBefore(const X509 *x509) -{ - // In OpenSSL, this function is an alias for |X509_getm_notBefore|, but our - // |X509_getm_notBefore| is const-correct. |X509_get_notBefore| was - // originally a macro, so it needs to capture both get0 and getm use cases. - return x509->cert_info->validity->notBefore; +ASN1_TIME *X509_get_notBefore(const X509 *x509) { + // In OpenSSL, this function is an alias for |X509_getm_notBefore|, but our + // |X509_getm_notBefore| is const-correct. |X509_get_notBefore| was + // originally a macro, so it needs to capture both get0 and getm use cases. + return x509->cert_info->validity->notBefore; } -int X509_set1_notAfter(X509 *x, const ASN1_TIME *tm) -{ - ASN1_TIME *in; +int X509_set1_notAfter(X509 *x, const ASN1_TIME *tm) { + ASN1_TIME *in; - if ((x == NULL) || (x->cert_info->validity == NULL)) - return (0); - in = x->cert_info->validity->notAfter; - if (in != tm) { - in = ASN1_STRING_dup(tm); - if (in != NULL) { - ASN1_TIME_free(x->cert_info->validity->notAfter); - x->cert_info->validity->notAfter = in; - } + if ((x == NULL) || (x->cert_info->validity == NULL)) { + return (0); + } + in = x->cert_info->validity->notAfter; + if (in != tm) { + in = ASN1_STRING_dup(tm); + if (in != NULL) { + ASN1_TIME_free(x->cert_info->validity->notAfter); + x->cert_info->validity->notAfter = in; } - return (in != NULL); + } + return (in != NULL); } -int X509_set_notAfter(X509 *x, const ASN1_TIME *tm) -{ - return X509_set1_notAfter(x, tm); +int X509_set_notAfter(X509 *x, const ASN1_TIME *tm) { + return X509_set1_notAfter(x, tm); } -const ASN1_TIME *X509_get0_notAfter(const X509 *x) -{ - return x->cert_info->validity->notAfter; +const ASN1_TIME *X509_get0_notAfter(const X509 *x) { + return x->cert_info->validity->notAfter; } -ASN1_TIME *X509_getm_notAfter(X509 *x) -{ - // Note this function takes a const |X509| pointer in OpenSSL. We require - // non-const as this allows mutating |x|. If it comes up for compatibility, - // we can relax this. - return x->cert_info->validity->notAfter; +ASN1_TIME *X509_getm_notAfter(X509 *x) { + // Note this function takes a const |X509| pointer in OpenSSL. We require + // non-const as this allows mutating |x|. If it comes up for compatibility, + // we can relax this. + return x->cert_info->validity->notAfter; } -ASN1_TIME *X509_get_notAfter(const X509 *x509) -{ - // In OpenSSL, this function is an alias for |X509_getm_notAfter|, but our - // |X509_getm_notAfter| is const-correct. |X509_get_notAfter| was - // originally a macro, so it needs to capture both get0 and getm use cases. - return x509->cert_info->validity->notAfter; +ASN1_TIME *X509_get_notAfter(const X509 *x509) { + // In OpenSSL, this function is an alias for |X509_getm_notAfter|, but our + // |X509_getm_notAfter| is const-correct. |X509_get_notAfter| was + // originally a macro, so it needs to capture both get0 and getm use cases. + return x509->cert_info->validity->notAfter; } void X509_get0_uids(const X509 *x509, const ASN1_BIT_STRING **out_issuer_uid, - const ASN1_BIT_STRING **out_subject_uid) -{ - if (out_issuer_uid != NULL) { - *out_issuer_uid = x509->cert_info->issuerUID; - } - if (out_subject_uid != NULL) { - *out_subject_uid = x509->cert_info->subjectUID; - } + const ASN1_BIT_STRING **out_subject_uid) { + if (out_issuer_uid != NULL) { + *out_issuer_uid = x509->cert_info->issuerUID; + } + if (out_subject_uid != NULL) { + *out_subject_uid = x509->cert_info->subjectUID; + } } -int X509_set_pubkey(X509 *x, EVP_PKEY *pkey) -{ - if ((x == NULL) || (x->cert_info == NULL)) - return (0); - return (X509_PUBKEY_set(&(x->cert_info->key), pkey)); +int X509_set_pubkey(X509 *x, EVP_PKEY *pkey) { + if ((x == NULL) || (x->cert_info == NULL)) { + return (0); + } + return (X509_PUBKEY_set(&(x->cert_info->key), pkey)); } -const STACK_OF(X509_EXTENSION) *X509_get0_extensions(const X509 *x) -{ - return x->cert_info->extensions; +const STACK_OF(X509_EXTENSION) *X509_get0_extensions(const X509 *x) { + return x->cert_info->extensions; } -const X509_ALGOR *X509_get0_tbs_sigalg(const X509 *x) -{ - return x->cert_info->signature; +const X509_ALGOR *X509_get0_tbs_sigalg(const X509 *x) { + return x->cert_info->signature; } -X509_PUBKEY *X509_get_X509_PUBKEY(const X509 *x509) -{ - return x509->cert_info->key; +X509_PUBKEY *X509_get_X509_PUBKEY(const X509 *x509) { + return x509->cert_info->key; } diff --git a/crypto/x509/x509_trs.c b/crypto/x509/x509_trs.c index d21548d1b7..9436b2fff6 100644 --- a/crypto/x509/x509_trs.c +++ b/crypto/x509/x509_trs.c @@ -93,230 +93,228 @@ static X509_TRUST trstandard[] = { {X509_TRUST_OCSP_REQUEST, 0, trust_1oid, (char *)"OCSP request", NID_ad_OCSP, NULL}, {X509_TRUST_TSA, 0, trust_1oidany, (char *)"TSA server", NID_time_stamp, - NULL} -}; + NULL}}; -#define X509_TRUST_COUNT (sizeof(trstandard)/sizeof(X509_TRUST)) +#define X509_TRUST_COUNT (sizeof(trstandard) / sizeof(X509_TRUST)) static STACK_OF(X509_TRUST) *trtable = NULL; -static int tr_cmp(const X509_TRUST **a, const X509_TRUST **b) -{ - return (*a)->trust - (*b)->trust; +static int tr_cmp(const X509_TRUST **a, const X509_TRUST **b) { + return (*a)->trust - (*b)->trust; } -int X509_check_trust(X509 *x, int id, int flags) -{ - X509_TRUST *pt; - int idx; - if (id == -1) - return 1; - /* We get this as a default value */ - if (id == 0) { - int rv; - rv = obj_trust(NID_anyExtendedKeyUsage, x, 0); - if (rv != X509_TRUST_UNTRUSTED) - return rv; - return trust_compat(NULL, x, 0); +int X509_check_trust(X509 *x, int id, int flags) { + X509_TRUST *pt; + int idx; + if (id == -1) { + return 1; + } + /* We get this as a default value */ + if (id == 0) { + int rv; + rv = obj_trust(NID_anyExtendedKeyUsage, x, 0); + if (rv != X509_TRUST_UNTRUSTED) { + return rv; } - idx = X509_TRUST_get_by_id(id); - if (idx == -1) - return obj_trust(id, x, flags); - pt = X509_TRUST_get0(idx); - return pt->check_trust(pt, x, flags); + return trust_compat(NULL, x, 0); + } + idx = X509_TRUST_get_by_id(id); + if (idx == -1) { + return obj_trust(id, x, flags); + } + pt = X509_TRUST_get0(idx); + return pt->check_trust(pt, x, flags); } -int X509_TRUST_get_count(void) -{ - if (!trtable) - return X509_TRUST_COUNT; - return sk_X509_TRUST_num(trtable) + X509_TRUST_COUNT; +int X509_TRUST_get_count(void) { + if (!trtable) { + return X509_TRUST_COUNT; + } + return sk_X509_TRUST_num(trtable) + X509_TRUST_COUNT; } -X509_TRUST *X509_TRUST_get0(int idx) -{ - if (idx < 0) - return NULL; - if (idx < (int)X509_TRUST_COUNT) - return trstandard + idx; - return sk_X509_TRUST_value(trtable, idx - X509_TRUST_COUNT); +X509_TRUST *X509_TRUST_get0(int idx) { + if (idx < 0) { + return NULL; + } + if (idx < (int)X509_TRUST_COUNT) { + return trstandard + idx; + } + return sk_X509_TRUST_value(trtable, idx - X509_TRUST_COUNT); } -int X509_TRUST_get_by_id(int id) -{ - X509_TRUST tmp; - size_t idx; - - if ((id >= X509_TRUST_MIN) && (id <= X509_TRUST_MAX)) - return id - X509_TRUST_MIN; - tmp.trust = id; - if (!trtable) - return -1; - sk_X509_TRUST_sort(trtable); - if (!sk_X509_TRUST_find(trtable, &idx, &tmp)) { - return -1; - } - return idx + X509_TRUST_COUNT; +int X509_TRUST_get_by_id(int id) { + X509_TRUST tmp; + size_t idx; + + if ((id >= X509_TRUST_MIN) && (id <= X509_TRUST_MAX)) { + return id - X509_TRUST_MIN; + } + tmp.trust = id; + if (!trtable) { + return -1; + } + sk_X509_TRUST_sort(trtable); + if (!sk_X509_TRUST_find(trtable, &idx, &tmp)) { + return -1; + } + return idx + X509_TRUST_COUNT; } -int X509_TRUST_set(int *t, int trust) -{ - if (X509_TRUST_get_by_id(trust) == -1) { - OPENSSL_PUT_ERROR(X509, X509_R_INVALID_TRUST); - return 0; - } - *t = trust; - return 1; +int X509_TRUST_set(int *t, int trust) { + if (X509_TRUST_get_by_id(trust) == -1) { + OPENSSL_PUT_ERROR(X509, X509_R_INVALID_TRUST); + return 0; + } + *t = trust; + return 1; } -int X509_TRUST_add(int id, int flags, int (*ck) (X509_TRUST *, X509 *, int), - char *name, int arg1, void *arg2) -{ - int idx; - X509_TRUST *trtmp; - char *name_dup; - - /* - * This is set according to what we change: application can't set it - */ - flags &= ~X509_TRUST_DYNAMIC; - /* This will always be set for application modified trust entries */ - flags |= X509_TRUST_DYNAMIC_NAME; - /* Get existing entry if any */ - idx = X509_TRUST_get_by_id(id); - /* Need a new entry */ - if (idx == -1) { - if (!(trtmp = OPENSSL_malloc(sizeof(X509_TRUST)))) { - OPENSSL_PUT_ERROR(X509, ERR_R_MALLOC_FAILURE); - return 0; - } - trtmp->flags = X509_TRUST_DYNAMIC; - } else - trtmp = X509_TRUST_get0(idx); - - /* Duplicate the supplied name. */ - name_dup = OPENSSL_strdup(name); - if (name_dup == NULL) { - OPENSSL_PUT_ERROR(X509, ERR_R_MALLOC_FAILURE); - if (idx == -1) - OPENSSL_free(trtmp); - return 0; +int X509_TRUST_add(int id, int flags, int (*ck)(X509_TRUST *, X509 *, int), + char *name, int arg1, void *arg2) { + int idx; + X509_TRUST *trtmp; + char *name_dup; + + /* + * This is set according to what we change: application can't set it + */ + flags &= ~X509_TRUST_DYNAMIC; + /* This will always be set for application modified trust entries */ + flags |= X509_TRUST_DYNAMIC_NAME; + /* Get existing entry if any */ + idx = X509_TRUST_get_by_id(id); + /* Need a new entry */ + if (idx == -1) { + if (!(trtmp = OPENSSL_malloc(sizeof(X509_TRUST)))) { + OPENSSL_PUT_ERROR(X509, ERR_R_MALLOC_FAILURE); + return 0; } - - /* OPENSSL_free existing name if dynamic */ - if (trtmp->flags & X509_TRUST_DYNAMIC_NAME) - OPENSSL_free(trtmp->name); - trtmp->name = name_dup; - /* Keep the dynamic flag of existing entry */ - trtmp->flags &= X509_TRUST_DYNAMIC; - /* Set all other flags */ - trtmp->flags |= flags; - - trtmp->trust = id; - trtmp->check_trust = ck; - trtmp->arg1 = arg1; - trtmp->arg2 = arg2; - - /* If its a new entry manage the dynamic table */ + trtmp->flags = X509_TRUST_DYNAMIC; + } else { + trtmp = X509_TRUST_get0(idx); + } + + /* Duplicate the supplied name. */ + name_dup = OPENSSL_strdup(name); + if (name_dup == NULL) { + OPENSSL_PUT_ERROR(X509, ERR_R_MALLOC_FAILURE); if (idx == -1) { - if (!trtable && !(trtable = sk_X509_TRUST_new(tr_cmp))) { - OPENSSL_PUT_ERROR(X509, ERR_R_MALLOC_FAILURE); - trtable_free(trtmp); - return 0; - } - if (!sk_X509_TRUST_push(trtable, trtmp)) { - OPENSSL_PUT_ERROR(X509, ERR_R_MALLOC_FAILURE); - trtable_free(trtmp); - return 0; - } + OPENSSL_free(trtmp); } - return 1; + return 0; + } + + /* OPENSSL_free existing name if dynamic */ + if (trtmp->flags & X509_TRUST_DYNAMIC_NAME) { + OPENSSL_free(trtmp->name); + } + trtmp->name = name_dup; + /* Keep the dynamic flag of existing entry */ + trtmp->flags &= X509_TRUST_DYNAMIC; + /* Set all other flags */ + trtmp->flags |= flags; + + trtmp->trust = id; + trtmp->check_trust = ck; + trtmp->arg1 = arg1; + trtmp->arg2 = arg2; + + /* If its a new entry manage the dynamic table */ + if (idx == -1) { + if (!trtable && !(trtable = sk_X509_TRUST_new(tr_cmp))) { + OPENSSL_PUT_ERROR(X509, ERR_R_MALLOC_FAILURE); + trtable_free(trtmp); + return 0; + } + if (!sk_X509_TRUST_push(trtable, trtmp)) { + OPENSSL_PUT_ERROR(X509, ERR_R_MALLOC_FAILURE); + trtable_free(trtmp); + return 0; + } + } + return 1; } -static void trtable_free(X509_TRUST *p) -{ - if (!p) - return; - if (p->flags & X509_TRUST_DYNAMIC) { - if (p->flags & X509_TRUST_DYNAMIC_NAME) - OPENSSL_free(p->name); - OPENSSL_free(p); +static void trtable_free(X509_TRUST *p) { + if (!p) { + return; + } + if (p->flags & X509_TRUST_DYNAMIC) { + if (p->flags & X509_TRUST_DYNAMIC_NAME) { + OPENSSL_free(p->name); } + OPENSSL_free(p); + } } -void X509_TRUST_cleanup(void) -{ - unsigned int i; - for (i = 0; i < X509_TRUST_COUNT; i++) - trtable_free(trstandard + i); - sk_X509_TRUST_pop_free(trtable, trtable_free); - trtable = NULL; +void X509_TRUST_cleanup(void) { + unsigned int i; + for (i = 0; i < X509_TRUST_COUNT; i++) { + trtable_free(trstandard + i); + } + sk_X509_TRUST_pop_free(trtable, trtable_free); + trtable = NULL; } -int X509_TRUST_get_flags(const X509_TRUST *xp) -{ - return xp->flags; -} +int X509_TRUST_get_flags(const X509_TRUST *xp) { return xp->flags; } -char *X509_TRUST_get0_name(const X509_TRUST *xp) -{ - return xp->name; -} +char *X509_TRUST_get0_name(const X509_TRUST *xp) { return xp->name; } -int X509_TRUST_get_trust(const X509_TRUST *xp) -{ - return xp->trust; -} +int X509_TRUST_get_trust(const X509_TRUST *xp) { return xp->trust; } -static int trust_1oidany(X509_TRUST *trust, X509 *x, int flags) -{ - if (x->aux && (x->aux->trust || x->aux->reject)) - return obj_trust(trust->arg1, x, flags); - /* - * we don't have any trust settings: for compatibility we return trusted - * if it is self signed - */ - return trust_compat(trust, x, flags); +static int trust_1oidany(X509_TRUST *trust, X509 *x, int flags) { + if (x->aux && (x->aux->trust || x->aux->reject)) { + return obj_trust(trust->arg1, x, flags); + } + /* + * we don't have any trust settings: for compatibility we return trusted + * if it is self signed + */ + return trust_compat(trust, x, flags); } -static int trust_1oid(X509_TRUST *trust, X509 *x, int flags) -{ - if (x->aux) - return obj_trust(trust->arg1, x, flags); - return X509_TRUST_UNTRUSTED; +static int trust_1oid(X509_TRUST *trust, X509 *x, int flags) { + if (x->aux) { + return obj_trust(trust->arg1, x, flags); + } + return X509_TRUST_UNTRUSTED; } -static int trust_compat(X509_TRUST *trust, X509 *x, int flags) -{ - if (!x509v3_cache_extensions(x)) - return X509_TRUST_UNTRUSTED; - if (x->ex_flags & EXFLAG_SS) - return X509_TRUST_TRUSTED; - else - return X509_TRUST_UNTRUSTED; +static int trust_compat(X509_TRUST *trust, X509 *x, int flags) { + if (!x509v3_cache_extensions(x)) { + return X509_TRUST_UNTRUSTED; + } + if (x->ex_flags & EXFLAG_SS) { + return X509_TRUST_TRUSTED; + } else { + return X509_TRUST_UNTRUSTED; + } } -static int obj_trust(int id, X509 *x, int flags) -{ - ASN1_OBJECT *obj; - size_t i; - X509_CERT_AUX *ax; - ax = x->aux; - if (!ax) - return X509_TRUST_UNTRUSTED; - if (ax->reject) { - for (i = 0; i < sk_ASN1_OBJECT_num(ax->reject); i++) { - obj = sk_ASN1_OBJECT_value(ax->reject, i); - if (OBJ_obj2nid(obj) == id) - return X509_TRUST_REJECTED; - } +static int obj_trust(int id, X509 *x, int flags) { + ASN1_OBJECT *obj; + size_t i; + X509_CERT_AUX *ax; + ax = x->aux; + if (!ax) { + return X509_TRUST_UNTRUSTED; + } + if (ax->reject) { + for (i = 0; i < sk_ASN1_OBJECT_num(ax->reject); i++) { + obj = sk_ASN1_OBJECT_value(ax->reject, i); + if (OBJ_obj2nid(obj) == id) { + return X509_TRUST_REJECTED; + } } - if (ax->trust) { - for (i = 0; i < sk_ASN1_OBJECT_num(ax->trust); i++) { - obj = sk_ASN1_OBJECT_value(ax->trust, i); - if (OBJ_obj2nid(obj) == id) - return X509_TRUST_TRUSTED; - } + } + if (ax->trust) { + for (i = 0; i < sk_ASN1_OBJECT_num(ax->trust); i++) { + obj = sk_ASN1_OBJECT_value(ax->trust, i); + if (OBJ_obj2nid(obj) == id) { + return X509_TRUST_TRUSTED; + } } - return X509_TRUST_UNTRUSTED; + } + return X509_TRUST_UNTRUSTED; } diff --git a/crypto/x509/x509_txt.c b/crypto/x509/x509_txt.c index 17e14a629b..16768bf3fd 100644 --- a/crypto/x509/x509_txt.c +++ b/crypto/x509/x509_txt.c @@ -56,149 +56,147 @@ #include -const char *X509_verify_cert_error_string(long err) -{ - switch (err) { +const char *X509_verify_cert_error_string(long err) { + switch (err) { case X509_V_OK: - return "ok"; + return "ok"; case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT: - return "unable to get issuer certificate"; + return "unable to get issuer certificate"; case X509_V_ERR_UNABLE_TO_GET_CRL: - return "unable to get certificate CRL"; + return "unable to get certificate CRL"; case X509_V_ERR_UNABLE_TO_DECRYPT_CERT_SIGNATURE: - return "unable to decrypt certificate's signature"; + return "unable to decrypt certificate's signature"; case X509_V_ERR_UNABLE_TO_DECRYPT_CRL_SIGNATURE: - return "unable to decrypt CRL's signature"; + return "unable to decrypt CRL's signature"; case X509_V_ERR_UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY: - return "unable to decode issuer public key"; + return "unable to decode issuer public key"; case X509_V_ERR_CERT_SIGNATURE_FAILURE: - return "certificate signature failure"; + return "certificate signature failure"; case X509_V_ERR_CRL_SIGNATURE_FAILURE: - return "CRL signature failure"; + return "CRL signature failure"; case X509_V_ERR_CERT_NOT_YET_VALID: - return "certificate is not yet valid"; + return "certificate is not yet valid"; case X509_V_ERR_CRL_NOT_YET_VALID: - return "CRL is not yet valid"; + return "CRL is not yet valid"; case X509_V_ERR_CERT_HAS_EXPIRED: - return "certificate has expired"; + return "certificate has expired"; case X509_V_ERR_CRL_HAS_EXPIRED: - return "CRL has expired"; + return "CRL has expired"; case X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD: - return "format error in certificate's notBefore field"; + return "format error in certificate's notBefore field"; case X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD: - return "format error in certificate's notAfter field"; + return "format error in certificate's notAfter field"; case X509_V_ERR_ERROR_IN_CRL_LAST_UPDATE_FIELD: - return "format error in CRL's lastUpdate field"; + return "format error in CRL's lastUpdate field"; case X509_V_ERR_ERROR_IN_CRL_NEXT_UPDATE_FIELD: - return "format error in CRL's nextUpdate field"; + return "format error in CRL's nextUpdate field"; case X509_V_ERR_OUT_OF_MEM: - return "out of memory"; + return "out of memory"; case X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT: - return "self signed certificate"; + return "self signed certificate"; case X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN: - return "self signed certificate in certificate chain"; + return "self signed certificate in certificate chain"; case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY: - return "unable to get local issuer certificate"; + return "unable to get local issuer certificate"; case X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE: - return "unable to verify the first certificate"; + return "unable to verify the first certificate"; case X509_V_ERR_CERT_CHAIN_TOO_LONG: - return "certificate chain too long"; + return "certificate chain too long"; case X509_V_ERR_CERT_REVOKED: - return "certificate revoked"; + return "certificate revoked"; case X509_V_ERR_INVALID_CA: - return "invalid CA certificate"; + return "invalid CA certificate"; case X509_V_ERR_INVALID_NON_CA: - return "invalid non-CA certificate (has CA markings)"; + return "invalid non-CA certificate (has CA markings)"; case X509_V_ERR_PATH_LENGTH_EXCEEDED: - return "path length constraint exceeded"; + return "path length constraint exceeded"; case X509_V_ERR_PROXY_PATH_LENGTH_EXCEEDED: - return "proxy path length constraint exceeded"; + return "proxy path length constraint exceeded"; case X509_V_ERR_PROXY_CERTIFICATES_NOT_ALLOWED: - return - "proxy certificates not allowed, please set the appropriate flag"; + return "proxy certificates not allowed, please set the appropriate flag"; case X509_V_ERR_INVALID_PURPOSE: - return "unsupported certificate purpose"; + return "unsupported certificate purpose"; case X509_V_ERR_CERT_UNTRUSTED: - return "certificate not trusted"; + return "certificate not trusted"; case X509_V_ERR_CERT_REJECTED: - return "certificate rejected"; + return "certificate rejected"; case X509_V_ERR_APPLICATION_VERIFICATION: - return "application verification failure"; + return "application verification failure"; case X509_V_ERR_SUBJECT_ISSUER_MISMATCH: - return "subject issuer mismatch"; + return "subject issuer mismatch"; case X509_V_ERR_AKID_SKID_MISMATCH: - return "authority and subject key identifier mismatch"; + return "authority and subject key identifier mismatch"; case X509_V_ERR_AKID_ISSUER_SERIAL_MISMATCH: - return "authority and issuer serial number mismatch"; + return "authority and issuer serial number mismatch"; case X509_V_ERR_KEYUSAGE_NO_CERTSIGN: - return "key usage does not include certificate signing"; + return "key usage does not include certificate signing"; case X509_V_ERR_UNABLE_TO_GET_CRL_ISSUER: - return "unable to get CRL issuer certificate"; + return "unable to get CRL issuer certificate"; case X509_V_ERR_UNHANDLED_CRITICAL_EXTENSION: - return "unhandled critical extension"; + return "unhandled critical extension"; case X509_V_ERR_KEYUSAGE_NO_CRL_SIGN: - return "key usage does not include CRL signing"; + return "key usage does not include CRL signing"; case X509_V_ERR_KEYUSAGE_NO_DIGITAL_SIGNATURE: - return "key usage does not include digital signature"; + return "key usage does not include digital signature"; case X509_V_ERR_UNHANDLED_CRITICAL_CRL_EXTENSION: - return "unhandled critical CRL extension"; + return "unhandled critical CRL extension"; case X509_V_ERR_INVALID_EXTENSION: - return "invalid or inconsistent certificate extension"; + return "invalid or inconsistent certificate extension"; case X509_V_ERR_INVALID_POLICY_EXTENSION: - return "invalid or inconsistent certificate policy extension"; + return "invalid or inconsistent certificate policy extension"; case X509_V_ERR_NO_EXPLICIT_POLICY: - return "no explicit policy"; + return "no explicit policy"; case X509_V_ERR_DIFFERENT_CRL_SCOPE: - return "Different CRL scope"; + return "Different CRL scope"; case X509_V_ERR_UNSUPPORTED_EXTENSION_FEATURE: - return "Unsupported extension feature"; + return "Unsupported extension feature"; case X509_V_ERR_UNNESTED_RESOURCE: - return "RFC 3779 resource not subset of parent's resources"; + return "RFC 3779 resource not subset of parent's resources"; case X509_V_ERR_PERMITTED_VIOLATION: - return "permitted subtree violation"; + return "permitted subtree violation"; case X509_V_ERR_EXCLUDED_VIOLATION: - return "excluded subtree violation"; + return "excluded subtree violation"; case X509_V_ERR_SUBTREE_MINMAX: - return "name constraints minimum and maximum not supported"; + return "name constraints minimum and maximum not supported"; case X509_V_ERR_UNSUPPORTED_CONSTRAINT_TYPE: - return "unsupported name constraint type"; + return "unsupported name constraint type"; case X509_V_ERR_UNSUPPORTED_CONSTRAINT_SYNTAX: - return "unsupported or invalid name constraint syntax"; + return "unsupported or invalid name constraint syntax"; case X509_V_ERR_UNSUPPORTED_NAME_SYNTAX: - return "unsupported or invalid name syntax"; + return "unsupported or invalid name syntax"; case X509_V_ERR_CRL_PATH_VALIDATION_ERROR: - return "CRL path validation error"; + return "CRL path validation error"; case X509_V_ERR_SUITE_B_INVALID_VERSION: - return "Suite B: certificate version invalid"; + return "Suite B: certificate version invalid"; case X509_V_ERR_SUITE_B_INVALID_ALGORITHM: - return "Suite B: invalid public key algorithm"; + return "Suite B: invalid public key algorithm"; case X509_V_ERR_SUITE_B_INVALID_CURVE: - return "Suite B: invalid ECC curve"; + return "Suite B: invalid ECC curve"; case X509_V_ERR_SUITE_B_INVALID_SIGNATURE_ALGORITHM: - return "Suite B: invalid signature algorithm"; + return "Suite B: invalid signature algorithm"; case X509_V_ERR_SUITE_B_LOS_NOT_ALLOWED: - return "Suite B: curve not allowed for this LOS"; + return "Suite B: curve not allowed for this LOS"; case X509_V_ERR_SUITE_B_CANNOT_SIGN_P_384_WITH_P_256: - return "Suite B: cannot sign P-384 with P-256"; + return "Suite B: cannot sign P-384 with P-256"; case X509_V_ERR_HOSTNAME_MISMATCH: - return "Hostname mismatch"; + return "Hostname mismatch"; case X509_V_ERR_EMAIL_MISMATCH: - return "Email address mismatch"; + return "Email address mismatch"; case X509_V_ERR_IP_ADDRESS_MISMATCH: - return "IP address mismatch"; + return "IP address mismatch"; case X509_V_ERR_INVALID_CALL: - return "Invalid certificate verification context"; + return "Invalid certificate verification context"; case X509_V_ERR_STORE_LOOKUP: - return "Issuer certificate lookup error"; + return "Issuer certificate lookup error"; case X509_V_ERR_NAME_CONSTRAINTS_WITHOUT_SANS: - return "Issuer has name constraints but leaf has no SANs"; + return "Issuer has name constraints but leaf has no SANs"; default: - return "unknown certificate verification error"; - } + return "unknown certificate verification error"; + } } diff --git a/crypto/x509/x509_v3.c b/crypto/x509/x509_v3.c index 985161d543..e26d1ab701 100644 --- a/crypto/x509/x509_v3.c +++ b/crypto/x509/x509_v3.c @@ -65,217 +65,228 @@ #include "internal.h" -int X509v3_get_ext_count(const STACK_OF(X509_EXTENSION) *x) -{ - if (x == NULL) - return (0); - return (sk_X509_EXTENSION_num(x)); +int X509v3_get_ext_count(const STACK_OF(X509_EXTENSION) *x) { + if (x == NULL) { + return (0); + } + return (sk_X509_EXTENSION_num(x)); } int X509v3_get_ext_by_NID(const STACK_OF(X509_EXTENSION) *x, int nid, - int lastpos) -{ - const ASN1_OBJECT *obj = OBJ_nid2obj(nid); - if (obj == NULL) { - return -1; - } - return X509v3_get_ext_by_OBJ(x, obj, lastpos); + int lastpos) { + const ASN1_OBJECT *obj = OBJ_nid2obj(nid); + if (obj == NULL) { + return -1; + } + return X509v3_get_ext_by_OBJ(x, obj, lastpos); } int X509v3_get_ext_by_OBJ(const STACK_OF(X509_EXTENSION) *sk, - const ASN1_OBJECT *obj, int lastpos) -{ - int n; - X509_EXTENSION *ex; + const ASN1_OBJECT *obj, int lastpos) { + int n; + X509_EXTENSION *ex; - if (sk == NULL) - return (-1); - lastpos++; - if (lastpos < 0) - lastpos = 0; - n = sk_X509_EXTENSION_num(sk); - for (; lastpos < n; lastpos++) { - ex = sk_X509_EXTENSION_value(sk, lastpos); - if (OBJ_cmp(ex->object, obj) == 0) - return (lastpos); - } + if (sk == NULL) { return (-1); + } + lastpos++; + if (lastpos < 0) { + lastpos = 0; + } + n = sk_X509_EXTENSION_num(sk); + for (; lastpos < n; lastpos++) { + ex = sk_X509_EXTENSION_value(sk, lastpos); + if (OBJ_cmp(ex->object, obj) == 0) { + return (lastpos); + } + } + return (-1); } int X509v3_get_ext_by_critical(const STACK_OF(X509_EXTENSION) *sk, int crit, - int lastpos) -{ - if (sk == NULL) { - return -1; - } + int lastpos) { + if (sk == NULL) { + return -1; + } - lastpos++; - if (lastpos < 0) { - lastpos = 0; - } + lastpos++; + if (lastpos < 0) { + lastpos = 0; + } - crit = !!crit; - int n = sk_X509_EXTENSION_num(sk); - for (; lastpos < n; lastpos++) { - const X509_EXTENSION *ex = sk_X509_EXTENSION_value(sk, lastpos); - if (X509_EXTENSION_get_critical(ex) == crit) { - return lastpos; - } + crit = !!crit; + int n = sk_X509_EXTENSION_num(sk); + for (; lastpos < n; lastpos++) { + const X509_EXTENSION *ex = sk_X509_EXTENSION_value(sk, lastpos); + if (X509_EXTENSION_get_critical(ex) == crit) { + return lastpos; } - return -1; + } + return -1; } -X509_EXTENSION *X509v3_get_ext(const STACK_OF(X509_EXTENSION) *x, int loc) -{ - if (x == NULL || loc < 0 || sk_X509_EXTENSION_num(x) <= (size_t)loc) - return NULL; - else - return sk_X509_EXTENSION_value(x, loc); +X509_EXTENSION *X509v3_get_ext(const STACK_OF(X509_EXTENSION) *x, int loc) { + if (x == NULL || loc < 0 || sk_X509_EXTENSION_num(x) <= (size_t)loc) { + return NULL; + } else { + return sk_X509_EXTENSION_value(x, loc); + } } -X509_EXTENSION *X509v3_delete_ext(STACK_OF(X509_EXTENSION) *x, int loc) -{ - X509_EXTENSION *ret; +X509_EXTENSION *X509v3_delete_ext(STACK_OF(X509_EXTENSION) *x, int loc) { + X509_EXTENSION *ret; - if (x == NULL || loc < 0 || sk_X509_EXTENSION_num(x) <= (size_t)loc) - return (NULL); - ret = sk_X509_EXTENSION_delete(x, loc); - return (ret); + if (x == NULL || loc < 0 || sk_X509_EXTENSION_num(x) <= (size_t)loc) { + return (NULL); + } + ret = sk_X509_EXTENSION_delete(x, loc); + return (ret); } STACK_OF(X509_EXTENSION) *X509v3_add_ext(STACK_OF(X509_EXTENSION) **x, - X509_EXTENSION *ex, int loc) -{ - X509_EXTENSION *new_ex = NULL; - int n; - STACK_OF(X509_EXTENSION) *sk = NULL; + X509_EXTENSION *ex, int loc) { + X509_EXTENSION *new_ex = NULL; + int n; + STACK_OF(X509_EXTENSION) *sk = NULL; - if (x == NULL) { - OPENSSL_PUT_ERROR(X509, ERR_R_PASSED_NULL_PARAMETER); - goto err2; - } + if (x == NULL) { + OPENSSL_PUT_ERROR(X509, ERR_R_PASSED_NULL_PARAMETER); + goto err2; + } - if (*x == NULL) { - if ((sk = sk_X509_EXTENSION_new_null()) == NULL) - goto err; - } else - sk = *x; + if (*x == NULL) { + if ((sk = sk_X509_EXTENSION_new_null()) == NULL) { + goto err; + } + } else { + sk = *x; + } - n = sk_X509_EXTENSION_num(sk); - if (loc > n) - loc = n; - else if (loc < 0) - loc = n; + n = sk_X509_EXTENSION_num(sk); + if (loc > n) { + loc = n; + } else if (loc < 0) { + loc = n; + } - if ((new_ex = X509_EXTENSION_dup(ex)) == NULL) - goto err2; - if (!sk_X509_EXTENSION_insert(sk, new_ex, loc)) - goto err; - if (*x == NULL) - *x = sk; - return (sk); - err: - OPENSSL_PUT_ERROR(X509, ERR_R_MALLOC_FAILURE); - err2: - X509_EXTENSION_free(new_ex); - sk_X509_EXTENSION_free(sk); - return NULL; + if ((new_ex = X509_EXTENSION_dup(ex)) == NULL) { + goto err2; + } + if (!sk_X509_EXTENSION_insert(sk, new_ex, loc)) { + goto err; + } + if (*x == NULL) { + *x = sk; + } + return (sk); +err: + OPENSSL_PUT_ERROR(X509, ERR_R_MALLOC_FAILURE); +err2: + X509_EXTENSION_free(new_ex); + sk_X509_EXTENSION_free(sk); + return NULL; } X509_EXTENSION *X509_EXTENSION_create_by_NID(X509_EXTENSION **ex, int nid, int crit, - const ASN1_OCTET_STRING *data) -{ - const ASN1_OBJECT *obj; - X509_EXTENSION *ret; + const ASN1_OCTET_STRING *data) { + const ASN1_OBJECT *obj; + X509_EXTENSION *ret; - obj = OBJ_nid2obj(nid); - if (obj == NULL) { - OPENSSL_PUT_ERROR(X509, X509_R_UNKNOWN_NID); - return (NULL); - } - ret = X509_EXTENSION_create_by_OBJ(ex, obj, crit, data); - return (ret); + obj = OBJ_nid2obj(nid); + if (obj == NULL) { + OPENSSL_PUT_ERROR(X509, X509_R_UNKNOWN_NID); + return (NULL); + } + ret = X509_EXTENSION_create_by_OBJ(ex, obj, crit, data); + return (ret); } X509_EXTENSION *X509_EXTENSION_create_by_OBJ(X509_EXTENSION **ex, const ASN1_OBJECT *obj, int crit, - const ASN1_OCTET_STRING *data) -{ - X509_EXTENSION *ret; + const ASN1_OCTET_STRING *data) { + X509_EXTENSION *ret; - if ((ex == NULL) || (*ex == NULL)) { - if ((ret = X509_EXTENSION_new()) == NULL) { - OPENSSL_PUT_ERROR(X509, ERR_R_MALLOC_FAILURE); - return (NULL); - } - } else - ret = *ex; + if ((ex == NULL) || (*ex == NULL)) { + if ((ret = X509_EXTENSION_new()) == NULL) { + OPENSSL_PUT_ERROR(X509, ERR_R_MALLOC_FAILURE); + return (NULL); + } + } else { + ret = *ex; + } - if (!X509_EXTENSION_set_object(ret, obj)) - goto err; - if (!X509_EXTENSION_set_critical(ret, crit)) - goto err; - if (!X509_EXTENSION_set_data(ret, data)) - goto err; + if (!X509_EXTENSION_set_object(ret, obj)) { + goto err; + } + if (!X509_EXTENSION_set_critical(ret, crit)) { + goto err; + } + if (!X509_EXTENSION_set_data(ret, data)) { + goto err; + } - if ((ex != NULL) && (*ex == NULL)) - *ex = ret; - return (ret); - err: - if ((ex == NULL) || (ret != *ex)) - X509_EXTENSION_free(ret); - return (NULL); + if ((ex != NULL) && (*ex == NULL)) { + *ex = ret; + } + return (ret); +err: + if ((ex == NULL) || (ret != *ex)) { + X509_EXTENSION_free(ret); + } + return (NULL); } -int X509_EXTENSION_set_object(X509_EXTENSION *ex, const ASN1_OBJECT *obj) -{ - if ((ex == NULL) || (obj == NULL)) - return (0); - ASN1_OBJECT_free(ex->object); - ex->object = OBJ_dup(obj); - return ex->object != NULL; +int X509_EXTENSION_set_object(X509_EXTENSION *ex, const ASN1_OBJECT *obj) { + if ((ex == NULL) || (obj == NULL)) { + return (0); + } + ASN1_OBJECT_free(ex->object); + ex->object = OBJ_dup(obj); + return ex->object != NULL; } -int X509_EXTENSION_set_critical(X509_EXTENSION *ex, int crit) -{ - if (ex == NULL) - return (0); - ex->critical = (crit) ? 0xFF : -1; - return (1); +int X509_EXTENSION_set_critical(X509_EXTENSION *ex, int crit) { + if (ex == NULL) { + return (0); + } + ex->critical = (crit) ? 0xFF : -1; + return (1); } -int X509_EXTENSION_set_data(X509_EXTENSION *ex, const ASN1_OCTET_STRING *data) -{ - int i; +int X509_EXTENSION_set_data(X509_EXTENSION *ex, const ASN1_OCTET_STRING *data) { + int i; - if (ex == NULL) - return (0); - i = ASN1_OCTET_STRING_set(ex->value, data->data, data->length); - if (!i) - return (0); - return (1); + if (ex == NULL) { + return (0); + } + i = ASN1_OCTET_STRING_set(ex->value, data->data, data->length); + if (!i) { + return (0); + } + return (1); } -ASN1_OBJECT *X509_EXTENSION_get_object(X509_EXTENSION *ex) -{ - if (ex == NULL) - return (NULL); - return (ex->object); +ASN1_OBJECT *X509_EXTENSION_get_object(X509_EXTENSION *ex) { + if (ex == NULL) { + return (NULL); + } + return (ex->object); } -ASN1_OCTET_STRING *X509_EXTENSION_get_data(X509_EXTENSION *ex) -{ - if (ex == NULL) - return (NULL); - return (ex->value); +ASN1_OCTET_STRING *X509_EXTENSION_get_data(X509_EXTENSION *ex) { + if (ex == NULL) { + return (NULL); + } + return (ex->value); } -int X509_EXTENSION_get_critical(const X509_EXTENSION *ex) -{ - if (ex == NULL) - return (0); - if (ex->critical > 0) - return 1; - return 0; +int X509_EXTENSION_get_critical(const X509_EXTENSION *ex) { + if (ex == NULL) { + return (0); + } + if (ex->critical > 0) { + return 1; + } + return 0; } diff --git a/crypto/x509/x509_vfy.c b/crypto/x509/x509_vfy.c index f41ae6e133..bbbecc6e1d 100644 --- a/crypto/x509/x509_vfy.c +++ b/crypto/x509/x509_vfy.c @@ -67,9 +67,9 @@ #include #include -#include "internal.h" #include "../internal.h" #include "../x509v3/internal.h" +#include "internal.h" static CRYPTO_EX_DATA_CLASS g_ex_data_class = CRYPTO_EX_DATA_CLASS_INIT_WITH_APP_DATA; @@ -78,39 +78,40 @@ static CRYPTO_EX_DATA_CLASS g_ex_data_class = /* No unhandled critical extensions */ -#define CRL_SCORE_NOCRITICAL 0x100 +#define CRL_SCORE_NOCRITICAL 0x100 /* certificate is within CRL scope */ -#define CRL_SCORE_SCOPE 0x080 +#define CRL_SCORE_SCOPE 0x080 /* CRL times valid */ -#define CRL_SCORE_TIME 0x040 +#define CRL_SCORE_TIME 0x040 /* Issuer name matches certificate */ -#define CRL_SCORE_ISSUER_NAME 0x020 +#define CRL_SCORE_ISSUER_NAME 0x020 /* If this score or above CRL is probably valid */ -#define CRL_SCORE_VALID (CRL_SCORE_NOCRITICAL|CRL_SCORE_TIME|CRL_SCORE_SCOPE) +#define CRL_SCORE_VALID \ + (CRL_SCORE_NOCRITICAL | CRL_SCORE_TIME | CRL_SCORE_SCOPE) /* CRL issuer is certificate issuer */ -#define CRL_SCORE_ISSUER_CERT 0x018 +#define CRL_SCORE_ISSUER_CERT 0x018 /* CRL issuer is on certificate path */ -#define CRL_SCORE_SAME_PATH 0x008 +#define CRL_SCORE_SAME_PATH 0x008 /* CRL issuer matches CRL AKID */ -#define CRL_SCORE_AKID 0x004 +#define CRL_SCORE_AKID 0x004 /* Have a delta CRL with valid times */ -#define CRL_SCORE_TIME_DELTA 0x002 +#define CRL_SCORE_TIME_DELTA 0x002 static int null_callback(int ok, X509_STORE_CTX *e); static int check_issued(X509_STORE_CTX *ctx, X509 *x, X509 *issuer); @@ -125,445 +126,460 @@ static int check_policy(X509_STORE_CTX *ctx); static int get_crl_score(X509_STORE_CTX *ctx, X509 **pissuer, unsigned int *preasons, X509_CRL *crl, X509 *x); -static int get_crl_delta(X509_STORE_CTX *ctx, - X509_CRL **pcrl, X509_CRL **pdcrl, X509 *x); -static void get_delta_sk(X509_STORE_CTX *ctx, X509_CRL **dcrl, - int *pcrl_score, X509_CRL *base, - STACK_OF(X509_CRL) *crls); +static int get_crl_delta(X509_STORE_CTX *ctx, X509_CRL **pcrl, X509_CRL **pdcrl, + X509 *x); +static void get_delta_sk(X509_STORE_CTX *ctx, X509_CRL **dcrl, int *pcrl_score, + X509_CRL *base, STACK_OF(X509_CRL) *crls); static void crl_akid_check(X509_STORE_CTX *ctx, X509_CRL *crl, X509 **pissuer, int *pcrl_score); static int crl_crldp_check(X509 *x, X509_CRL *crl, int crl_score, unsigned int *preasons); static int check_crl_path(X509_STORE_CTX *ctx, X509 *x); -static int check_crl_chain(X509_STORE_CTX *ctx, - STACK_OF(X509) *cert_path, +static int check_crl_chain(X509_STORE_CTX *ctx, STACK_OF(X509) *cert_path, STACK_OF(X509) *crl_path); static int internal_verify(X509_STORE_CTX *ctx); -static int null_callback(int ok, X509_STORE_CTX *e) -{ - return ok; -} +static int null_callback(int ok, X509_STORE_CTX *e) { return ok; } /* cert_self_signed checks if |x| is self-signed. If |x| is valid, it returns * one and sets |*out_is_self_signed| to the result. If |x| is invalid, it * returns zero. */ -static int cert_self_signed(X509 *x, int *out_is_self_signed) -{ - if (!x509v3_cache_extensions(x)) { - return 0; - } - *out_is_self_signed = (x->ex_flags & EXFLAG_SS) != 0; - return 1; +static int cert_self_signed(X509 *x, int *out_is_self_signed) { + if (!x509v3_cache_extensions(x)) { + return 0; + } + *out_is_self_signed = (x->ex_flags & EXFLAG_SS) != 0; + return 1; } /* Given a certificate try and find an exact match in the store */ -static X509 *lookup_cert_match(X509_STORE_CTX *ctx, X509 *x) -{ - STACK_OF(X509) *certs; - X509 *xtmp = NULL; - size_t i; - /* Lookup all certs with matching subject name */ - certs = ctx->lookup_certs(ctx, X509_get_subject_name(x)); - if (certs == NULL) - return NULL; - /* Look for exact match */ - for (i = 0; i < sk_X509_num(certs); i++) { - xtmp = sk_X509_value(certs, i); - if (!X509_cmp(xtmp, x)) - break; - } - if (i < sk_X509_num(certs)) - X509_up_ref(xtmp); - else - xtmp = NULL; - sk_X509_pop_free(certs, X509_free); - return xtmp; -} - -int X509_verify_cert(X509_STORE_CTX *ctx) -{ - X509 *x, *xtmp, *xtmp2, *chain_ss = NULL; - int bad_chain = 0; - X509_VERIFY_PARAM *param = ctx->param; - int depth, i, ok = 0; - int num, j, retry, trust; - STACK_OF(X509) *sktmp = NULL; - - if (ctx->cert == NULL) { - OPENSSL_PUT_ERROR(X509, X509_R_NO_CERT_SET_FOR_US_TO_VERIFY); - ctx->error = X509_V_ERR_INVALID_CALL; - return -1; - } - if (ctx->chain != NULL) { - /* - * This X509_STORE_CTX has already been used to verify a cert. We - * cannot do another one. - */ - OPENSSL_PUT_ERROR(X509, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); - ctx->error = X509_V_ERR_INVALID_CALL; - return -1; - } - +static X509 *lookup_cert_match(X509_STORE_CTX *ctx, X509 *x) { + STACK_OF(X509) *certs; + X509 *xtmp = NULL; + size_t i; + /* Lookup all certs with matching subject name */ + certs = ctx->lookup_certs(ctx, X509_get_subject_name(x)); + if (certs == NULL) { + return NULL; + } + /* Look for exact match */ + for (i = 0; i < sk_X509_num(certs); i++) { + xtmp = sk_X509_value(certs, i); + if (!X509_cmp(xtmp, x)) { + break; + } + } + if (i < sk_X509_num(certs)) { + X509_up_ref(xtmp); + } else { + xtmp = NULL; + } + sk_X509_pop_free(certs, X509_free); + return xtmp; +} + +int X509_verify_cert(X509_STORE_CTX *ctx) { + X509 *x, *xtmp, *xtmp2, *chain_ss = NULL; + int bad_chain = 0; + X509_VERIFY_PARAM *param = ctx->param; + int depth, i, ok = 0; + int num, j, retry, trust; + STACK_OF(X509) *sktmp = NULL; + + if (ctx->cert == NULL) { + OPENSSL_PUT_ERROR(X509, X509_R_NO_CERT_SET_FOR_US_TO_VERIFY); + ctx->error = X509_V_ERR_INVALID_CALL; + return -1; + } + if (ctx->chain != NULL) { /* - * first we make sure the chain we are going to build is present and that - * the first entry is in place + * This X509_STORE_CTX has already been used to verify a cert. We + * cannot do another one. */ - ctx->chain = sk_X509_new_null(); - if (ctx->chain == NULL || !sk_X509_push(ctx->chain, ctx->cert)) { - OPENSSL_PUT_ERROR(X509, ERR_R_MALLOC_FAILURE); - ctx->error = X509_V_ERR_OUT_OF_MEM; - goto end; - } - X509_up_ref(ctx->cert); - ctx->last_untrusted = 1; + OPENSSL_PUT_ERROR(X509, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); + ctx->error = X509_V_ERR_INVALID_CALL; + return -1; + } + + /* + * first we make sure the chain we are going to build is present and that + * the first entry is in place + */ + ctx->chain = sk_X509_new_null(); + if (ctx->chain == NULL || !sk_X509_push(ctx->chain, ctx->cert)) { + OPENSSL_PUT_ERROR(X509, ERR_R_MALLOC_FAILURE); + ctx->error = X509_V_ERR_OUT_OF_MEM; + goto end; + } + X509_up_ref(ctx->cert); + ctx->last_untrusted = 1; + + /* We use a temporary STACK so we can chop and hack at it. */ + if (ctx->untrusted != NULL && (sktmp = sk_X509_dup(ctx->untrusted)) == NULL) { + OPENSSL_PUT_ERROR(X509, ERR_R_MALLOC_FAILURE); + ctx->error = X509_V_ERR_OUT_OF_MEM; + goto end; + } - /* We use a temporary STACK so we can chop and hack at it. */ - if (ctx->untrusted != NULL - && (sktmp = sk_X509_dup(ctx->untrusted)) == NULL) { - OPENSSL_PUT_ERROR(X509, ERR_R_MALLOC_FAILURE); - ctx->error = X509_V_ERR_OUT_OF_MEM; - goto end; + num = sk_X509_num(ctx->chain); + x = sk_X509_value(ctx->chain, num - 1); + depth = param->depth; + + for (;;) { + /* If we have enough, we break */ + if (depth < num) { + break; /* FIXME: If this happens, we should take + * note of it and, if appropriate, use the + * X509_V_ERR_CERT_CHAIN_TOO_LONG error code + * later. */ } - num = sk_X509_num(ctx->chain); - x = sk_X509_value(ctx->chain, num - 1); - depth = param->depth; + int is_self_signed; + if (!cert_self_signed(x, &is_self_signed)) { + ctx->error = X509_V_ERR_INVALID_EXTENSION; + goto end; + } - for (;;) { - /* If we have enough, we break */ - if (depth < num) - break; /* FIXME: If this happens, we should take - * note of it and, if appropriate, use the - * X509_V_ERR_CERT_CHAIN_TOO_LONG error code - * later. */ - - int is_self_signed; - if (!cert_self_signed(x, &is_self_signed)) { - ctx->error = X509_V_ERR_INVALID_EXTENSION; - goto end; + /* If we are self signed, we break */ + if (is_self_signed) { + break; + } + /* + * If asked see if we can find issuer in trusted store first + */ + if (ctx->param->flags & X509_V_FLAG_TRUSTED_FIRST) { + ok = ctx->get_issuer(&xtmp, ctx, x); + if (ok < 0) { + ctx->error = X509_V_ERR_STORE_LOOKUP; + goto end; + } + /* + * If successful for now free up cert so it will be picked up + * again later. + */ + if (ok > 0) { + X509_free(xtmp); + break; + } + } + + /* If we were passed a cert chain, use it first */ + if (sktmp != NULL) { + xtmp = find_issuer(ctx, sktmp, x); + if (xtmp != NULL) { + if (!sk_X509_push(ctx->chain, xtmp)) { + OPENSSL_PUT_ERROR(X509, ERR_R_MALLOC_FAILURE); + ctx->error = X509_V_ERR_OUT_OF_MEM; + ok = 0; + goto end; } - - /* If we are self signed, we break */ - if (is_self_signed) - break; + X509_up_ref(xtmp); + (void)sk_X509_delete_ptr(sktmp, xtmp); + ctx->last_untrusted++; + x = xtmp; + num++; /* - * If asked see if we can find issuer in trusted store first + * reparse the full chain for the next one */ - if (ctx->param->flags & X509_V_FLAG_TRUSTED_FIRST) { - ok = ctx->get_issuer(&xtmp, ctx, x); - if (ok < 0) { - ctx->error = X509_V_ERR_STORE_LOOKUP; - goto end; - } - /* - * If successful for now free up cert so it will be picked up - * again later. - */ - if (ok > 0) { - X509_free(xtmp); - break; - } - } - - /* If we were passed a cert chain, use it first */ - if (sktmp != NULL) { - xtmp = find_issuer(ctx, sktmp, x); - if (xtmp != NULL) { - if (!sk_X509_push(ctx->chain, xtmp)) { - OPENSSL_PUT_ERROR(X509, ERR_R_MALLOC_FAILURE); - ctx->error = X509_V_ERR_OUT_OF_MEM; - ok = 0; - goto end; - } - X509_up_ref(xtmp); - (void)sk_X509_delete_ptr(sktmp, xtmp); - ctx->last_untrusted++; - x = xtmp; - num++; - /* - * reparse the full chain for the next one - */ - continue; - } - } - break; + continue; + } } + break; + } + + /* Remember how many untrusted certs we have */ + j = num; + /* + * at this point, chain should contain a list of untrusted certificates. + * We now need to add at least one trusted one, if possible, otherwise we + * complain. + */ - /* Remember how many untrusted certs we have */ - j = num; + do { /* - * at this point, chain should contain a list of untrusted certificates. - * We now need to add at least one trusted one, if possible, otherwise we - * complain. + * Examine last certificate in chain and see if it is self signed. */ + i = sk_X509_num(ctx->chain); + x = sk_X509_value(ctx->chain, i - 1); - do { + int is_self_signed; + if (!cert_self_signed(x, &is_self_signed)) { + ctx->error = X509_V_ERR_INVALID_EXTENSION; + goto end; + } + + if (is_self_signed) { + /* we have a self signed certificate */ + if (sk_X509_num(ctx->chain) == 1) { /* - * Examine last certificate in chain and see if it is self signed. + * We have a single self signed certificate: see if we can + * find it in the store. We must have an exact match to avoid + * possible impersonation. */ - i = sk_X509_num(ctx->chain); - x = sk_X509_value(ctx->chain, i - 1); - - int is_self_signed; - if (!cert_self_signed(x, &is_self_signed)) { - ctx->error = X509_V_ERR_INVALID_EXTENSION; - goto end; - } - - if (is_self_signed) { - /* we have a self signed certificate */ - if (sk_X509_num(ctx->chain) == 1) { - /* - * We have a single self signed certificate: see if we can - * find it in the store. We must have an exact match to avoid - * possible impersonation. - */ - ok = ctx->get_issuer(&xtmp, ctx, x); - if ((ok <= 0) || X509_cmp(x, xtmp)) { - ctx->error = X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT; - ctx->current_cert = x; - ctx->error_depth = i - 1; - if (ok == 1) - X509_free(xtmp); - bad_chain = 1; - ok = ctx->verify_cb(0, ctx); - if (!ok) - goto end; - } else { - /* - * We have a match: replace certificate with store - * version so we get any trust settings. - */ - X509_free(x); - x = xtmp; - (void)sk_X509_set(ctx->chain, i - 1, x); - ctx->last_untrusted = 0; - } - } else { - /* - * extract and save self signed certificate for later use - */ - chain_ss = sk_X509_pop(ctx->chain); - ctx->last_untrusted--; - num--; - j--; - x = sk_X509_value(ctx->chain, num - 1); - } - } - /* We now lookup certs from the certificate store */ - for (;;) { - /* If we have enough, we break */ - if (depth < num) - break; - if (!cert_self_signed(x, &is_self_signed)) { - ctx->error = X509_V_ERR_INVALID_EXTENSION; - goto end; - } - /* If we are self signed, we break */ - if (is_self_signed) - break; - ok = ctx->get_issuer(&xtmp, ctx, x); - - if (ok < 0) { - ctx->error = X509_V_ERR_STORE_LOOKUP; - goto end; - } - if (ok == 0) - break; - x = xtmp; - if (!sk_X509_push(ctx->chain, x)) { - X509_free(xtmp); - OPENSSL_PUT_ERROR(X509, ERR_R_MALLOC_FAILURE); - ctx->error = X509_V_ERR_OUT_OF_MEM; - ok = 0; - goto end; - } - num++; - } - - /* we now have our chain, lets check it... */ - trust = check_trust(ctx); - - /* If explicitly rejected error */ - if (trust == X509_TRUST_REJECTED) { - ok = 0; + ok = ctx->get_issuer(&xtmp, ctx, x); + if ((ok <= 0) || X509_cmp(x, xtmp)) { + ctx->error = X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT; + ctx->current_cert = x; + ctx->error_depth = i - 1; + if (ok == 1) { + X509_free(xtmp); + } + bad_chain = 1; + ok = ctx->verify_cb(0, ctx); + if (!ok) { goto end; + } + } else { + /* + * We have a match: replace certificate with store + * version so we get any trust settings. + */ + X509_free(x); + x = xtmp; + (void)sk_X509_set(ctx->chain, i - 1, x); + ctx->last_untrusted = 0; } + } else { /* - * If it's not explicitly trusted then check if there is an alternative - * chain that could be used. We only do this if we haven't already - * checked via TRUSTED_FIRST and the user hasn't switched off alternate - * chain checking + * extract and save self signed certificate for later use */ - retry = 0; - if (trust != X509_TRUST_TRUSTED - && !(ctx->param->flags & X509_V_FLAG_TRUSTED_FIRST) - && !(ctx->param->flags & X509_V_FLAG_NO_ALT_CHAINS)) { - while (j-- > 1) { - xtmp2 = sk_X509_value(ctx->chain, j - 1); - ok = ctx->get_issuer(&xtmp, ctx, xtmp2); - if (ok < 0) - goto end; - /* Check if we found an alternate chain */ - if (ok > 0) { - /* - * Free up the found cert we'll add it again later - */ - X509_free(xtmp); - - /* - * Dump all the certs above this point - we've found an - * alternate chain - */ - while (num > j) { - xtmp = sk_X509_pop(ctx->chain); - X509_free(xtmp); - num--; - } - ctx->last_untrusted = sk_X509_num(ctx->chain); - retry = 1; - break; - } - } - } - } while (retry); - - /* - * If not explicitly trusted then indicate error unless it's a single - * self signed certificate in which case we've indicated an error already - * and set bad_chain == 1 - */ - if (trust != X509_TRUST_TRUSTED && !bad_chain) { - if ((chain_ss == NULL) || !ctx->check_issued(ctx, x, chain_ss)) { - if (ctx->last_untrusted >= num) - ctx->error = X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY; - else - ctx->error = X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT; - ctx->current_cert = x; - } else { - - sk_X509_push(ctx->chain, chain_ss); - num++; - ctx->last_untrusted = num; - ctx->current_cert = chain_ss; - ctx->error = X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN; - chain_ss = NULL; - } - - ctx->error_depth = num - 1; - bad_chain = 1; - ok = ctx->verify_cb(0, ctx); - if (!ok) - goto end; - } - - /* We have the chain complete: now we need to check its purpose */ - ok = check_chain_extensions(ctx); - - if (!ok) + chain_ss = sk_X509_pop(ctx->chain); + ctx->last_untrusted--; + num--; + j--; + x = sk_X509_value(ctx->chain, num - 1); + } + } + /* We now lookup certs from the certificate store */ + for (;;) { + /* If we have enough, we break */ + if (depth < num) { + break; + } + if (!cert_self_signed(x, &is_self_signed)) { + ctx->error = X509_V_ERR_INVALID_EXTENSION; goto end; + } + /* If we are self signed, we break */ + if (is_self_signed) { + break; + } + ok = ctx->get_issuer(&xtmp, ctx, x); - ok = check_id(ctx); - - if (!ok) + if (ok < 0) { + ctx->error = X509_V_ERR_STORE_LOOKUP; goto end; + } + if (ok == 0) { + break; + } + x = xtmp; + if (!sk_X509_push(ctx->chain, x)) { + X509_free(xtmp); + OPENSSL_PUT_ERROR(X509, ERR_R_MALLOC_FAILURE); + ctx->error = X509_V_ERR_OUT_OF_MEM; + ok = 0; + goto end; + } + num++; + } + /* we now have our chain, lets check it... */ + trust = check_trust(ctx); + + /* If explicitly rejected error */ + if (trust == X509_TRUST_REJECTED) { + ok = 0; + goto end; + } /* - * Check revocation status: we do this after copying parameters because - * they may be needed for CRL signature verification. + * If it's not explicitly trusted then check if there is an alternative + * chain that could be used. We only do this if we haven't already + * checked via TRUSTED_FIRST and the user hasn't switched off alternate + * chain checking */ + retry = 0; + if (trust != X509_TRUST_TRUSTED && + !(ctx->param->flags & X509_V_FLAG_TRUSTED_FIRST) && + !(ctx->param->flags & X509_V_FLAG_NO_ALT_CHAINS)) { + while (j-- > 1) { + xtmp2 = sk_X509_value(ctx->chain, j - 1); + ok = ctx->get_issuer(&xtmp, ctx, xtmp2); + if (ok < 0) { + goto end; + } + /* Check if we found an alternate chain */ + if (ok > 0) { + /* + * Free up the found cert we'll add it again later + */ + X509_free(xtmp); + + /* + * Dump all the certs above this point - we've found an + * alternate chain + */ + while (num > j) { + xtmp = sk_X509_pop(ctx->chain); + X509_free(xtmp); + num--; + } + ctx->last_untrusted = sk_X509_num(ctx->chain); + retry = 1; + break; + } + } + } + } while (retry); + + /* + * If not explicitly trusted then indicate error unless it's a single + * self signed certificate in which case we've indicated an error already + * and set bad_chain == 1 + */ + if (trust != X509_TRUST_TRUSTED && !bad_chain) { + if ((chain_ss == NULL) || !ctx->check_issued(ctx, x, chain_ss)) { + if (ctx->last_untrusted >= num) { + ctx->error = X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY; + } else { + ctx->error = X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT; + } + ctx->current_cert = x; + } else { + sk_X509_push(ctx->chain, chain_ss); + num++; + ctx->last_untrusted = num; + ctx->current_cert = chain_ss; + ctx->error = X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN; + chain_ss = NULL; + } - ok = ctx->check_revocation(ctx); - if (!ok) - goto end; - - int err = X509_chain_check_suiteb(&ctx->error_depth, NULL, ctx->chain, - ctx->param->flags); - if (err != X509_V_OK) { - ctx->error = err; - ctx->current_cert = sk_X509_value(ctx->chain, ctx->error_depth); - ok = ctx->verify_cb(0, ctx); - if (!ok) - goto end; + ctx->error_depth = num - 1; + bad_chain = 1; + ok = ctx->verify_cb(0, ctx); + if (!ok) { + goto end; } + } - /* At this point, we have a chain and need to verify it */ - if (ctx->verify != NULL) - ok = ctx->verify(ctx); - else - ok = internal_verify(ctx); - if (!ok) - goto end; + /* We have the chain complete: now we need to check its purpose */ + ok = check_chain_extensions(ctx); - /* Check name constraints */ + if (!ok) { + goto end; + } - ok = check_name_constraints(ctx); - if (!ok) - goto end; + ok = check_id(ctx); + + if (!ok) { + goto end; + } - /* If we get this far evaluate policies */ - if (!bad_chain && (ctx->param->flags & X509_V_FLAG_POLICY_CHECK)) - ok = ctx->check_policy(ctx); + /* + * Check revocation status: we do this after copying parameters because + * they may be needed for CRL signature verification. + */ - end: - if (sktmp != NULL) - sk_X509_free(sktmp); - if (chain_ss != NULL) - X509_free(chain_ss); + ok = ctx->check_revocation(ctx); + if (!ok) { + goto end; + } - /* Safety net, error returns must set ctx->error */ - if (ok <= 0 && ctx->error == X509_V_OK) - ctx->error = X509_V_ERR_UNSPECIFIED; - return ok; + int err = X509_chain_check_suiteb(&ctx->error_depth, NULL, ctx->chain, + ctx->param->flags); + if (err != X509_V_OK) { + ctx->error = err; + ctx->current_cert = sk_X509_value(ctx->chain, ctx->error_depth); + ok = ctx->verify_cb(0, ctx); + if (!ok) { + goto end; + } + } + + /* At this point, we have a chain and need to verify it */ + if (ctx->verify != NULL) { + ok = ctx->verify(ctx); + } else { + ok = internal_verify(ctx); + } + if (!ok) { + goto end; + } + + /* Check name constraints */ + + ok = check_name_constraints(ctx); + if (!ok) { + goto end; + } + + /* If we get this far evaluate policies */ + if (!bad_chain && (ctx->param->flags & X509_V_FLAG_POLICY_CHECK)) { + ok = ctx->check_policy(ctx); + } + +end: + if (sktmp != NULL) { + sk_X509_free(sktmp); + } + if (chain_ss != NULL) { + X509_free(chain_ss); + } + + /* Safety net, error returns must set ctx->error */ + if (ok <= 0 && ctx->error == X509_V_OK) { + ctx->error = X509_V_ERR_UNSPECIFIED; + } + return ok; } /* * Given a STACK_OF(X509) find the issuer of cert (if any) */ -static X509 *find_issuer(X509_STORE_CTX *ctx, STACK_OF(X509) *sk, X509 *x) -{ - size_t i; - X509 *issuer; - for (i = 0; i < sk_X509_num(sk); i++) { - issuer = sk_X509_value(sk, i); - if (ctx->check_issued(ctx, x, issuer)) - return issuer; +static X509 *find_issuer(X509_STORE_CTX *ctx, STACK_OF(X509) *sk, X509 *x) { + size_t i; + X509 *issuer; + for (i = 0; i < sk_X509_num(sk); i++) { + issuer = sk_X509_value(sk, i); + if (ctx->check_issued(ctx, x, issuer)) { + return issuer; } - return NULL; + } + return NULL; } /* Given a possible certificate and issuer check them */ -static int check_issued(X509_STORE_CTX *ctx, X509 *x, X509 *issuer) -{ - int ret; - ret = X509_check_issued(issuer, x); - if (ret == X509_V_OK) - return 1; - /* If we haven't asked for issuer errors don't set ctx */ - if (!(ctx->param->flags & X509_V_FLAG_CB_ISSUER_CHECK)) - return 0; +static int check_issued(X509_STORE_CTX *ctx, X509 *x, X509 *issuer) { + int ret; + ret = X509_check_issued(issuer, x); + if (ret == X509_V_OK) { + return 1; + } + /* If we haven't asked for issuer errors don't set ctx */ + if (!(ctx->param->flags & X509_V_FLAG_CB_ISSUER_CHECK)) { + return 0; + } - ctx->error = ret; - ctx->current_cert = x; - ctx->current_issuer = issuer; - return ctx->verify_cb(0, ctx); + ctx->error = ret; + ctx->current_cert = x; + ctx->current_issuer = issuer; + return ctx->verify_cb(0, ctx); } /* Alternative lookup method: look from a STACK stored in other_ctx */ -static int get_issuer_sk(X509 **issuer, X509_STORE_CTX *ctx, X509 *x) -{ - *issuer = find_issuer(ctx, ctx->other_ctx, x); - if (*issuer) { - X509_up_ref(*issuer); - return 1; - } else - return 0; +static int get_issuer_sk(X509 **issuer, X509_STORE_CTX *ctx, X509 *x) { + *issuer = find_issuer(ctx, ctx->other_ctx, x); + if (*issuer) { + X509_up_ref(*issuer); + return 1; + } else { + return 0; + } } /* @@ -571,540 +587,571 @@ static int get_issuer_sk(X509 **issuer, X509_STORE_CTX *ctx, X509 *x) * purpose */ -static int check_chain_extensions(X509_STORE_CTX *ctx) -{ - int i, ok = 0, plen = 0; - X509 *x; - int proxy_path_length = 0; - int purpose; - int allow_proxy_certs; - - enum { - // ca_or_leaf allows either type of certificate so that direct use of - // self-signed certificates works. - ca_or_leaf, - must_be_ca, - must_not_be_ca, - } ca_requirement; - - /* CRL path validation */ - if (ctx->parent) { - allow_proxy_certs = 0; - purpose = X509_PURPOSE_CRL_SIGN; - } else { - allow_proxy_certs = - ! !(ctx->param->flags & X509_V_FLAG_ALLOW_PROXY_CERTS); - purpose = ctx->param->purpose; +static int check_chain_extensions(X509_STORE_CTX *ctx) { + int i, ok = 0, plen = 0; + X509 *x; + int proxy_path_length = 0; + int purpose; + int allow_proxy_certs; + + enum { + // ca_or_leaf allows either type of certificate so that direct use of + // self-signed certificates works. + ca_or_leaf, + must_be_ca, + must_not_be_ca, + } ca_requirement; + + /* CRL path validation */ + if (ctx->parent) { + allow_proxy_certs = 0; + purpose = X509_PURPOSE_CRL_SIGN; + } else { + allow_proxy_certs = !!(ctx->param->flags & X509_V_FLAG_ALLOW_PROXY_CERTS); + purpose = ctx->param->purpose; + } + + ca_requirement = ca_or_leaf; + + /* Check all untrusted certificates */ + for (i = 0; i < ctx->last_untrusted; i++) { + int ret; + x = sk_X509_value(ctx->chain, i); + if (!(ctx->param->flags & X509_V_FLAG_IGNORE_CRITICAL) && + (x->ex_flags & EXFLAG_CRITICAL)) { + ctx->error = X509_V_ERR_UNHANDLED_CRITICAL_EXTENSION; + ctx->error_depth = i; + ctx->current_cert = x; + ok = ctx->verify_cb(0, ctx); + if (!ok) { + goto end; + } + } + if (!allow_proxy_certs && (x->ex_flags & EXFLAG_PROXY)) { + ctx->error = X509_V_ERR_PROXY_CERTIFICATES_NOT_ALLOWED; + ctx->error_depth = i; + ctx->current_cert = x; + ok = ctx->verify_cb(0, ctx); + if (!ok) { + goto end; + } } - ca_requirement = ca_or_leaf; - - /* Check all untrusted certificates */ - for (i = 0; i < ctx->last_untrusted; i++) { - int ret; - x = sk_X509_value(ctx->chain, i); - if (!(ctx->param->flags & X509_V_FLAG_IGNORE_CRITICAL) - && (x->ex_flags & EXFLAG_CRITICAL)) { - ctx->error = X509_V_ERR_UNHANDLED_CRITICAL_EXTENSION; - ctx->error_depth = i; - ctx->current_cert = x; - ok = ctx->verify_cb(0, ctx); - if (!ok) - goto end; - } - if (!allow_proxy_certs && (x->ex_flags & EXFLAG_PROXY)) { - ctx->error = X509_V_ERR_PROXY_CERTIFICATES_NOT_ALLOWED; - ctx->error_depth = i; - ctx->current_cert = x; - ok = ctx->verify_cb(0, ctx); - if (!ok) - goto end; - } - - switch (ca_requirement) { - case ca_or_leaf: - ret = 1; - break; - case must_not_be_ca: - if (X509_check_ca(x)) { - ret = 0; - ctx->error = X509_V_ERR_INVALID_NON_CA; - } else - ret = 1; - break; - case must_be_ca: - if (!X509_check_ca(x)) { - ret = 0; - ctx->error = X509_V_ERR_INVALID_CA; - } else - ret = 1; - break; - default: - // impossible. - ret = 0; - } - - if (ret == 0) { - ctx->error_depth = i; - ctx->current_cert = x; - ok = ctx->verify_cb(0, ctx); - if (!ok) - goto end; - } - if (ctx->param->purpose > 0) { - ret = X509_check_purpose(x, purpose, ca_requirement == must_be_ca); - if (ret != 1) { - ret = 0; - ctx->error = X509_V_ERR_INVALID_PURPOSE; - ctx->error_depth = i; - ctx->current_cert = x; - ok = ctx->verify_cb(0, ctx); - if (!ok) - goto end; - } - } - /* Check pathlen if not self issued */ - if ((i > 1) && !(x->ex_flags & EXFLAG_SI) - && (x->ex_pathlen != -1) - && (plen > (x->ex_pathlen + proxy_path_length + 1))) { - ctx->error = X509_V_ERR_PATH_LENGTH_EXCEEDED; - ctx->error_depth = i; - ctx->current_cert = x; - ok = ctx->verify_cb(0, ctx); - if (!ok) - goto end; + switch (ca_requirement) { + case ca_or_leaf: + ret = 1; + break; + case must_not_be_ca: + if (X509_check_ca(x)) { + ret = 0; + ctx->error = X509_V_ERR_INVALID_NON_CA; + } else { + ret = 1; } - /* Increment path length if not self issued */ - if (!(x->ex_flags & EXFLAG_SI)) - plen++; - /* - * If this certificate is a proxy certificate, the next certificate - * must be another proxy certificate or a EE certificate. If not, - * the next certificate must be a CA certificate. - */ - if (x->ex_flags & EXFLAG_PROXY) { - if (x->ex_pcpathlen != -1 && i > x->ex_pcpathlen) { - ctx->error = X509_V_ERR_PROXY_PATH_LENGTH_EXCEEDED; - ctx->error_depth = i; - ctx->current_cert = x; - ok = ctx->verify_cb(0, ctx); - if (!ok) - goto end; - } - proxy_path_length++; - ca_requirement = must_not_be_ca; + break; + case must_be_ca: + if (!X509_check_ca(x)) { + ret = 0; + ctx->error = X509_V_ERR_INVALID_CA; } else { - ca_requirement = must_be_ca; + ret = 1; } + break; + default: + // impossible. + ret = 0; } - ok = 1; - end: - return ok; -} -static int reject_dns_name_in_common_name(X509 *x509) -{ - X509_NAME *name = X509_get_subject_name(x509); - int i = -1; - for (;;) { - i = X509_NAME_get_index_by_NID(name, NID_commonName, i); - if (i == -1) { - return X509_V_OK; - } - - X509_NAME_ENTRY *entry = X509_NAME_get_entry(name, i); - ASN1_STRING *common_name = X509_NAME_ENTRY_get_data(entry); - unsigned char *idval; - int idlen = ASN1_STRING_to_UTF8(&idval, common_name); - if (idlen < 0) { - return X509_V_ERR_OUT_OF_MEM; - } - /* Only process attributes that look like host names. Note it is - * important that this check be mirrored in |X509_check_host|. */ - int looks_like_dns = x509v3_looks_like_dns_name(idval, (size_t)idlen); - OPENSSL_free(idval); - if (looks_like_dns) { - return X509_V_ERR_NAME_CONSTRAINTS_WITHOUT_SANS; + if (ret == 0) { + ctx->error_depth = i; + ctx->current_cert = x; + ok = ctx->verify_cb(0, ctx); + if (!ok) { + goto end; + } + } + if (ctx->param->purpose > 0) { + ret = X509_check_purpose(x, purpose, ca_requirement == must_be_ca); + if (ret != 1) { + ret = 0; + ctx->error = X509_V_ERR_INVALID_PURPOSE; + ctx->error_depth = i; + ctx->current_cert = x; + ok = ctx->verify_cb(0, ctx); + if (!ok) { + goto end; } + } + } + /* Check pathlen if not self issued */ + if ((i > 1) && !(x->ex_flags & EXFLAG_SI) && (x->ex_pathlen != -1) && + (plen > (x->ex_pathlen + proxy_path_length + 1))) { + ctx->error = X509_V_ERR_PATH_LENGTH_EXCEEDED; + ctx->error_depth = i; + ctx->current_cert = x; + ok = ctx->verify_cb(0, ctx); + if (!ok) { + goto end; + } } -} - -static int check_name_constraints(X509_STORE_CTX *ctx) -{ - int i, j, rv; - int has_name_constraints = 0; - /* Check name constraints for all certificates */ - for (i = sk_X509_num(ctx->chain) - 1; i >= 0; i--) { - X509 *x = sk_X509_value(ctx->chain, i); - /* Ignore self issued certs unless last in chain */ - if (i && (x->ex_flags & EXFLAG_SI)) - continue; - /* - * Check against constraints for all certificates higher in chain - * including trust anchor. Trust anchor not strictly speaking needed - * but if it includes constraints it is to be assumed it expects them - * to be obeyed. - */ - for (j = sk_X509_num(ctx->chain) - 1; j > i; j--) { - NAME_CONSTRAINTS *nc = sk_X509_value(ctx->chain, j)->nc; - if (nc) { - has_name_constraints = 1; - rv = NAME_CONSTRAINTS_check(x, nc); - switch (rv) { - case X509_V_OK: - continue; - case X509_V_ERR_OUT_OF_MEM: - ctx->error = rv; - return 0; - default: - ctx->error = rv; - ctx->error_depth = i; - ctx->current_cert = x; - if (!ctx->verify_cb(0, ctx)) - return 0; - break; - } - } + /* Increment path length if not self issued */ + if (!(x->ex_flags & EXFLAG_SI)) { + plen++; + } + /* + * If this certificate is a proxy certificate, the next certificate + * must be another proxy certificate or a EE certificate. If not, + * the next certificate must be a CA certificate. + */ + if (x->ex_flags & EXFLAG_PROXY) { + if (x->ex_pcpathlen != -1 && i > x->ex_pcpathlen) { + ctx->error = X509_V_ERR_PROXY_PATH_LENGTH_EXCEEDED; + ctx->error_depth = i; + ctx->current_cert = x; + ok = ctx->verify_cb(0, ctx); + if (!ok) { + goto end; } + } + proxy_path_length++; + ca_requirement = must_not_be_ca; + } else { + ca_requirement = must_be_ca; + } + } + ok = 1; +end: + return ok; +} + +static int reject_dns_name_in_common_name(X509 *x509) { + X509_NAME *name = X509_get_subject_name(x509); + int i = -1; + for (;;) { + i = X509_NAME_get_index_by_NID(name, NID_commonName, i); + if (i == -1) { + return X509_V_OK; + } + + X509_NAME_ENTRY *entry = X509_NAME_get_entry(name, i); + ASN1_STRING *common_name = X509_NAME_ENTRY_get_data(entry); + unsigned char *idval; + int idlen = ASN1_STRING_to_UTF8(&idval, common_name); + if (idlen < 0) { + return X509_V_ERR_OUT_OF_MEM; + } + /* Only process attributes that look like host names. Note it is + * important that this check be mirrored in |X509_check_host|. */ + int looks_like_dns = x509v3_looks_like_dns_name(idval, (size_t)idlen); + OPENSSL_free(idval); + if (looks_like_dns) { + return X509_V_ERR_NAME_CONSTRAINTS_WITHOUT_SANS; + } + } +} + +static int check_name_constraints(X509_STORE_CTX *ctx) { + int i, j, rv; + int has_name_constraints = 0; + /* Check name constraints for all certificates */ + for (i = sk_X509_num(ctx->chain) - 1; i >= 0; i--) { + X509 *x = sk_X509_value(ctx->chain, i); + /* Ignore self issued certs unless last in chain */ + if (i && (x->ex_flags & EXFLAG_SI)) { + continue; } - - /* Name constraints do not match against the common name, but - * |X509_check_host| still implements the legacy behavior where, on - * certificates lacking a SAN list, DNS-like names in the common name are - * checked instead. - * - * While we could apply the name constraints to the common name, name - * constraints are rare enough that can hold such certificates to a higher - * standard. Note this does not make "DNS-like" heuristic failures any - * worse. A decorative common-name misidentified as a DNS name would fail - * the name constraint anyway. */ - X509 *leaf = sk_X509_value(ctx->chain, 0); - if (has_name_constraints && leaf->altname == NULL) { - rv = reject_dns_name_in_common_name(leaf); + /* + * Check against constraints for all certificates higher in chain + * including trust anchor. Trust anchor not strictly speaking needed + * but if it includes constraints it is to be assumed it expects them + * to be obeyed. + */ + for (j = sk_X509_num(ctx->chain) - 1; j > i; j--) { + NAME_CONSTRAINTS *nc = sk_X509_value(ctx->chain, j)->nc; + if (nc) { + has_name_constraints = 1; + rv = NAME_CONSTRAINTS_check(x, nc); switch (rv) { - case X509_V_OK: - break; - case X509_V_ERR_OUT_OF_MEM: + case X509_V_OK: + continue; + case X509_V_ERR_OUT_OF_MEM: ctx->error = rv; return 0; - default: + default: ctx->error = rv; ctx->error_depth = i; - ctx->current_cert = leaf; - if (!ctx->verify_cb(0, ctx)) - return 0; + ctx->current_cert = x; + if (!ctx->verify_cb(0, ctx)) { + return 0; + } break; } + } + } + } + + /* Name constraints do not match against the common name, but + * |X509_check_host| still implements the legacy behavior where, on + * certificates lacking a SAN list, DNS-like names in the common name are + * checked instead. + * + * While we could apply the name constraints to the common name, name + * constraints are rare enough that can hold such certificates to a higher + * standard. Note this does not make "DNS-like" heuristic failures any + * worse. A decorative common-name misidentified as a DNS name would fail + * the name constraint anyway. */ + X509 *leaf = sk_X509_value(ctx->chain, 0); + if (has_name_constraints && leaf->altname == NULL) { + rv = reject_dns_name_in_common_name(leaf); + switch (rv) { + case X509_V_OK: + break; + case X509_V_ERR_OUT_OF_MEM: + ctx->error = rv; + return 0; + default: + ctx->error = rv; + ctx->error_depth = i; + ctx->current_cert = leaf; + if (!ctx->verify_cb(0, ctx)) { + return 0; + } + break; } + } - return 1; + return 1; } -static int check_id_error(X509_STORE_CTX *ctx, int errcode) -{ - ctx->error = errcode; - ctx->current_cert = ctx->cert; - ctx->error_depth = 0; - return ctx->verify_cb(0, ctx); +static int check_id_error(X509_STORE_CTX *ctx, int errcode) { + ctx->error = errcode; + ctx->current_cert = ctx->cert; + ctx->error_depth = 0; + return ctx->verify_cb(0, ctx); } -static int check_hosts(X509 *x, X509_VERIFY_PARAM *param) -{ - size_t i; - size_t n = sk_OPENSSL_STRING_num(param->hosts); - char *name; +static int check_hosts(X509 *x, X509_VERIFY_PARAM *param) { + size_t i; + size_t n = sk_OPENSSL_STRING_num(param->hosts); + char *name; - if (param->peername != NULL) { - OPENSSL_free(param->peername); - param->peername = NULL; - } - for (i = 0; i < n; ++i) { - name = sk_OPENSSL_STRING_value(param->hosts, i); - if (X509_check_host(x, name, strlen(name), param->hostflags, - ¶m->peername) > 0) - return 1; + if (param->peername != NULL) { + OPENSSL_free(param->peername); + param->peername = NULL; + } + for (i = 0; i < n; ++i) { + name = sk_OPENSSL_STRING_value(param->hosts, i); + if (X509_check_host(x, name, strlen(name), param->hostflags, + ¶m->peername) > 0) { + return 1; } - return n == 0; + } + return n == 0; } -static int check_id(X509_STORE_CTX *ctx) -{ - X509_VERIFY_PARAM *vpm = ctx->param; - X509 *x = ctx->cert; - if (vpm->poison) { - if (!check_id_error(ctx, X509_V_ERR_INVALID_CALL)) - return 0; +static int check_id(X509_STORE_CTX *ctx) { + X509_VERIFY_PARAM *vpm = ctx->param; + X509 *x = ctx->cert; + if (vpm->poison) { + if (!check_id_error(ctx, X509_V_ERR_INVALID_CALL)) { + return 0; } - if (vpm->hosts && check_hosts(x, vpm) <= 0) { - if (!check_id_error(ctx, X509_V_ERR_HOSTNAME_MISMATCH)) - return 0; + } + if (vpm->hosts && check_hosts(x, vpm) <= 0) { + if (!check_id_error(ctx, X509_V_ERR_HOSTNAME_MISMATCH)) { + return 0; } - if (vpm->email && X509_check_email(x, vpm->email, vpm->emaillen, 0) <= 0) { - if (!check_id_error(ctx, X509_V_ERR_EMAIL_MISMATCH)) - return 0; + } + if (vpm->email && X509_check_email(x, vpm->email, vpm->emaillen, 0) <= 0) { + if (!check_id_error(ctx, X509_V_ERR_EMAIL_MISMATCH)) { + return 0; } - if (vpm->ip && X509_check_ip(x, vpm->ip, vpm->iplen, 0) <= 0) { - if (!check_id_error(ctx, X509_V_ERR_IP_ADDRESS_MISMATCH)) - return 0; + } + if (vpm->ip && X509_check_ip(x, vpm->ip, vpm->iplen, 0) <= 0) { + if (!check_id_error(ctx, X509_V_ERR_IP_ADDRESS_MISMATCH)) { + return 0; } - return 1; + } + return 1; } -static int check_trust(X509_STORE_CTX *ctx) -{ - size_t i; - int ok; - X509 *x = NULL; - /* Check all trusted certificates in chain */ - for (i = ctx->last_untrusted; i < sk_X509_num(ctx->chain); i++) { - x = sk_X509_value(ctx->chain, i); - ok = X509_check_trust(x, ctx->param->trust, 0); - /* If explicitly trusted return trusted */ - if (ok == X509_TRUST_TRUSTED) - return X509_TRUST_TRUSTED; - /* - * If explicitly rejected notify callback and reject if not - * overridden. - */ - if (ok == X509_TRUST_REJECTED) { - ctx->error_depth = i; - ctx->current_cert = x; - ctx->error = X509_V_ERR_CERT_REJECTED; - ok = ctx->verify_cb(0, ctx); - if (!ok) - return X509_TRUST_REJECTED; - } +static int check_trust(X509_STORE_CTX *ctx) { + size_t i; + int ok; + X509 *x = NULL; + /* Check all trusted certificates in chain */ + for (i = ctx->last_untrusted; i < sk_X509_num(ctx->chain); i++) { + x = sk_X509_value(ctx->chain, i); + ok = X509_check_trust(x, ctx->param->trust, 0); + /* If explicitly trusted return trusted */ + if (ok == X509_TRUST_TRUSTED) { + return X509_TRUST_TRUSTED; } /* - * If we accept partial chains and have at least one trusted certificate - * return success. + * If explicitly rejected notify callback and reject if not + * overridden. */ - if (ctx->param->flags & X509_V_FLAG_PARTIAL_CHAIN) { - X509 *mx; - if (ctx->last_untrusted < (int)sk_X509_num(ctx->chain)) - return X509_TRUST_TRUSTED; - x = sk_X509_value(ctx->chain, 0); - mx = lookup_cert_match(ctx, x); - if (mx) { - (void)sk_X509_set(ctx->chain, 0, mx); - X509_free(x); - ctx->last_untrusted = 0; - return X509_TRUST_TRUSTED; - } + if (ok == X509_TRUST_REJECTED) { + ctx->error_depth = i; + ctx->current_cert = x; + ctx->error = X509_V_ERR_CERT_REJECTED; + ok = ctx->verify_cb(0, ctx); + if (!ok) { + return X509_TRUST_REJECTED; + } + } + } + /* + * If we accept partial chains and have at least one trusted certificate + * return success. + */ + if (ctx->param->flags & X509_V_FLAG_PARTIAL_CHAIN) { + X509 *mx; + if (ctx->last_untrusted < (int)sk_X509_num(ctx->chain)) { + return X509_TRUST_TRUSTED; + } + x = sk_X509_value(ctx->chain, 0); + mx = lookup_cert_match(ctx, x); + if (mx) { + (void)sk_X509_set(ctx->chain, 0, mx); + X509_free(x); + ctx->last_untrusted = 0; + return X509_TRUST_TRUSTED; + } + } + + /* + * If no trusted certs in chain at all return untrusted and allow + * standard (no issuer cert) etc errors to be indicated. + */ + return X509_TRUST_UNTRUSTED; +} + +static int check_revocation(X509_STORE_CTX *ctx) { + int i, last, ok; + if (!(ctx->param->flags & X509_V_FLAG_CRL_CHECK)) { + return 1; + } + if (ctx->param->flags & X509_V_FLAG_CRL_CHECK_ALL) { + last = sk_X509_num(ctx->chain) - 1; + } else { + /* If checking CRL paths this isn't the EE certificate */ + if (ctx->parent) { + return 1; + } + last = 0; + } + for (i = 0; i <= last; i++) { + ctx->error_depth = i; + ok = check_cert(ctx); + if (!ok) { + return ok; + } + } + return 1; +} + +static int check_cert(X509_STORE_CTX *ctx) { + X509_CRL *crl = NULL, *dcrl = NULL; + X509 *x; + int ok = 0, cnum; + unsigned int last_reasons; + cnum = ctx->error_depth; + x = sk_X509_value(ctx->chain, cnum); + ctx->current_cert = x; + ctx->current_issuer = NULL; + ctx->current_crl_score = 0; + ctx->current_reasons = 0; + while (ctx->current_reasons != CRLDP_ALL_REASONS) { + last_reasons = ctx->current_reasons; + /* Try to retrieve relevant CRL */ + if (ctx->get_crl) { + ok = ctx->get_crl(ctx, &crl, x); + } else { + ok = get_crl_delta(ctx, &crl, &dcrl, x); } - /* - * If no trusted certs in chain at all return untrusted and allow - * standard (no issuer cert) etc errors to be indicated. + * If error looking up CRL, nothing we can do except notify callback */ - return X509_TRUST_UNTRUSTED; -} - -static int check_revocation(X509_STORE_CTX *ctx) -{ - int i, last, ok; - if (!(ctx->param->flags & X509_V_FLAG_CRL_CHECK)) - return 1; - if (ctx->param->flags & X509_V_FLAG_CRL_CHECK_ALL) - last = sk_X509_num(ctx->chain) - 1; - else { - /* If checking CRL paths this isn't the EE certificate */ - if (ctx->parent) - return 1; - last = 0; - } - for (i = 0; i <= last; i++) { - ctx->error_depth = i; - ok = check_cert(ctx); - if (!ok) - return ok; + if (!ok) { + ctx->error = X509_V_ERR_UNABLE_TO_GET_CRL; + ok = ctx->verify_cb(0, ctx); + goto err; + } + ctx->current_crl = crl; + ok = ctx->check_crl(ctx, crl); + if (!ok) { + goto err; } - return 1; -} - -static int check_cert(X509_STORE_CTX *ctx) -{ - X509_CRL *crl = NULL, *dcrl = NULL; - X509 *x; - int ok = 0, cnum; - unsigned int last_reasons; - cnum = ctx->error_depth; - x = sk_X509_value(ctx->chain, cnum); - ctx->current_cert = x; - ctx->current_issuer = NULL; - ctx->current_crl_score = 0; - ctx->current_reasons = 0; - while (ctx->current_reasons != CRLDP_ALL_REASONS) { - last_reasons = ctx->current_reasons; - /* Try to retrieve relevant CRL */ - if (ctx->get_crl) - ok = ctx->get_crl(ctx, &crl, x); - else - ok = get_crl_delta(ctx, &crl, &dcrl, x); - /* - * If error looking up CRL, nothing we can do except notify callback - */ - if (!ok) { - ctx->error = X509_V_ERR_UNABLE_TO_GET_CRL; - ok = ctx->verify_cb(0, ctx); - goto err; - } - ctx->current_crl = crl; - ok = ctx->check_crl(ctx, crl); - if (!ok) - goto err; - if (dcrl) { - ok = ctx->check_crl(ctx, dcrl); - if (!ok) - goto err; - ok = ctx->cert_crl(ctx, dcrl, x); - if (!ok) - goto err; - } else - ok = 1; - - /* Don't look in full CRL if delta reason is removefromCRL */ - if (ok != 2) { - ok = ctx->cert_crl(ctx, crl, x); - if (!ok) - goto err; - } + if (dcrl) { + ok = ctx->check_crl(ctx, dcrl); + if (!ok) { + goto err; + } + ok = ctx->cert_crl(ctx, dcrl, x); + if (!ok) { + goto err; + } + } else { + ok = 1; + } - X509_CRL_free(crl); - X509_CRL_free(dcrl); - crl = NULL; - dcrl = NULL; - /* - * If reasons not updated we wont get anywhere by another iteration, - * so exit loop. - */ - if (last_reasons == ctx->current_reasons) { - ctx->error = X509_V_ERR_UNABLE_TO_GET_CRL; - ok = ctx->verify_cb(0, ctx); - goto err; - } + /* Don't look in full CRL if delta reason is removefromCRL */ + if (ok != 2) { + ok = ctx->cert_crl(ctx, crl, x); + if (!ok) { + goto err; + } } - err: + X509_CRL_free(crl); X509_CRL_free(dcrl); + crl = NULL; + dcrl = NULL; + /* + * If reasons not updated we wont get anywhere by another iteration, + * so exit loop. + */ + if (last_reasons == ctx->current_reasons) { + ctx->error = X509_V_ERR_UNABLE_TO_GET_CRL; + ok = ctx->verify_cb(0, ctx); + goto err; + } + } +err: + X509_CRL_free(crl); + X509_CRL_free(dcrl); - ctx->current_crl = NULL; - return ok; - + ctx->current_crl = NULL; + return ok; } /* Check CRL times against values in X509_STORE_CTX */ -static int check_crl_time(X509_STORE_CTX *ctx, X509_CRL *crl, int notify) -{ - time_t *ptime; - int i; - if (notify) - ctx->current_crl = crl; - if (ctx->param->flags & X509_V_FLAG_USE_CHECK_TIME) - ptime = &ctx->param->check_time; - else - ptime = NULL; - - i = X509_cmp_time(X509_CRL_get0_lastUpdate(crl), ptime); - if (i == 0) { - if (!notify) - return 0; - ctx->error = X509_V_ERR_ERROR_IN_CRL_LAST_UPDATE_FIELD; - if (!ctx->verify_cb(0, ctx)) - return 0; +static int check_crl_time(X509_STORE_CTX *ctx, X509_CRL *crl, int notify) { + time_t *ptime; + int i; + if (notify) { + ctx->current_crl = crl; + } + if (ctx->param->flags & X509_V_FLAG_USE_CHECK_TIME) { + ptime = &ctx->param->check_time; + } else { + ptime = NULL; + } + + i = X509_cmp_time(X509_CRL_get0_lastUpdate(crl), ptime); + if (i == 0) { + if (!notify) { + return 0; } + ctx->error = X509_V_ERR_ERROR_IN_CRL_LAST_UPDATE_FIELD; + if (!ctx->verify_cb(0, ctx)) { + return 0; + } + } - if (i > 0) { - if (!notify) - return 0; - ctx->error = X509_V_ERR_CRL_NOT_YET_VALID; - if (!ctx->verify_cb(0, ctx)) - return 0; + if (i > 0) { + if (!notify) { + return 0; } + ctx->error = X509_V_ERR_CRL_NOT_YET_VALID; + if (!ctx->verify_cb(0, ctx)) { + return 0; + } + } - if (X509_CRL_get0_nextUpdate(crl)) { - i = X509_cmp_time(X509_CRL_get0_nextUpdate(crl), ptime); + if (X509_CRL_get0_nextUpdate(crl)) { + i = X509_cmp_time(X509_CRL_get0_nextUpdate(crl), ptime); - if (i == 0) { - if (!notify) - return 0; - ctx->error = X509_V_ERR_ERROR_IN_CRL_NEXT_UPDATE_FIELD; - if (!ctx->verify_cb(0, ctx)) - return 0; - } - /* Ignore expiry of base CRL is delta is valid */ - if ((i < 0) && !(ctx->current_crl_score & CRL_SCORE_TIME_DELTA)) { - if (!notify) - return 0; - ctx->error = X509_V_ERR_CRL_HAS_EXPIRED; - if (!ctx->verify_cb(0, ctx)) - return 0; - } + if (i == 0) { + if (!notify) { + return 0; + } + ctx->error = X509_V_ERR_ERROR_IN_CRL_NEXT_UPDATE_FIELD; + if (!ctx->verify_cb(0, ctx)) { + return 0; + } } + /* Ignore expiry of base CRL is delta is valid */ + if ((i < 0) && !(ctx->current_crl_score & CRL_SCORE_TIME_DELTA)) { + if (!notify) { + return 0; + } + ctx->error = X509_V_ERR_CRL_HAS_EXPIRED; + if (!ctx->verify_cb(0, ctx)) { + return 0; + } + } + } - if (notify) - ctx->current_crl = NULL; + if (notify) { + ctx->current_crl = NULL; + } - return 1; + return 1; } static int get_crl_sk(X509_STORE_CTX *ctx, X509_CRL **pcrl, X509_CRL **pdcrl, X509 **pissuer, int *pscore, unsigned int *preasons, - STACK_OF(X509_CRL) *crls) -{ - int crl_score, best_score = *pscore; - size_t i; - unsigned int reasons, best_reasons = 0; - X509 *x = ctx->current_cert; - X509_CRL *crl, *best_crl = NULL; - X509 *crl_issuer = NULL, *best_crl_issuer = NULL; - - for (i = 0; i < sk_X509_CRL_num(crls); i++) { - crl = sk_X509_CRL_value(crls, i); - reasons = *preasons; - crl_score = get_crl_score(ctx, &crl_issuer, &reasons, crl, x); - if (crl_score < best_score || crl_score == 0) - continue; - /* If current CRL is equivalent use it if it is newer */ - if (crl_score == best_score && best_crl != NULL) { - int day, sec; - if (ASN1_TIME_diff(&day, &sec, X509_CRL_get0_lastUpdate(best_crl), - X509_CRL_get0_lastUpdate(crl)) == 0) - continue; - /* - * ASN1_TIME_diff never returns inconsistent signs for |day| - * and |sec|. - */ - if (day <= 0 && sec <= 0) - continue; - } - best_crl = crl; - best_crl_issuer = crl_issuer; - best_score = crl_score; - best_reasons = reasons; - } - - if (best_crl) { - if (*pcrl) - X509_CRL_free(*pcrl); - *pcrl = best_crl; - *pissuer = best_crl_issuer; - *pscore = best_score; - *preasons = best_reasons; - X509_CRL_up_ref(best_crl); - if (*pdcrl) { - X509_CRL_free(*pdcrl); - *pdcrl = NULL; - } - get_delta_sk(ctx, pdcrl, pscore, best_crl, crls); - } - - if (best_score >= CRL_SCORE_VALID) - return 1; + STACK_OF(X509_CRL) *crls) { + int crl_score, best_score = *pscore; + size_t i; + unsigned int reasons, best_reasons = 0; + X509 *x = ctx->current_cert; + X509_CRL *crl, *best_crl = NULL; + X509 *crl_issuer = NULL, *best_crl_issuer = NULL; + + for (i = 0; i < sk_X509_CRL_num(crls); i++) { + crl = sk_X509_CRL_value(crls, i); + reasons = *preasons; + crl_score = get_crl_score(ctx, &crl_issuer, &reasons, crl, x); + if (crl_score < best_score || crl_score == 0) { + continue; + } + /* If current CRL is equivalent use it if it is newer */ + if (crl_score == best_score && best_crl != NULL) { + int day, sec; + if (ASN1_TIME_diff(&day, &sec, X509_CRL_get0_lastUpdate(best_crl), + X509_CRL_get0_lastUpdate(crl)) == 0) { + continue; + } + /* + * ASN1_TIME_diff never returns inconsistent signs for |day| + * and |sec|. + */ + if (day <= 0 && sec <= 0) { + continue; + } + } + best_crl = crl; + best_crl_issuer = crl_issuer; + best_score = crl_score; + best_reasons = reasons; + } + + if (best_crl) { + if (*pcrl) { + X509_CRL_free(*pcrl); + } + *pcrl = best_crl; + *pissuer = best_crl_issuer; + *pscore = best_score; + *preasons = best_reasons; + X509_CRL_up_ref(best_crl); + if (*pdcrl) { + X509_CRL_free(*pdcrl); + *pdcrl = NULL; + } + get_delta_sk(ctx, pdcrl, pscore, best_crl, crls); + } + + if (best_score >= CRL_SCORE_VALID) { + return 1; + } - return 0; + return 0; } /* @@ -1112,66 +1159,77 @@ static int get_crl_sk(X509_STORE_CTX *ctx, X509_CRL **pcrl, X509_CRL **pdcrl, * both present or both absent. If both present all fields must be identical. */ -static int crl_extension_match(X509_CRL *a, X509_CRL *b, int nid) -{ - ASN1_OCTET_STRING *exta, *extb; - int i; - i = X509_CRL_get_ext_by_NID(a, nid, -1); - if (i >= 0) { - /* Can't have multiple occurrences */ - if (X509_CRL_get_ext_by_NID(a, nid, i) != -1) - return 0; - exta = X509_EXTENSION_get_data(X509_CRL_get_ext(a, i)); - } else - exta = NULL; - - i = X509_CRL_get_ext_by_NID(b, nid, -1); +static int crl_extension_match(X509_CRL *a, X509_CRL *b, int nid) { + ASN1_OCTET_STRING *exta, *extb; + int i; + i = X509_CRL_get_ext_by_NID(a, nid, -1); + if (i >= 0) { + /* Can't have multiple occurrences */ + if (X509_CRL_get_ext_by_NID(a, nid, i) != -1) { + return 0; + } + exta = X509_EXTENSION_get_data(X509_CRL_get_ext(a, i)); + } else { + exta = NULL; + } - if (i >= 0) { + i = X509_CRL_get_ext_by_NID(b, nid, -1); - if (X509_CRL_get_ext_by_NID(b, nid, i) != -1) - return 0; - extb = X509_EXTENSION_get_data(X509_CRL_get_ext(b, i)); - } else - extb = NULL; + if (i >= 0) { + if (X509_CRL_get_ext_by_NID(b, nid, i) != -1) { + return 0; + } + extb = X509_EXTENSION_get_data(X509_CRL_get_ext(b, i)); + } else { + extb = NULL; + } - if (!exta && !extb) - return 1; + if (!exta && !extb) { + return 1; + } - if (!exta || !extb) - return 0; + if (!exta || !extb) { + return 0; + } - if (ASN1_OCTET_STRING_cmp(exta, extb)) - return 0; + if (ASN1_OCTET_STRING_cmp(exta, extb)) { + return 0; + } - return 1; + return 1; } /* See if a base and delta are compatible */ -static int check_delta_base(X509_CRL *delta, X509_CRL *base) -{ - /* Delta CRL must be a delta */ - if (!delta->base_crl_number) - return 0; - /* Base must have a CRL number */ - if (!base->crl_number) - return 0; - /* Issuer names must match */ - if (X509_NAME_cmp(X509_CRL_get_issuer(base), X509_CRL_get_issuer(delta))) - return 0; - /* AKID and IDP must match */ - if (!crl_extension_match(delta, base, NID_authority_key_identifier)) - return 0; - if (!crl_extension_match(delta, base, NID_issuing_distribution_point)) - return 0; - /* Delta CRL base number must not exceed Full CRL number. */ - if (ASN1_INTEGER_cmp(delta->base_crl_number, base->crl_number) > 0) - return 0; - /* Delta CRL number must exceed full CRL number */ - if (ASN1_INTEGER_cmp(delta->crl_number, base->crl_number) > 0) - return 1; +static int check_delta_base(X509_CRL *delta, X509_CRL *base) { + /* Delta CRL must be a delta */ + if (!delta->base_crl_number) { return 0; + } + /* Base must have a CRL number */ + if (!base->crl_number) { + return 0; + } + /* Issuer names must match */ + if (X509_NAME_cmp(X509_CRL_get_issuer(base), X509_CRL_get_issuer(delta))) { + return 0; + } + /* AKID and IDP must match */ + if (!crl_extension_match(delta, base, NID_authority_key_identifier)) { + return 0; + } + if (!crl_extension_match(delta, base, NID_issuing_distribution_point)) { + return 0; + } + /* Delta CRL base number must not exceed Full CRL number. */ + if (ASN1_INTEGER_cmp(delta->base_crl_number, base->crl_number) > 0) { + return 0; + } + /* Delta CRL number must exceed full CRL number */ + if (ASN1_INTEGER_cmp(delta->crl_number, base->crl_number) > 0) { + return 1; + } + return 0; } /* @@ -1180,25 +1238,27 @@ static int check_delta_base(X509_CRL *delta, X509_CRL *base) */ static void get_delta_sk(X509_STORE_CTX *ctx, X509_CRL **dcrl, int *pscore, - X509_CRL *base, STACK_OF(X509_CRL) *crls) -{ - X509_CRL *delta; - size_t i; - if (!(ctx->param->flags & X509_V_FLAG_USE_DELTAS)) - return; - if (!((ctx->current_cert->ex_flags | base->flags) & EXFLAG_FRESHEST)) - return; - for (i = 0; i < sk_X509_CRL_num(crls); i++) { - delta = sk_X509_CRL_value(crls, i); - if (check_delta_base(delta, base)) { - if (check_crl_time(ctx, delta, 0)) - *pscore |= CRL_SCORE_TIME_DELTA; - X509_CRL_up_ref(delta); - *dcrl = delta; - return; - } - } - *dcrl = NULL; + X509_CRL *base, STACK_OF(X509_CRL) *crls) { + X509_CRL *delta; + size_t i; + if (!(ctx->param->flags & X509_V_FLAG_USE_DELTAS)) { + return; + } + if (!((ctx->current_cert->ex_flags | base->flags) & EXFLAG_FRESHEST)) { + return; + } + for (i = 0; i < sk_X509_CRL_num(crls); i++) { + delta = sk_X509_CRL_value(crls, i); + if (check_delta_base(delta, base)) { + if (check_crl_time(ctx, delta, 0)) { + *pscore |= CRL_SCORE_TIME_DELTA; + } + X509_CRL_up_ref(delta); + *dcrl = delta; + return; + } + } + *dcrl = NULL; } /* @@ -1210,118 +1270,128 @@ static void get_delta_sk(X509_STORE_CTX *ctx, X509_CRL **dcrl, int *pscore, */ static int get_crl_score(X509_STORE_CTX *ctx, X509 **pissuer, - unsigned int *preasons, X509_CRL *crl, X509 *x) -{ - - int crl_score = 0; - unsigned int tmp_reasons = *preasons, crl_reasons; + unsigned int *preasons, X509_CRL *crl, X509 *x) { + int crl_score = 0; + unsigned int tmp_reasons = *preasons, crl_reasons; - /* First see if we can reject CRL straight away */ + /* First see if we can reject CRL straight away */ - /* Invalid IDP cannot be processed */ - if (crl->idp_flags & IDP_INVALID) - return 0; - /* Reason codes or indirect CRLs need extended CRL support */ - if (!(ctx->param->flags & X509_V_FLAG_EXTENDED_CRL_SUPPORT)) { - if (crl->idp_flags & (IDP_INDIRECT | IDP_REASONS)) - return 0; - } else if (crl->idp_flags & IDP_REASONS) { - /* If no new reasons reject */ - if (!(crl->idp_reasons & ~tmp_reasons)) - return 0; + /* Invalid IDP cannot be processed */ + if (crl->idp_flags & IDP_INVALID) { + return 0; + } + /* Reason codes or indirect CRLs need extended CRL support */ + if (!(ctx->param->flags & X509_V_FLAG_EXTENDED_CRL_SUPPORT)) { + if (crl->idp_flags & (IDP_INDIRECT | IDP_REASONS)) { + return 0; + } + } else if (crl->idp_flags & IDP_REASONS) { + /* If no new reasons reject */ + if (!(crl->idp_reasons & ~tmp_reasons)) { + return 0; + } + } + /* Don't process deltas at this stage */ + else if (crl->base_crl_number) { + return 0; + } + /* If issuer name doesn't match certificate need indirect CRL */ + if (X509_NAME_cmp(X509_get_issuer_name(x), X509_CRL_get_issuer(crl))) { + if (!(crl->idp_flags & IDP_INDIRECT)) { + return 0; } - /* Don't process deltas at this stage */ - else if (crl->base_crl_number) - return 0; - /* If issuer name doesn't match certificate need indirect CRL */ - if (X509_NAME_cmp(X509_get_issuer_name(x), X509_CRL_get_issuer(crl))) { - if (!(crl->idp_flags & IDP_INDIRECT)) - return 0; - } else - crl_score |= CRL_SCORE_ISSUER_NAME; + } else { + crl_score |= CRL_SCORE_ISSUER_NAME; + } - if (!(crl->flags & EXFLAG_CRITICAL)) - crl_score |= CRL_SCORE_NOCRITICAL; + if (!(crl->flags & EXFLAG_CRITICAL)) { + crl_score |= CRL_SCORE_NOCRITICAL; + } - /* Check expiry */ - if (check_crl_time(ctx, crl, 0)) - crl_score |= CRL_SCORE_TIME; + /* Check expiry */ + if (check_crl_time(ctx, crl, 0)) { + crl_score |= CRL_SCORE_TIME; + } - /* Check authority key ID and locate certificate issuer */ - crl_akid_check(ctx, crl, pissuer, &crl_score); + /* Check authority key ID and locate certificate issuer */ + crl_akid_check(ctx, crl, pissuer, &crl_score); - /* If we can't locate certificate issuer at this point forget it */ + /* If we can't locate certificate issuer at this point forget it */ - if (!(crl_score & CRL_SCORE_AKID)) - return 0; + if (!(crl_score & CRL_SCORE_AKID)) { + return 0; + } - /* Check cert for matching CRL distribution points */ + /* Check cert for matching CRL distribution points */ - if (crl_crldp_check(x, crl, crl_score, &crl_reasons)) { - /* If no new reasons reject */ - if (!(crl_reasons & ~tmp_reasons)) - return 0; - tmp_reasons |= crl_reasons; - crl_score |= CRL_SCORE_SCOPE; + if (crl_crldp_check(x, crl, crl_score, &crl_reasons)) { + /* If no new reasons reject */ + if (!(crl_reasons & ~tmp_reasons)) { + return 0; } + tmp_reasons |= crl_reasons; + crl_score |= CRL_SCORE_SCOPE; + } - *preasons = tmp_reasons; - - return crl_score; + *preasons = tmp_reasons; + return crl_score; } -static void crl_akid_check(X509_STORE_CTX *ctx, X509_CRL *crl, - X509 **pissuer, int *pcrl_score) -{ - X509 *crl_issuer = NULL; - X509_NAME *cnm = X509_CRL_get_issuer(crl); - int cidx = ctx->error_depth; - size_t i; +static void crl_akid_check(X509_STORE_CTX *ctx, X509_CRL *crl, X509 **pissuer, + int *pcrl_score) { + X509 *crl_issuer = NULL; + X509_NAME *cnm = X509_CRL_get_issuer(crl); + int cidx = ctx->error_depth; + size_t i; - if ((size_t)cidx != sk_X509_num(ctx->chain) - 1) - cidx++; + if ((size_t)cidx != sk_X509_num(ctx->chain) - 1) { + cidx++; + } - crl_issuer = sk_X509_value(ctx->chain, cidx); + crl_issuer = sk_X509_value(ctx->chain, cidx); - if (X509_check_akid(crl_issuer, crl->akid) == X509_V_OK) { - if (*pcrl_score & CRL_SCORE_ISSUER_NAME) { - *pcrl_score |= CRL_SCORE_AKID | CRL_SCORE_ISSUER_CERT; - *pissuer = crl_issuer; - return; - } + if (X509_check_akid(crl_issuer, crl->akid) == X509_V_OK) { + if (*pcrl_score & CRL_SCORE_ISSUER_NAME) { + *pcrl_score |= CRL_SCORE_AKID | CRL_SCORE_ISSUER_CERT; + *pissuer = crl_issuer; + return; } + } - for (cidx++; cidx < (int)sk_X509_num(ctx->chain); cidx++) { - crl_issuer = sk_X509_value(ctx->chain, cidx); - if (X509_NAME_cmp(X509_get_subject_name(crl_issuer), cnm)) - continue; - if (X509_check_akid(crl_issuer, crl->akid) == X509_V_OK) { - *pcrl_score |= CRL_SCORE_AKID | CRL_SCORE_SAME_PATH; - *pissuer = crl_issuer; - return; - } + for (cidx++; cidx < (int)sk_X509_num(ctx->chain); cidx++) { + crl_issuer = sk_X509_value(ctx->chain, cidx); + if (X509_NAME_cmp(X509_get_subject_name(crl_issuer), cnm)) { + continue; + } + if (X509_check_akid(crl_issuer, crl->akid) == X509_V_OK) { + *pcrl_score |= CRL_SCORE_AKID | CRL_SCORE_SAME_PATH; + *pissuer = crl_issuer; + return; } + } - /* Anything else needs extended CRL support */ + /* Anything else needs extended CRL support */ - if (!(ctx->param->flags & X509_V_FLAG_EXTENDED_CRL_SUPPORT)) - return; + if (!(ctx->param->flags & X509_V_FLAG_EXTENDED_CRL_SUPPORT)) { + return; + } - /* - * Otherwise the CRL issuer is not on the path. Look for it in the set of - * untrusted certificates. - */ - for (i = 0; i < sk_X509_num(ctx->untrusted); i++) { - crl_issuer = sk_X509_value(ctx->untrusted, i); - if (X509_NAME_cmp(X509_get_subject_name(crl_issuer), cnm)) - continue; - if (X509_check_akid(crl_issuer, crl->akid) == X509_V_OK) { - *pissuer = crl_issuer; - *pcrl_score |= CRL_SCORE_AKID; - return; - } + /* + * Otherwise the CRL issuer is not on the path. Look for it in the set of + * untrusted certificates. + */ + for (i = 0; i < sk_X509_num(ctx->untrusted); i++) { + crl_issuer = sk_X509_value(ctx->untrusted, i); + if (X509_NAME_cmp(X509_get_subject_name(crl_issuer), cnm)) { + continue; + } + if (X509_check_akid(crl_issuer, crl->akid) == X509_V_OK) { + *pissuer = crl_issuer; + *pcrl_score |= CRL_SCORE_AKID; + return; } + } } /* @@ -1331,35 +1401,37 @@ static void crl_akid_check(X509_STORE_CTX *ctx, X509_CRL *crl, * be duplicated by the parent, but this will rarely be used in practice. */ -static int check_crl_path(X509_STORE_CTX *ctx, X509 *x) -{ - X509_STORE_CTX crl_ctx; - int ret; - /* Don't allow recursive CRL path validation */ - if (ctx->parent) - return 0; - if (!X509_STORE_CTX_init(&crl_ctx, ctx->ctx, x, ctx->untrusted)) - return -1; +static int check_crl_path(X509_STORE_CTX *ctx, X509 *x) { + X509_STORE_CTX crl_ctx; + int ret; + /* Don't allow recursive CRL path validation */ + if (ctx->parent) { + return 0; + } + if (!X509_STORE_CTX_init(&crl_ctx, ctx->ctx, x, ctx->untrusted)) { + return -1; + } - crl_ctx.crls = ctx->crls; - /* Copy verify params across */ - X509_STORE_CTX_set0_param(&crl_ctx, ctx->param); + crl_ctx.crls = ctx->crls; + /* Copy verify params across */ + X509_STORE_CTX_set0_param(&crl_ctx, ctx->param); - crl_ctx.parent = ctx; - crl_ctx.verify_cb = ctx->verify_cb; + crl_ctx.parent = ctx; + crl_ctx.verify_cb = ctx->verify_cb; - /* Verify CRL issuer */ - ret = X509_verify_cert(&crl_ctx); + /* Verify CRL issuer */ + ret = X509_verify_cert(&crl_ctx); - if (ret <= 0) - goto err; + if (ret <= 0) { + goto err; + } - /* Check chain is acceptable */ + /* Check chain is acceptable */ - ret = check_crl_chain(ctx, ctx->chain, crl_ctx.chain); - err: - X509_STORE_CTX_cleanup(&crl_ctx); - return ret; + ret = check_crl_chain(ctx, ctx->chain, crl_ctx.chain); +err: + X509_STORE_CTX_cleanup(&crl_ctx); + return ret; } /* @@ -1371,16 +1443,15 @@ static int check_crl_path(X509_STORE_CTX *ctx, X509 *x) * RFC 5280 version */ -static int check_crl_chain(X509_STORE_CTX *ctx, - STACK_OF(X509) *cert_path, - STACK_OF(X509) *crl_path) -{ - X509 *cert_ta, *crl_ta; - cert_ta = sk_X509_value(cert_path, sk_X509_num(cert_path) - 1); - crl_ta = sk_X509_value(crl_path, sk_X509_num(crl_path) - 1); - if (!X509_cmp(cert_ta, crl_ta)) - return 1; - return 0; +static int check_crl_chain(X509_STORE_CTX *ctx, STACK_OF(X509) *cert_path, + STACK_OF(X509) *crl_path) { + X509 *cert_ta, *crl_ta; + cert_ta = sk_X509_value(cert_path, sk_X509_num(cert_path) - 1); + crl_ta = sk_X509_value(crl_path, sk_X509_num(crl_path) - 1); + if (!X509_cmp(cert_ta, crl_ta)) { + return 1; + } + return 0; } /* @@ -1390,110 +1461,121 @@ static int check_crl_chain(X509_STORE_CTX *ctx, * compare two GENERAL_NAMES. 4. One is NULL: automatic match. */ -static int idp_check_dp(DIST_POINT_NAME *a, DIST_POINT_NAME *b) -{ - X509_NAME *nm = NULL; - GENERAL_NAMES *gens = NULL; - GENERAL_NAME *gena, *genb; - size_t i, j; - if (!a || !b) +static int idp_check_dp(DIST_POINT_NAME *a, DIST_POINT_NAME *b) { + X509_NAME *nm = NULL; + GENERAL_NAMES *gens = NULL; + GENERAL_NAME *gena, *genb; + size_t i, j; + if (!a || !b) { + return 1; + } + if (a->type == 1) { + if (!a->dpname) { + return 0; + } + /* Case 1: two X509_NAME */ + if (b->type == 1) { + if (!b->dpname) { + return 0; + } + if (!X509_NAME_cmp(a->dpname, b->dpname)) { return 1; - if (a->type == 1) { - if (!a->dpname) - return 0; - /* Case 1: two X509_NAME */ - if (b->type == 1) { - if (!b->dpname) - return 0; - if (!X509_NAME_cmp(a->dpname, b->dpname)) - return 1; - else - return 0; - } - /* Case 2: set name and GENERAL_NAMES appropriately */ - nm = a->dpname; - gens = b->name.fullname; - } else if (b->type == 1) { - if (!b->dpname) - return 0; - /* Case 2: set name and GENERAL_NAMES appropriately */ - gens = a->name.fullname; - nm = b->dpname; - } - - /* Handle case 2 with one GENERAL_NAMES and one X509_NAME */ - if (nm) { - for (i = 0; i < sk_GENERAL_NAME_num(gens); i++) { - gena = sk_GENERAL_NAME_value(gens, i); - if (gena->type != GEN_DIRNAME) - continue; - if (!X509_NAME_cmp(nm, gena->d.directoryName)) - return 1; - } + } else { return 0; + } + } + /* Case 2: set name and GENERAL_NAMES appropriately */ + nm = a->dpname; + gens = b->name.fullname; + } else if (b->type == 1) { + if (!b->dpname) { + return 0; + } + /* Case 2: set name and GENERAL_NAMES appropriately */ + gens = a->name.fullname; + nm = b->dpname; + } + + /* Handle case 2 with one GENERAL_NAMES and one X509_NAME */ + if (nm) { + for (i = 0; i < sk_GENERAL_NAME_num(gens); i++) { + gena = sk_GENERAL_NAME_value(gens, i); + if (gena->type != GEN_DIRNAME) { + continue; + } + if (!X509_NAME_cmp(nm, gena->d.directoryName)) { + return 1; + } } + return 0; + } - /* Else case 3: two GENERAL_NAMES */ + /* Else case 3: two GENERAL_NAMES */ - for (i = 0; i < sk_GENERAL_NAME_num(a->name.fullname); i++) { - gena = sk_GENERAL_NAME_value(a->name.fullname, i); - for (j = 0; j < sk_GENERAL_NAME_num(b->name.fullname); j++) { - genb = sk_GENERAL_NAME_value(b->name.fullname, j); - if (!GENERAL_NAME_cmp(gena, genb)) - return 1; - } + for (i = 0; i < sk_GENERAL_NAME_num(a->name.fullname); i++) { + gena = sk_GENERAL_NAME_value(a->name.fullname, i); + for (j = 0; j < sk_GENERAL_NAME_num(b->name.fullname); j++) { + genb = sk_GENERAL_NAME_value(b->name.fullname, j); + if (!GENERAL_NAME_cmp(gena, genb)) { + return 1; + } } + } - return 0; - + return 0; } -static int crldp_check_crlissuer(DIST_POINT *dp, X509_CRL *crl, int crl_score) -{ - size_t i; - X509_NAME *nm = X509_CRL_get_issuer(crl); - /* If no CRLissuer return is successful iff don't need a match */ - if (!dp->CRLissuer) - return ! !(crl_score & CRL_SCORE_ISSUER_NAME); - for (i = 0; i < sk_GENERAL_NAME_num(dp->CRLissuer); i++) { - GENERAL_NAME *gen = sk_GENERAL_NAME_value(dp->CRLissuer, i); - if (gen->type != GEN_DIRNAME) - continue; - if (!X509_NAME_cmp(gen->d.directoryName, nm)) - return 1; +static int crldp_check_crlissuer(DIST_POINT *dp, X509_CRL *crl, int crl_score) { + size_t i; + X509_NAME *nm = X509_CRL_get_issuer(crl); + /* If no CRLissuer return is successful iff don't need a match */ + if (!dp->CRLissuer) { + return !!(crl_score & CRL_SCORE_ISSUER_NAME); + } + for (i = 0; i < sk_GENERAL_NAME_num(dp->CRLissuer); i++) { + GENERAL_NAME *gen = sk_GENERAL_NAME_value(dp->CRLissuer, i); + if (gen->type != GEN_DIRNAME) { + continue; } - return 0; + if (!X509_NAME_cmp(gen->d.directoryName, nm)) { + return 1; + } + } + return 0; } /* Check CRLDP and IDP */ static int crl_crldp_check(X509 *x, X509_CRL *crl, int crl_score, - unsigned int *preasons) -{ - size_t i; - if (crl->idp_flags & IDP_ONLYATTR) - return 0; - if (x->ex_flags & EXFLAG_CA) { - if (crl->idp_flags & IDP_ONLYUSER) - return 0; - } else { - if (crl->idp_flags & IDP_ONLYCA) - return 0; - } - *preasons = crl->idp_reasons; - for (i = 0; i < sk_DIST_POINT_num(x->crldp); i++) { - DIST_POINT *dp = sk_DIST_POINT_value(x->crldp, i); - if (crldp_check_crlissuer(dp, crl, crl_score)) { - if (!crl->idp || idp_check_dp(dp->distpoint, crl->idp->distpoint)) { - *preasons &= dp->dp_reasons; - return 1; - } - } - } - if ((!crl->idp || !crl->idp->distpoint) - && (crl_score & CRL_SCORE_ISSUER_NAME)) - return 1; + unsigned int *preasons) { + size_t i; + if (crl->idp_flags & IDP_ONLYATTR) { return 0; + } + if (x->ex_flags & EXFLAG_CA) { + if (crl->idp_flags & IDP_ONLYUSER) { + return 0; + } + } else { + if (crl->idp_flags & IDP_ONLYCA) { + return 0; + } + } + *preasons = crl->idp_reasons; + for (i = 0; i < sk_DIST_POINT_num(x->crldp); i++) { + DIST_POINT *dp = sk_DIST_POINT_value(x->crldp, i); + if (crldp_check_crlissuer(dp, crl, crl_score)) { + if (!crl->idp || idp_check_dp(dp->distpoint, crl->idp->distpoint)) { + *preasons &= dp->dp_reasons; + return 1; + } + } + } + if ((!crl->idp || !crl->idp->distpoint) && + (crl_score & CRL_SCORE_ISSUER_NAME)) { + return 1; + } + return 0; } /* @@ -1501,678 +1583,684 @@ static int crl_crldp_check(X509 *x, X509_CRL *crl, int crl_score, * to find a delta CRL too */ -static int get_crl_delta(X509_STORE_CTX *ctx, - X509_CRL **pcrl, X509_CRL **pdcrl, X509 *x) -{ - int ok; - X509 *issuer = NULL; - int crl_score = 0; - unsigned int reasons; - X509_CRL *crl = NULL, *dcrl = NULL; - STACK_OF(X509_CRL) *skcrl; - X509_NAME *nm = X509_get_issuer_name(x); - reasons = ctx->current_reasons; - ok = get_crl_sk(ctx, &crl, &dcrl, - &issuer, &crl_score, &reasons, ctx->crls); +static int get_crl_delta(X509_STORE_CTX *ctx, X509_CRL **pcrl, X509_CRL **pdcrl, + X509 *x) { + int ok; + X509 *issuer = NULL; + int crl_score = 0; + unsigned int reasons; + X509_CRL *crl = NULL, *dcrl = NULL; + STACK_OF(X509_CRL) *skcrl; + X509_NAME *nm = X509_get_issuer_name(x); + reasons = ctx->current_reasons; + ok = get_crl_sk(ctx, &crl, &dcrl, &issuer, &crl_score, &reasons, ctx->crls); - if (ok) - goto done; + if (ok) { + goto done; + } - /* Lookup CRLs from store */ + /* Lookup CRLs from store */ - skcrl = ctx->lookup_crls(ctx, nm); + skcrl = ctx->lookup_crls(ctx, nm); - /* If no CRLs found and a near match from get_crl_sk use that */ - if (!skcrl && crl) - goto done; + /* If no CRLs found and a near match from get_crl_sk use that */ + if (!skcrl && crl) { + goto done; + } - get_crl_sk(ctx, &crl, &dcrl, &issuer, &crl_score, &reasons, skcrl); + get_crl_sk(ctx, &crl, &dcrl, &issuer, &crl_score, &reasons, skcrl); - sk_X509_CRL_pop_free(skcrl, X509_CRL_free); + sk_X509_CRL_pop_free(skcrl, X509_CRL_free); - done: +done: - /* If we got any kind of CRL use it and return success */ - if (crl) { - ctx->current_issuer = issuer; - ctx->current_crl_score = crl_score; - ctx->current_reasons = reasons; - *pcrl = crl; - *pdcrl = dcrl; - return 1; - } + /* If we got any kind of CRL use it and return success */ + if (crl) { + ctx->current_issuer = issuer; + ctx->current_crl_score = crl_score; + ctx->current_reasons = reasons; + *pcrl = crl; + *pdcrl = dcrl; + return 1; + } - return 0; + return 0; } /* Check CRL validity */ -static int check_crl(X509_STORE_CTX *ctx, X509_CRL *crl) -{ - X509 *issuer = NULL; - EVP_PKEY *ikey = NULL; - int ok = 0, chnum, cnum; - cnum = ctx->error_depth; - chnum = sk_X509_num(ctx->chain) - 1; - /* if we have an alternative CRL issuer cert use that */ - if (ctx->current_issuer) - issuer = ctx->current_issuer; +static int check_crl(X509_STORE_CTX *ctx, X509_CRL *crl) { + X509 *issuer = NULL; + EVP_PKEY *ikey = NULL; + int ok = 0, chnum, cnum; + cnum = ctx->error_depth; + chnum = sk_X509_num(ctx->chain) - 1; + /* if we have an alternative CRL issuer cert use that */ + if (ctx->current_issuer) { + issuer = ctx->current_issuer; + } + + /* + * Else find CRL issuer: if not last certificate then issuer is next + * certificate in chain. + */ + else if (cnum < chnum) { + issuer = sk_X509_value(ctx->chain, cnum + 1); + } else { + issuer = sk_X509_value(ctx->chain, chnum); + /* If not self signed, can't check signature */ + if (!ctx->check_issued(ctx, issuer, issuer)) { + ctx->error = X509_V_ERR_UNABLE_TO_GET_CRL_ISSUER; + ok = ctx->verify_cb(0, ctx); + if (!ok) { + goto err; + } + } + } + if (issuer) { /* - * Else find CRL issuer: if not last certificate then issuer is next - * certificate in chain. + * Skip most tests for deltas because they have already been done */ - else if (cnum < chnum) - issuer = sk_X509_value(ctx->chain, cnum + 1); - else { - issuer = sk_X509_value(ctx->chain, chnum); - /* If not self signed, can't check signature */ - if (!ctx->check_issued(ctx, issuer, issuer)) { - ctx->error = X509_V_ERR_UNABLE_TO_GET_CRL_ISSUER; - ok = ctx->verify_cb(0, ctx); - if (!ok) - goto err; + if (!crl->base_crl_number) { + /* Check for cRLSign bit if keyUsage present */ + if ((issuer->ex_flags & EXFLAG_KUSAGE) && + !(issuer->ex_kusage & KU_CRL_SIGN)) { + ctx->error = X509_V_ERR_KEYUSAGE_NO_CRL_SIGN; + ok = ctx->verify_cb(0, ctx); + if (!ok) { + goto err; } - } - - if (issuer) { - /* - * Skip most tests for deltas because they have already been done - */ - if (!crl->base_crl_number) { - /* Check for cRLSign bit if keyUsage present */ - if ((issuer->ex_flags & EXFLAG_KUSAGE) && - !(issuer->ex_kusage & KU_CRL_SIGN)) { - ctx->error = X509_V_ERR_KEYUSAGE_NO_CRL_SIGN; - ok = ctx->verify_cb(0, ctx); - if (!ok) - goto err; - } - - if (!(ctx->current_crl_score & CRL_SCORE_SCOPE)) { - ctx->error = X509_V_ERR_DIFFERENT_CRL_SCOPE; - ok = ctx->verify_cb(0, ctx); - if (!ok) - goto err; - } - - if (!(ctx->current_crl_score & CRL_SCORE_SAME_PATH)) { - if (check_crl_path(ctx, ctx->current_issuer) <= 0) { - ctx->error = X509_V_ERR_CRL_PATH_VALIDATION_ERROR; - ok = ctx->verify_cb(0, ctx); - if (!ok) - goto err; - } - } - - if (crl->idp_flags & IDP_INVALID) { - ctx->error = X509_V_ERR_INVALID_EXTENSION; - ok = ctx->verify_cb(0, ctx); - if (!ok) - goto err; - } + } + if (!(ctx->current_crl_score & CRL_SCORE_SCOPE)) { + ctx->error = X509_V_ERR_DIFFERENT_CRL_SCOPE; + ok = ctx->verify_cb(0, ctx); + if (!ok) { + goto err; } + } - if (!(ctx->current_crl_score & CRL_SCORE_TIME)) { - ok = check_crl_time(ctx, crl, 1); - if (!ok) - goto err; + if (!(ctx->current_crl_score & CRL_SCORE_SAME_PATH)) { + if (check_crl_path(ctx, ctx->current_issuer) <= 0) { + ctx->error = X509_V_ERR_CRL_PATH_VALIDATION_ERROR; + ok = ctx->verify_cb(0, ctx); + if (!ok) { + goto err; + } } + } - /* Attempt to get issuer certificate public key */ - ikey = X509_get_pubkey(issuer); - - if (!ikey) { - ctx->error = X509_V_ERR_UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY; - ok = ctx->verify_cb(0, ctx); - if (!ok) - goto err; - } else { - int rv; - rv = X509_CRL_check_suiteb(crl, ikey, ctx->param->flags); - if (rv != X509_V_OK) { - ctx->error = rv; - ok = ctx->verify_cb(0, ctx); - if (!ok) - goto err; - } - /* Verify CRL signature */ - if (X509_CRL_verify(crl, ikey) <= 0) { - ctx->error = X509_V_ERR_CRL_SIGNATURE_FAILURE; - ok = ctx->verify_cb(0, ctx); - if (!ok) - goto err; - } + if (crl->idp_flags & IDP_INVALID) { + ctx->error = X509_V_ERR_INVALID_EXTENSION; + ok = ctx->verify_cb(0, ctx); + if (!ok) { + goto err; } + } } - ok = 1; + if (!(ctx->current_crl_score & CRL_SCORE_TIME)) { + ok = check_crl_time(ctx, crl, 1); + if (!ok) { + goto err; + } + } - err: - EVP_PKEY_free(ikey); - return ok; -} + /* Attempt to get issuer certificate public key */ + ikey = X509_get_pubkey(issuer); -/* Check certificate against CRL */ -static int cert_crl(X509_STORE_CTX *ctx, X509_CRL *crl, X509 *x) -{ - int ok; - X509_REVOKED *rev; - /* - * The rules changed for this... previously if a CRL contained unhandled - * critical extensions it could still be used to indicate a certificate - * was revoked. This has since been changed since critical extension can - * change the meaning of CRL entries. - */ - if (!(ctx->param->flags & X509_V_FLAG_IGNORE_CRITICAL) - && (crl->flags & EXFLAG_CRITICAL)) { - ctx->error = X509_V_ERR_UNHANDLED_CRITICAL_CRL_EXTENSION; + if (!ikey) { + ctx->error = X509_V_ERR_UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY; + ok = ctx->verify_cb(0, ctx); + if (!ok) { + goto err; + } + } else { + int rv; + rv = X509_CRL_check_suiteb(crl, ikey, ctx->param->flags); + if (rv != X509_V_OK) { + ctx->error = rv; ok = ctx->verify_cb(0, ctx); - if (!ok) - return 0; - } - /* - * Look for serial number of certificate in CRL If found make sure reason - * is not removeFromCRL. - */ - if (X509_CRL_get0_by_cert(crl, &rev, x)) { - if (rev->reason == CRL_REASON_REMOVE_FROM_CRL) - return 2; - ctx->error = X509_V_ERR_CERT_REVOKED; + if (!ok) { + goto err; + } + } + /* Verify CRL signature */ + if (X509_CRL_verify(crl, ikey) <= 0) { + ctx->error = X509_V_ERR_CRL_SIGNATURE_FAILURE; ok = ctx->verify_cb(0, ctx); - if (!ok) - return 0; + if (!ok) { + goto err; + } + } } + } - return 1; + ok = 1; + +err: + EVP_PKEY_free(ikey); + return ok; } -static int check_policy(X509_STORE_CTX *ctx) -{ - int ret; - if (ctx->parent) - return 1; - ret = X509_policy_check(&ctx->tree, &ctx->explicit_policy, ctx->chain, - ctx->param->policies, ctx->param->flags); - if (ret == 0) { - OPENSSL_PUT_ERROR(X509, ERR_R_MALLOC_FAILURE); - ctx->error = X509_V_ERR_OUT_OF_MEM; +/* Check certificate against CRL */ +static int cert_crl(X509_STORE_CTX *ctx, X509_CRL *crl, X509 *x) { + int ok; + X509_REVOKED *rev; + /* + * The rules changed for this... previously if a CRL contained unhandled + * critical extensions it could still be used to indicate a certificate + * was revoked. This has since been changed since critical extension can + * change the meaning of CRL entries. + */ + if (!(ctx->param->flags & X509_V_FLAG_IGNORE_CRITICAL) && + (crl->flags & EXFLAG_CRITICAL)) { + ctx->error = X509_V_ERR_UNHANDLED_CRITICAL_CRL_EXTENSION; + ok = ctx->verify_cb(0, ctx); + if (!ok) { + return 0; + } + } + /* + * Look for serial number of certificate in CRL If found make sure reason + * is not removeFromCRL. + */ + if (X509_CRL_get0_by_cert(crl, &rev, x)) { + if (rev->reason == CRL_REASON_REMOVE_FROM_CRL) { + return 2; + } + ctx->error = X509_V_ERR_CERT_REVOKED; + ok = ctx->verify_cb(0, ctx); + if (!ok) { + return 0; + } + } + + return 1; +} + +static int check_policy(X509_STORE_CTX *ctx) { + int ret; + if (ctx->parent) { + return 1; + } + ret = X509_policy_check(&ctx->tree, &ctx->explicit_policy, ctx->chain, + ctx->param->policies, ctx->param->flags); + if (ret == 0) { + OPENSSL_PUT_ERROR(X509, ERR_R_MALLOC_FAILURE); + ctx->error = X509_V_ERR_OUT_OF_MEM; + return 0; + } + /* Invalid or inconsistent extensions */ + if (ret == -1) { + /* + * Locate certificates with bad extensions and notify callback. + */ + X509 *x; + size_t i; + for (i = 1; i < sk_X509_num(ctx->chain); i++) { + x = sk_X509_value(ctx->chain, i); + if (!(x->ex_flags & EXFLAG_INVALID_POLICY)) { + continue; + } + ctx->current_cert = x; + ctx->error = X509_V_ERR_INVALID_POLICY_EXTENSION; + if (!ctx->verify_cb(0, ctx)) { return 0; + } } - /* Invalid or inconsistent extensions */ - if (ret == -1) { - /* - * Locate certificates with bad extensions and notify callback. - */ - X509 *x; - size_t i; - for (i = 1; i < sk_X509_num(ctx->chain); i++) { - x = sk_X509_value(ctx->chain, i); - if (!(x->ex_flags & EXFLAG_INVALID_POLICY)) - continue; - ctx->current_cert = x; - ctx->error = X509_V_ERR_INVALID_POLICY_EXTENSION; - if (!ctx->verify_cb(0, ctx)) - return 0; - } - return 1; - } - if (ret == -2) { - ctx->current_cert = NULL; - ctx->error = X509_V_ERR_NO_EXPLICIT_POLICY; - return ctx->verify_cb(0, ctx); - } + return 1; + } + if (ret == -2) { + ctx->current_cert = NULL; + ctx->error = X509_V_ERR_NO_EXPLICIT_POLICY; + return ctx->verify_cb(0, ctx); + } - if (ctx->param->flags & X509_V_FLAG_NOTIFY_POLICY) { - ctx->current_cert = NULL; - /* - * Verification errors need to be "sticky", a callback may have allowed - * an SSL handshake to continue despite an error, and we must then - * remain in an error state. Therefore, we MUST NOT clear earlier - * verification errors by setting the error to X509_V_OK. - */ - if (!ctx->verify_cb(2, ctx)) - return 0; + if (ctx->param->flags & X509_V_FLAG_NOTIFY_POLICY) { + ctx->current_cert = NULL; + /* + * Verification errors need to be "sticky", a callback may have allowed + * an SSL handshake to continue despite an error, and we must then + * remain in an error state. Therefore, we MUST NOT clear earlier + * verification errors by setting the error to X509_V_OK. + */ + if (!ctx->verify_cb(2, ctx)) { + return 0; } + } - return 1; + return 1; } -static int check_cert_time(X509_STORE_CTX *ctx, X509 *x) -{ - time_t *ptime; - int i; +static int check_cert_time(X509_STORE_CTX *ctx, X509 *x) { + time_t *ptime; + int i; - if (ctx->param->flags & X509_V_FLAG_USE_CHECK_TIME) - ptime = &ctx->param->check_time; - else - ptime = NULL; + if (ctx->param->flags & X509_V_FLAG_USE_CHECK_TIME) { + ptime = &ctx->param->check_time; + } else { + ptime = NULL; + } - i = X509_cmp_time(X509_get_notBefore(x), ptime); - if (i == 0) { - ctx->error = X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD; - ctx->current_cert = x; - if (!ctx->verify_cb(0, ctx)) - return 0; + i = X509_cmp_time(X509_get_notBefore(x), ptime); + if (i == 0) { + ctx->error = X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD; + ctx->current_cert = x; + if (!ctx->verify_cb(0, ctx)) { + return 0; } + } - if (i > 0) { - ctx->error = X509_V_ERR_CERT_NOT_YET_VALID; - ctx->current_cert = x; - if (!ctx->verify_cb(0, ctx)) - return 0; + if (i > 0) { + ctx->error = X509_V_ERR_CERT_NOT_YET_VALID; + ctx->current_cert = x; + if (!ctx->verify_cb(0, ctx)) { + return 0; } + } - i = X509_cmp_time(X509_get_notAfter(x), ptime); - if (i == 0) { - ctx->error = X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD; - ctx->current_cert = x; - if (!ctx->verify_cb(0, ctx)) - return 0; + i = X509_cmp_time(X509_get_notAfter(x), ptime); + if (i == 0) { + ctx->error = X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD; + ctx->current_cert = x; + if (!ctx->verify_cb(0, ctx)) { + return 0; } + } - if (i < 0) { - ctx->error = X509_V_ERR_CERT_HAS_EXPIRED; - ctx->current_cert = x; - if (!ctx->verify_cb(0, ctx)) - return 0; + if (i < 0) { + ctx->error = X509_V_ERR_CERT_HAS_EXPIRED; + ctx->current_cert = x; + if (!ctx->verify_cb(0, ctx)) { + return 0; } + } - return 1; + return 1; } -static int internal_verify(X509_STORE_CTX *ctx) -{ - int ok = 0, n; - X509 *xs, *xi; - EVP_PKEY *pkey = NULL; +static int internal_verify(X509_STORE_CTX *ctx) { + int ok = 0, n; + X509 *xs, *xi; + EVP_PKEY *pkey = NULL; - n = sk_X509_num(ctx->chain); - ctx->error_depth = n - 1; - n--; - xi = sk_X509_value(ctx->chain, n); - - if (ctx->check_issued(ctx, xi, xi)) - xs = xi; - else { - if (ctx->param->flags & X509_V_FLAG_PARTIAL_CHAIN) { - xs = xi; - goto check_cert; - } - if (n <= 0) { - ctx->error = X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE; - ctx->current_cert = xi; - ok = ctx->verify_cb(0, ctx); - goto end; - } else { - n--; - ctx->error_depth = n; - xs = sk_X509_value(ctx->chain, n); - } + n = sk_X509_num(ctx->chain); + ctx->error_depth = n - 1; + n--; + xi = sk_X509_value(ctx->chain, n); + + if (ctx->check_issued(ctx, xi, xi)) { + xs = xi; + } else { + if (ctx->param->flags & X509_V_FLAG_PARTIAL_CHAIN) { + xs = xi; + goto check_cert; + } + if (n <= 0) { + ctx->error = X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE; + ctx->current_cert = xi; + ok = ctx->verify_cb(0, ctx); + goto end; + } else { + n--; + ctx->error_depth = n; + xs = sk_X509_value(ctx->chain, n); } + } -/* ctx->error=0; not needed */ - while (n >= 0) { - ctx->error_depth = n; + /* ctx->error=0; not needed */ + while (n >= 0) { + ctx->error_depth = n; - /* - * Skip signature check for self signed certificates unless - * explicitly asked for. It doesn't add any security and just wastes - * time. - */ - if (xs != xi || (ctx->param->flags & X509_V_FLAG_CHECK_SS_SIGNATURE)) { - if ((pkey = X509_get_pubkey(xi)) == NULL) { - ctx->error = X509_V_ERR_UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY; - ctx->current_cert = xi; - ok = ctx->verify_cb(0, ctx); - if (!ok) - goto end; - } else if (X509_verify(xs, pkey) <= 0) { - ctx->error = X509_V_ERR_CERT_SIGNATURE_FAILURE; - ctx->current_cert = xs; - ok = ctx->verify_cb(0, ctx); - if (!ok) { - EVP_PKEY_free(pkey); - goto end; - } - } - EVP_PKEY_free(pkey); - pkey = NULL; + /* + * Skip signature check for self signed certificates unless + * explicitly asked for. It doesn't add any security and just wastes + * time. + */ + if (xs != xi || (ctx->param->flags & X509_V_FLAG_CHECK_SS_SIGNATURE)) { + if ((pkey = X509_get_pubkey(xi)) == NULL) { + ctx->error = X509_V_ERR_UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY; + ctx->current_cert = xi; + ok = ctx->verify_cb(0, ctx); + if (!ok) { + goto end; } - - check_cert: - ok = check_cert_time(ctx, xs); - if (!ok) - goto end; - - /* The last error (if any) is still in the error value */ - ctx->current_issuer = xi; + } else if (X509_verify(xs, pkey) <= 0) { + ctx->error = X509_V_ERR_CERT_SIGNATURE_FAILURE; ctx->current_cert = xs; - ok = ctx->verify_cb(1, ctx); - if (!ok) - goto end; - - n--; - if (n >= 0) { - xi = xs; - xs = sk_X509_value(ctx->chain, n); + ok = ctx->verify_cb(0, ctx); + if (!ok) { + EVP_PKEY_free(pkey); + goto end; } + } + EVP_PKEY_free(pkey); + pkey = NULL; } - ok = 1; - end: - return ok; -} -int X509_cmp_current_time(const ASN1_TIME *ctm) -{ - return X509_cmp_time(ctm, NULL); -} + check_cert: + ok = check_cert_time(ctx, xs); + if (!ok) { + goto end; + } -int X509_cmp_time(const ASN1_TIME *ctm, time_t *cmp_time) -{ - static const size_t utctime_length = sizeof("YYMMDDHHMMSSZ") - 1; - static const size_t generalizedtime_length = sizeof("YYYYMMDDHHMMSSZ") - 1; - ASN1_TIME *asn1_cmp_time = NULL; - int i, day, sec, ret = 0; + /* The last error (if any) is still in the error value */ + ctx->current_issuer = xi; + ctx->current_cert = xs; + ok = ctx->verify_cb(1, ctx); + if (!ok) { + goto end; + } - /* - * Note that ASN.1 allows much more slack in the time format than RFC 5280. - * In RFC 5280, the representation is fixed: - * UTCTime: YYMMDDHHMMSSZ - * GeneralizedTime: YYYYMMDDHHMMSSZ - * - * We do NOT currently enforce the following RFC 5280 requirement: - * "CAs conforming to this profile MUST always encode certificate - * validity dates through the year 2049 as UTCTime; certificate validity - * dates in 2050 or later MUST be encoded as GeneralizedTime." - */ - switch (ctm->type) { + n--; + if (n >= 0) { + xi = xs; + xs = sk_X509_value(ctx->chain, n); + } + } + ok = 1; +end: + return ok; +} + +int X509_cmp_current_time(const ASN1_TIME *ctm) { + return X509_cmp_time(ctm, NULL); +} + +int X509_cmp_time(const ASN1_TIME *ctm, time_t *cmp_time) { + static const size_t utctime_length = sizeof("YYMMDDHHMMSSZ") - 1; + static const size_t generalizedtime_length = sizeof("YYYYMMDDHHMMSSZ") - 1; + ASN1_TIME *asn1_cmp_time = NULL; + int i, day, sec, ret = 0; + + /* + * Note that ASN.1 allows much more slack in the time format than RFC 5280. + * In RFC 5280, the representation is fixed: + * UTCTime: YYMMDDHHMMSSZ + * GeneralizedTime: YYYYMMDDHHMMSSZ + * + * We do NOT currently enforce the following RFC 5280 requirement: + * "CAs conforming to this profile MUST always encode certificate + * validity dates through the year 2049 as UTCTime; certificate validity + * dates in 2050 or later MUST be encoded as GeneralizedTime." + */ + switch (ctm->type) { case V_ASN1_UTCTIME: - if (ctm->length != (int)(utctime_length)) - return 0; - break; - case V_ASN1_GENERALIZEDTIME: - if (ctm->length != (int)(generalizedtime_length)) - return 0; - break; - default: + if (ctm->length != (int)(utctime_length)) { return 0; - } - - /** - * Verify the format: the ASN.1 functions we use below allow a more - * flexible format than what's mandated by RFC 5280. - * Digit and date ranges will be verified in the conversion methods. - */ - for (i = 0; i < ctm->length - 1; i++) { - if (!isdigit(ctm->data[i])) - return 0; - } - if (ctm->data[ctm->length - 1] != 'Z') + } + break; + case V_ASN1_GENERALIZEDTIME: + if (ctm->length != (int)(generalizedtime_length)) { return 0; + } + break; + default: + return 0; + } + + /** + * Verify the format: the ASN.1 functions we use below allow a more + * flexible format than what's mandated by RFC 5280. + * Digit and date ranges will be verified in the conversion methods. + */ + for (i = 0; i < ctm->length - 1; i++) { + if (!isdigit(ctm->data[i])) { + return 0; + } + } + if (ctm->data[ctm->length - 1] != 'Z') { + return 0; + } - /* - * There is ASN1_UTCTIME_cmp_time_t but no - * ASN1_GENERALIZEDTIME_cmp_time_t or ASN1_TIME_cmp_time_t, - * so we go through ASN.1 - */ - asn1_cmp_time = X509_time_adj(NULL, 0, cmp_time); - if (asn1_cmp_time == NULL) - goto err; - if (!ASN1_TIME_diff(&day, &sec, ctm, asn1_cmp_time)) - goto err; + /* + * There is ASN1_UTCTIME_cmp_time_t but no + * ASN1_GENERALIZEDTIME_cmp_time_t or ASN1_TIME_cmp_time_t, + * so we go through ASN.1 + */ + asn1_cmp_time = X509_time_adj(NULL, 0, cmp_time); + if (asn1_cmp_time == NULL) { + goto err; + } + if (!ASN1_TIME_diff(&day, &sec, ctm, asn1_cmp_time)) { + goto err; + } - /* - * X509_cmp_time comparison is <=. - * The return value 0 is reserved for errors. - */ - ret = (day >= 0 && sec >= 0) ? -1 : 1; + /* + * X509_cmp_time comparison is <=. + * The return value 0 is reserved for errors. + */ + ret = (day >= 0 && sec >= 0) ? -1 : 1; - err: - ASN1_TIME_free(asn1_cmp_time); - return ret; +err: + ASN1_TIME_free(asn1_cmp_time); + return ret; } -ASN1_TIME *X509_gmtime_adj(ASN1_TIME *s, long offset_sec) -{ - return X509_time_adj(s, offset_sec, NULL); +ASN1_TIME *X509_gmtime_adj(ASN1_TIME *s, long offset_sec) { + return X509_time_adj(s, offset_sec, NULL); } -ASN1_TIME *X509_time_adj(ASN1_TIME *s, long offset_sec, time_t *in_tm) -{ - return X509_time_adj_ex(s, 0, offset_sec, in_tm); +ASN1_TIME *X509_time_adj(ASN1_TIME *s, long offset_sec, time_t *in_tm) { + return X509_time_adj_ex(s, 0, offset_sec, in_tm); } -ASN1_TIME *X509_time_adj_ex(ASN1_TIME *s, - int offset_day, long offset_sec, time_t *in_tm) -{ - time_t t = 0; +ASN1_TIME *X509_time_adj_ex(ASN1_TIME *s, int offset_day, long offset_sec, + time_t *in_tm) { + time_t t = 0; - if (in_tm) { - t = *in_tm; - } else { - time(&t); - } + if (in_tm) { + t = *in_tm; + } else { + time(&t); + } - return ASN1_TIME_adj(s, t, offset_day, offset_sec); + return ASN1_TIME_adj(s, t, offset_day, offset_sec); } /* Make a delta CRL as the diff between two full CRLs */ -X509_CRL *X509_CRL_diff(X509_CRL *base, X509_CRL *newer, - EVP_PKEY *skey, const EVP_MD *md, unsigned int flags) -{ - X509_CRL *crl = NULL; - int i; - size_t j; - STACK_OF(X509_REVOKED) *revs = NULL; - /* CRLs can't be delta already */ - if (base->base_crl_number || newer->base_crl_number) { - OPENSSL_PUT_ERROR(X509, X509_R_CRL_ALREADY_DELTA); - return NULL; - } - /* Base and new CRL must have a CRL number */ - if (!base->crl_number || !newer->crl_number) { - OPENSSL_PUT_ERROR(X509, X509_R_NO_CRL_NUMBER); - return NULL; - } - /* Issuer names must match */ - if (X509_NAME_cmp(X509_CRL_get_issuer(base), X509_CRL_get_issuer(newer))) { - OPENSSL_PUT_ERROR(X509, X509_R_ISSUER_MISMATCH); - return NULL; - } - /* AKID and IDP must match */ - if (!crl_extension_match(base, newer, NID_authority_key_identifier)) { - OPENSSL_PUT_ERROR(X509, X509_R_AKID_MISMATCH); - return NULL; - } - if (!crl_extension_match(base, newer, NID_issuing_distribution_point)) { - OPENSSL_PUT_ERROR(X509, X509_R_IDP_MISMATCH); - return NULL; - } - /* Newer CRL number must exceed full CRL number */ - if (ASN1_INTEGER_cmp(newer->crl_number, base->crl_number) <= 0) { - OPENSSL_PUT_ERROR(X509, X509_R_NEWER_CRL_NOT_NEWER); - return NULL; - } - /* CRLs must verify */ - if (skey && (X509_CRL_verify(base, skey) <= 0 || - X509_CRL_verify(newer, skey) <= 0)) { - OPENSSL_PUT_ERROR(X509, X509_R_CRL_VERIFY_FAILURE); - return NULL; - } - /* Create new CRL */ - crl = X509_CRL_new(); - if (!crl || !X509_CRL_set_version(crl, X509_CRL_VERSION_2)) - goto memerr; - /* Set issuer name */ - if (!X509_CRL_set_issuer_name(crl, X509_CRL_get_issuer(newer))) - goto memerr; - - if (!X509_CRL_set1_lastUpdate(crl, X509_CRL_get0_lastUpdate(newer))) - goto memerr; - if (!X509_CRL_set1_nextUpdate(crl, X509_CRL_get0_nextUpdate(newer))) - goto memerr; - - /* Set base CRL number: must be critical */ - - if (!X509_CRL_add1_ext_i2d(crl, NID_delta_crl, base->crl_number, 1, 0)) - goto memerr; - +X509_CRL *X509_CRL_diff(X509_CRL *base, X509_CRL *newer, EVP_PKEY *skey, + const EVP_MD *md, unsigned int flags) { + X509_CRL *crl = NULL; + int i; + size_t j; + STACK_OF(X509_REVOKED) *revs = NULL; + /* CRLs can't be delta already */ + if (base->base_crl_number || newer->base_crl_number) { + OPENSSL_PUT_ERROR(X509, X509_R_CRL_ALREADY_DELTA); + return NULL; + } + /* Base and new CRL must have a CRL number */ + if (!base->crl_number || !newer->crl_number) { + OPENSSL_PUT_ERROR(X509, X509_R_NO_CRL_NUMBER); + return NULL; + } + /* Issuer names must match */ + if (X509_NAME_cmp(X509_CRL_get_issuer(base), X509_CRL_get_issuer(newer))) { + OPENSSL_PUT_ERROR(X509, X509_R_ISSUER_MISMATCH); + return NULL; + } + /* AKID and IDP must match */ + if (!crl_extension_match(base, newer, NID_authority_key_identifier)) { + OPENSSL_PUT_ERROR(X509, X509_R_AKID_MISMATCH); + return NULL; + } + if (!crl_extension_match(base, newer, NID_issuing_distribution_point)) { + OPENSSL_PUT_ERROR(X509, X509_R_IDP_MISMATCH); + return NULL; + } + /* Newer CRL number must exceed full CRL number */ + if (ASN1_INTEGER_cmp(newer->crl_number, base->crl_number) <= 0) { + OPENSSL_PUT_ERROR(X509, X509_R_NEWER_CRL_NOT_NEWER); + return NULL; + } + /* CRLs must verify */ + if (skey && + (X509_CRL_verify(base, skey) <= 0 || X509_CRL_verify(newer, skey) <= 0)) { + OPENSSL_PUT_ERROR(X509, X509_R_CRL_VERIFY_FAILURE); + return NULL; + } + /* Create new CRL */ + crl = X509_CRL_new(); + if (!crl || !X509_CRL_set_version(crl, X509_CRL_VERSION_2)) { + goto memerr; + } + /* Set issuer name */ + if (!X509_CRL_set_issuer_name(crl, X509_CRL_get_issuer(newer))) { + goto memerr; + } + + if (!X509_CRL_set1_lastUpdate(crl, X509_CRL_get0_lastUpdate(newer))) { + goto memerr; + } + if (!X509_CRL_set1_nextUpdate(crl, X509_CRL_get0_nextUpdate(newer))) { + goto memerr; + } + + /* Set base CRL number: must be critical */ + + if (!X509_CRL_add1_ext_i2d(crl, NID_delta_crl, base->crl_number, 1, 0)) { + goto memerr; + } + + /* + * Copy extensions across from newest CRL to delta: this will set CRL + * number to correct value too. + */ + + for (i = 0; i < X509_CRL_get_ext_count(newer); i++) { + X509_EXTENSION *ext; + ext = X509_CRL_get_ext(newer, i); + if (!X509_CRL_add_ext(crl, ext, -1)) { + goto memerr; + } + } + + /* Go through revoked entries, copying as needed */ + + revs = X509_CRL_get_REVOKED(newer); + + for (j = 0; j < sk_X509_REVOKED_num(revs); j++) { + X509_REVOKED *rvn, *rvtmp; + rvn = sk_X509_REVOKED_value(revs, j); /* - * Copy extensions across from newest CRL to delta: this will set CRL - * number to correct value too. + * Add only if not also in base. TODO: need something cleverer here + * for some more complex CRLs covering multiple CAs. */ - - for (i = 0; i < X509_CRL_get_ext_count(newer); i++) { - X509_EXTENSION *ext; - ext = X509_CRL_get_ext(newer, i); - if (!X509_CRL_add_ext(crl, ext, -1)) - goto memerr; - } - - /* Go through revoked entries, copying as needed */ - - revs = X509_CRL_get_REVOKED(newer); - - for (j = 0; j < sk_X509_REVOKED_num(revs); j++) { - X509_REVOKED *rvn, *rvtmp; - rvn = sk_X509_REVOKED_value(revs, j); - /* - * Add only if not also in base. TODO: need something cleverer here - * for some more complex CRLs covering multiple CAs. - */ - if (!X509_CRL_get0_by_serial(base, &rvtmp, rvn->serialNumber)) { - rvtmp = X509_REVOKED_dup(rvn); - if (!rvtmp) - goto memerr; - if (!X509_CRL_add0_revoked(crl, rvtmp)) { - X509_REVOKED_free(rvtmp); - goto memerr; - } - } + if (!X509_CRL_get0_by_serial(base, &rvtmp, rvn->serialNumber)) { + rvtmp = X509_REVOKED_dup(rvn); + if (!rvtmp) { + goto memerr; + } + if (!X509_CRL_add0_revoked(crl, rvtmp)) { + X509_REVOKED_free(rvtmp); + goto memerr; + } } - /* TODO: optionally prune deleted entries */ + } + /* TODO: optionally prune deleted entries */ - if (skey && md && !X509_CRL_sign(crl, skey, md)) - goto memerr; + if (skey && md && !X509_CRL_sign(crl, skey, md)) { + goto memerr; + } - return crl; + return crl; - memerr: - OPENSSL_PUT_ERROR(X509, ERR_R_MALLOC_FAILURE); - if (crl) - X509_CRL_free(crl); - return NULL; +memerr: + OPENSSL_PUT_ERROR(X509, ERR_R_MALLOC_FAILURE); + if (crl) { + X509_CRL_free(crl); + } + return NULL; } int X509_STORE_CTX_get_ex_new_index(long argl, void *argp, - CRYPTO_EX_unused * unused, + CRYPTO_EX_unused *unused, CRYPTO_EX_dup *dup_unused, - CRYPTO_EX_free *free_func) -{ - /* - * This function is (usually) called only once, by - * SSL_get_ex_data_X509_STORE_CTX_idx (ssl/ssl_cert.c). - */ - int index; - if (!CRYPTO_get_ex_new_index(&g_ex_data_class, &index, argl, argp, - free_func)) { - return -1; - } - return index; + CRYPTO_EX_free *free_func) { + /* + * This function is (usually) called only once, by + * SSL_get_ex_data_X509_STORE_CTX_idx (ssl/ssl_cert.c). + */ + int index; + if (!CRYPTO_get_ex_new_index(&g_ex_data_class, &index, argl, argp, + free_func)) { + return -1; + } + return index; } -int X509_STORE_CTX_set_ex_data(X509_STORE_CTX *ctx, int idx, void *data) -{ - return CRYPTO_set_ex_data(&ctx->ex_data, idx, data); +int X509_STORE_CTX_set_ex_data(X509_STORE_CTX *ctx, int idx, void *data) { + return CRYPTO_set_ex_data(&ctx->ex_data, idx, data); } -void *X509_STORE_CTX_get_ex_data(X509_STORE_CTX *ctx, int idx) -{ - return CRYPTO_get_ex_data(&ctx->ex_data, idx); +void *X509_STORE_CTX_get_ex_data(X509_STORE_CTX *ctx, int idx) { + return CRYPTO_get_ex_data(&ctx->ex_data, idx); } -int X509_STORE_CTX_get_error(X509_STORE_CTX *ctx) -{ - return ctx->error; -} +int X509_STORE_CTX_get_error(X509_STORE_CTX *ctx) { return ctx->error; } -void X509_STORE_CTX_set_error(X509_STORE_CTX *ctx, int err) -{ - ctx->error = err; +void X509_STORE_CTX_set_error(X509_STORE_CTX *ctx, int err) { + ctx->error = err; } -int X509_STORE_CTX_get_error_depth(X509_STORE_CTX *ctx) -{ - return ctx->error_depth; +int X509_STORE_CTX_get_error_depth(X509_STORE_CTX *ctx) { + return ctx->error_depth; } -X509 *X509_STORE_CTX_get_current_cert(X509_STORE_CTX *ctx) -{ - return ctx->current_cert; +X509 *X509_STORE_CTX_get_current_cert(X509_STORE_CTX *ctx) { + return ctx->current_cert; } -STACK_OF(X509) *X509_STORE_CTX_get_chain(X509_STORE_CTX *ctx) -{ - return ctx->chain; +STACK_OF(X509) *X509_STORE_CTX_get_chain(X509_STORE_CTX *ctx) { + return ctx->chain; } -STACK_OF(X509) *X509_STORE_CTX_get0_chain(X509_STORE_CTX *ctx) -{ - return ctx->chain; +STACK_OF(X509) *X509_STORE_CTX_get0_chain(X509_STORE_CTX *ctx) { + return ctx->chain; } -STACK_OF(X509) *X509_STORE_CTX_get1_chain(X509_STORE_CTX *ctx) -{ - if (!ctx->chain) - return NULL; - return X509_chain_up_ref(ctx->chain); +STACK_OF(X509) *X509_STORE_CTX_get1_chain(X509_STORE_CTX *ctx) { + if (!ctx->chain) { + return NULL; + } + return X509_chain_up_ref(ctx->chain); } -X509 *X509_STORE_CTX_get0_current_issuer(X509_STORE_CTX *ctx) -{ - return ctx->current_issuer; +X509 *X509_STORE_CTX_get0_current_issuer(X509_STORE_CTX *ctx) { + return ctx->current_issuer; } -X509_CRL *X509_STORE_CTX_get0_current_crl(X509_STORE_CTX *ctx) -{ - return ctx->current_crl; +X509_CRL *X509_STORE_CTX_get0_current_crl(X509_STORE_CTX *ctx) { + return ctx->current_crl; } -X509_STORE_CTX *X509_STORE_CTX_get0_parent_ctx(X509_STORE_CTX *ctx) -{ - return ctx->parent; +X509_STORE_CTX *X509_STORE_CTX_get0_parent_ctx(X509_STORE_CTX *ctx) { + return ctx->parent; } -void X509_STORE_CTX_set_cert(X509_STORE_CTX *ctx, X509 *x) -{ - ctx->cert = x; -} +void X509_STORE_CTX_set_cert(X509_STORE_CTX *ctx, X509 *x) { ctx->cert = x; } -void X509_STORE_CTX_set_chain(X509_STORE_CTX *ctx, STACK_OF(X509) *sk) -{ - ctx->untrusted = sk; +void X509_STORE_CTX_set_chain(X509_STORE_CTX *ctx, STACK_OF(X509) *sk) { + ctx->untrusted = sk; } -STACK_OF(X509) *X509_STORE_CTX_get0_untrusted(X509_STORE_CTX *ctx) -{ - return ctx->untrusted; +STACK_OF(X509) *X509_STORE_CTX_get0_untrusted(X509_STORE_CTX *ctx) { + return ctx->untrusted; } -void X509_STORE_CTX_set0_crls(X509_STORE_CTX *ctx, STACK_OF(X509_CRL) *sk) -{ - ctx->crls = sk; +void X509_STORE_CTX_set0_crls(X509_STORE_CTX *ctx, STACK_OF(X509_CRL) *sk) { + ctx->crls = sk; } -int X509_STORE_CTX_set_purpose(X509_STORE_CTX *ctx, int purpose) -{ - return X509_STORE_CTX_purpose_inherit(ctx, 0, purpose, 0); +int X509_STORE_CTX_set_purpose(X509_STORE_CTX *ctx, int purpose) { + return X509_STORE_CTX_purpose_inherit(ctx, 0, purpose, 0); } -int X509_STORE_CTX_set_trust(X509_STORE_CTX *ctx, int trust) -{ - return X509_STORE_CTX_purpose_inherit(ctx, 0, 0, trust); +int X509_STORE_CTX_set_trust(X509_STORE_CTX *ctx, int trust) { + return X509_STORE_CTX_purpose_inherit(ctx, 0, 0, trust); } /* @@ -2187,169 +2275,179 @@ int X509_STORE_CTX_set_trust(X509_STORE_CTX *ctx, int trust) */ int X509_STORE_CTX_purpose_inherit(X509_STORE_CTX *ctx, int def_purpose, - int purpose, int trust) -{ - int idx; - /* If purpose not set use default */ - if (!purpose) - purpose = def_purpose; - /* If we have a purpose then check it is valid */ - if (purpose) { - X509_PURPOSE *ptmp; - idx = X509_PURPOSE_get_by_id(purpose); - if (idx == -1) { - OPENSSL_PUT_ERROR(X509, X509_R_UNKNOWN_PURPOSE_ID); - return 0; - } - ptmp = X509_PURPOSE_get0(idx); - if (ptmp->trust == X509_TRUST_DEFAULT) { - idx = X509_PURPOSE_get_by_id(def_purpose); - if (idx == -1) { - OPENSSL_PUT_ERROR(X509, X509_R_UNKNOWN_PURPOSE_ID); - return 0; - } - ptmp = X509_PURPOSE_get0(idx); - } - /* If trust not set then get from purpose default */ - if (!trust) - trust = ptmp->trust; - } - if (trust) { - idx = X509_TRUST_get_by_id(trust); - if (idx == -1) { - OPENSSL_PUT_ERROR(X509, X509_R_UNKNOWN_TRUST_ID); - return 0; - } - } - - if (purpose && !ctx->param->purpose) - ctx->param->purpose = purpose; - if (trust && !ctx->param->trust) - ctx->param->trust = trust; - return 1; -} - -X509_STORE_CTX *X509_STORE_CTX_new(void) -{ - X509_STORE_CTX *ctx; - ctx = (X509_STORE_CTX *)OPENSSL_malloc(sizeof(X509_STORE_CTX)); - if (!ctx) { - OPENSSL_PUT_ERROR(X509, ERR_R_MALLOC_FAILURE); - return NULL; - } - X509_STORE_CTX_zero(ctx); - return ctx; + int purpose, int trust) { + int idx; + /* If purpose not set use default */ + if (!purpose) { + purpose = def_purpose; + } + /* If we have a purpose then check it is valid */ + if (purpose) { + X509_PURPOSE *ptmp; + idx = X509_PURPOSE_get_by_id(purpose); + if (idx == -1) { + OPENSSL_PUT_ERROR(X509, X509_R_UNKNOWN_PURPOSE_ID); + return 0; + } + ptmp = X509_PURPOSE_get0(idx); + if (ptmp->trust == X509_TRUST_DEFAULT) { + idx = X509_PURPOSE_get_by_id(def_purpose); + if (idx == -1) { + OPENSSL_PUT_ERROR(X509, X509_R_UNKNOWN_PURPOSE_ID); + return 0; + } + ptmp = X509_PURPOSE_get0(idx); + } + /* If trust not set then get from purpose default */ + if (!trust) { + trust = ptmp->trust; + } + } + if (trust) { + idx = X509_TRUST_get_by_id(trust); + if (idx == -1) { + OPENSSL_PUT_ERROR(X509, X509_R_UNKNOWN_TRUST_ID); + return 0; + } + } + + if (purpose && !ctx->param->purpose) { + ctx->param->purpose = purpose; + } + if (trust && !ctx->param->trust) { + ctx->param->trust = trust; + } + return 1; +} + +X509_STORE_CTX *X509_STORE_CTX_new(void) { + X509_STORE_CTX *ctx; + ctx = (X509_STORE_CTX *)OPENSSL_malloc(sizeof(X509_STORE_CTX)); + if (!ctx) { + OPENSSL_PUT_ERROR(X509, ERR_R_MALLOC_FAILURE); + return NULL; + } + X509_STORE_CTX_zero(ctx); + return ctx; } -void X509_STORE_CTX_zero(X509_STORE_CTX *ctx) -{ - OPENSSL_memset(ctx, 0, sizeof(X509_STORE_CTX)); +void X509_STORE_CTX_zero(X509_STORE_CTX *ctx) { + OPENSSL_memset(ctx, 0, sizeof(X509_STORE_CTX)); } -void X509_STORE_CTX_free(X509_STORE_CTX *ctx) -{ - if (ctx == NULL) { - return; - } - X509_STORE_CTX_cleanup(ctx); - OPENSSL_free(ctx); +void X509_STORE_CTX_free(X509_STORE_CTX *ctx) { + if (ctx == NULL) { + return; + } + X509_STORE_CTX_cleanup(ctx); + OPENSSL_free(ctx); } int X509_STORE_CTX_init(X509_STORE_CTX *ctx, X509_STORE *store, X509 *x509, - STACK_OF(X509) *chain) -{ - X509_STORE_CTX_zero(ctx); - ctx->ctx = store; - ctx->cert = x509; - ctx->untrusted = chain; - - CRYPTO_new_ex_data(&ctx->ex_data); - - if (store == NULL) { - OPENSSL_PUT_ERROR(X509, ERR_R_PASSED_NULL_PARAMETER); - goto err; - } - - ctx->param = X509_VERIFY_PARAM_new(); - if (!ctx->param) - goto err; - - /* - * Inherit callbacks and flags from X509_STORE. - */ - + STACK_OF(X509) *chain) { + X509_STORE_CTX_zero(ctx); + ctx->ctx = store; + ctx->cert = x509; + ctx->untrusted = chain; + + CRYPTO_new_ex_data(&ctx->ex_data); + + if (store == NULL) { + OPENSSL_PUT_ERROR(X509, ERR_R_PASSED_NULL_PARAMETER); + goto err; + } + + ctx->param = X509_VERIFY_PARAM_new(); + if (!ctx->param) { + goto err; + } + + /* + * Inherit callbacks and flags from X509_STORE. + */ + + ctx->verify_cb = store->verify_cb; + ctx->cleanup = store->cleanup; + + if (!X509_VERIFY_PARAM_inherit(ctx->param, store->param) || + !X509_VERIFY_PARAM_inherit(ctx->param, + X509_VERIFY_PARAM_lookup("default"))) { + goto err; + } + + if (store->check_issued) { + ctx->check_issued = store->check_issued; + } else { + ctx->check_issued = check_issued; + } + + if (store->get_issuer) { + ctx->get_issuer = store->get_issuer; + } else { + ctx->get_issuer = X509_STORE_CTX_get1_issuer; + } + + if (store->verify_cb) { ctx->verify_cb = store->verify_cb; - ctx->cleanup = store->cleanup; - - if (!X509_VERIFY_PARAM_inherit(ctx->param, store->param) || - !X509_VERIFY_PARAM_inherit(ctx->param, - X509_VERIFY_PARAM_lookup("default"))) { - goto err; - } - - if (store->check_issued) - ctx->check_issued = store->check_issued; - else - ctx->check_issued = check_issued; - - if (store->get_issuer) - ctx->get_issuer = store->get_issuer; - else - ctx->get_issuer = X509_STORE_CTX_get1_issuer; - - if (store->verify_cb) - ctx->verify_cb = store->verify_cb; - else - ctx->verify_cb = null_callback; - - if (store->verify) - ctx->verify = store->verify; - else - ctx->verify = internal_verify; - - if (store->check_revocation) - ctx->check_revocation = store->check_revocation; - else - ctx->check_revocation = check_revocation; - - if (store->get_crl) - ctx->get_crl = store->get_crl; - else - ctx->get_crl = NULL; - - if (store->check_crl) - ctx->check_crl = store->check_crl; - else - ctx->check_crl = check_crl; - - if (store->cert_crl) - ctx->cert_crl = store->cert_crl; - else - ctx->cert_crl = cert_crl; - - if (store->lookup_certs) - ctx->lookup_certs = store->lookup_certs; - else - ctx->lookup_certs = X509_STORE_get1_certs; - - if (store->lookup_crls) - ctx->lookup_crls = store->lookup_crls; - else - ctx->lookup_crls = X509_STORE_get1_crls; - - ctx->check_policy = check_policy; - - return 1; - - err: - CRYPTO_free_ex_data(&g_ex_data_class, ctx, &ctx->ex_data); - if (ctx->param != NULL) { - X509_VERIFY_PARAM_free(ctx->param); - } - - OPENSSL_memset(ctx, 0, sizeof(X509_STORE_CTX)); - OPENSSL_PUT_ERROR(X509, ERR_R_MALLOC_FAILURE); - return 0; + } else { + ctx->verify_cb = null_callback; + } + + if (store->verify) { + ctx->verify = store->verify; + } else { + ctx->verify = internal_verify; + } + + if (store->check_revocation) { + ctx->check_revocation = store->check_revocation; + } else { + ctx->check_revocation = check_revocation; + } + + if (store->get_crl) { + ctx->get_crl = store->get_crl; + } else { + ctx->get_crl = NULL; + } + + if (store->check_crl) { + ctx->check_crl = store->check_crl; + } else { + ctx->check_crl = check_crl; + } + + if (store->cert_crl) { + ctx->cert_crl = store->cert_crl; + } else { + ctx->cert_crl = cert_crl; + } + + if (store->lookup_certs) { + ctx->lookup_certs = store->lookup_certs; + } else { + ctx->lookup_certs = X509_STORE_get1_certs; + } + + if (store->lookup_crls) { + ctx->lookup_crls = store->lookup_crls; + } else { + ctx->lookup_crls = X509_STORE_get1_crls; + } + + ctx->check_policy = check_policy; + + return 1; + +err: + CRYPTO_free_ex_data(&g_ex_data_class, ctx, &ctx->ex_data); + if (ctx->param != NULL) { + X509_VERIFY_PARAM_free(ctx->param); + } + + OPENSSL_memset(ctx, 0, sizeof(X509_STORE_CTX)); + OPENSSL_PUT_ERROR(X509, ERR_R_MALLOC_FAILURE); + return 0; } /* @@ -2357,91 +2455,80 @@ int X509_STORE_CTX_init(X509_STORE_CTX *ctx, X509_STORE *store, X509 *x509, * avoids X509_STORE nastiness where it isn't needed. */ -void X509_STORE_CTX_trusted_stack(X509_STORE_CTX *ctx, STACK_OF(X509) *sk) -{ - ctx->other_ctx = sk; - ctx->get_issuer = get_issuer_sk; +void X509_STORE_CTX_trusted_stack(X509_STORE_CTX *ctx, STACK_OF(X509) *sk) { + ctx->other_ctx = sk; + ctx->get_issuer = get_issuer_sk; } -void X509_STORE_CTX_cleanup(X509_STORE_CTX *ctx) -{ - /* We need to be idempotent because, unfortunately, |X509_STORE_CTX_free| - * also calls this function. */ - if (ctx->cleanup != NULL) { - ctx->cleanup(ctx); - ctx->cleanup = NULL; - } - if (ctx->param != NULL) { - if (ctx->parent == NULL) - X509_VERIFY_PARAM_free(ctx->param); - ctx->param = NULL; - } - if (ctx->tree != NULL) { - X509_policy_tree_free(ctx->tree); - ctx->tree = NULL; +void X509_STORE_CTX_cleanup(X509_STORE_CTX *ctx) { + /* We need to be idempotent because, unfortunately, |X509_STORE_CTX_free| + * also calls this function. */ + if (ctx->cleanup != NULL) { + ctx->cleanup(ctx); + ctx->cleanup = NULL; + } + if (ctx->param != NULL) { + if (ctx->parent == NULL) { + X509_VERIFY_PARAM_free(ctx->param); } - if (ctx->chain != NULL) { - sk_X509_pop_free(ctx->chain, X509_free); - ctx->chain = NULL; - } - CRYPTO_free_ex_data(&g_ex_data_class, ctx, &(ctx->ex_data)); - OPENSSL_memset(&ctx->ex_data, 0, sizeof(CRYPTO_EX_DATA)); + ctx->param = NULL; + } + if (ctx->tree != NULL) { + X509_policy_tree_free(ctx->tree); + ctx->tree = NULL; + } + if (ctx->chain != NULL) { + sk_X509_pop_free(ctx->chain, X509_free); + ctx->chain = NULL; + } + CRYPTO_free_ex_data(&g_ex_data_class, ctx, &(ctx->ex_data)); + OPENSSL_memset(&ctx->ex_data, 0, sizeof(CRYPTO_EX_DATA)); } -void X509_STORE_CTX_set_depth(X509_STORE_CTX *ctx, int depth) -{ - X509_VERIFY_PARAM_set_depth(ctx->param, depth); +void X509_STORE_CTX_set_depth(X509_STORE_CTX *ctx, int depth) { + X509_VERIFY_PARAM_set_depth(ctx->param, depth); } -void X509_STORE_CTX_set_flags(X509_STORE_CTX *ctx, unsigned long flags) -{ - X509_VERIFY_PARAM_set_flags(ctx->param, flags); +void X509_STORE_CTX_set_flags(X509_STORE_CTX *ctx, unsigned long flags) { + X509_VERIFY_PARAM_set_flags(ctx->param, flags); } void X509_STORE_CTX_set_time(X509_STORE_CTX *ctx, unsigned long flags, - time_t t) -{ - X509_VERIFY_PARAM_set_time(ctx->param, t); + time_t t) { + X509_VERIFY_PARAM_set_time(ctx->param, t); } -X509 *X509_STORE_CTX_get0_cert(X509_STORE_CTX *ctx) -{ - return ctx->cert; -} +X509 *X509_STORE_CTX_get0_cert(X509_STORE_CTX *ctx) { return ctx->cert; } void X509_STORE_CTX_set_verify_cb(X509_STORE_CTX *ctx, - int (*verify_cb) (int, X509_STORE_CTX *)) -{ - ctx->verify_cb = verify_cb; + int (*verify_cb)(int, X509_STORE_CTX *)) { + ctx->verify_cb = verify_cb; } -X509_POLICY_TREE *X509_STORE_CTX_get0_policy_tree(X509_STORE_CTX *ctx) -{ - return ctx->tree; +X509_POLICY_TREE *X509_STORE_CTX_get0_policy_tree(X509_STORE_CTX *ctx) { + return ctx->tree; } -int X509_STORE_CTX_get_explicit_policy(X509_STORE_CTX *ctx) -{ - return ctx->explicit_policy; +int X509_STORE_CTX_get_explicit_policy(X509_STORE_CTX *ctx) { + return ctx->explicit_policy; } -int X509_STORE_CTX_set_default(X509_STORE_CTX *ctx, const char *name) -{ - const X509_VERIFY_PARAM *param; - param = X509_VERIFY_PARAM_lookup(name); - if (!param) - return 0; - return X509_VERIFY_PARAM_inherit(ctx->param, param); +int X509_STORE_CTX_set_default(X509_STORE_CTX *ctx, const char *name) { + const X509_VERIFY_PARAM *param; + param = X509_VERIFY_PARAM_lookup(name); + if (!param) { + return 0; + } + return X509_VERIFY_PARAM_inherit(ctx->param, param); } -X509_VERIFY_PARAM *X509_STORE_CTX_get0_param(X509_STORE_CTX *ctx) -{ - return ctx->param; +X509_VERIFY_PARAM *X509_STORE_CTX_get0_param(X509_STORE_CTX *ctx) { + return ctx->param; } -void X509_STORE_CTX_set0_param(X509_STORE_CTX *ctx, X509_VERIFY_PARAM *param) -{ - if (ctx->param) - X509_VERIFY_PARAM_free(ctx->param); - ctx->param = param; +void X509_STORE_CTX_set0_param(X509_STORE_CTX *ctx, X509_VERIFY_PARAM *param) { + if (ctx->param) { + X509_VERIFY_PARAM_free(ctx->param); + } + ctx->param = param; } diff --git a/crypto/x509/x509_vpm.c b/crypto/x509/x509_vpm.c index 29d5341efc..9555c56e27 100644 --- a/crypto/x509/x509_vpm.c +++ b/crypto/x509/x509_vpm.c @@ -62,9 +62,9 @@ #include #include -#include "internal.h" #include "../internal.h" #include "../x509v3/internal.h" +#include "internal.h" /* X509_VERIFY_PARAM functions */ @@ -72,117 +72,112 @@ #define SET_HOST 0 #define ADD_HOST 1 -static char *str_copy(char *s) -{ - return OPENSSL_strdup(s); -} +static char *str_copy(char *s) { return OPENSSL_strdup(s); } -static void str_free(char *s) -{ - OPENSSL_free(s); -} +static void str_free(char *s) { OPENSSL_free(s); } #define string_stack_free(sk) sk_OPENSSL_STRING_pop_free(sk, str_free) static int int_x509_param_set_hosts(X509_VERIFY_PARAM *param, int mode, - const char *name, size_t namelen) -{ - char *copy; - - if (name == NULL || namelen == 0) { - // Unlike OpenSSL, we reject trying to set or add an empty name. - return 0; - } + const char *name, size_t namelen) { + char *copy; - /* - * Refuse names with embedded NUL bytes. - * XXX: Do we need to push an error onto the error stack? - */ - if (name && OPENSSL_memchr(name, '\0', namelen)) - return 0; - - if (mode == SET_HOST && param->hosts) { - string_stack_free(param->hosts); - param->hosts = NULL; - } + if (name == NULL || namelen == 0) { + // Unlike OpenSSL, we reject trying to set or add an empty name. + return 0; + } - copy = OPENSSL_strndup(name, namelen); - if (copy == NULL) - return 0; + /* + * Refuse names with embedded NUL bytes. + * XXX: Do we need to push an error onto the error stack? + */ + if (name && OPENSSL_memchr(name, '\0', namelen)) { + return 0; + } - if (param->hosts == NULL && - (param->hosts = sk_OPENSSL_STRING_new_null()) == NULL) { - OPENSSL_free(copy); - return 0; - } + if (mode == SET_HOST && param->hosts) { + string_stack_free(param->hosts); + param->hosts = NULL; + } - if (!sk_OPENSSL_STRING_push(param->hosts, copy)) { - OPENSSL_free(copy); - if (sk_OPENSSL_STRING_num(param->hosts) == 0) { - sk_OPENSSL_STRING_free(param->hosts); - param->hosts = NULL; - } - return 0; - } + copy = OPENSSL_strndup(name, namelen); + if (copy == NULL) { + return 0; + } - return 1; -} + if (param->hosts == NULL && + (param->hosts = sk_OPENSSL_STRING_new_null()) == NULL) { + OPENSSL_free(copy); + return 0; + } -static void x509_verify_param_zero(X509_VERIFY_PARAM *param) -{ - if (!param) - return; - param->name = NULL; - param->purpose = 0; - param->trust = 0; - /* - * param->inh_flags = X509_VP_FLAG_DEFAULT; - */ - param->inh_flags = 0; - param->flags = 0; - param->depth = -1; - if (param->policies) { - sk_ASN1_OBJECT_pop_free(param->policies, ASN1_OBJECT_free); - param->policies = NULL; - } - if (param->hosts) { - string_stack_free(param->hosts); - param->hosts = NULL; - } - if (param->peername) { - OPENSSL_free(param->peername); - param->peername = NULL; + if (!sk_OPENSSL_STRING_push(param->hosts, copy)) { + OPENSSL_free(copy); + if (sk_OPENSSL_STRING_num(param->hosts) == 0) { + sk_OPENSSL_STRING_free(param->hosts); + param->hosts = NULL; } - if (param->email) { - OPENSSL_free(param->email); - param->email = NULL; - param->emaillen = 0; - } - if (param->ip) { - OPENSSL_free(param->ip); - param->ip = NULL; - param->iplen = 0; - } - param->poison = 0; -} - -X509_VERIFY_PARAM *X509_VERIFY_PARAM_new(void) -{ - X509_VERIFY_PARAM *param; - param = OPENSSL_malloc(sizeof(X509_VERIFY_PARAM)); - if (!param) - return NULL; - OPENSSL_memset(param, 0, sizeof(X509_VERIFY_PARAM)); - x509_verify_param_zero(param); - return param; + return 0; + } + + return 1; +} + +static void x509_verify_param_zero(X509_VERIFY_PARAM *param) { + if (!param) { + return; + } + param->name = NULL; + param->purpose = 0; + param->trust = 0; + /* + * param->inh_flags = X509_VP_FLAG_DEFAULT; + */ + param->inh_flags = 0; + param->flags = 0; + param->depth = -1; + if (param->policies) { + sk_ASN1_OBJECT_pop_free(param->policies, ASN1_OBJECT_free); + param->policies = NULL; + } + if (param->hosts) { + string_stack_free(param->hosts); + param->hosts = NULL; + } + if (param->peername) { + OPENSSL_free(param->peername); + param->peername = NULL; + } + if (param->email) { + OPENSSL_free(param->email); + param->email = NULL; + param->emaillen = 0; + } + if (param->ip) { + OPENSSL_free(param->ip); + param->ip = NULL; + param->iplen = 0; + } + param->poison = 0; +} + +X509_VERIFY_PARAM *X509_VERIFY_PARAM_new(void) { + X509_VERIFY_PARAM *param; + param = OPENSSL_malloc(sizeof(X509_VERIFY_PARAM)); + if (!param) { + return NULL; + } + OPENSSL_memset(param, 0, sizeof(X509_VERIFY_PARAM)); + x509_verify_param_zero(param); + return param; } -void X509_VERIFY_PARAM_free(X509_VERIFY_PARAM *param) -{ - if (param == NULL) - return; - x509_verify_param_zero(param); - OPENSSL_free(param); +void X509_VERIFY_PARAM_free(X509_VERIFY_PARAM *param) { + if (param == NULL) { + return; + } + x509_verify_param_zero(param); + OPENSSL_free(param); } /*- @@ -225,294 +220,292 @@ void X509_VERIFY_PARAM_free(X509_VERIFY_PARAM *param) /* Macro to test and copy a field if necessary */ -#define x509_verify_param_copy(field, def) \ - if (test_x509_verify_param_copy(field, def)) \ - dest->field = src->field +#define x509_verify_param_copy(field, def) \ + if (test_x509_verify_param_copy(field, def)) \ + dest->field = src->field int X509_VERIFY_PARAM_inherit(X509_VERIFY_PARAM *dest, - const X509_VERIFY_PARAM *src) -{ - unsigned long inh_flags; - int to_default, to_overwrite; - if (!src) - return 1; - inh_flags = dest->inh_flags | src->inh_flags; - - if (inh_flags & X509_VP_FLAG_ONCE) - dest->inh_flags = 0; - - if (inh_flags & X509_VP_FLAG_LOCKED) - return 1; - - if (inh_flags & X509_VP_FLAG_DEFAULT) - to_default = 1; - else - to_default = 0; - - if (inh_flags & X509_VP_FLAG_OVERWRITE) - to_overwrite = 1; - else - to_overwrite = 0; - - x509_verify_param_copy(purpose, 0); - x509_verify_param_copy(trust, 0); - x509_verify_param_copy(depth, -1); - - /* If overwrite or check time not set, copy across */ - - if (to_overwrite || !(dest->flags & X509_V_FLAG_USE_CHECK_TIME)) { - dest->check_time = src->check_time; - dest->flags &= ~X509_V_FLAG_USE_CHECK_TIME; - /* Don't need to copy flag: that is done below */ - } + const X509_VERIFY_PARAM *src) { + unsigned long inh_flags; + int to_default, to_overwrite; + if (!src) { + return 1; + } + inh_flags = dest->inh_flags | src->inh_flags; - if (inh_flags & X509_VP_FLAG_RESET_FLAGS) - dest->flags = 0; + if (inh_flags & X509_VP_FLAG_ONCE) { + dest->inh_flags = 0; + } - dest->flags |= src->flags; + if (inh_flags & X509_VP_FLAG_LOCKED) { + return 1; + } - if (test_x509_verify_param_copy(policies, NULL)) { - if (!X509_VERIFY_PARAM_set1_policies(dest, src->policies)) - return 0; - } + if (inh_flags & X509_VP_FLAG_DEFAULT) { + to_default = 1; + } else { + to_default = 0; + } - /* Copy the host flags if and only if we're copying the host list */ - if (test_x509_verify_param_copy(hosts, NULL)) { - if (dest->hosts) { - string_stack_free(dest->hosts); - dest->hosts = NULL; - } - if (src->hosts) { - dest->hosts = - sk_OPENSSL_STRING_deep_copy(src->hosts, str_copy, str_free); - if (dest->hosts == NULL) - return 0; - dest->hostflags = src->hostflags; - } - } + if (inh_flags & X509_VP_FLAG_OVERWRITE) { + to_overwrite = 1; + } else { + to_overwrite = 0; + } - if (test_x509_verify_param_copy(email, NULL)) { - if (!X509_VERIFY_PARAM_set1_email(dest, src->email, src->emaillen)) - return 0; - } + x509_verify_param_copy(purpose, 0); + x509_verify_param_copy(trust, 0); + x509_verify_param_copy(depth, -1); - if (test_x509_verify_param_copy(ip, NULL)) { - if (!X509_VERIFY_PARAM_set1_ip(dest, src->ip, src->iplen)) - return 0; - } + /* If overwrite or check time not set, copy across */ - dest->poison = src->poison; + if (to_overwrite || !(dest->flags & X509_V_FLAG_USE_CHECK_TIME)) { + dest->check_time = src->check_time; + dest->flags &= ~X509_V_FLAG_USE_CHECK_TIME; + /* Don't need to copy flag: that is done below */ + } - return 1; -} + if (inh_flags & X509_VP_FLAG_RESET_FLAGS) { + dest->flags = 0; + } -int X509_VERIFY_PARAM_set1(X509_VERIFY_PARAM *to, - const X509_VERIFY_PARAM *from) -{ - unsigned long save_flags = to->inh_flags; - int ret; - to->inh_flags |= X509_VP_FLAG_DEFAULT; - ret = X509_VERIFY_PARAM_inherit(to, from); - to->inh_flags = save_flags; - return ret; -} - -static int int_x509_param_set1(char **pdest, size_t *pdestlen, - const char *src, size_t srclen) -{ - void *tmp; - if (src == NULL || srclen == 0) { - // Unlike OpenSSL, we do not allow an empty string to disable previously - // configured checks. - return 0; + dest->flags |= src->flags; + + if (test_x509_verify_param_copy(policies, NULL)) { + if (!X509_VERIFY_PARAM_set1_policies(dest, src->policies)) { + return 0; } + } - tmp = OPENSSL_memdup(src, srclen); - if (!tmp) { + /* Copy the host flags if and only if we're copying the host list */ + if (test_x509_verify_param_copy(hosts, NULL)) { + if (dest->hosts) { + string_stack_free(dest->hosts); + dest->hosts = NULL; + } + if (src->hosts) { + dest->hosts = sk_OPENSSL_STRING_deep_copy(src->hosts, str_copy, str_free); + if (dest->hosts == NULL) { return 0; + } + dest->hostflags = src->hostflags; } + } - if (*pdest) - OPENSSL_free(*pdest); - *pdest = tmp; - if (pdestlen) - *pdestlen = srclen; - return 1; + if (test_x509_verify_param_copy(email, NULL)) { + if (!X509_VERIFY_PARAM_set1_email(dest, src->email, src->emaillen)) { + return 0; + } + } + + if (test_x509_verify_param_copy(ip, NULL)) { + if (!X509_VERIFY_PARAM_set1_ip(dest, src->ip, src->iplen)) { + return 0; + } + } + + dest->poison = src->poison; + + return 1; } -int X509_VERIFY_PARAM_set1_name(X509_VERIFY_PARAM *param, const char *name) -{ - if (param->name) - OPENSSL_free(param->name); - param->name = OPENSSL_strdup(name); - if (param->name) - return 1; +int X509_VERIFY_PARAM_set1(X509_VERIFY_PARAM *to, + const X509_VERIFY_PARAM *from) { + unsigned long save_flags = to->inh_flags; + int ret; + to->inh_flags |= X509_VP_FLAG_DEFAULT; + ret = X509_VERIFY_PARAM_inherit(to, from); + to->inh_flags = save_flags; + return ret; +} + +static int int_x509_param_set1(char **pdest, size_t *pdestlen, const char *src, + size_t srclen) { + void *tmp; + if (src == NULL || srclen == 0) { + // Unlike OpenSSL, we do not allow an empty string to disable previously + // configured checks. return 0; -} + } -int X509_VERIFY_PARAM_set_flags(X509_VERIFY_PARAM *param, unsigned long flags) -{ - param->flags |= flags; - if (flags & X509_V_FLAG_POLICY_MASK) - param->flags |= X509_V_FLAG_POLICY_CHECK; + tmp = OPENSSL_memdup(src, srclen); + if (!tmp) { + return 0; + } + + if (*pdest) { + OPENSSL_free(*pdest); + } + *pdest = tmp; + if (pdestlen) { + *pdestlen = srclen; + } + return 1; +} + +int X509_VERIFY_PARAM_set1_name(X509_VERIFY_PARAM *param, const char *name) { + if (param->name) { + OPENSSL_free(param->name); + } + param->name = OPENSSL_strdup(name); + if (param->name) { return 1; + } + return 0; +} + +int X509_VERIFY_PARAM_set_flags(X509_VERIFY_PARAM *param, unsigned long flags) { + param->flags |= flags; + if (flags & X509_V_FLAG_POLICY_MASK) { + param->flags |= X509_V_FLAG_POLICY_CHECK; + } + return 1; } int X509_VERIFY_PARAM_clear_flags(X509_VERIFY_PARAM *param, - unsigned long flags) -{ - param->flags &= ~flags; - return 1; + unsigned long flags) { + param->flags &= ~flags; + return 1; } -unsigned long X509_VERIFY_PARAM_get_flags(X509_VERIFY_PARAM *param) -{ - return param->flags; +unsigned long X509_VERIFY_PARAM_get_flags(X509_VERIFY_PARAM *param) { + return param->flags; } -int X509_VERIFY_PARAM_set_purpose(X509_VERIFY_PARAM *param, int purpose) -{ - return X509_PURPOSE_set(¶m->purpose, purpose); +int X509_VERIFY_PARAM_set_purpose(X509_VERIFY_PARAM *param, int purpose) { + return X509_PURPOSE_set(¶m->purpose, purpose); } -int X509_VERIFY_PARAM_set_trust(X509_VERIFY_PARAM *param, int trust) -{ - return X509_TRUST_set(¶m->trust, trust); +int X509_VERIFY_PARAM_set_trust(X509_VERIFY_PARAM *param, int trust) { + return X509_TRUST_set(¶m->trust, trust); } -void X509_VERIFY_PARAM_set_depth(X509_VERIFY_PARAM *param, int depth) -{ - param->depth = depth; +void X509_VERIFY_PARAM_set_depth(X509_VERIFY_PARAM *param, int depth) { + param->depth = depth; } -void X509_VERIFY_PARAM_set_time(X509_VERIFY_PARAM *param, time_t t) -{ - param->check_time = t; - param->flags |= X509_V_FLAG_USE_CHECK_TIME; +void X509_VERIFY_PARAM_set_time(X509_VERIFY_PARAM *param, time_t t) { + param->check_time = t; + param->flags |= X509_V_FLAG_USE_CHECK_TIME; } int X509_VERIFY_PARAM_add0_policy(X509_VERIFY_PARAM *param, - ASN1_OBJECT *policy) -{ + ASN1_OBJECT *policy) { + if (!param->policies) { + param->policies = sk_ASN1_OBJECT_new_null(); if (!param->policies) { - param->policies = sk_ASN1_OBJECT_new_null(); - if (!param->policies) - return 0; + return 0; } - if (!sk_ASN1_OBJECT_push(param->policies, policy)) - return 0; - return 1; + } + if (!sk_ASN1_OBJECT_push(param->policies, policy)) { + return 0; + } + return 1; } int X509_VERIFY_PARAM_set1_policies(X509_VERIFY_PARAM *param, - STACK_OF(ASN1_OBJECT) *policies) -{ - size_t i; - ASN1_OBJECT *oid, *doid; - if (!param) - return 0; - if (param->policies) - sk_ASN1_OBJECT_pop_free(param->policies, ASN1_OBJECT_free); + STACK_OF(ASN1_OBJECT) *policies) { + size_t i; + ASN1_OBJECT *oid, *doid; + if (!param) { + return 0; + } + if (param->policies) { + sk_ASN1_OBJECT_pop_free(param->policies, ASN1_OBJECT_free); + } - if (!policies) { - param->policies = NULL; - return 1; - } + if (!policies) { + param->policies = NULL; + return 1; + } - param->policies = sk_ASN1_OBJECT_new_null(); - if (!param->policies) - return 0; + param->policies = sk_ASN1_OBJECT_new_null(); + if (!param->policies) { + return 0; + } - for (i = 0; i < sk_ASN1_OBJECT_num(policies); i++) { - oid = sk_ASN1_OBJECT_value(policies, i); - doid = OBJ_dup(oid); - if (!doid) - return 0; - if (!sk_ASN1_OBJECT_push(param->policies, doid)) { - ASN1_OBJECT_free(doid); - return 0; - } + for (i = 0; i < sk_ASN1_OBJECT_num(policies); i++) { + oid = sk_ASN1_OBJECT_value(policies, i); + doid = OBJ_dup(oid); + if (!doid) { + return 0; } - param->flags |= X509_V_FLAG_POLICY_CHECK; - return 1; + if (!sk_ASN1_OBJECT_push(param->policies, doid)) { + ASN1_OBJECT_free(doid); + return 0; + } + } + param->flags |= X509_V_FLAG_POLICY_CHECK; + return 1; } -int X509_VERIFY_PARAM_set1_host(X509_VERIFY_PARAM *param, - const char *name, size_t namelen) -{ - if (!int_x509_param_set_hosts(param, SET_HOST, name, namelen)) { - param->poison = 1; - return 0; - } - return 1; +int X509_VERIFY_PARAM_set1_host(X509_VERIFY_PARAM *param, const char *name, + size_t namelen) { + if (!int_x509_param_set_hosts(param, SET_HOST, name, namelen)) { + param->poison = 1; + return 0; + } + return 1; } -int X509_VERIFY_PARAM_add1_host(X509_VERIFY_PARAM *param, - const char *name, size_t namelen) -{ - if (!int_x509_param_set_hosts(param, ADD_HOST, name, namelen)) { - param->poison = 1; - return 0; - } - return 1; +int X509_VERIFY_PARAM_add1_host(X509_VERIFY_PARAM *param, const char *name, + size_t namelen) { + if (!int_x509_param_set_hosts(param, ADD_HOST, name, namelen)) { + param->poison = 1; + return 0; + } + return 1; } void X509_VERIFY_PARAM_set_hostflags(X509_VERIFY_PARAM *param, - unsigned int flags) -{ - param->hostflags = flags; + unsigned int flags) { + param->hostflags = flags; } -char *X509_VERIFY_PARAM_get0_peername(X509_VERIFY_PARAM *param) -{ - return param->peername; +char *X509_VERIFY_PARAM_get0_peername(X509_VERIFY_PARAM *param) { + return param->peername; } -int X509_VERIFY_PARAM_set1_email(X509_VERIFY_PARAM *param, - const char *email, size_t emaillen) -{ - if (OPENSSL_memchr(email, '\0', emaillen) != NULL || - !int_x509_param_set1(¶m->email, ¶m->emaillen, - email, emaillen)) { - param->poison = 1; - return 0; - } +int X509_VERIFY_PARAM_set1_email(X509_VERIFY_PARAM *param, const char *email, + size_t emaillen) { + if (OPENSSL_memchr(email, '\0', emaillen) != NULL || + !int_x509_param_set1(¶m->email, ¶m->emaillen, email, emaillen)) { + param->poison = 1; + return 0; + } - return 1; + return 1; } -int X509_VERIFY_PARAM_set1_ip(X509_VERIFY_PARAM *param, - const unsigned char *ip, size_t iplen) -{ - if ((iplen != 4 && iplen != 16) || - !int_x509_param_set1((char **)¶m->ip, ¶m->iplen, - (char *)ip, iplen)) { - param->poison = 1; - return 0; - } +int X509_VERIFY_PARAM_set1_ip(X509_VERIFY_PARAM *param, const unsigned char *ip, + size_t iplen) { + if ((iplen != 4 && iplen != 16) || + !int_x509_param_set1((char **)¶m->ip, ¶m->iplen, (char *)ip, + iplen)) { + param->poison = 1; + return 0; + } - return 1; + return 1; } -int X509_VERIFY_PARAM_set1_ip_asc(X509_VERIFY_PARAM *param, const char *ipasc) -{ - unsigned char ipout[16]; - size_t iplen; +int X509_VERIFY_PARAM_set1_ip_asc(X509_VERIFY_PARAM *param, const char *ipasc) { + unsigned char ipout[16]; + size_t iplen; - iplen = (size_t)x509v3_a2i_ipadd(ipout, ipasc); - if (iplen == 0) - return 0; - return X509_VERIFY_PARAM_set1_ip(param, ipout, iplen); + iplen = (size_t)x509v3_a2i_ipadd(ipout, ipasc); + if (iplen == 0) { + return 0; + } + return X509_VERIFY_PARAM_set1_ip(param, ipout, iplen); } -int X509_VERIFY_PARAM_get_depth(const X509_VERIFY_PARAM *param) -{ - return param->depth; +int X509_VERIFY_PARAM_get_depth(const X509_VERIFY_PARAM *param) { + return param->depth; } -const char *X509_VERIFY_PARAM_get0_name(const X509_VERIFY_PARAM *param) -{ - return param->name; +const char *X509_VERIFY_PARAM_get0_name(const X509_VERIFY_PARAM *param) { + return param->name; } #define vpm_empty_id NULL, 0U, NULL, NULL, 0, NULL, 0, 0 @@ -524,8 +517,7 @@ const char *X509_VERIFY_PARAM_get0_name(const X509_VERIFY_PARAM *param) */ static const X509_VERIFY_PARAM default_table[] = { - { - (char *)"default", /* X509 default parameters */ + {(char *)"default", /* X509 default parameters */ 0, /* Check time */ 0, /* internal flags */ X509_V_FLAG_TRUSTED_FIRST, /* flags */ @@ -534,118 +526,113 @@ static const X509_VERIFY_PARAM default_table[] = { 100, /* depth */ NULL, /* policies */ vpm_empty_id}, - { - (char *)"pkcs7", /* S/MIME sign parameters */ - 0, /* Check time */ - 0, /* internal flags */ - 0, /* flags */ - X509_PURPOSE_SMIME_SIGN, /* purpose */ - X509_TRUST_EMAIL, /* trust */ - -1, /* depth */ - NULL, /* policies */ + {(char *)"pkcs7", /* S/MIME sign parameters */ + 0, /* Check time */ + 0, /* internal flags */ + 0, /* flags */ + X509_PURPOSE_SMIME_SIGN, /* purpose */ + X509_TRUST_EMAIL, /* trust */ + -1, /* depth */ + NULL, /* policies */ vpm_empty_id}, - { - (char *)"smime_sign", /* S/MIME sign parameters */ - 0, /* Check time */ - 0, /* internal flags */ - 0, /* flags */ - X509_PURPOSE_SMIME_SIGN, /* purpose */ - X509_TRUST_EMAIL, /* trust */ - -1, /* depth */ - NULL, /* policies */ + {(char *)"smime_sign", /* S/MIME sign parameters */ + 0, /* Check time */ + 0, /* internal flags */ + 0, /* flags */ + X509_PURPOSE_SMIME_SIGN, /* purpose */ + X509_TRUST_EMAIL, /* trust */ + -1, /* depth */ + NULL, /* policies */ vpm_empty_id}, - { - (char *)"ssl_client", /* SSL/TLS client parameters */ - 0, /* Check time */ - 0, /* internal flags */ - 0, /* flags */ - X509_PURPOSE_SSL_CLIENT, /* purpose */ - X509_TRUST_SSL_CLIENT, /* trust */ - -1, /* depth */ - NULL, /* policies */ + {(char *)"ssl_client", /* SSL/TLS client parameters */ + 0, /* Check time */ + 0, /* internal flags */ + 0, /* flags */ + X509_PURPOSE_SSL_CLIENT, /* purpose */ + X509_TRUST_SSL_CLIENT, /* trust */ + -1, /* depth */ + NULL, /* policies */ vpm_empty_id}, - { - (char *)"ssl_server", /* SSL/TLS server parameters */ - 0, /* Check time */ - 0, /* internal flags */ - 0, /* flags */ - X509_PURPOSE_SSL_SERVER, /* purpose */ - X509_TRUST_SSL_SERVER, /* trust */ - -1, /* depth */ - NULL, /* policies */ - vpm_empty_id} -}; + {(char *)"ssl_server", /* SSL/TLS server parameters */ + 0, /* Check time */ + 0, /* internal flags */ + 0, /* flags */ + X509_PURPOSE_SSL_SERVER, /* purpose */ + X509_TRUST_SSL_SERVER, /* trust */ + -1, /* depth */ + NULL, /* policies */ + vpm_empty_id}}; static STACK_OF(X509_VERIFY_PARAM) *param_table = NULL; -static int param_cmp(const X509_VERIFY_PARAM **a, const X509_VERIFY_PARAM **b) -{ - return strcmp((*a)->name, (*b)->name); +static int param_cmp(const X509_VERIFY_PARAM **a, const X509_VERIFY_PARAM **b) { + return strcmp((*a)->name, (*b)->name); } -int X509_VERIFY_PARAM_add0_table(X509_VERIFY_PARAM *param) -{ - X509_VERIFY_PARAM *ptmp; +int X509_VERIFY_PARAM_add0_table(X509_VERIFY_PARAM *param) { + X509_VERIFY_PARAM *ptmp; + if (!param_table) { + param_table = sk_X509_VERIFY_PARAM_new(param_cmp); if (!param_table) { - param_table = sk_X509_VERIFY_PARAM_new(param_cmp); - if (!param_table) - return 0; - } else { - size_t idx; - - sk_X509_VERIFY_PARAM_sort(param_table); - if (sk_X509_VERIFY_PARAM_find(param_table, &idx, param)) { - ptmp = sk_X509_VERIFY_PARAM_value(param_table, idx); - X509_VERIFY_PARAM_free(ptmp); - (void)sk_X509_VERIFY_PARAM_delete(param_table, idx); - } + return 0; } - if (!sk_X509_VERIFY_PARAM_push(param_table, param)) - return 0; - return 1; + } else { + size_t idx; + + sk_X509_VERIFY_PARAM_sort(param_table); + if (sk_X509_VERIFY_PARAM_find(param_table, &idx, param)) { + ptmp = sk_X509_VERIFY_PARAM_value(param_table, idx); + X509_VERIFY_PARAM_free(ptmp); + (void)sk_X509_VERIFY_PARAM_delete(param_table, idx); + } + } + if (!sk_X509_VERIFY_PARAM_push(param_table, param)) { + return 0; + } + return 1; } -int X509_VERIFY_PARAM_get_count(void) -{ - int num = sizeof(default_table) / sizeof(X509_VERIFY_PARAM); - if (param_table) - num += sk_X509_VERIFY_PARAM_num(param_table); - return num; +int X509_VERIFY_PARAM_get_count(void) { + int num = sizeof(default_table) / sizeof(X509_VERIFY_PARAM); + if (param_table) { + num += sk_X509_VERIFY_PARAM_num(param_table); + } + return num; } -const X509_VERIFY_PARAM *X509_VERIFY_PARAM_get0(int id) -{ - int num = sizeof(default_table) / sizeof(X509_VERIFY_PARAM); - if (id < num) - return default_table + id; - return sk_X509_VERIFY_PARAM_value(param_table, id - num); +const X509_VERIFY_PARAM *X509_VERIFY_PARAM_get0(int id) { + int num = sizeof(default_table) / sizeof(X509_VERIFY_PARAM); + if (id < num) { + return default_table + id; + } + return sk_X509_VERIFY_PARAM_value(param_table, id - num); } -const X509_VERIFY_PARAM *X509_VERIFY_PARAM_lookup(const char *name) -{ - X509_VERIFY_PARAM pm; - unsigned i, limit; +const X509_VERIFY_PARAM *X509_VERIFY_PARAM_lookup(const char *name) { + X509_VERIFY_PARAM pm; + unsigned i, limit; - pm.name = (char *)name; - if (param_table) { - size_t idx; - sk_X509_VERIFY_PARAM_sort(param_table); - if (sk_X509_VERIFY_PARAM_find(param_table, &idx, &pm)) - return sk_X509_VERIFY_PARAM_value(param_table, idx); + pm.name = (char *)name; + if (param_table) { + size_t idx; + sk_X509_VERIFY_PARAM_sort(param_table); + if (sk_X509_VERIFY_PARAM_find(param_table, &idx, &pm)) { + return sk_X509_VERIFY_PARAM_value(param_table, idx); } + } - limit = sizeof(default_table) / sizeof(X509_VERIFY_PARAM); - for (i = 0; i < limit; i++) { - if (strcmp(default_table[i].name, name) == 0) { - return &default_table[i]; - } + limit = sizeof(default_table) / sizeof(X509_VERIFY_PARAM); + for (i = 0; i < limit; i++) { + if (strcmp(default_table[i].name, name) == 0) { + return &default_table[i]; } - return NULL; + } + return NULL; } -void X509_VERIFY_PARAM_table_cleanup(void) -{ - if (param_table) - sk_X509_VERIFY_PARAM_pop_free(param_table, X509_VERIFY_PARAM_free); - param_table = NULL; +void X509_VERIFY_PARAM_table_cleanup(void) { + if (param_table) { + sk_X509_VERIFY_PARAM_pop_free(param_table, X509_VERIFY_PARAM_free); + } + param_table = NULL; } diff --git a/crypto/x509/x509cset.c b/crypto/x509/x509cset.c index a51406bcfc..27c7140579 100644 --- a/crypto/x509/x509cset.c +++ b/crypto/x509/x509cset.c @@ -62,231 +62,213 @@ #include "../internal.h" #include "internal.h" -int X509_CRL_set_version(X509_CRL *x, long version) -{ - if (x == NULL) { - return 0; - } - - if (version < X509_CRL_VERSION_1 || version > X509_CRL_VERSION_2) { - OPENSSL_PUT_ERROR(X509, X509_R_INVALID_VERSION); - return 0; - } - - /* v1(0) is default and is represented by omitting the version. */ - if (version == X509_CRL_VERSION_1) { - ASN1_INTEGER_free(x->crl->version); - x->crl->version = NULL; - return 1; - } +int X509_CRL_set_version(X509_CRL *x, long version) { + if (x == NULL) { + return 0; + } + + if (version < X509_CRL_VERSION_1 || version > X509_CRL_VERSION_2) { + OPENSSL_PUT_ERROR(X509, X509_R_INVALID_VERSION); + return 0; + } + + /* v1(0) is default and is represented by omitting the version. */ + if (version == X509_CRL_VERSION_1) { + ASN1_INTEGER_free(x->crl->version); + x->crl->version = NULL; + return 1; + } + if (x->crl->version == NULL) { + x->crl->version = ASN1_INTEGER_new(); if (x->crl->version == NULL) { - x->crl->version = ASN1_INTEGER_new(); - if (x->crl->version == NULL) { - return 0; - } + return 0; } - return ASN1_INTEGER_set(x->crl->version, version); + } + return ASN1_INTEGER_set(x->crl->version, version); } -int X509_CRL_set_issuer_name(X509_CRL *x, X509_NAME *name) -{ - if ((x == NULL) || (x->crl == NULL)) - return (0); - return (X509_NAME_set(&x->crl->issuer, name)); +int X509_CRL_set_issuer_name(X509_CRL *x, X509_NAME *name) { + if ((x == NULL) || (x->crl == NULL)) { + return (0); + } + return (X509_NAME_set(&x->crl->issuer, name)); } -int X509_CRL_set1_lastUpdate(X509_CRL *x, const ASN1_TIME *tm) -{ - ASN1_TIME *in; - - if (x == NULL) - return (0); - in = x->crl->lastUpdate; - if (in != tm) { - in = ASN1_STRING_dup(tm); - if (in != NULL) { - ASN1_TIME_free(x->crl->lastUpdate); - x->crl->lastUpdate = in; - } +int X509_CRL_set1_lastUpdate(X509_CRL *x, const ASN1_TIME *tm) { + ASN1_TIME *in; + + if (x == NULL) { + return (0); + } + in = x->crl->lastUpdate; + if (in != tm) { + in = ASN1_STRING_dup(tm); + if (in != NULL) { + ASN1_TIME_free(x->crl->lastUpdate); + x->crl->lastUpdate = in; } - return (in != NULL); + } + return (in != NULL); } -int X509_CRL_set1_nextUpdate(X509_CRL *x, const ASN1_TIME *tm) -{ - ASN1_TIME *in; - - if (x == NULL) - return (0); - in = x->crl->nextUpdate; - if (in != tm) { - in = ASN1_STRING_dup(tm); - if (in != NULL) { - ASN1_TIME_free(x->crl->nextUpdate); - x->crl->nextUpdate = in; - } +int X509_CRL_set1_nextUpdate(X509_CRL *x, const ASN1_TIME *tm) { + ASN1_TIME *in; + + if (x == NULL) { + return (0); + } + in = x->crl->nextUpdate; + if (in != tm) { + in = ASN1_STRING_dup(tm); + if (in != NULL) { + ASN1_TIME_free(x->crl->nextUpdate); + x->crl->nextUpdate = in; } - return (in != NULL); + } + return (in != NULL); } -int X509_CRL_sort(X509_CRL *c) -{ - /* Sort the data so it will be written in serial number order. */ - sk_X509_REVOKED_sort(c->crl->revoked); - c->crl->enc.modified = 1; - return 1; +int X509_CRL_sort(X509_CRL *c) { + /* Sort the data so it will be written in serial number order. */ + sk_X509_REVOKED_sort(c->crl->revoked); + c->crl->enc.modified = 1; + return 1; } -int X509_CRL_up_ref(X509_CRL *crl) -{ - CRYPTO_refcount_inc(&crl->references); - return 1; +int X509_CRL_up_ref(X509_CRL *crl) { + CRYPTO_refcount_inc(&crl->references); + return 1; } -long X509_CRL_get_version(const X509_CRL *crl) -{ - return ASN1_INTEGER_get(crl->crl->version); +long X509_CRL_get_version(const X509_CRL *crl) { + return ASN1_INTEGER_get(crl->crl->version); } -const ASN1_TIME *X509_CRL_get0_lastUpdate(const X509_CRL *crl) -{ - return crl->crl->lastUpdate; +const ASN1_TIME *X509_CRL_get0_lastUpdate(const X509_CRL *crl) { + return crl->crl->lastUpdate; } -const ASN1_TIME *X509_CRL_get0_nextUpdate(const X509_CRL *crl) -{ - return crl->crl->nextUpdate; +const ASN1_TIME *X509_CRL_get0_nextUpdate(const X509_CRL *crl) { + return crl->crl->nextUpdate; } -ASN1_TIME *X509_CRL_get_lastUpdate(X509_CRL *crl) -{ - return crl->crl->lastUpdate; +ASN1_TIME *X509_CRL_get_lastUpdate(X509_CRL *crl) { + return crl->crl->lastUpdate; } -ASN1_TIME *X509_CRL_get_nextUpdate(X509_CRL *crl) -{ - return crl->crl->nextUpdate; +ASN1_TIME *X509_CRL_get_nextUpdate(X509_CRL *crl) { + return crl->crl->nextUpdate; } -X509_NAME *X509_CRL_get_issuer(const X509_CRL *crl) -{ - return crl->crl->issuer; -} +X509_NAME *X509_CRL_get_issuer(const X509_CRL *crl) { return crl->crl->issuer; } -STACK_OF(X509_REVOKED) *X509_CRL_get_REVOKED(X509_CRL *crl) -{ - return crl->crl->revoked; +STACK_OF(X509_REVOKED) *X509_CRL_get_REVOKED(X509_CRL *crl) { + return crl->crl->revoked; } -const STACK_OF(X509_EXTENSION) *X509_CRL_get0_extensions(const X509_CRL *crl) -{ - return crl->crl->extensions; +const STACK_OF(X509_EXTENSION) *X509_CRL_get0_extensions(const X509_CRL *crl) { + return crl->crl->extensions; } void X509_CRL_get0_signature(const X509_CRL *crl, const ASN1_BIT_STRING **psig, - const X509_ALGOR **palg) -{ - if (psig != NULL) - *psig = crl->signature; - if (palg != NULL) - *palg = crl->sig_alg; + const X509_ALGOR **palg) { + if (psig != NULL) { + *psig = crl->signature; + } + if (palg != NULL) { + *palg = crl->sig_alg; + } } -int X509_CRL_get_signature_nid(const X509_CRL *crl) -{ - return OBJ_obj2nid(crl->sig_alg->algorithm); +int X509_CRL_get_signature_nid(const X509_CRL *crl) { + return OBJ_obj2nid(crl->sig_alg->algorithm); } -const ASN1_TIME *X509_REVOKED_get0_revocationDate(const X509_REVOKED *revoked) -{ - return revoked->revocationDate; +const ASN1_TIME *X509_REVOKED_get0_revocationDate(const X509_REVOKED *revoked) { + return revoked->revocationDate; } -int X509_REVOKED_set_revocationDate(X509_REVOKED *revoked, const ASN1_TIME *tm) -{ - ASN1_TIME *in; - - if (revoked == NULL) - return (0); - in = revoked->revocationDate; - if (in != tm) { - in = ASN1_STRING_dup(tm); - if (in != NULL) { - ASN1_TIME_free(revoked->revocationDate); - revoked->revocationDate = in; - } +int X509_REVOKED_set_revocationDate(X509_REVOKED *revoked, + const ASN1_TIME *tm) { + ASN1_TIME *in; + + if (revoked == NULL) { + return (0); + } + in = revoked->revocationDate; + if (in != tm) { + in = ASN1_STRING_dup(tm); + if (in != NULL) { + ASN1_TIME_free(revoked->revocationDate); + revoked->revocationDate = in; } - return (in != NULL); + } + return (in != NULL); } -const ASN1_INTEGER *X509_REVOKED_get0_serialNumber(const X509_REVOKED *revoked) -{ - return revoked->serialNumber; +const ASN1_INTEGER *X509_REVOKED_get0_serialNumber( + const X509_REVOKED *revoked) { + return revoked->serialNumber; } int X509_REVOKED_set_serialNumber(X509_REVOKED *revoked, - const ASN1_INTEGER *serial) -{ - ASN1_INTEGER *in; - - if (revoked == NULL) - return (0); - in = revoked->serialNumber; - if (in != serial) { - in = ASN1_INTEGER_dup(serial); - if (in != NULL) { - ASN1_INTEGER_free(revoked->serialNumber); - revoked->serialNumber = in; - } + const ASN1_INTEGER *serial) { + ASN1_INTEGER *in; + + if (revoked == NULL) { + return (0); + } + in = revoked->serialNumber; + if (in != serial) { + in = ASN1_INTEGER_dup(serial); + if (in != NULL) { + ASN1_INTEGER_free(revoked->serialNumber); + revoked->serialNumber = in; } - return (in != NULL); + } + return (in != NULL); } -const STACK_OF(X509_EXTENSION) * - X509_REVOKED_get0_extensions(const X509_REVOKED *r) -{ - return r->extensions; +const STACK_OF(X509_EXTENSION) *X509_REVOKED_get0_extensions( + const X509_REVOKED *r) { + return r->extensions; } -int i2d_re_X509_CRL_tbs(X509_CRL *crl, unsigned char **outp) -{ - crl->crl->enc.modified = 1; - return i2d_X509_CRL_INFO(crl->crl, outp); +int i2d_re_X509_CRL_tbs(X509_CRL *crl, unsigned char **outp) { + crl->crl->enc.modified = 1; + return i2d_X509_CRL_INFO(crl->crl, outp); } -int i2d_X509_CRL_tbs(X509_CRL *crl, unsigned char **outp) -{ - return i2d_X509_CRL_INFO(crl->crl, outp); +int i2d_X509_CRL_tbs(X509_CRL *crl, unsigned char **outp) { + return i2d_X509_CRL_INFO(crl->crl, outp); } -int X509_CRL_set1_signature_algo(X509_CRL *crl, const X509_ALGOR *algo) -{ - /* TODO(https://crbug.com/boringssl/407): Generated ASN.1 dup functions - * should be const. Alternatively, when we can embed required fields - * directly in structs, import |X509_ALGOR_copy| from upstream. */ - X509_ALGOR *copy1 = X509_ALGOR_dup((X509_ALGOR *)algo); - X509_ALGOR *copy2 = X509_ALGOR_dup((X509_ALGOR *)algo); - if (copy1 == NULL || copy2 == NULL) { - X509_ALGOR_free(copy1); - X509_ALGOR_free(copy2); - return 0; - } - - X509_ALGOR_free(crl->sig_alg); - crl->sig_alg = copy1; - X509_ALGOR_free(crl->crl->sig_alg); - crl->crl->sig_alg = copy2; - return 1; +int X509_CRL_set1_signature_algo(X509_CRL *crl, const X509_ALGOR *algo) { + /* TODO(https://crbug.com/boringssl/407): Generated ASN.1 dup functions + * should be const. Alternatively, when we can embed required fields + * directly in structs, import |X509_ALGOR_copy| from upstream. */ + X509_ALGOR *copy1 = X509_ALGOR_dup((X509_ALGOR *)algo); + X509_ALGOR *copy2 = X509_ALGOR_dup((X509_ALGOR *)algo); + if (copy1 == NULL || copy2 == NULL) { + X509_ALGOR_free(copy1); + X509_ALGOR_free(copy2); + return 0; + } + + X509_ALGOR_free(crl->sig_alg); + crl->sig_alg = copy1; + X509_ALGOR_free(crl->crl->sig_alg); + crl->crl->sig_alg = copy2; + return 1; } int X509_CRL_set1_signature_value(X509_CRL *crl, const uint8_t *sig, - size_t sig_len) -{ - if (!ASN1_STRING_set(crl->signature, sig, sig_len)) { - return 0; - } - crl->signature->flags &= ~(ASN1_STRING_FLAG_BITS_LEFT | 0x07); - crl->signature->flags |= ASN1_STRING_FLAG_BITS_LEFT; - return 1; + size_t sig_len) { + if (!ASN1_STRING_set(crl->signature, sig, sig_len)) { + return 0; + } + crl->signature->flags &= ~(ASN1_STRING_FLAG_BITS_LEFT | 0x07); + crl->signature->flags |= ASN1_STRING_FLAG_BITS_LEFT; + return 1; } diff --git a/crypto/x509/x509name.c b/crypto/x509/x509name.c index 6bc09521fb..d3aa6de372 100644 --- a/crypto/x509/x509name.c +++ b/crypto/x509/x509name.c @@ -68,156 +68,163 @@ int X509_NAME_get_text_by_NID(const X509_NAME *name, int nid, char *buf, - int len) -{ - const ASN1_OBJECT *obj; - - obj = OBJ_nid2obj(nid); - if (obj == NULL) - return (-1); - return (X509_NAME_get_text_by_OBJ(name, obj, buf, len)); + int len) { + const ASN1_OBJECT *obj; + + obj = OBJ_nid2obj(nid); + if (obj == NULL) { + return (-1); + } + return (X509_NAME_get_text_by_OBJ(name, obj, buf, len)); } int X509_NAME_get_text_by_OBJ(const X509_NAME *name, const ASN1_OBJECT *obj, - char *buf, int len) -{ - int i; - ASN1_STRING *data; - - i = X509_NAME_get_index_by_OBJ(name, obj, -1); - if (i < 0) - return (-1); - data = X509_NAME_ENTRY_get_data(X509_NAME_get_entry(name, i)); - i = (data->length > (len - 1)) ? (len - 1) : data->length; - if (buf == NULL) - return (data->length); - OPENSSL_memcpy(buf, data->data, i); - buf[i] = '\0'; - return (i); + char *buf, int len) { + int i; + ASN1_STRING *data; + + i = X509_NAME_get_index_by_OBJ(name, obj, -1); + if (i < 0) { + return (-1); + } + data = X509_NAME_ENTRY_get_data(X509_NAME_get_entry(name, i)); + i = (data->length > (len - 1)) ? (len - 1) : data->length; + if (buf == NULL) { + return (data->length); + } + OPENSSL_memcpy(buf, data->data, i); + buf[i] = '\0'; + return (i); } -int X509_NAME_entry_count(const X509_NAME *name) -{ - if (name == NULL) - return (0); - return (sk_X509_NAME_ENTRY_num(name->entries)); +int X509_NAME_entry_count(const X509_NAME *name) { + if (name == NULL) { + return (0); + } + return (sk_X509_NAME_ENTRY_num(name->entries)); } -int X509_NAME_get_index_by_NID(const X509_NAME *name, int nid, int lastpos) -{ - const ASN1_OBJECT *obj; +int X509_NAME_get_index_by_NID(const X509_NAME *name, int nid, int lastpos) { + const ASN1_OBJECT *obj; - obj = OBJ_nid2obj(nid); - if (obj == NULL) - return (-2); - return (X509_NAME_get_index_by_OBJ(name, obj, lastpos)); + obj = OBJ_nid2obj(nid); + if (obj == NULL) { + return (-2); + } + return (X509_NAME_get_index_by_OBJ(name, obj, lastpos)); } /* NOTE: you should be passsing -1, not 0 as lastpos */ int X509_NAME_get_index_by_OBJ(const X509_NAME *name, const ASN1_OBJECT *obj, - int lastpos) -{ - int n; - X509_NAME_ENTRY *ne; - STACK_OF(X509_NAME_ENTRY) *sk; - - if (name == NULL) - return (-1); - if (lastpos < 0) - lastpos = -1; - sk = name->entries; - n = sk_X509_NAME_ENTRY_num(sk); - for (lastpos++; lastpos < n; lastpos++) { - ne = sk_X509_NAME_ENTRY_value(sk, lastpos); - if (OBJ_cmp(ne->object, obj) == 0) - return (lastpos); - } + int lastpos) { + int n; + X509_NAME_ENTRY *ne; + STACK_OF(X509_NAME_ENTRY) *sk; + + if (name == NULL) { return (-1); + } + if (lastpos < 0) { + lastpos = -1; + } + sk = name->entries; + n = sk_X509_NAME_ENTRY_num(sk); + for (lastpos++; lastpos < n; lastpos++) { + ne = sk_X509_NAME_ENTRY_value(sk, lastpos); + if (OBJ_cmp(ne->object, obj) == 0) { + return (lastpos); + } + } + return (-1); } -X509_NAME_ENTRY *X509_NAME_get_entry(const X509_NAME *name, int loc) -{ - if (name == NULL || loc < 0 - || sk_X509_NAME_ENTRY_num(name->entries) <= (size_t)loc) - return (NULL); - else - return (sk_X509_NAME_ENTRY_value(name->entries, loc)); +X509_NAME_ENTRY *X509_NAME_get_entry(const X509_NAME *name, int loc) { + if (name == NULL || loc < 0 || + sk_X509_NAME_ENTRY_num(name->entries) <= (size_t)loc) { + return (NULL); + } else { + return (sk_X509_NAME_ENTRY_value(name->entries, loc)); + } } -X509_NAME_ENTRY *X509_NAME_delete_entry(X509_NAME *name, int loc) -{ - X509_NAME_ENTRY *ret; - int i, n, set_prev, set_next; - STACK_OF(X509_NAME_ENTRY) *sk; - - if (name == NULL || loc < 0 - || sk_X509_NAME_ENTRY_num(name->entries) <= (size_t)loc) - return (NULL); - sk = name->entries; - ret = sk_X509_NAME_ENTRY_delete(sk, loc); - n = sk_X509_NAME_ENTRY_num(sk); - name->modified = 1; - if (loc == n) - return (ret); - - /* else we need to fixup the set field */ - if (loc != 0) - set_prev = (sk_X509_NAME_ENTRY_value(sk, loc - 1))->set; - else - set_prev = ret->set - 1; - set_next = sk_X509_NAME_ENTRY_value(sk, loc)->set; - - /* - * set_prev is the previous set set is the current set set_next is the - * following prev 1 1 1 1 1 1 1 1 set 1 1 2 2 next 1 1 2 2 2 2 3 2 so - * basically only if prev and next differ by 2, then re-number down by 1 - */ - if (set_prev + 1 < set_next) - for (i = loc; i < n; i++) - sk_X509_NAME_ENTRY_value(sk, i)->set--; +X509_NAME_ENTRY *X509_NAME_delete_entry(X509_NAME *name, int loc) { + X509_NAME_ENTRY *ret; + int i, n, set_prev, set_next; + STACK_OF(X509_NAME_ENTRY) *sk; + + if (name == NULL || loc < 0 || + sk_X509_NAME_ENTRY_num(name->entries) <= (size_t)loc) { + return (NULL); + } + sk = name->entries; + ret = sk_X509_NAME_ENTRY_delete(sk, loc); + n = sk_X509_NAME_ENTRY_num(sk); + name->modified = 1; + if (loc == n) { return (ret); + } + + /* else we need to fixup the set field */ + if (loc != 0) { + set_prev = (sk_X509_NAME_ENTRY_value(sk, loc - 1))->set; + } else { + set_prev = ret->set - 1; + } + set_next = sk_X509_NAME_ENTRY_value(sk, loc)->set; + + /* + * set_prev is the previous set set is the current set set_next is the + * following prev 1 1 1 1 1 1 1 1 set 1 1 2 2 next 1 1 2 2 2 2 3 2 so + * basically only if prev and next differ by 2, then re-number down by 1 + */ + if (set_prev + 1 < set_next) { + for (i = loc; i < n; i++) { + sk_X509_NAME_ENTRY_value(sk, i)->set--; + } + } + return (ret); } int X509_NAME_add_entry_by_OBJ(X509_NAME *name, ASN1_OBJECT *obj, int type, const unsigned char *bytes, int len, int loc, - int set) -{ - X509_NAME_ENTRY *ne; - int ret; - ne = X509_NAME_ENTRY_create_by_OBJ(NULL, obj, type, bytes, len); - if (!ne) - return 0; - ret = X509_NAME_add_entry(name, ne, loc, set); - X509_NAME_ENTRY_free(ne); - return ret; + int set) { + X509_NAME_ENTRY *ne; + int ret; + ne = X509_NAME_ENTRY_create_by_OBJ(NULL, obj, type, bytes, len); + if (!ne) { + return 0; + } + ret = X509_NAME_add_entry(name, ne, loc, set); + X509_NAME_ENTRY_free(ne); + return ret; } int X509_NAME_add_entry_by_NID(X509_NAME *name, int nid, int type, const unsigned char *bytes, int len, int loc, - int set) -{ - X509_NAME_ENTRY *ne; - int ret; - ne = X509_NAME_ENTRY_create_by_NID(NULL, nid, type, bytes, len); - if (!ne) - return 0; - ret = X509_NAME_add_entry(name, ne, loc, set); - X509_NAME_ENTRY_free(ne); - return ret; + int set) { + X509_NAME_ENTRY *ne; + int ret; + ne = X509_NAME_ENTRY_create_by_NID(NULL, nid, type, bytes, len); + if (!ne) { + return 0; + } + ret = X509_NAME_add_entry(name, ne, loc, set); + X509_NAME_ENTRY_free(ne); + return ret; } int X509_NAME_add_entry_by_txt(X509_NAME *name, const char *field, int type, const unsigned char *bytes, int len, int loc, - int set) -{ - X509_NAME_ENTRY *ne; - int ret; - ne = X509_NAME_ENTRY_create_by_txt(NULL, field, type, bytes, len); - if (!ne) - return 0; - ret = X509_NAME_add_entry(name, ne, loc, set); - X509_NAME_ENTRY_free(ne); - return ret; + int set) { + X509_NAME_ENTRY *ne; + int ret; + ne = X509_NAME_ENTRY_create_by_txt(NULL, field, type, bytes, len); + if (!ne) { + return 0; + } + ret = X509_NAME_add_entry(name, ne, loc, set); + X509_NAME_ENTRY_free(ne); + return ret; } /* @@ -225,164 +232,175 @@ int X509_NAME_add_entry_by_txt(X509_NAME *name, const char *field, int type, * guy we are about to stomp on. */ int X509_NAME_add_entry(X509_NAME *name, X509_NAME_ENTRY *ne, int loc, - int set) -{ - X509_NAME_ENTRY *new_name = NULL; - int n, i, inc; - STACK_OF(X509_NAME_ENTRY) *sk; - - if (name == NULL) - return (0); - sk = name->entries; - n = sk_X509_NAME_ENTRY_num(sk); - if (loc > n) - loc = n; - else if (loc < 0) - loc = n; - - inc = (set == 0); - name->modified = 1; - - if (set == -1) { - if (loc == 0) { - set = 0; - inc = 1; - } else { - set = sk_X509_NAME_ENTRY_value(sk, loc - 1)->set; - } - } else { /* if (set >= 0) */ - - if (loc >= n) { - if (loc != 0) - set = sk_X509_NAME_ENTRY_value(sk, loc - 1)->set + 1; - else - set = 0; - } else - set = sk_X509_NAME_ENTRY_value(sk, loc)->set; - } + int set) { + X509_NAME_ENTRY *new_name = NULL; + int n, i, inc; + STACK_OF(X509_NAME_ENTRY) *sk; - if ((new_name = X509_NAME_ENTRY_dup(ne)) == NULL) - goto err; - new_name->set = set; - if (!sk_X509_NAME_ENTRY_insert(sk, new_name, loc)) { - OPENSSL_PUT_ERROR(X509, ERR_R_MALLOC_FAILURE); - goto err; + if (name == NULL) { + return (0); + } + sk = name->entries; + n = sk_X509_NAME_ENTRY_num(sk); + if (loc > n) { + loc = n; + } else if (loc < 0) { + loc = n; + } + + inc = (set == 0); + name->modified = 1; + + if (set == -1) { + if (loc == 0) { + set = 0; + inc = 1; + } else { + set = sk_X509_NAME_ENTRY_value(sk, loc - 1)->set; } - if (inc) { - n = sk_X509_NAME_ENTRY_num(sk); - for (i = loc + 1; i < n; i++) - sk_X509_NAME_ENTRY_value(sk, i)->set += 1; + } else { /* if (set >= 0) */ + + if (loc >= n) { + if (loc != 0) { + set = sk_X509_NAME_ENTRY_value(sk, loc - 1)->set + 1; + } else { + set = 0; + } + } else { + set = sk_X509_NAME_ENTRY_value(sk, loc)->set; } - return (1); - err: - if (new_name != NULL) - X509_NAME_ENTRY_free(new_name); - return (0); + } + + if ((new_name = X509_NAME_ENTRY_dup(ne)) == NULL) { + goto err; + } + new_name->set = set; + if (!sk_X509_NAME_ENTRY_insert(sk, new_name, loc)) { + OPENSSL_PUT_ERROR(X509, ERR_R_MALLOC_FAILURE); + goto err; + } + if (inc) { + n = sk_X509_NAME_ENTRY_num(sk); + for (i = loc + 1; i < n; i++) { + sk_X509_NAME_ENTRY_value(sk, i)->set += 1; + } + } + return (1); +err: + if (new_name != NULL) { + X509_NAME_ENTRY_free(new_name); + } + return (0); } X509_NAME_ENTRY *X509_NAME_ENTRY_create_by_txt(X509_NAME_ENTRY **ne, const char *field, int type, const unsigned char *bytes, - int len) -{ - ASN1_OBJECT *obj; - X509_NAME_ENTRY *nentry; - - obj = OBJ_txt2obj(field, 0); - if (obj == NULL) { - OPENSSL_PUT_ERROR(X509, X509_R_INVALID_FIELD_NAME); - ERR_add_error_data(2, "name=", field); - return (NULL); - } - nentry = X509_NAME_ENTRY_create_by_OBJ(ne, obj, type, bytes, len); - ASN1_OBJECT_free(obj); - return nentry; + int len) { + ASN1_OBJECT *obj; + X509_NAME_ENTRY *nentry; + + obj = OBJ_txt2obj(field, 0); + if (obj == NULL) { + OPENSSL_PUT_ERROR(X509, X509_R_INVALID_FIELD_NAME); + ERR_add_error_data(2, "name=", field); + return (NULL); + } + nentry = X509_NAME_ENTRY_create_by_OBJ(ne, obj, type, bytes, len); + ASN1_OBJECT_free(obj); + return nentry; } X509_NAME_ENTRY *X509_NAME_ENTRY_create_by_NID(X509_NAME_ENTRY **ne, int nid, int type, const unsigned char *bytes, - int len) -{ - const ASN1_OBJECT *obj = OBJ_nid2obj(nid); - if (obj == NULL) { - OPENSSL_PUT_ERROR(X509, X509_R_UNKNOWN_NID); - return NULL; - } - return X509_NAME_ENTRY_create_by_OBJ(ne, obj, type, bytes, len); + int len) { + const ASN1_OBJECT *obj = OBJ_nid2obj(nid); + if (obj == NULL) { + OPENSSL_PUT_ERROR(X509, X509_R_UNKNOWN_NID); + return NULL; + } + return X509_NAME_ENTRY_create_by_OBJ(ne, obj, type, bytes, len); } X509_NAME_ENTRY *X509_NAME_ENTRY_create_by_OBJ(X509_NAME_ENTRY **ne, - const ASN1_OBJECT *obj, - int type, + const ASN1_OBJECT *obj, int type, const unsigned char *bytes, - int len) -{ - X509_NAME_ENTRY *ret; - - if ((ne == NULL) || (*ne == NULL)) { - if ((ret = X509_NAME_ENTRY_new()) == NULL) - return (NULL); - } else - ret = *ne; - - if (!X509_NAME_ENTRY_set_object(ret, obj)) - goto err; - if (!X509_NAME_ENTRY_set_data(ret, type, bytes, len)) - goto err; - - if ((ne != NULL) && (*ne == NULL)) - *ne = ret; - return (ret); - err: - if ((ne == NULL) || (ret != *ne)) - X509_NAME_ENTRY_free(ret); - return (NULL); -} + int len) { + X509_NAME_ENTRY *ret; -int X509_NAME_ENTRY_set_object(X509_NAME_ENTRY *ne, const ASN1_OBJECT *obj) -{ - if ((ne == NULL) || (obj == NULL)) { - OPENSSL_PUT_ERROR(X509, ERR_R_PASSED_NULL_PARAMETER); - return (0); + if ((ne == NULL) || (*ne == NULL)) { + if ((ret = X509_NAME_ENTRY_new()) == NULL) { + return (NULL); } - ASN1_OBJECT_free(ne->object); - ne->object = OBJ_dup(obj); - return ((ne->object == NULL) ? 0 : 1); + } else { + ret = *ne; + } + + if (!X509_NAME_ENTRY_set_object(ret, obj)) { + goto err; + } + if (!X509_NAME_ENTRY_set_data(ret, type, bytes, len)) { + goto err; + } + + if ((ne != NULL) && (*ne == NULL)) { + *ne = ret; + } + return (ret); +err: + if ((ne == NULL) || (ret != *ne)) { + X509_NAME_ENTRY_free(ret); + } + return (NULL); +} + +int X509_NAME_ENTRY_set_object(X509_NAME_ENTRY *ne, const ASN1_OBJECT *obj) { + if ((ne == NULL) || (obj == NULL)) { + OPENSSL_PUT_ERROR(X509, ERR_R_PASSED_NULL_PARAMETER); + return (0); + } + ASN1_OBJECT_free(ne->object); + ne->object = OBJ_dup(obj); + return ((ne->object == NULL) ? 0 : 1); } int X509_NAME_ENTRY_set_data(X509_NAME_ENTRY *ne, int type, - const unsigned char *bytes, int len) -{ - int i; - - if ((ne == NULL) || ((bytes == NULL) && (len != 0))) - return (0); - if ((type > 0) && (type & MBSTRING_FLAG)) - return ASN1_STRING_set_by_NID(&ne->value, bytes, - len, type, - OBJ_obj2nid(ne->object)) ? 1 : 0; - if (len < 0) - len = strlen((const char *)bytes); - i = ASN1_STRING_set(ne->value, bytes, len); - if (!i) - return (0); - if (type != V_ASN1_UNDEF) { - ne->value->type = type; - } - return (1); + const unsigned char *bytes, int len) { + int i; + + if ((ne == NULL) || ((bytes == NULL) && (len != 0))) { + return (0); + } + if ((type > 0) && (type & MBSTRING_FLAG)) { + return ASN1_STRING_set_by_NID(&ne->value, bytes, len, type, + OBJ_obj2nid(ne->object)) + ? 1 + : 0; + } + if (len < 0) { + len = strlen((const char *)bytes); + } + i = ASN1_STRING_set(ne->value, bytes, len); + if (!i) { + return (0); + } + if (type != V_ASN1_UNDEF) { + ne->value->type = type; + } + return (1); } -ASN1_OBJECT *X509_NAME_ENTRY_get_object(const X509_NAME_ENTRY *ne) -{ - if (ne == NULL) - return (NULL); - return (ne->object); +ASN1_OBJECT *X509_NAME_ENTRY_get_object(const X509_NAME_ENTRY *ne) { + if (ne == NULL) { + return (NULL); + } + return (ne->object); } -ASN1_STRING *X509_NAME_ENTRY_get_data(const X509_NAME_ENTRY *ne) -{ - if (ne == NULL) - return (NULL); - return (ne->value); +ASN1_STRING *X509_NAME_ENTRY_get_data(const X509_NAME_ENTRY *ne) { + if (ne == NULL) { + return (NULL); + } + return (ne->value); } diff --git a/crypto/x509/x509rset.c b/crypto/x509/x509rset.c index 108485c3a6..1d5457f5bb 100644 --- a/crypto/x509/x509rset.c +++ b/crypto/x509/x509rset.c @@ -62,54 +62,51 @@ #include "internal.h" -int X509_REQ_set_version(X509_REQ *x, long version) -{ - if (x == NULL) { - return 0; - } - if (version != X509_REQ_VERSION_1) { - OPENSSL_PUT_ERROR(X509, X509_R_INVALID_VERSION); - return 0; - } - return ASN1_INTEGER_set(x->req_info->version, version); +int X509_REQ_set_version(X509_REQ *x, long version) { + if (x == NULL) { + return 0; + } + if (version != X509_REQ_VERSION_1) { + OPENSSL_PUT_ERROR(X509, X509_R_INVALID_VERSION); + return 0; + } + return ASN1_INTEGER_set(x->req_info->version, version); } -int X509_REQ_set_subject_name(X509_REQ *x, X509_NAME *name) -{ - if ((x == NULL) || (x->req_info == NULL)) - return (0); - return (X509_NAME_set(&x->req_info->subject, name)); +int X509_REQ_set_subject_name(X509_REQ *x, X509_NAME *name) { + if ((x == NULL) || (x->req_info == NULL)) { + return (0); + } + return (X509_NAME_set(&x->req_info->subject, name)); } -int X509_REQ_set_pubkey(X509_REQ *x, EVP_PKEY *pkey) -{ - if ((x == NULL) || (x->req_info == NULL)) - return (0); - return (X509_PUBKEY_set(&x->req_info->pubkey, pkey)); +int X509_REQ_set_pubkey(X509_REQ *x, EVP_PKEY *pkey) { + if ((x == NULL) || (x->req_info == NULL)) { + return (0); + } + return (X509_PUBKEY_set(&x->req_info->pubkey, pkey)); } -int X509_REQ_set1_signature_algo(X509_REQ *req, const X509_ALGOR *algo) -{ - /* TODO(https://crbug.com/boringssl/407): Generated ASN.1 dup functions - * should be const. Alternatively, when we can embed required fields - * directly in structs, import |X509_ALGOR_copy| from upstream. */ - X509_ALGOR *copy = X509_ALGOR_dup((X509_ALGOR *)algo); - if (copy == NULL) { - return 0; - } +int X509_REQ_set1_signature_algo(X509_REQ *req, const X509_ALGOR *algo) { + /* TODO(https://crbug.com/boringssl/407): Generated ASN.1 dup functions + * should be const. Alternatively, when we can embed required fields + * directly in structs, import |X509_ALGOR_copy| from upstream. */ + X509_ALGOR *copy = X509_ALGOR_dup((X509_ALGOR *)algo); + if (copy == NULL) { + return 0; + } - X509_ALGOR_free(req->sig_alg); - req->sig_alg = copy; - return 1; + X509_ALGOR_free(req->sig_alg); + req->sig_alg = copy; + return 1; } int X509_REQ_set1_signature_value(X509_REQ *req, const uint8_t *sig, - size_t sig_len) -{ - if (!ASN1_STRING_set(req->signature, sig, sig_len)) { - return 0; - } - req->signature->flags &= ~(ASN1_STRING_FLAG_BITS_LEFT | 0x07); - req->signature->flags |= ASN1_STRING_FLAG_BITS_LEFT; - return 1; + size_t sig_len) { + if (!ASN1_STRING_set(req->signature, sig, sig_len)) { + return 0; + } + req->signature->flags &= ~(ASN1_STRING_FLAG_BITS_LEFT | 0x07); + req->signature->flags |= ASN1_STRING_FLAG_BITS_LEFT; + return 1; } diff --git a/crypto/x509/x509spki.c b/crypto/x509/x509spki.c index 4a9b95e769..88ab9cdaca 100644 --- a/crypto/x509/x509spki.c +++ b/crypto/x509/x509spki.c @@ -61,77 +61,76 @@ #include #include -int NETSCAPE_SPKI_set_pubkey(NETSCAPE_SPKI *x, EVP_PKEY *pkey) -{ - if ((x == NULL) || (x->spkac == NULL)) - return (0); - return (X509_PUBKEY_set(&(x->spkac->pubkey), pkey)); +int NETSCAPE_SPKI_set_pubkey(NETSCAPE_SPKI *x, EVP_PKEY *pkey) { + if ((x == NULL) || (x->spkac == NULL)) { + return (0); + } + return (X509_PUBKEY_set(&(x->spkac->pubkey), pkey)); } -EVP_PKEY *NETSCAPE_SPKI_get_pubkey(NETSCAPE_SPKI *x) -{ - if ((x == NULL) || (x->spkac == NULL)) - return (NULL); - return (X509_PUBKEY_get(x->spkac->pubkey)); +EVP_PKEY *NETSCAPE_SPKI_get_pubkey(NETSCAPE_SPKI *x) { + if ((x == NULL) || (x->spkac == NULL)) { + return (NULL); + } + return (X509_PUBKEY_get(x->spkac->pubkey)); } /* Load a Netscape SPKI from a base64 encoded string */ -NETSCAPE_SPKI *NETSCAPE_SPKI_b64_decode(const char *str, int len) -{ - unsigned char *spki_der; - const unsigned char *p; - size_t spki_len; - NETSCAPE_SPKI *spki; - if (len <= 0) - len = strlen(str); - if (!EVP_DecodedLength(&spki_len, len)) { - OPENSSL_PUT_ERROR(X509, X509_R_BASE64_DECODE_ERROR); - return NULL; - } - if (!(spki_der = OPENSSL_malloc(spki_len))) { - OPENSSL_PUT_ERROR(X509, ERR_R_MALLOC_FAILURE); - return NULL; - } - if (!EVP_DecodeBase64 - (spki_der, &spki_len, spki_len, (const uint8_t *)str, len)) { - OPENSSL_PUT_ERROR(X509, X509_R_BASE64_DECODE_ERROR); - OPENSSL_free(spki_der); - return NULL; - } - p = spki_der; - spki = d2i_NETSCAPE_SPKI(NULL, &p, spki_len); +NETSCAPE_SPKI *NETSCAPE_SPKI_b64_decode(const char *str, int len) { + unsigned char *spki_der; + const unsigned char *p; + size_t spki_len; + NETSCAPE_SPKI *spki; + if (len <= 0) { + len = strlen(str); + } + if (!EVP_DecodedLength(&spki_len, len)) { + OPENSSL_PUT_ERROR(X509, X509_R_BASE64_DECODE_ERROR); + return NULL; + } + if (!(spki_der = OPENSSL_malloc(spki_len))) { + OPENSSL_PUT_ERROR(X509, ERR_R_MALLOC_FAILURE); + return NULL; + } + if (!EVP_DecodeBase64(spki_der, &spki_len, spki_len, (const uint8_t *)str, + len)) { + OPENSSL_PUT_ERROR(X509, X509_R_BASE64_DECODE_ERROR); OPENSSL_free(spki_der); - return spki; + return NULL; + } + p = spki_der; + spki = d2i_NETSCAPE_SPKI(NULL, &p, spki_len); + OPENSSL_free(spki_der); + return spki; } /* Generate a base64 encoded string from an SPKI */ -char *NETSCAPE_SPKI_b64_encode(NETSCAPE_SPKI *spki) -{ - unsigned char *der_spki, *p; - char *b64_str; - size_t b64_len; - int der_len; - der_len = i2d_NETSCAPE_SPKI(spki, NULL); - if (!EVP_EncodedLength(&b64_len, der_len)) { - OPENSSL_PUT_ERROR(X509, ERR_R_OVERFLOW); - return NULL; - } - der_spki = OPENSSL_malloc(der_len); - if (der_spki == NULL) { - OPENSSL_PUT_ERROR(X509, ERR_R_MALLOC_FAILURE); - return NULL; - } - b64_str = OPENSSL_malloc(b64_len); - if (b64_str == NULL) { - OPENSSL_free(der_spki); - OPENSSL_PUT_ERROR(X509, ERR_R_MALLOC_FAILURE); - return NULL; - } - p = der_spki; - i2d_NETSCAPE_SPKI(spki, &p); - EVP_EncodeBlock((unsigned char *)b64_str, der_spki, der_len); +char *NETSCAPE_SPKI_b64_encode(NETSCAPE_SPKI *spki) { + unsigned char *der_spki, *p; + char *b64_str; + size_t b64_len; + int der_len; + der_len = i2d_NETSCAPE_SPKI(spki, NULL); + if (!EVP_EncodedLength(&b64_len, der_len)) { + OPENSSL_PUT_ERROR(X509, ERR_R_OVERFLOW); + return NULL; + } + der_spki = OPENSSL_malloc(der_len); + if (der_spki == NULL) { + OPENSSL_PUT_ERROR(X509, ERR_R_MALLOC_FAILURE); + return NULL; + } + b64_str = OPENSSL_malloc(b64_len); + if (b64_str == NULL) { OPENSSL_free(der_spki); - return b64_str; + OPENSSL_PUT_ERROR(X509, ERR_R_MALLOC_FAILURE); + return NULL; + } + p = der_spki; + i2d_NETSCAPE_SPKI(spki, &p); + EVP_EncodeBlock((unsigned char *)b64_str, der_spki, der_len); + OPENSSL_free(der_spki); + return b64_str; } diff --git a/crypto/x509/x_algor.c b/crypto/x509/x_algor.c index 3f49c6581a..8285fb3128 100644 --- a/crypto/x509/x_algor.c +++ b/crypto/x509/x_algor.c @@ -65,89 +65,93 @@ ASN1_SEQUENCE(X509_ALGOR) = { - ASN1_SIMPLE(X509_ALGOR, algorithm, ASN1_OBJECT), - ASN1_OPT(X509_ALGOR, parameter, ASN1_ANY), + ASN1_SIMPLE(X509_ALGOR, algorithm, ASN1_OBJECT), + ASN1_OPT(X509_ALGOR, parameter, ASN1_ANY), } ASN1_SEQUENCE_END(X509_ALGOR) -ASN1_ITEM_TEMPLATE(X509_ALGORS) = - ASN1_EX_TEMPLATE_TYPE(ASN1_TFLG_SEQUENCE_OF, 0, algorithms, X509_ALGOR) +ASN1_ITEM_TEMPLATE(X509_ALGORS) = ASN1_EX_TEMPLATE_TYPE(ASN1_TFLG_SEQUENCE_OF, + 0, algorithms, + X509_ALGOR) ASN1_ITEM_TEMPLATE_END(X509_ALGORS) IMPLEMENT_ASN1_FUNCTIONS(X509_ALGOR) IMPLEMENT_ASN1_ENCODE_FUNCTIONS_fname(X509_ALGORS, X509_ALGORS, X509_ALGORS) IMPLEMENT_ASN1_DUP_FUNCTION(X509_ALGOR) -int X509_ALGOR_set0(X509_ALGOR *alg, ASN1_OBJECT *aobj, int ptype, void *pval) -{ - if (!alg) - return 0; - if (ptype != V_ASN1_UNDEF) { - if (alg->parameter == NULL) - alg->parameter = ASN1_TYPE_new(); - if (alg->parameter == NULL) - return 0; +int X509_ALGOR_set0(X509_ALGOR *alg, ASN1_OBJECT *aobj, int ptype, void *pval) { + if (!alg) { + return 0; + } + if (ptype != V_ASN1_UNDEF) { + if (alg->parameter == NULL) { + alg->parameter = ASN1_TYPE_new(); } - if (alg) { - ASN1_OBJECT_free(alg->algorithm); - alg->algorithm = aobj; + if (alg->parameter == NULL) { + return 0; } - if (ptype == 0) - return 1; - if (ptype == V_ASN1_UNDEF) { - if (alg->parameter) { - ASN1_TYPE_free(alg->parameter); - alg->parameter = NULL; - } - } else - ASN1_TYPE_set(alg->parameter, ptype, pval); + } + if (alg) { + ASN1_OBJECT_free(alg->algorithm); + alg->algorithm = aobj; + } + if (ptype == 0) { return 1; + } + if (ptype == V_ASN1_UNDEF) { + if (alg->parameter) { + ASN1_TYPE_free(alg->parameter); + alg->parameter = NULL; + } + } else { + ASN1_TYPE_set(alg->parameter, ptype, pval); + } + return 1; } void X509_ALGOR_get0(const ASN1_OBJECT **out_obj, int *out_param_type, - const void **out_param_value, const X509_ALGOR *alg) -{ - if (out_obj != NULL) { - *out_obj = alg->algorithm; + const void **out_param_value, const X509_ALGOR *alg) { + if (out_obj != NULL) { + *out_obj = alg->algorithm; + } + if (out_param_type != NULL) { + int type = V_ASN1_UNDEF; + const void *value = NULL; + if (alg->parameter != NULL) { + type = alg->parameter->type; + value = asn1_type_value_as_pointer(alg->parameter); } - if (out_param_type != NULL) { - int type = V_ASN1_UNDEF; - const void *value = NULL; - if (alg->parameter != NULL) { - type = alg->parameter->type; - value = asn1_type_value_as_pointer(alg->parameter); - } - *out_param_type = type; - if (out_param_value != NULL) { - *out_param_value = value; - } + *out_param_type = type; + if (out_param_value != NULL) { + *out_param_value = value; } + } } /* Set up an X509_ALGOR DigestAlgorithmIdentifier from an EVP_MD */ -void X509_ALGOR_set_md(X509_ALGOR *alg, const EVP_MD *md) -{ - int param_type; - - if (EVP_MD_flags(md) & EVP_MD_FLAG_DIGALGID_ABSENT) - param_type = V_ASN1_UNDEF; - else - param_type = V_ASN1_NULL; +void X509_ALGOR_set_md(X509_ALGOR *alg, const EVP_MD *md) { + int param_type; - X509_ALGOR_set0(alg, OBJ_nid2obj(EVP_MD_type(md)), param_type, NULL); + if (EVP_MD_flags(md) & EVP_MD_FLAG_DIGALGID_ABSENT) { + param_type = V_ASN1_UNDEF; + } else { + param_type = V_ASN1_NULL; + } + X509_ALGOR_set0(alg, OBJ_nid2obj(EVP_MD_type(md)), param_type, NULL); } /* * X509_ALGOR_cmp returns 0 if |a| and |b| are equal and non-zero otherwise. */ -int X509_ALGOR_cmp(const X509_ALGOR *a, const X509_ALGOR *b) -{ - int rv; - rv = OBJ_cmp(a->algorithm, b->algorithm); - if (rv) - return rv; - if (!a->parameter && !b->parameter) - return 0; - return ASN1_TYPE_cmp(a->parameter, b->parameter); +int X509_ALGOR_cmp(const X509_ALGOR *a, const X509_ALGOR *b) { + int rv; + rv = OBJ_cmp(a->algorithm, b->algorithm); + if (rv) { + return rv; + } + if (!a->parameter && !b->parameter) { + return 0; + } + return ASN1_TYPE_cmp(a->parameter, b->parameter); } diff --git a/crypto/x509/x_all.c b/crypto/x509/x_all.c index 7ceff504ab..ad92df1524 100644 --- a/crypto/x509/x_all.c +++ b/crypto/x509/x_all.c @@ -69,135 +69,110 @@ #include "internal.h" -int X509_verify(X509 *x509, EVP_PKEY *pkey) -{ - if (X509_ALGOR_cmp(x509->sig_alg, x509->cert_info->signature)) { - OPENSSL_PUT_ERROR(X509, X509_R_SIGNATURE_ALGORITHM_MISMATCH); - return 0; - } - return ASN1_item_verify(ASN1_ITEM_rptr(X509_CINF), x509->sig_alg, - x509->signature, x509->cert_info, pkey); +int X509_verify(X509 *x509, EVP_PKEY *pkey) { + if (X509_ALGOR_cmp(x509->sig_alg, x509->cert_info->signature)) { + OPENSSL_PUT_ERROR(X509, X509_R_SIGNATURE_ALGORITHM_MISMATCH); + return 0; + } + return ASN1_item_verify(ASN1_ITEM_rptr(X509_CINF), x509->sig_alg, + x509->signature, x509->cert_info, pkey); } -int X509_REQ_verify(X509_REQ *req, EVP_PKEY *pkey) -{ - return ASN1_item_verify(ASN1_ITEM_rptr(X509_REQ_INFO), - req->sig_alg, req->signature, req->req_info, pkey); +int X509_REQ_verify(X509_REQ *req, EVP_PKEY *pkey) { + return ASN1_item_verify(ASN1_ITEM_rptr(X509_REQ_INFO), req->sig_alg, + req->signature, req->req_info, pkey); } -int X509_sign(X509 *x, EVP_PKEY *pkey, const EVP_MD *md) -{ - x->cert_info->enc.modified = 1; - return (ASN1_item_sign(ASN1_ITEM_rptr(X509_CINF), x->cert_info->signature, - x->sig_alg, x->signature, x->cert_info, pkey, md)); +int X509_sign(X509 *x, EVP_PKEY *pkey, const EVP_MD *md) { + x->cert_info->enc.modified = 1; + return (ASN1_item_sign(ASN1_ITEM_rptr(X509_CINF), x->cert_info->signature, + x->sig_alg, x->signature, x->cert_info, pkey, md)); } -int X509_sign_ctx(X509 *x, EVP_MD_CTX *ctx) -{ - x->cert_info->enc.modified = 1; - return ASN1_item_sign_ctx(ASN1_ITEM_rptr(X509_CINF), - x->cert_info->signature, - x->sig_alg, x->signature, x->cert_info, ctx); +int X509_sign_ctx(X509 *x, EVP_MD_CTX *ctx) { + x->cert_info->enc.modified = 1; + return ASN1_item_sign_ctx(ASN1_ITEM_rptr(X509_CINF), x->cert_info->signature, + x->sig_alg, x->signature, x->cert_info, ctx); } -int X509_REQ_sign(X509_REQ *x, EVP_PKEY *pkey, const EVP_MD *md) -{ - return (ASN1_item_sign(ASN1_ITEM_rptr(X509_REQ_INFO), x->sig_alg, NULL, - x->signature, x->req_info, pkey, md)); +int X509_REQ_sign(X509_REQ *x, EVP_PKEY *pkey, const EVP_MD *md) { + return (ASN1_item_sign(ASN1_ITEM_rptr(X509_REQ_INFO), x->sig_alg, NULL, + x->signature, x->req_info, pkey, md)); } -int X509_REQ_sign_ctx(X509_REQ *x, EVP_MD_CTX *ctx) -{ - return ASN1_item_sign_ctx(ASN1_ITEM_rptr(X509_REQ_INFO), - x->sig_alg, NULL, x->signature, x->req_info, - ctx); +int X509_REQ_sign_ctx(X509_REQ *x, EVP_MD_CTX *ctx) { + return ASN1_item_sign_ctx(ASN1_ITEM_rptr(X509_REQ_INFO), x->sig_alg, NULL, + x->signature, x->req_info, ctx); } -int X509_CRL_sign(X509_CRL *x, EVP_PKEY *pkey, const EVP_MD *md) -{ - x->crl->enc.modified = 1; - return (ASN1_item_sign(ASN1_ITEM_rptr(X509_CRL_INFO), x->crl->sig_alg, - x->sig_alg, x->signature, x->crl, pkey, md)); +int X509_CRL_sign(X509_CRL *x, EVP_PKEY *pkey, const EVP_MD *md) { + x->crl->enc.modified = 1; + return (ASN1_item_sign(ASN1_ITEM_rptr(X509_CRL_INFO), x->crl->sig_alg, + x->sig_alg, x->signature, x->crl, pkey, md)); } -int X509_CRL_sign_ctx(X509_CRL *x, EVP_MD_CTX *ctx) -{ - x->crl->enc.modified = 1; - return ASN1_item_sign_ctx(ASN1_ITEM_rptr(X509_CRL_INFO), - x->crl->sig_alg, x->sig_alg, x->signature, - x->crl, ctx); +int X509_CRL_sign_ctx(X509_CRL *x, EVP_MD_CTX *ctx) { + x->crl->enc.modified = 1; + return ASN1_item_sign_ctx(ASN1_ITEM_rptr(X509_CRL_INFO), x->crl->sig_alg, + x->sig_alg, x->signature, x->crl, ctx); } -int NETSCAPE_SPKI_sign(NETSCAPE_SPKI *x, EVP_PKEY *pkey, const EVP_MD *md) -{ - return (ASN1_item_sign(ASN1_ITEM_rptr(NETSCAPE_SPKAC), x->sig_algor, NULL, - x->signature, x->spkac, pkey, md)); +int NETSCAPE_SPKI_sign(NETSCAPE_SPKI *x, EVP_PKEY *pkey, const EVP_MD *md) { + return (ASN1_item_sign(ASN1_ITEM_rptr(NETSCAPE_SPKAC), x->sig_algor, NULL, + x->signature, x->spkac, pkey, md)); } -int NETSCAPE_SPKI_verify(NETSCAPE_SPKI *spki, EVP_PKEY *pkey) -{ - return (ASN1_item_verify(ASN1_ITEM_rptr(NETSCAPE_SPKAC), spki->sig_algor, - spki->signature, spki->spkac, pkey)); +int NETSCAPE_SPKI_verify(NETSCAPE_SPKI *spki, EVP_PKEY *pkey) { + return (ASN1_item_verify(ASN1_ITEM_rptr(NETSCAPE_SPKAC), spki->sig_algor, + spki->signature, spki->spkac, pkey)); } -X509 *d2i_X509_fp(FILE *fp, X509 **x509) -{ - return ASN1_item_d2i_fp(ASN1_ITEM_rptr(X509), fp, x509); +X509 *d2i_X509_fp(FILE *fp, X509 **x509) { + return ASN1_item_d2i_fp(ASN1_ITEM_rptr(X509), fp, x509); } -int i2d_X509_fp(FILE *fp, X509 *x509) -{ - return ASN1_item_i2d_fp(ASN1_ITEM_rptr(X509), fp, x509); +int i2d_X509_fp(FILE *fp, X509 *x509) { + return ASN1_item_i2d_fp(ASN1_ITEM_rptr(X509), fp, x509); } -X509 *d2i_X509_bio(BIO *bp, X509 **x509) -{ - return ASN1_item_d2i_bio(ASN1_ITEM_rptr(X509), bp, x509); +X509 *d2i_X509_bio(BIO *bp, X509 **x509) { + return ASN1_item_d2i_bio(ASN1_ITEM_rptr(X509), bp, x509); } -int i2d_X509_bio(BIO *bp, X509 *x509) -{ - return ASN1_item_i2d_bio(ASN1_ITEM_rptr(X509), bp, x509); +int i2d_X509_bio(BIO *bp, X509 *x509) { + return ASN1_item_i2d_bio(ASN1_ITEM_rptr(X509), bp, x509); } -X509_CRL *d2i_X509_CRL_fp(FILE *fp, X509_CRL **crl) -{ - return ASN1_item_d2i_fp(ASN1_ITEM_rptr(X509_CRL), fp, crl); +X509_CRL *d2i_X509_CRL_fp(FILE *fp, X509_CRL **crl) { + return ASN1_item_d2i_fp(ASN1_ITEM_rptr(X509_CRL), fp, crl); } -int i2d_X509_CRL_fp(FILE *fp, X509_CRL *crl) -{ - return ASN1_item_i2d_fp(ASN1_ITEM_rptr(X509_CRL), fp, crl); +int i2d_X509_CRL_fp(FILE *fp, X509_CRL *crl) { + return ASN1_item_i2d_fp(ASN1_ITEM_rptr(X509_CRL), fp, crl); } -X509_CRL *d2i_X509_CRL_bio(BIO *bp, X509_CRL **crl) -{ - return ASN1_item_d2i_bio(ASN1_ITEM_rptr(X509_CRL), bp, crl); +X509_CRL *d2i_X509_CRL_bio(BIO *bp, X509_CRL **crl) { + return ASN1_item_d2i_bio(ASN1_ITEM_rptr(X509_CRL), bp, crl); } -int i2d_X509_CRL_bio(BIO *bp, X509_CRL *crl) -{ - return ASN1_item_i2d_bio(ASN1_ITEM_rptr(X509_CRL), bp, crl); +int i2d_X509_CRL_bio(BIO *bp, X509_CRL *crl) { + return ASN1_item_i2d_bio(ASN1_ITEM_rptr(X509_CRL), bp, crl); } -X509_REQ *d2i_X509_REQ_fp(FILE *fp, X509_REQ **req) -{ - return ASN1_item_d2i_fp(ASN1_ITEM_rptr(X509_REQ), fp, req); +X509_REQ *d2i_X509_REQ_fp(FILE *fp, X509_REQ **req) { + return ASN1_item_d2i_fp(ASN1_ITEM_rptr(X509_REQ), fp, req); } -int i2d_X509_REQ_fp(FILE *fp, X509_REQ *req) -{ - return ASN1_item_i2d_fp(ASN1_ITEM_rptr(X509_REQ), fp, req); +int i2d_X509_REQ_fp(FILE *fp, X509_REQ *req) { + return ASN1_item_i2d_fp(ASN1_ITEM_rptr(X509_REQ), fp, req); } -X509_REQ *d2i_X509_REQ_bio(BIO *bp, X509_REQ **req) -{ - return ASN1_item_d2i_bio(ASN1_ITEM_rptr(X509_REQ), bp, req); +X509_REQ *d2i_X509_REQ_bio(BIO *bp, X509_REQ **req) { + return ASN1_item_d2i_bio(ASN1_ITEM_rptr(X509_REQ), bp, req); } -int i2d_X509_REQ_bio(BIO *bp, X509_REQ *req) -{ - return ASN1_item_i2d_bio(ASN1_ITEM_rptr(X509_REQ), bp, req); +int i2d_X509_REQ_bio(BIO *bp, X509_REQ *req) { + return ASN1_item_i2d_bio(ASN1_ITEM_rptr(X509_REQ), bp, req); } @@ -292,42 +267,37 @@ IMPLEMENT_I2D_BIO(EC_KEY, i2d_ECPrivateKey_bio, i2d_ECPrivateKey) IMPLEMENT_D2I_BIO(EC_KEY, d2i_EC_PUBKEY_bio, d2i_EC_PUBKEY) IMPLEMENT_I2D_BIO(EC_KEY, i2d_EC_PUBKEY_bio, i2d_EC_PUBKEY) -int X509_pubkey_digest(const X509 *data, const EVP_MD *type, - unsigned char *md, unsigned int *len) -{ - ASN1_BIT_STRING *key; - key = X509_get0_pubkey_bitstr(data); - if (!key) - return 0; - return EVP_Digest(key->data, key->length, md, len, type, NULL); +int X509_pubkey_digest(const X509 *data, const EVP_MD *type, unsigned char *md, + unsigned int *len) { + ASN1_BIT_STRING *key; + key = X509_get0_pubkey_bitstr(data); + if (!key) { + return 0; + } + return EVP_Digest(key->data, key->length, md, len, type, NULL); } int X509_digest(const X509 *data, const EVP_MD *type, unsigned char *md, - unsigned int *len) -{ - return (ASN1_item_digest - (ASN1_ITEM_rptr(X509), type, (char *)data, md, len)); + unsigned int *len) { + return (ASN1_item_digest(ASN1_ITEM_rptr(X509), type, (char *)data, md, len)); } -int X509_CRL_digest(const X509_CRL *data, const EVP_MD *type, - unsigned char *md, unsigned int *len) -{ - return (ASN1_item_digest - (ASN1_ITEM_rptr(X509_CRL), type, (char *)data, md, len)); +int X509_CRL_digest(const X509_CRL *data, const EVP_MD *type, unsigned char *md, + unsigned int *len) { + return ( + ASN1_item_digest(ASN1_ITEM_rptr(X509_CRL), type, (char *)data, md, len)); } -int X509_REQ_digest(const X509_REQ *data, const EVP_MD *type, - unsigned char *md, unsigned int *len) -{ - return (ASN1_item_digest - (ASN1_ITEM_rptr(X509_REQ), type, (char *)data, md, len)); +int X509_REQ_digest(const X509_REQ *data, const EVP_MD *type, unsigned char *md, + unsigned int *len) { + return ( + ASN1_item_digest(ASN1_ITEM_rptr(X509_REQ), type, (char *)data, md, len)); } int X509_NAME_digest(const X509_NAME *data, const EVP_MD *type, - unsigned char *md, unsigned int *len) -{ - return (ASN1_item_digest - (ASN1_ITEM_rptr(X509_NAME), type, (char *)data, md, len)); + unsigned char *md, unsigned int *len) { + return ( + ASN1_item_digest(ASN1_ITEM_rptr(X509_NAME), type, (char *)data, md, len)); } IMPLEMENT_D2I_FP(X509_SIG, d2i_PKCS8_fp, d2i_PKCS8_bio) @@ -341,16 +311,16 @@ IMPLEMENT_D2I_FP(PKCS8_PRIV_KEY_INFO, d2i_PKCS8_PRIV_KEY_INFO_fp, IMPLEMENT_I2D_FP(PKCS8_PRIV_KEY_INFO, i2d_PKCS8_PRIV_KEY_INFO_fp, i2d_PKCS8_PRIV_KEY_INFO_bio) -int i2d_PKCS8PrivateKeyInfo_fp(FILE *fp, EVP_PKEY *key) -{ - PKCS8_PRIV_KEY_INFO *p8inf; - int ret; - p8inf = EVP_PKEY2PKCS8(key); - if (!p8inf) - return 0; - ret = i2d_PKCS8_PRIV_KEY_INFO_fp(fp, p8inf); - PKCS8_PRIV_KEY_INFO_free(p8inf); - return ret; +int i2d_PKCS8PrivateKeyInfo_fp(FILE *fp, EVP_PKEY *key) { + PKCS8_PRIV_KEY_INFO *p8inf; + int ret; + p8inf = EVP_PKEY2PKCS8(key); + if (!p8inf) { + return 0; + } + ret = i2d_PKCS8_PRIV_KEY_INFO_fp(fp, p8inf); + PKCS8_PRIV_KEY_INFO_free(p8inf); + return ret; } IMPLEMENT_D2I_FP(EVP_PKEY, d2i_PrivateKey_fp, d2i_PrivateKey_bio) @@ -364,16 +334,16 @@ IMPLEMENT_D2I_BIO(PKCS8_PRIV_KEY_INFO, d2i_PKCS8_PRIV_KEY_INFO_bio, IMPLEMENT_I2D_BIO(PKCS8_PRIV_KEY_INFO, i2d_PKCS8_PRIV_KEY_INFO_bio, i2d_PKCS8_PRIV_KEY_INFO) -int i2d_PKCS8PrivateKeyInfo_bio(BIO *bp, EVP_PKEY *key) -{ - PKCS8_PRIV_KEY_INFO *p8inf; - int ret; - p8inf = EVP_PKEY2PKCS8(key); - if (!p8inf) - return 0; - ret = i2d_PKCS8_PRIV_KEY_INFO_bio(bp, p8inf); - PKCS8_PRIV_KEY_INFO_free(p8inf); - return ret; +int i2d_PKCS8PrivateKeyInfo_bio(BIO *bp, EVP_PKEY *key) { + PKCS8_PRIV_KEY_INFO *p8inf; + int ret; + p8inf = EVP_PKEY2PKCS8(key); + if (!p8inf) { + return 0; + } + ret = i2d_PKCS8_PRIV_KEY_INFO_bio(bp, p8inf); + PKCS8_PRIV_KEY_INFO_free(p8inf); + return ret; } IMPLEMENT_D2I_BIO(EVP_PKEY, d2i_PrivateKey_bio, d2i_AutoPrivateKey) diff --git a/crypto/x509/x_attrib.c b/crypto/x509/x_attrib.c index 91b3ee8f3b..a434bc29f1 100644 --- a/crypto/x509/x_attrib.c +++ b/crypto/x509/x_attrib.c @@ -56,43 +56,42 @@ #include #include -#include #include +#include #include "internal.h" ASN1_SEQUENCE(X509_ATTRIBUTE) = { - ASN1_SIMPLE(X509_ATTRIBUTE, object, ASN1_OBJECT), - ASN1_SET_OF(X509_ATTRIBUTE, set, ASN1_ANY), + ASN1_SIMPLE(X509_ATTRIBUTE, object, ASN1_OBJECT), + ASN1_SET_OF(X509_ATTRIBUTE, set, ASN1_ANY), } ASN1_SEQUENCE_END(X509_ATTRIBUTE) IMPLEMENT_ASN1_FUNCTIONS(X509_ATTRIBUTE) IMPLEMENT_ASN1_DUP_FUNCTION(X509_ATTRIBUTE) -X509_ATTRIBUTE *X509_ATTRIBUTE_create(int nid, int attrtype, void *value) -{ - ASN1_OBJECT *obj = OBJ_nid2obj(nid); - if (obj == NULL) { - return NULL; - } +X509_ATTRIBUTE *X509_ATTRIBUTE_create(int nid, int attrtype, void *value) { + ASN1_OBJECT *obj = OBJ_nid2obj(nid); + if (obj == NULL) { + return NULL; + } - X509_ATTRIBUTE *ret = X509_ATTRIBUTE_new(); - ASN1_TYPE *val = ASN1_TYPE_new(); - if (ret == NULL || val == NULL) { - goto err; - } + X509_ATTRIBUTE *ret = X509_ATTRIBUTE_new(); + ASN1_TYPE *val = ASN1_TYPE_new(); + if (ret == NULL || val == NULL) { + goto err; + } - ret->object = obj; - if (!sk_ASN1_TYPE_push(ret->set, val)) { - goto err; - } + ret->object = obj; + if (!sk_ASN1_TYPE_push(ret->set, val)) { + goto err; + } - ASN1_TYPE_set(val, attrtype, value); - return ret; + ASN1_TYPE_set(val, attrtype, value); + return ret; - err: - X509_ATTRIBUTE_free(ret); - ASN1_TYPE_free(val); - return NULL; +err: + X509_ATTRIBUTE_free(ret); + ASN1_TYPE_free(val); + return NULL; } diff --git a/crypto/x509/x_crl.c b/crypto/x509/x_crl.c index 6a902c98a3..7b237970b5 100644 --- a/crypto/x509/x_crl.c +++ b/crypto/x509/x_crl.c @@ -72,9 +72,9 @@ static int X509_REVOKED_cmp(const X509_REVOKED **a, const X509_REVOKED **b); static int setup_idp(X509_CRL *crl, ISSUING_DIST_POINT *idp); ASN1_SEQUENCE(X509_REVOKED) = { - ASN1_SIMPLE(X509_REVOKED,serialNumber, ASN1_INTEGER), - ASN1_SIMPLE(X509_REVOKED,revocationDate, ASN1_TIME), - ASN1_SEQUENCE_OF_OPT(X509_REVOKED,extensions, X509_EXTENSION), + ASN1_SIMPLE(X509_REVOKED, serialNumber, ASN1_INTEGER), + ASN1_SIMPLE(X509_REVOKED, revocationDate, ASN1_TIME), + ASN1_SEQUENCE_OF_OPT(X509_REVOKED, extensions, X509_EXTENSION), } ASN1_SEQUENCE_END(X509_REVOKED) static int crl_lookup(X509_CRL *crl, X509_REVOKED **ret, ASN1_INTEGER *serial, @@ -86,33 +86,33 @@ static int crl_lookup(X509_CRL *crl, X509_REVOKED **ret, ASN1_INTEGER *serial, * revoked field. */ static int crl_inf_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it, - void *exarg) -{ - X509_CRL_INFO *a = (X509_CRL_INFO *)*pval; - - if (!a || !a->revoked) - return 1; - switch (operation) { - /* - * Just set cmp function here. We don't sort because that would - * affect the output of X509_CRL_print(). - */ - case ASN1_OP_D2I_POST: - (void)sk_X509_REVOKED_set_cmp_func(a->revoked, X509_REVOKED_cmp); - break; - } + void *exarg) { + X509_CRL_INFO *a = (X509_CRL_INFO *)*pval; + + if (!a || !a->revoked) { return 1; + } + switch (operation) { + /* + * Just set cmp function here. We don't sort because that would + * affect the output of X509_CRL_print(). + */ + case ASN1_OP_D2I_POST: + (void)sk_X509_REVOKED_set_cmp_func(a->revoked, X509_REVOKED_cmp); + break; + } + return 1; } ASN1_SEQUENCE_enc(X509_CRL_INFO, enc, crl_inf_cb) = { - ASN1_OPT(X509_CRL_INFO, version, ASN1_INTEGER), - ASN1_SIMPLE(X509_CRL_INFO, sig_alg, X509_ALGOR), - ASN1_SIMPLE(X509_CRL_INFO, issuer, X509_NAME), - ASN1_SIMPLE(X509_CRL_INFO, lastUpdate, ASN1_TIME), - ASN1_OPT(X509_CRL_INFO, nextUpdate, ASN1_TIME), - ASN1_SEQUENCE_OF_OPT(X509_CRL_INFO, revoked, X509_REVOKED), - ASN1_EXP_SEQUENCE_OF_OPT(X509_CRL_INFO, extensions, X509_EXTENSION, 0), + ASN1_OPT(X509_CRL_INFO, version, ASN1_INTEGER), + ASN1_SIMPLE(X509_CRL_INFO, sig_alg, X509_ALGOR), + ASN1_SIMPLE(X509_CRL_INFO, issuer, X509_NAME), + ASN1_SIMPLE(X509_CRL_INFO, lastUpdate, ASN1_TIME), + ASN1_OPT(X509_CRL_INFO, nextUpdate, ASN1_TIME), + ASN1_SEQUENCE_OF_OPT(X509_CRL_INFO, revoked, X509_REVOKED), + ASN1_EXP_SEQUENCE_OF_OPT(X509_CRL_INFO, extensions, X509_EXTENSION, 0), } ASN1_SEQUENCE_END_enc(X509_CRL_INFO, X509_CRL_INFO) /* @@ -120,72 +120,71 @@ ASN1_SEQUENCE_enc(X509_CRL_INFO, enc, crl_inf_cb) = { * for unhandled critical CRL entry extensions. */ -static int crl_set_issuers(X509_CRL *crl) -{ - - size_t i, k; - int j; - GENERAL_NAMES *gens, *gtmp; - STACK_OF(X509_REVOKED) *revoked; - - revoked = X509_CRL_get_REVOKED(crl); - - gens = NULL; - for (i = 0; i < sk_X509_REVOKED_num(revoked); i++) { - X509_REVOKED *rev = sk_X509_REVOKED_value(revoked, i); - STACK_OF(X509_EXTENSION) *exts; - ASN1_ENUMERATED *reason; - X509_EXTENSION *ext; - gtmp = X509_REVOKED_get_ext_d2i(rev, - NID_certificate_issuer, &j, NULL); - if (!gtmp && (j != -1)) { - crl->flags |= EXFLAG_INVALID; - return 1; - } +static int crl_set_issuers(X509_CRL *crl) { + size_t i, k; + int j; + GENERAL_NAMES *gens, *gtmp; + STACK_OF(X509_REVOKED) *revoked; - if (gtmp) { - gens = gtmp; - if (!crl->issuers) { - crl->issuers = sk_GENERAL_NAMES_new_null(); - if (!crl->issuers) - return 0; - } - if (!sk_GENERAL_NAMES_push(crl->issuers, gtmp)) - return 0; - } - rev->issuer = gens; + revoked = X509_CRL_get_REVOKED(crl); - reason = X509_REVOKED_get_ext_d2i(rev, NID_crl_reason, &j, NULL); - if (!reason && (j != -1)) { - crl->flags |= EXFLAG_INVALID; - return 1; - } + gens = NULL; + for (i = 0; i < sk_X509_REVOKED_num(revoked); i++) { + X509_REVOKED *rev = sk_X509_REVOKED_value(revoked, i); + STACK_OF(X509_EXTENSION) *exts; + ASN1_ENUMERATED *reason; + X509_EXTENSION *ext; + gtmp = X509_REVOKED_get_ext_d2i(rev, NID_certificate_issuer, &j, NULL); + if (!gtmp && (j != -1)) { + crl->flags |= EXFLAG_INVALID; + return 1; + } - if (reason) { - rev->reason = ASN1_ENUMERATED_get(reason); - ASN1_ENUMERATED_free(reason); - } else - rev->reason = CRL_REASON_NONE; - - /* Check for critical CRL entry extensions */ - - exts = rev->extensions; - - for (k = 0; k < sk_X509_EXTENSION_num(exts); k++) { - ext = sk_X509_EXTENSION_value(exts, k); - if (X509_EXTENSION_get_critical(ext)) { - if (OBJ_obj2nid(X509_EXTENSION_get_object(ext)) == - NID_certificate_issuer) - continue; - crl->flags |= EXFLAG_CRITICAL; - break; - } + if (gtmp) { + gens = gtmp; + if (!crl->issuers) { + crl->issuers = sk_GENERAL_NAMES_new_null(); + if (!crl->issuers) { + return 0; } + } + if (!sk_GENERAL_NAMES_push(crl->issuers, gtmp)) { + return 0; + } + } + rev->issuer = gens; + reason = X509_REVOKED_get_ext_d2i(rev, NID_crl_reason, &j, NULL); + if (!reason && (j != -1)) { + crl->flags |= EXFLAG_INVALID; + return 1; } - return 1; + if (reason) { + rev->reason = ASN1_ENUMERATED_get(reason); + ASN1_ENUMERATED_free(reason); + } else { + rev->reason = CRL_REASON_NONE; + } + + /* Check for critical CRL entry extensions */ + exts = rev->extensions; + + for (k = 0; k < sk_X509_EXTENSION_num(exts); k++) { + ext = sk_X509_EXTENSION_value(exts, k); + if (X509_EXTENSION_get_critical(ext)) { + if (OBJ_obj2nid(X509_EXTENSION_get_object(ext)) == + NID_certificate_issuer) { + continue; + } + crl->flags |= EXFLAG_CRITICAL; + break; + } + } + } + + return 1; } /* @@ -193,170 +192,170 @@ static int crl_set_issuers(X509_CRL *crl) * and hash of the whole CRL. */ static int crl_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it, - void *exarg) -{ - X509_CRL *crl = (X509_CRL *)*pval; - STACK_OF(X509_EXTENSION) *exts; - X509_EXTENSION *ext; - size_t idx; - int i; - - switch (operation) { + void *exarg) { + X509_CRL *crl = (X509_CRL *)*pval; + STACK_OF(X509_EXTENSION) *exts; + X509_EXTENSION *ext; + size_t idx; + int i; + + switch (operation) { case ASN1_OP_NEW_POST: - crl->idp = NULL; - crl->akid = NULL; - crl->flags = 0; - crl->idp_flags = 0; - crl->idp_reasons = CRLDP_ALL_REASONS; - crl->issuers = NULL; - crl->crl_number = NULL; - crl->base_crl_number = NULL; - break; + crl->idp = NULL; + crl->akid = NULL; + crl->flags = 0; + crl->idp_flags = 0; + crl->idp_reasons = CRLDP_ALL_REASONS; + crl->issuers = NULL; + crl->crl_number = NULL; + crl->base_crl_number = NULL; + break; case ASN1_OP_D2I_POST: { - /* The version must be one of v1(0) or v2(1). */ - long version = X509_CRL_VERSION_1; - if (crl->crl->version != NULL) { - version = ASN1_INTEGER_get(crl->crl->version); - /* TODO(https://crbug.com/boringssl/364): |X509_CRL_VERSION_1| - * should also be rejected. This means an explicitly-encoded X.509v1 - * version. v1 is DEFAULT, so DER requires it be omitted. */ - if (version < X509_CRL_VERSION_1 || version > X509_CRL_VERSION_2) { - OPENSSL_PUT_ERROR(X509, X509_R_INVALID_VERSION); - return 0; - } + /* The version must be one of v1(0) or v2(1). */ + long version = X509_CRL_VERSION_1; + if (crl->crl->version != NULL) { + version = ASN1_INTEGER_get(crl->crl->version); + /* TODO(https://crbug.com/boringssl/364): |X509_CRL_VERSION_1| + * should also be rejected. This means an explicitly-encoded X.509v1 + * version. v1 is DEFAULT, so DER requires it be omitted. */ + if (version < X509_CRL_VERSION_1 || version > X509_CRL_VERSION_2) { + OPENSSL_PUT_ERROR(X509, X509_R_INVALID_VERSION); + return 0; } + } - /* Per RFC 5280, section 5.1.2.1, extensions require v2. */ - if (version != X509_CRL_VERSION_2 && crl->crl->extensions != NULL) { - OPENSSL_PUT_ERROR(X509, X509_R_INVALID_FIELD_FOR_VERSION); - return 0; - } + /* Per RFC 5280, section 5.1.2.1, extensions require v2. */ + if (version != X509_CRL_VERSION_2 && crl->crl->extensions != NULL) { + OPENSSL_PUT_ERROR(X509, X509_R_INVALID_FIELD_FOR_VERSION); + return 0; + } - if (!X509_CRL_digest(crl, EVP_sha256(), crl->crl_hash, NULL)) { - return 0; - } + if (!X509_CRL_digest(crl, EVP_sha256(), crl->crl_hash, NULL)) { + return 0; + } - crl->idp = X509_CRL_get_ext_d2i(crl, - NID_issuing_distribution_point, &i, - NULL); - if (crl->idp != NULL) { - if (!setup_idp(crl, crl->idp)) { - return 0; - } - } else if (i != -1) { - return 0; + crl->idp = + X509_CRL_get_ext_d2i(crl, NID_issuing_distribution_point, &i, NULL); + if (crl->idp != NULL) { + if (!setup_idp(crl, crl->idp)) { + return 0; } + } else if (i != -1) { + return 0; + } - crl->akid = X509_CRL_get_ext_d2i(crl, - NID_authority_key_identifier, &i, - NULL); - if (crl->akid == NULL && i != -1) { - return 0; - } + crl->akid = + X509_CRL_get_ext_d2i(crl, NID_authority_key_identifier, &i, NULL); + if (crl->akid == NULL && i != -1) { + return 0; + } - crl->crl_number = X509_CRL_get_ext_d2i(crl, - NID_crl_number, &i, NULL); - if (crl->crl_number == NULL && i != -1) { - return 0; - } + crl->crl_number = X509_CRL_get_ext_d2i(crl, NID_crl_number, &i, NULL); + if (crl->crl_number == NULL && i != -1) { + return 0; + } - crl->base_crl_number = X509_CRL_get_ext_d2i(crl, NID_delta_crl, &i, - NULL); - if (crl->base_crl_number == NULL && i != -1) { - return 0; - } - /* Delta CRLs must have CRL number */ - if (crl->base_crl_number && !crl->crl_number) { - OPENSSL_PUT_ERROR(X509, X509_R_DELTA_CRL_WITHOUT_CRL_NUMBER); - return 0; + crl->base_crl_number = X509_CRL_get_ext_d2i(crl, NID_delta_crl, &i, NULL); + if (crl->base_crl_number == NULL && i != -1) { + return 0; + } + /* Delta CRLs must have CRL number */ + if (crl->base_crl_number && !crl->crl_number) { + OPENSSL_PUT_ERROR(X509, X509_R_DELTA_CRL_WITHOUT_CRL_NUMBER); + return 0; + } + + /* + * See if we have any unhandled critical CRL extensions and indicate + * this in a flag. We only currently handle IDP so anything else + * critical sets the flag. This code accesses the X509_CRL structure + * directly: applications shouldn't do this. + */ + + exts = crl->crl->extensions; + + for (idx = 0; idx < sk_X509_EXTENSION_num(exts); idx++) { + int nid; + ext = sk_X509_EXTENSION_value(exts, idx); + nid = OBJ_obj2nid(X509_EXTENSION_get_object(ext)); + if (nid == NID_freshest_crl) { + crl->flags |= EXFLAG_FRESHEST; } - - /* - * See if we have any unhandled critical CRL extensions and indicate - * this in a flag. We only currently handle IDP so anything else - * critical sets the flag. This code accesses the X509_CRL structure - * directly: applications shouldn't do this. - */ - - exts = crl->crl->extensions; - - for (idx = 0; idx < sk_X509_EXTENSION_num(exts); idx++) { - int nid; - ext = sk_X509_EXTENSION_value(exts, idx); - nid = OBJ_obj2nid(X509_EXTENSION_get_object(ext)); - if (nid == NID_freshest_crl) - crl->flags |= EXFLAG_FRESHEST; - if (X509_EXTENSION_get_critical(ext)) { - /* We handle IDP and deltas */ - if ((nid == NID_issuing_distribution_point) - || (nid == NID_authority_key_identifier) - || (nid == NID_delta_crl)) - continue; - crl->flags |= EXFLAG_CRITICAL; - break; - } + if (X509_EXTENSION_get_critical(ext)) { + /* We handle IDP and deltas */ + if ((nid == NID_issuing_distribution_point) || + (nid == NID_authority_key_identifier) || (nid == NID_delta_crl)) { + continue; + } + crl->flags |= EXFLAG_CRITICAL; + break; } + } - if (!crl_set_issuers(crl)) - return 0; + if (!crl_set_issuers(crl)) { + return 0; + } - break; + break; } case ASN1_OP_FREE_POST: - AUTHORITY_KEYID_free(crl->akid); - ISSUING_DIST_POINT_free(crl->idp); - ASN1_INTEGER_free(crl->crl_number); - ASN1_INTEGER_free(crl->base_crl_number); - sk_GENERAL_NAMES_pop_free(crl->issuers, GENERAL_NAMES_free); - break; - } - return 1; + AUTHORITY_KEYID_free(crl->akid); + ISSUING_DIST_POINT_free(crl->idp); + ASN1_INTEGER_free(crl->crl_number); + ASN1_INTEGER_free(crl->base_crl_number); + sk_GENERAL_NAMES_pop_free(crl->issuers, GENERAL_NAMES_free); + break; + } + return 1; } /* Convert IDP into a more convenient form */ -static int setup_idp(X509_CRL *crl, ISSUING_DIST_POINT *idp) -{ - int idp_only = 0; - /* Set various flags according to IDP */ - crl->idp_flags |= IDP_PRESENT; - if (idp->onlyuser > 0) { - idp_only++; - crl->idp_flags |= IDP_ONLYUSER; +static int setup_idp(X509_CRL *crl, ISSUING_DIST_POINT *idp) { + int idp_only = 0; + /* Set various flags according to IDP */ + crl->idp_flags |= IDP_PRESENT; + if (idp->onlyuser > 0) { + idp_only++; + crl->idp_flags |= IDP_ONLYUSER; + } + if (idp->onlyCA > 0) { + idp_only++; + crl->idp_flags |= IDP_ONLYCA; + } + if (idp->onlyattr > 0) { + idp_only++; + crl->idp_flags |= IDP_ONLYATTR; + } + + if (idp_only > 1) { + crl->idp_flags |= IDP_INVALID; + } + + if (idp->indirectCRL > 0) { + crl->idp_flags |= IDP_INDIRECT; + } + + if (idp->onlysomereasons) { + crl->idp_flags |= IDP_REASONS; + if (idp->onlysomereasons->length > 0) { + crl->idp_reasons = idp->onlysomereasons->data[0]; } - if (idp->onlyCA > 0) { - idp_only++; - crl->idp_flags |= IDP_ONLYCA; - } - if (idp->onlyattr > 0) { - idp_only++; - crl->idp_flags |= IDP_ONLYATTR; - } - - if (idp_only > 1) - crl->idp_flags |= IDP_INVALID; - - if (idp->indirectCRL > 0) - crl->idp_flags |= IDP_INDIRECT; - - if (idp->onlysomereasons) { - crl->idp_flags |= IDP_REASONS; - if (idp->onlysomereasons->length > 0) - crl->idp_reasons = idp->onlysomereasons->data[0]; - if (idp->onlysomereasons->length > 1) - crl->idp_reasons |= (idp->onlysomereasons->data[1] << 8); - crl->idp_reasons &= CRLDP_ALL_REASONS; + if (idp->onlysomereasons->length > 1) { + crl->idp_reasons |= (idp->onlysomereasons->data[1] << 8); } + crl->idp_reasons &= CRLDP_ALL_REASONS; + } - return DIST_POINT_set_dpname(idp->distpoint, X509_CRL_get_issuer(crl)); + return DIST_POINT_set_dpname(idp->distpoint, X509_CRL_get_issuer(crl)); } ASN1_SEQUENCE_ref(X509_CRL, crl_cb) = { - ASN1_SIMPLE(X509_CRL, crl, X509_CRL_INFO), - ASN1_SIMPLE(X509_CRL, sig_alg, X509_ALGOR), - ASN1_SIMPLE(X509_CRL, signature, ASN1_BIT_STRING), + ASN1_SIMPLE(X509_CRL, crl, X509_CRL_INFO), + ASN1_SIMPLE(X509_CRL, sig_alg, X509_ALGOR), + ASN1_SIMPLE(X509_CRL, signature, ASN1_BIT_STRING), } ASN1_SEQUENCE_END_ref(X509_CRL, X509_CRL) IMPLEMENT_ASN1_FUNCTIONS(X509_REVOKED) @@ -367,114 +366,116 @@ IMPLEMENT_ASN1_FUNCTIONS(X509_CRL_INFO) IMPLEMENT_ASN1_FUNCTIONS(X509_CRL) IMPLEMENT_ASN1_DUP_FUNCTION(X509_CRL) -static int X509_REVOKED_cmp(const X509_REVOKED **a, const X509_REVOKED **b) -{ - return ASN1_STRING_cmp((*a)->serialNumber, (*b)->serialNumber); +static int X509_REVOKED_cmp(const X509_REVOKED **a, const X509_REVOKED **b) { + return ASN1_STRING_cmp((*a)->serialNumber, (*b)->serialNumber); } -int X509_CRL_add0_revoked(X509_CRL *crl, X509_REVOKED *rev) -{ - X509_CRL_INFO *inf; - inf = crl->crl; - if (!inf->revoked) - inf->revoked = sk_X509_REVOKED_new(X509_REVOKED_cmp); - if (!inf->revoked || !sk_X509_REVOKED_push(inf->revoked, rev)) { - OPENSSL_PUT_ERROR(X509, ERR_R_MALLOC_FAILURE); - return 0; - } - inf->enc.modified = 1; - return 1; +int X509_CRL_add0_revoked(X509_CRL *crl, X509_REVOKED *rev) { + X509_CRL_INFO *inf; + inf = crl->crl; + if (!inf->revoked) { + inf->revoked = sk_X509_REVOKED_new(X509_REVOKED_cmp); + } + if (!inf->revoked || !sk_X509_REVOKED_push(inf->revoked, rev)) { + OPENSSL_PUT_ERROR(X509, ERR_R_MALLOC_FAILURE); + return 0; + } + inf->enc.modified = 1; + return 1; } -int X509_CRL_verify(X509_CRL *crl, EVP_PKEY *pkey) -{ - if (X509_ALGOR_cmp(crl->sig_alg, crl->crl->sig_alg) != 0) { - OPENSSL_PUT_ERROR(X509, X509_R_SIGNATURE_ALGORITHM_MISMATCH); - return 0; - } +int X509_CRL_verify(X509_CRL *crl, EVP_PKEY *pkey) { + if (X509_ALGOR_cmp(crl->sig_alg, crl->crl->sig_alg) != 0) { + OPENSSL_PUT_ERROR(X509, X509_R_SIGNATURE_ALGORITHM_MISMATCH); + return 0; + } - return ASN1_item_verify(ASN1_ITEM_rptr(X509_CRL_INFO), - crl->sig_alg, crl->signature, crl->crl, pkey); + return ASN1_item_verify(ASN1_ITEM_rptr(X509_CRL_INFO), crl->sig_alg, + crl->signature, crl->crl, pkey); } -int X509_CRL_get0_by_serial(X509_CRL *crl, - X509_REVOKED **ret, ASN1_INTEGER *serial) -{ - return crl_lookup(crl, ret, serial, NULL); +int X509_CRL_get0_by_serial(X509_CRL *crl, X509_REVOKED **ret, + ASN1_INTEGER *serial) { + return crl_lookup(crl, ret, serial, NULL); } -int X509_CRL_get0_by_cert(X509_CRL *crl, X509_REVOKED **ret, X509 *x) -{ - return crl_lookup(crl, ret, X509_get_serialNumber(x), - X509_get_issuer_name(x)); +int X509_CRL_get0_by_cert(X509_CRL *crl, X509_REVOKED **ret, X509 *x) { + return crl_lookup(crl, ret, X509_get_serialNumber(x), + X509_get_issuer_name(x)); } static int crl_revoked_issuer_match(X509_CRL *crl, X509_NAME *nm, - X509_REVOKED *rev) -{ - size_t i; - - if (!rev->issuer) { - if (!nm) - return 1; - if (!X509_NAME_cmp(nm, X509_CRL_get_issuer(crl))) - return 1; - return 0; - } + X509_REVOKED *rev) { + size_t i; - if (!nm) - nm = X509_CRL_get_issuer(crl); - - for (i = 0; i < sk_GENERAL_NAME_num(rev->issuer); i++) { - GENERAL_NAME *gen = sk_GENERAL_NAME_value(rev->issuer, i); - if (gen->type != GEN_DIRNAME) - continue; - if (!X509_NAME_cmp(nm, gen->d.directoryName)) - return 1; + if (!rev->issuer) { + if (!nm) { + return 1; + } + if (!X509_NAME_cmp(nm, X509_CRL_get_issuer(crl))) { + return 1; } return 0; + } + + if (!nm) { + nm = X509_CRL_get_issuer(crl); + } + for (i = 0; i < sk_GENERAL_NAME_num(rev->issuer); i++) { + GENERAL_NAME *gen = sk_GENERAL_NAME_value(rev->issuer, i); + if (gen->type != GEN_DIRNAME) { + continue; + } + if (!X509_NAME_cmp(nm, gen->d.directoryName)) { + return 1; + } + } + return 0; } static struct CRYPTO_STATIC_MUTEX g_crl_sort_lock = CRYPTO_STATIC_MUTEX_INIT; static int crl_lookup(X509_CRL *crl, X509_REVOKED **ret, ASN1_INTEGER *serial, - X509_NAME *issuer) -{ - X509_REVOKED rtmp, *rev; - size_t idx; - rtmp.serialNumber = serial; - /* - * Sort revoked into serial number order if not already sorted. Do this - * under a lock to avoid race condition. - */ - - CRYPTO_STATIC_MUTEX_lock_read(&g_crl_sort_lock); - const int is_sorted = sk_X509_REVOKED_is_sorted(crl->crl->revoked); - CRYPTO_STATIC_MUTEX_unlock_read(&g_crl_sort_lock); - - if (!is_sorted) { - CRYPTO_STATIC_MUTEX_lock_write(&g_crl_sort_lock); - if (!sk_X509_REVOKED_is_sorted(crl->crl->revoked)) { - sk_X509_REVOKED_sort(crl->crl->revoked); - } - CRYPTO_STATIC_MUTEX_unlock_write(&g_crl_sort_lock); + X509_NAME *issuer) { + X509_REVOKED rtmp, *rev; + size_t idx; + rtmp.serialNumber = serial; + /* + * Sort revoked into serial number order if not already sorted. Do this + * under a lock to avoid race condition. + */ + + CRYPTO_STATIC_MUTEX_lock_read(&g_crl_sort_lock); + const int is_sorted = sk_X509_REVOKED_is_sorted(crl->crl->revoked); + CRYPTO_STATIC_MUTEX_unlock_read(&g_crl_sort_lock); + + if (!is_sorted) { + CRYPTO_STATIC_MUTEX_lock_write(&g_crl_sort_lock); + if (!sk_X509_REVOKED_is_sorted(crl->crl->revoked)) { + sk_X509_REVOKED_sort(crl->crl->revoked); } + CRYPTO_STATIC_MUTEX_unlock_write(&g_crl_sort_lock); + } - if (!sk_X509_REVOKED_find(crl->crl->revoked, &idx, &rtmp)) - return 0; - /* Need to look for matching name */ - for (; idx < sk_X509_REVOKED_num(crl->crl->revoked); idx++) { - rev = sk_X509_REVOKED_value(crl->crl->revoked, idx); - if (ASN1_INTEGER_cmp(rev->serialNumber, serial)) - return 0; - if (crl_revoked_issuer_match(crl, issuer, rev)) { - if (ret) - *ret = rev; - if (rev->reason == CRL_REASON_REMOVE_FROM_CRL) - return 2; - return 1; - } - } + if (!sk_X509_REVOKED_find(crl->crl->revoked, &idx, &rtmp)) { return 0; + } + /* Need to look for matching name */ + for (; idx < sk_X509_REVOKED_num(crl->crl->revoked); idx++) { + rev = sk_X509_REVOKED_value(crl->crl->revoked, idx); + if (ASN1_INTEGER_cmp(rev->serialNumber, serial)) { + return 0; + } + if (crl_revoked_issuer_match(crl, issuer, rev)) { + if (ret) { + *ret = rev; + } + if (rev->reason == CRL_REASON_REMOVE_FROM_CRL) { + return 2; + } + return 1; + } + } + return 0; } diff --git a/crypto/x509/x_exten.c b/crypto/x509/x_exten.c index 7e336fb612..53d2b711f6 100644 --- a/crypto/x509/x_exten.c +++ b/crypto/x509/x_exten.c @@ -63,15 +63,16 @@ ASN1_SEQUENCE(X509_EXTENSION) = { - ASN1_SIMPLE(X509_EXTENSION, object, ASN1_OBJECT), - ASN1_OPT(X509_EXTENSION, critical, ASN1_BOOLEAN), - ASN1_SIMPLE(X509_EXTENSION, value, ASN1_OCTET_STRING), + ASN1_SIMPLE(X509_EXTENSION, object, ASN1_OBJECT), + ASN1_OPT(X509_EXTENSION, critical, ASN1_BOOLEAN), + ASN1_SIMPLE(X509_EXTENSION, value, ASN1_OCTET_STRING), } ASN1_SEQUENCE_END(X509_EXTENSION) ASN1_ITEM_TEMPLATE(X509_EXTENSIONS) = - ASN1_EX_TEMPLATE_TYPE(ASN1_TFLG_SEQUENCE_OF, 0, Extension, X509_EXTENSION) + ASN1_EX_TEMPLATE_TYPE(ASN1_TFLG_SEQUENCE_OF, 0, Extension, X509_EXTENSION) ASN1_ITEM_TEMPLATE_END(X509_EXTENSIONS) IMPLEMENT_ASN1_FUNCTIONS(X509_EXTENSION) -IMPLEMENT_ASN1_ENCODE_FUNCTIONS_fname(X509_EXTENSIONS, X509_EXTENSIONS, X509_EXTENSIONS) +IMPLEMENT_ASN1_ENCODE_FUNCTIONS_fname(X509_EXTENSIONS, X509_EXTENSIONS, + X509_EXTENSIONS) IMPLEMENT_ASN1_DUP_FUNCTION(X509_EXTENSION) diff --git a/crypto/x509/x_info.c b/crypto/x509/x_info.c index 177cd0eb58..420bc19b42 100644 --- a/crypto/x509/x_info.c +++ b/crypto/x509/x_info.c @@ -61,38 +61,41 @@ #include #include -X509_INFO *X509_INFO_new(void) -{ - X509_INFO *ret = NULL; +X509_INFO *X509_INFO_new(void) { + X509_INFO *ret = NULL; - ret = (X509_INFO *)OPENSSL_malloc(sizeof(X509_INFO)); - if (ret == NULL) { - OPENSSL_PUT_ERROR(X509, ERR_R_MALLOC_FAILURE); - return (NULL); - } + ret = (X509_INFO *)OPENSSL_malloc(sizeof(X509_INFO)); + if (ret == NULL) { + OPENSSL_PUT_ERROR(X509, ERR_R_MALLOC_FAILURE); + return (NULL); + } - ret->enc_cipher.cipher = NULL; - ret->enc_len = 0; - ret->enc_data = NULL; + ret->enc_cipher.cipher = NULL; + ret->enc_len = 0; + ret->enc_data = NULL; - ret->x509 = NULL; - ret->crl = NULL; - ret->x_pkey = NULL; - return (ret); + ret->x509 = NULL; + ret->crl = NULL; + ret->x_pkey = NULL; + return (ret); } -void X509_INFO_free(X509_INFO *x) -{ - if (x == NULL) - return; +void X509_INFO_free(X509_INFO *x) { + if (x == NULL) { + return; + } - if (x->x509 != NULL) - X509_free(x->x509); - if (x->crl != NULL) - X509_CRL_free(x->crl); - if (x->x_pkey != NULL) - X509_PKEY_free(x->x_pkey); - if (x->enc_data != NULL) - OPENSSL_free(x->enc_data); - OPENSSL_free(x); + if (x->x509 != NULL) { + X509_free(x->x509); + } + if (x->crl != NULL) { + X509_CRL_free(x->crl); + } + if (x->x_pkey != NULL) { + X509_PKEY_free(x->x_pkey); + } + if (x->enc_data != NULL) { + OPENSSL_free(x->enc_data); + } + OPENSSL_free(x); } diff --git a/crypto/x509/x_name.c b/crypto/x509/x_name.c index d90ca3f5cc..58c1083a5e 100644 --- a/crypto/x509/x_name.c +++ b/crypto/x509/x_name.c @@ -81,10 +81,9 @@ DEFINE_STACK_OF(STACK_OF_X509_NAME_ENTRY) #define X509_NAME_MAX (1024 * 1024) -static int x509_name_ex_d2i(ASN1_VALUE **val, - const unsigned char **in, long len, - const ASN1_ITEM *it, - int tag, int aclass, char opt, ASN1_TLC *ctx); +static int x509_name_ex_d2i(ASN1_VALUE **val, const unsigned char **in, + long len, const ASN1_ITEM *it, int tag, int aclass, + char opt, ASN1_TLC *ctx); static int x509_name_ex_i2d(ASN1_VALUE **val, unsigned char **out, const ASN1_ITEM *it, int tag, int aclass); @@ -94,12 +93,12 @@ static void x509_name_ex_free(ASN1_VALUE **val, const ASN1_ITEM *it); static int x509_name_encode(X509_NAME *a); static int x509_name_canon(X509_NAME *a); static int asn1_string_canon(ASN1_STRING *out, ASN1_STRING *in); -static int i2d_name_canon(STACK_OF(STACK_OF_X509_NAME_ENTRY) * intname, +static int i2d_name_canon(STACK_OF(STACK_OF_X509_NAME_ENTRY) *intname, unsigned char **in); ASN1_SEQUENCE(X509_NAME_ENTRY) = { - ASN1_SIMPLE(X509_NAME_ENTRY, object, ASN1_OBJECT), - ASN1_SIMPLE(X509_NAME_ENTRY, value, ASN1_PRINTABLE), + ASN1_SIMPLE(X509_NAME_ENTRY, object, ASN1_OBJECT), + ASN1_SIMPLE(X509_NAME_ENTRY, value, ASN1_PRINTABLE), } ASN1_SEQUENCE_END(X509_NAME_ENTRY) IMPLEMENT_ASN1_FUNCTIONS(X509_NAME_ENTRY) @@ -110,12 +109,13 @@ IMPLEMENT_ASN1_DUP_FUNCTION(X509_NAME_ENTRY) * declare two template wrappers for this */ -ASN1_ITEM_TEMPLATE(X509_NAME_ENTRIES) = - ASN1_EX_TEMPLATE_TYPE(ASN1_TFLG_SET_OF, 0, RDNS, X509_NAME_ENTRY) +ASN1_ITEM_TEMPLATE(X509_NAME_ENTRIES) = ASN1_EX_TEMPLATE_TYPE(ASN1_TFLG_SET_OF, + 0, RDNS, + X509_NAME_ENTRY) ASN1_ITEM_TEMPLATE_END(X509_NAME_ENTRIES) ASN1_ITEM_TEMPLATE(X509_NAME_INTERNAL) = - ASN1_EX_TEMPLATE_TYPE(ASN1_TFLG_SEQUENCE_OF, 0, Name, X509_NAME_ENTRIES) + ASN1_EX_TEMPLATE_TYPE(ASN1_TFLG_SEQUENCE_OF, 0, Name, X509_NAME_ENTRIES) ASN1_ITEM_TEMPLATE_END(X509_NAME_INTERNAL) /* @@ -129,7 +129,7 @@ static const ASN1_EXTERN_FUNCS x509_name_ff = { NULL, x509_name_ex_new, x509_name_ex_free, - 0, /* Default clear behaviour is OK */ + 0, /* Default clear behaviour is OK */ x509_name_ex_d2i, x509_name_ex_i2d, NULL, @@ -141,191 +141,193 @@ IMPLEMENT_ASN1_FUNCTIONS(X509_NAME) IMPLEMENT_ASN1_DUP_FUNCTION(X509_NAME) -static int x509_name_ex_new(ASN1_VALUE **val, const ASN1_ITEM *it) -{ - X509_NAME *ret = NULL; - ret = OPENSSL_malloc(sizeof(X509_NAME)); - if (!ret) - goto memerr; - if ((ret->entries = sk_X509_NAME_ENTRY_new_null()) == NULL) - goto memerr; - if ((ret->bytes = BUF_MEM_new()) == NULL) - goto memerr; - ret->canon_enc = NULL; - ret->canon_enclen = 0; - ret->modified = 1; - *val = (ASN1_VALUE *)ret; - return 1; - - memerr: - OPENSSL_PUT_ERROR(X509, ERR_R_MALLOC_FAILURE); - if (ret) { - if (ret->entries) - sk_X509_NAME_ENTRY_free(ret->entries); - OPENSSL_free(ret); +static int x509_name_ex_new(ASN1_VALUE **val, const ASN1_ITEM *it) { + X509_NAME *ret = NULL; + ret = OPENSSL_malloc(sizeof(X509_NAME)); + if (!ret) { + goto memerr; + } + if ((ret->entries = sk_X509_NAME_ENTRY_new_null()) == NULL) { + goto memerr; + } + if ((ret->bytes = BUF_MEM_new()) == NULL) { + goto memerr; + } + ret->canon_enc = NULL; + ret->canon_enclen = 0; + ret->modified = 1; + *val = (ASN1_VALUE *)ret; + return 1; + +memerr: + OPENSSL_PUT_ERROR(X509, ERR_R_MALLOC_FAILURE); + if (ret) { + if (ret->entries) { + sk_X509_NAME_ENTRY_free(ret->entries); } - return 0; + OPENSSL_free(ret); + } + return 0; } -static void x509_name_ex_free(ASN1_VALUE **pval, const ASN1_ITEM *it) -{ - X509_NAME *a; - if (!pval || !*pval) - return; - a = (X509_NAME *)*pval; - - BUF_MEM_free(a->bytes); - sk_X509_NAME_ENTRY_pop_free(a->entries, X509_NAME_ENTRY_free); - if (a->canon_enc) - OPENSSL_free(a->canon_enc); - OPENSSL_free(a); - *pval = NULL; +static void x509_name_ex_free(ASN1_VALUE **pval, const ASN1_ITEM *it) { + X509_NAME *a; + if (!pval || !*pval) { + return; + } + a = (X509_NAME *)*pval; + + BUF_MEM_free(a->bytes); + sk_X509_NAME_ENTRY_pop_free(a->entries, X509_NAME_ENTRY_free); + if (a->canon_enc) { + OPENSSL_free(a->canon_enc); + } + OPENSSL_free(a); + *pval = NULL; } -static void local_sk_X509_NAME_ENTRY_free(STACK_OF(X509_NAME_ENTRY) *ne) -{ - sk_X509_NAME_ENTRY_free(ne); +static void local_sk_X509_NAME_ENTRY_free(STACK_OF(X509_NAME_ENTRY) *ne) { + sk_X509_NAME_ENTRY_free(ne); } -static void local_sk_X509_NAME_ENTRY_pop_free(STACK_OF(X509_NAME_ENTRY) *ne) -{ - sk_X509_NAME_ENTRY_pop_free(ne, X509_NAME_ENTRY_free); +static void local_sk_X509_NAME_ENTRY_pop_free(STACK_OF(X509_NAME_ENTRY) *ne) { + sk_X509_NAME_ENTRY_pop_free(ne, X509_NAME_ENTRY_free); } -static int x509_name_ex_d2i(ASN1_VALUE **val, - const unsigned char **in, long len, - const ASN1_ITEM *it, int tag, int aclass, - char opt, ASN1_TLC *ctx) -{ - const unsigned char *p = *in, *q; - STACK_OF(STACK_OF_X509_NAME_ENTRY) *intname = NULL; - X509_NAME *nm = NULL; - size_t i, j; - int ret; - STACK_OF(X509_NAME_ENTRY) *entries; - X509_NAME_ENTRY *entry; - /* Bound the size of an X509_NAME we are willing to parse. */ - if (len > X509_NAME_MAX) { - len = X509_NAME_MAX; - } - q = p; - - /* Get internal representation of Name */ - ASN1_VALUE *intname_val = NULL; - ret = ASN1_item_ex_d2i(&intname_val, - &p, len, ASN1_ITEM_rptr(X509_NAME_INTERNAL), - tag, aclass, opt, ctx); - if (ret <= 0) - return ret; - intname = (STACK_OF(STACK_OF_X509_NAME_ENTRY) *)intname_val; - - if (*val) - x509_name_ex_free(val, NULL); - ASN1_VALUE *nm_val = NULL; - if (!x509_name_ex_new(&nm_val, NULL)) - goto err; - nm = (X509_NAME *)nm_val; - /* We've decoded it: now cache encoding */ - if (!BUF_MEM_grow(nm->bytes, p - q)) +static int x509_name_ex_d2i(ASN1_VALUE **val, const unsigned char **in, + long len, const ASN1_ITEM *it, int tag, int aclass, + char opt, ASN1_TLC *ctx) { + const unsigned char *p = *in, *q; + STACK_OF(STACK_OF_X509_NAME_ENTRY) *intname = NULL; + X509_NAME *nm = NULL; + size_t i, j; + int ret; + STACK_OF(X509_NAME_ENTRY) *entries; + X509_NAME_ENTRY *entry; + /* Bound the size of an X509_NAME we are willing to parse. */ + if (len > X509_NAME_MAX) { + len = X509_NAME_MAX; + } + q = p; + + /* Get internal representation of Name */ + ASN1_VALUE *intname_val = NULL; + ret = ASN1_item_ex_d2i(&intname_val, &p, len, + ASN1_ITEM_rptr(X509_NAME_INTERNAL), tag, aclass, opt, + ctx); + if (ret <= 0) { + return ret; + } + intname = (STACK_OF(STACK_OF_X509_NAME_ENTRY) *)intname_val; + + if (*val) { + x509_name_ex_free(val, NULL); + } + ASN1_VALUE *nm_val = NULL; + if (!x509_name_ex_new(&nm_val, NULL)) { + goto err; + } + nm = (X509_NAME *)nm_val; + /* We've decoded it: now cache encoding */ + if (!BUF_MEM_grow(nm->bytes, p - q)) { + goto err; + } + OPENSSL_memcpy(nm->bytes->data, q, p - q); + + /* Convert internal representation to X509_NAME structure */ + for (i = 0; i < sk_STACK_OF_X509_NAME_ENTRY_num(intname); i++) { + entries = sk_STACK_OF_X509_NAME_ENTRY_value(intname, i); + for (j = 0; j < sk_X509_NAME_ENTRY_num(entries); j++) { + entry = sk_X509_NAME_ENTRY_value(entries, j); + entry->set = i; + if (!sk_X509_NAME_ENTRY_push(nm->entries, entry)) { goto err; - OPENSSL_memcpy(nm->bytes->data, q, p - q); - - /* Convert internal representation to X509_NAME structure */ - for (i = 0; i < sk_STACK_OF_X509_NAME_ENTRY_num(intname); i++) { - entries = sk_STACK_OF_X509_NAME_ENTRY_value(intname, i); - for (j = 0; j < sk_X509_NAME_ENTRY_num(entries); j++) { - entry = sk_X509_NAME_ENTRY_value(entries, j); - entry->set = i; - if (!sk_X509_NAME_ENTRY_push(nm->entries, entry)) - goto err; - (void)sk_X509_NAME_ENTRY_set(entries, j, NULL); - } + } + (void)sk_X509_NAME_ENTRY_set(entries, j, NULL); } - ret = x509_name_canon(nm); - if (!ret) - goto err; - sk_STACK_OF_X509_NAME_ENTRY_pop_free(intname, - local_sk_X509_NAME_ENTRY_free); - nm->modified = 0; - *val = (ASN1_VALUE *)nm; - *in = p; - return ret; - err: - X509_NAME_free(nm); - sk_STACK_OF_X509_NAME_ENTRY_pop_free(intname, - local_sk_X509_NAME_ENTRY_pop_free); - OPENSSL_PUT_ERROR(X509, ERR_R_ASN1_LIB); - return 0; + } + ret = x509_name_canon(nm); + if (!ret) { + goto err; + } + sk_STACK_OF_X509_NAME_ENTRY_pop_free(intname, local_sk_X509_NAME_ENTRY_free); + nm->modified = 0; + *val = (ASN1_VALUE *)nm; + *in = p; + return ret; +err: + X509_NAME_free(nm); + sk_STACK_OF_X509_NAME_ENTRY_pop_free(intname, + local_sk_X509_NAME_ENTRY_pop_free); + OPENSSL_PUT_ERROR(X509, ERR_R_ASN1_LIB); + return 0; } static int x509_name_ex_i2d(ASN1_VALUE **val, unsigned char **out, - const ASN1_ITEM *it, int tag, int aclass) -{ - X509_NAME *a = (X509_NAME *)*val; - if (a->modified && - (!x509_name_encode(a) || - !x509_name_canon(a))) { - return -1; - } - int ret = a->bytes->length; - if (out != NULL) { - OPENSSL_memcpy(*out, a->bytes->data, ret); - *out += ret; - } - return ret; + const ASN1_ITEM *it, int tag, int aclass) { + X509_NAME *a = (X509_NAME *)*val; + if (a->modified && (!x509_name_encode(a) || !x509_name_canon(a))) { + return -1; + } + int ret = a->bytes->length; + if (out != NULL) { + OPENSSL_memcpy(*out, a->bytes->data, ret); + *out += ret; + } + return ret; } -static int x509_name_encode(X509_NAME *a) -{ - int len; - unsigned char *p; - STACK_OF(X509_NAME_ENTRY) *entries = NULL; - X509_NAME_ENTRY *entry; - int set = -1; - size_t i; - STACK_OF(STACK_OF_X509_NAME_ENTRY) *intname = - sk_STACK_OF_X509_NAME_ENTRY_new_null(); - if (!intname) +static int x509_name_encode(X509_NAME *a) { + int len; + unsigned char *p; + STACK_OF(X509_NAME_ENTRY) *entries = NULL; + X509_NAME_ENTRY *entry; + int set = -1; + size_t i; + STACK_OF(STACK_OF_X509_NAME_ENTRY) *intname = + sk_STACK_OF_X509_NAME_ENTRY_new_null(); + if (!intname) { + goto memerr; + } + for (i = 0; i < sk_X509_NAME_ENTRY_num(a->entries); i++) { + entry = sk_X509_NAME_ENTRY_value(a->entries, i); + if (entry->set != set) { + entries = sk_X509_NAME_ENTRY_new_null(); + if (!entries) { goto memerr; - for (i = 0; i < sk_X509_NAME_ENTRY_num(a->entries); i++) { - entry = sk_X509_NAME_ENTRY_value(a->entries, i); - if (entry->set != set) { - entries = sk_X509_NAME_ENTRY_new_null(); - if (!entries) - goto memerr; - if (!sk_STACK_OF_X509_NAME_ENTRY_push(intname, entries)) { - sk_X509_NAME_ENTRY_free(entries); - goto memerr; - } - set = entry->set; - } - if (!sk_X509_NAME_ENTRY_push(entries, entry)) - goto memerr; - } - ASN1_VALUE *intname_val = (ASN1_VALUE *)intname; - len = - ASN1_item_ex_i2d(&intname_val, NULL, ASN1_ITEM_rptr(X509_NAME_INTERNAL), - /*tag=*/-1, /*aclass=*/0); - if (len <= 0) { - goto err; - } - if (!BUF_MEM_grow(a->bytes, len)) + } + if (!sk_STACK_OF_X509_NAME_ENTRY_push(intname, entries)) { + sk_X509_NAME_ENTRY_free(entries); goto memerr; - p = (unsigned char *)a->bytes->data; - if (ASN1_item_ex_i2d(&intname_val, &p, ASN1_ITEM_rptr(X509_NAME_INTERNAL), - /*tag=*/-1, /*aclass=*/0) <= 0) { - goto err; + } + set = entry->set; } - sk_STACK_OF_X509_NAME_ENTRY_pop_free(intname, - local_sk_X509_NAME_ENTRY_free); - a->modified = 0; - return 1; - memerr: - OPENSSL_PUT_ERROR(X509, ERR_R_MALLOC_FAILURE); + if (!sk_X509_NAME_ENTRY_push(entries, entry)) { + goto memerr; + } + } + ASN1_VALUE *intname_val = (ASN1_VALUE *)intname; + len = ASN1_item_ex_i2d(&intname_val, NULL, ASN1_ITEM_rptr(X509_NAME_INTERNAL), + /*tag=*/-1, /*aclass=*/0); + if (len <= 0) { + goto err; + } + if (!BUF_MEM_grow(a->bytes, len)) { + goto memerr; + } + p = (unsigned char *)a->bytes->data; + if (ASN1_item_ex_i2d(&intname_val, &p, ASN1_ITEM_rptr(X509_NAME_INTERNAL), + /*tag=*/-1, /*aclass=*/0) <= 0) { + goto err; + } + sk_STACK_OF_X509_NAME_ENTRY_pop_free(intname, local_sk_X509_NAME_ENTRY_free); + a->modified = 0; + return 1; +memerr: + OPENSSL_PUT_ERROR(X509, ERR_R_MALLOC_FAILURE); err: - sk_STACK_OF_X509_NAME_ENTRY_pop_free(intname, - local_sk_X509_NAME_ENTRY_free); - return 0; + sk_STACK_OF_X509_NAME_ENTRY_pop_free(intname, local_sk_X509_NAME_ENTRY_free); + return 0; } /* @@ -334,211 +336,217 @@ static int x509_name_encode(X509_NAME *a) * spaces collapsed, converted to lower case and the leading SEQUENCE header * removed. In future we could also normalize the UTF8 too. By doing this * comparison of Name structures can be rapidly perfomed by just using - * OPENSSL_memcmp() of the canonical encoding. By omitting the leading SEQUENCE name - * constraints of type dirName can also be checked with a simple OPENSSL_memcmp(). + * OPENSSL_memcmp() of the canonical encoding. By omitting the leading SEQUENCE + * name constraints of type dirName can also be checked with a simple + * OPENSSL_memcmp(). */ -static int x509_name_canon(X509_NAME *a) -{ - unsigned char *p; - STACK_OF(STACK_OF_X509_NAME_ENTRY) *intname = NULL; - STACK_OF(X509_NAME_ENTRY) *entries = NULL; - X509_NAME_ENTRY *entry, *tmpentry = NULL; - int set = -1, ret = 0, len; - size_t i; - - if (a->canon_enc) { - OPENSSL_free(a->canon_enc); - a->canon_enc = NULL; +static int x509_name_canon(X509_NAME *a) { + unsigned char *p; + STACK_OF(STACK_OF_X509_NAME_ENTRY) *intname = NULL; + STACK_OF(X509_NAME_ENTRY) *entries = NULL; + X509_NAME_ENTRY *entry, *tmpentry = NULL; + int set = -1, ret = 0, len; + size_t i; + + if (a->canon_enc) { + OPENSSL_free(a->canon_enc); + a->canon_enc = NULL; + } + /* Special case: empty X509_NAME => null encoding */ + if (sk_X509_NAME_ENTRY_num(a->entries) == 0) { + a->canon_enclen = 0; + return 1; + } + intname = sk_STACK_OF_X509_NAME_ENTRY_new_null(); + if (!intname) { + goto err; + } + for (i = 0; i < sk_X509_NAME_ENTRY_num(a->entries); i++) { + entry = sk_X509_NAME_ENTRY_value(a->entries, i); + if (entry->set != set) { + entries = sk_X509_NAME_ENTRY_new_null(); + if (!entries) { + goto err; + } + if (!sk_STACK_OF_X509_NAME_ENTRY_push(intname, entries)) { + sk_X509_NAME_ENTRY_free(entries); + goto err; + } + set = entry->set; } - /* Special case: empty X509_NAME => null encoding */ - if (sk_X509_NAME_ENTRY_num(a->entries) == 0) { - a->canon_enclen = 0; - return 1; + tmpentry = X509_NAME_ENTRY_new(); + if (tmpentry == NULL) { + goto err; } - intname = sk_STACK_OF_X509_NAME_ENTRY_new_null(); - if (!intname) - goto err; - for (i = 0; i < sk_X509_NAME_ENTRY_num(a->entries); i++) { - entry = sk_X509_NAME_ENTRY_value(a->entries, i); - if (entry->set != set) { - entries = sk_X509_NAME_ENTRY_new_null(); - if (!entries) - goto err; - if (!sk_STACK_OF_X509_NAME_ENTRY_push(intname, entries)) { - sk_X509_NAME_ENTRY_free(entries); - goto err; - } - set = entry->set; - } - tmpentry = X509_NAME_ENTRY_new(); - if (tmpentry == NULL) - goto err; - tmpentry->object = OBJ_dup(entry->object); - if (!asn1_string_canon(tmpentry->value, entry->value)) - goto err; - if (!sk_X509_NAME_ENTRY_push(entries, tmpentry)) - goto err; - tmpentry = NULL; + tmpentry->object = OBJ_dup(entry->object); + if (!asn1_string_canon(tmpentry->value, entry->value)) { + goto err; + } + if (!sk_X509_NAME_ENTRY_push(entries, tmpentry)) { + goto err; } + tmpentry = NULL; + } - /* Finally generate encoding */ + /* Finally generate encoding */ - len = i2d_name_canon(intname, NULL); - if (len < 0) { - goto err; - } - a->canon_enclen = len; + len = i2d_name_canon(intname, NULL); + if (len < 0) { + goto err; + } + a->canon_enclen = len; - p = OPENSSL_malloc(a->canon_enclen); + p = OPENSSL_malloc(a->canon_enclen); - if (!p) - goto err; + if (!p) { + goto err; + } - a->canon_enc = p; + a->canon_enc = p; - i2d_name_canon(intname, &p); + i2d_name_canon(intname, &p); - ret = 1; + ret = 1; - err: +err: - if (tmpentry) - X509_NAME_ENTRY_free(tmpentry); - if (intname) - sk_STACK_OF_X509_NAME_ENTRY_pop_free(intname, - local_sk_X509_NAME_ENTRY_pop_free); - return ret; + if (tmpentry) { + X509_NAME_ENTRY_free(tmpentry); + } + if (intname) { + sk_STACK_OF_X509_NAME_ENTRY_pop_free(intname, + local_sk_X509_NAME_ENTRY_pop_free); + } + return ret; } /* Bitmap of all the types of string that will be canonicalized. */ -#define ASN1_MASK_CANON \ - (B_ASN1_UTF8STRING | B_ASN1_BMPSTRING | B_ASN1_UNIVERSALSTRING \ - | B_ASN1_PRINTABLESTRING | B_ASN1_T61STRING | B_ASN1_IA5STRING \ - | B_ASN1_VISIBLESTRING) - -static int asn1_string_canon(ASN1_STRING *out, ASN1_STRING *in) -{ - unsigned char *to, *from; - int len, i; - - /* If type not in bitmask just copy string across */ - if (!(ASN1_tag2bit(in->type) & ASN1_MASK_CANON)) { - if (!ASN1_STRING_copy(out, in)) - return 0; - return 1; +#define ASN1_MASK_CANON \ + (B_ASN1_UTF8STRING | B_ASN1_BMPSTRING | B_ASN1_UNIVERSALSTRING | \ + B_ASN1_PRINTABLESTRING | B_ASN1_T61STRING | B_ASN1_IA5STRING | \ + B_ASN1_VISIBLESTRING) + +static int asn1_string_canon(ASN1_STRING *out, ASN1_STRING *in) { + unsigned char *to, *from; + int len, i; + + /* If type not in bitmask just copy string across */ + if (!(ASN1_tag2bit(in->type) & ASN1_MASK_CANON)) { + if (!ASN1_STRING_copy(out, in)) { + return 0; } + return 1; + } - out->type = V_ASN1_UTF8STRING; - out->length = ASN1_STRING_to_UTF8(&out->data, in); - if (out->length == -1) - return 0; + out->type = V_ASN1_UTF8STRING; + out->length = ASN1_STRING_to_UTF8(&out->data, in); + if (out->length == -1) { + return 0; + } - to = out->data; - from = to; + to = out->data; + from = to; - len = out->length; + len = out->length; - /* - * Convert string in place to canonical form. Ultimately we may need to - * handle a wider range of characters but for now ignore anything with - * MSB set and rely on the isspace() and tolower() functions. - */ + /* + * Convert string in place to canonical form. Ultimately we may need to + * handle a wider range of characters but for now ignore anything with + * MSB set and rely on the isspace() and tolower() functions. + */ - /* Ignore leading spaces */ - while ((len > 0) && !(*from & 0x80) && isspace(*from)) { - from++; - len--; - } + /* Ignore leading spaces */ + while ((len > 0) && !(*from & 0x80) && isspace(*from)) { + from++; + len--; + } - to = from + len; + to = from + len; - /* Ignore trailing spaces */ - while ((len > 0) && !(to[-1] & 0x80) && isspace(to[-1])) { - to--; - len--; - } + /* Ignore trailing spaces */ + while ((len > 0) && !(to[-1] & 0x80) && isspace(to[-1])) { + to--; + len--; + } - to = out->data; - - i = 0; - while (i < len) { - /* If MSB set just copy across */ - if (*from & 0x80) { - *to++ = *from++; - i++; - } - /* Collapse multiple spaces */ - else if (isspace(*from)) { - /* Copy one space across */ - *to++ = ' '; - /* - * Ignore subsequent spaces. Note: don't need to check len here - * because we know the last character is a non-space so we can't - * overflow. - */ - do { - from++; - i++; - } - while (!(*from & 0x80) && isspace(*from)); - } else { - *to++ = OPENSSL_tolower(*from); - from++; - i++; - } - } + to = out->data; - out->length = to - out->data; + i = 0; + while (i < len) { + /* If MSB set just copy across */ + if (*from & 0x80) { + *to++ = *from++; + i++; + } + /* Collapse multiple spaces */ + else if (isspace(*from)) { + /* Copy one space across */ + *to++ = ' '; + /* + * Ignore subsequent spaces. Note: don't need to check len here + * because we know the last character is a non-space so we can't + * overflow. + */ + do { + from++; + i++; + } while (!(*from & 0x80) && isspace(*from)); + } else { + *to++ = OPENSSL_tolower(*from); + from++; + i++; + } + } - return 1; + out->length = to - out->data; + return 1; } -static int i2d_name_canon(STACK_OF(STACK_OF_X509_NAME_ENTRY) * _intname, - unsigned char **in) -{ - int len, ltmp; - size_t i; - ASN1_VALUE *v; - STACK_OF(ASN1_VALUE) *intname = (STACK_OF(ASN1_VALUE) *)_intname; - - len = 0; - for (i = 0; i < sk_ASN1_VALUE_num(intname); i++) { - v = sk_ASN1_VALUE_value(intname, i); - ltmp = ASN1_item_ex_i2d(&v, in, ASN1_ITEM_rptr(X509_NAME_ENTRIES), - /*tag=*/-1, /*aclass=*/0); - if (ltmp < 0) - return ltmp; - len += ltmp; +static int i2d_name_canon(STACK_OF(STACK_OF_X509_NAME_ENTRY) *_intname, + unsigned char **in) { + int len, ltmp; + size_t i; + ASN1_VALUE *v; + STACK_OF(ASN1_VALUE) *intname = (STACK_OF(ASN1_VALUE) *)_intname; + + len = 0; + for (i = 0; i < sk_ASN1_VALUE_num(intname); i++) { + v = sk_ASN1_VALUE_value(intname, i); + ltmp = ASN1_item_ex_i2d(&v, in, ASN1_ITEM_rptr(X509_NAME_ENTRIES), + /*tag=*/-1, /*aclass=*/0); + if (ltmp < 0) { + return ltmp; } - return len; + len += ltmp; + } + return len; } -int X509_NAME_set(X509_NAME **xn, X509_NAME *name) -{ - if ((name = X509_NAME_dup(name)) == NULL) - return 0; - X509_NAME_free(*xn); - *xn = name; - return 1; +int X509_NAME_set(X509_NAME **xn, X509_NAME *name) { + if ((name = X509_NAME_dup(name)) == NULL) { + return 0; + } + X509_NAME_free(*xn); + *xn = name; + return 1; } -int X509_NAME_ENTRY_set(const X509_NAME_ENTRY *ne) -{ - return ne->set; -} +int X509_NAME_ENTRY_set(const X509_NAME_ENTRY *ne) { return ne->set; } int X509_NAME_get0_der(X509_NAME *nm, const unsigned char **pder, - size_t *pderlen) -{ - /* Make sure encoding is valid */ - if (i2d_X509_NAME(nm, NULL) <= 0) - return 0; - if (pder != NULL) - *pder = (unsigned char *)nm->bytes->data; - if (pderlen != NULL) - *pderlen = nm->bytes->length; - return 1; + size_t *pderlen) { + /* Make sure encoding is valid */ + if (i2d_X509_NAME(nm, NULL) <= 0) { + return 0; + } + if (pder != NULL) { + *pder = (unsigned char *)nm->bytes->data; + } + if (pderlen != NULL) { + *pderlen = nm->bytes->length; + } + return 1; } diff --git a/crypto/x509/x_pkey.c b/crypto/x509/x_pkey.c index e562d7309e..52bc5b673d 100644 --- a/crypto/x509/x_pkey.c +++ b/crypto/x509/x_pkey.c @@ -66,41 +66,47 @@ #include "../internal.h" -X509_PKEY *X509_PKEY_new(void) -{ - X509_PKEY *ret = OPENSSL_malloc(sizeof(X509_PKEY)); - if (ret == NULL) { - OPENSSL_PUT_ERROR(X509, ERR_R_MALLOC_FAILURE); - goto err; - } - OPENSSL_memset(ret, 0, sizeof(X509_PKEY)); +X509_PKEY *X509_PKEY_new(void) { + X509_PKEY *ret = OPENSSL_malloc(sizeof(X509_PKEY)); + if (ret == NULL) { + OPENSSL_PUT_ERROR(X509, ERR_R_MALLOC_FAILURE); + goto err; + } + OPENSSL_memset(ret, 0, sizeof(X509_PKEY)); - ret->enc_algor = X509_ALGOR_new(); - if (ret->enc_algor == NULL) - goto err; - ret->enc_pkey = ASN1_OCTET_STRING_new(); - if (ret->enc_pkey == NULL) - goto err; - return ret; + ret->enc_algor = X509_ALGOR_new(); + if (ret->enc_algor == NULL) { + goto err; + } + ret->enc_pkey = ASN1_OCTET_STRING_new(); + if (ret->enc_pkey == NULL) { + goto err; + } + return ret; - err: - if (ret != NULL) - X509_PKEY_free(ret); - return NULL; +err: + if (ret != NULL) { + X509_PKEY_free(ret); + } + return NULL; } -void X509_PKEY_free(X509_PKEY *x) -{ - if (x == NULL) - return; +void X509_PKEY_free(X509_PKEY *x) { + if (x == NULL) { + return; + } - if (x->enc_algor != NULL) - X509_ALGOR_free(x->enc_algor); - if (x->enc_pkey != NULL) - ASN1_OCTET_STRING_free(x->enc_pkey); - if (x->dec_pkey != NULL) - EVP_PKEY_free(x->dec_pkey); - if ((x->key_data != NULL) && (x->key_free)) - OPENSSL_free(x->key_data); - OPENSSL_free(x); + if (x->enc_algor != NULL) { + X509_ALGOR_free(x->enc_algor); + } + if (x->enc_pkey != NULL) { + ASN1_OCTET_STRING_free(x->enc_pkey); + } + if (x->dec_pkey != NULL) { + EVP_PKEY_free(x->dec_pkey); + } + if ((x->key_data != NULL) && (x->key_free)) { + OPENSSL_free(x->key_data); + } + OPENSSL_free(x); } diff --git a/crypto/x509/x_pubkey.c b/crypto/x509/x_pubkey.c index 90d95fbf06..12e7d68cbc 100644 --- a/crypto/x509/x_pubkey.c +++ b/crypto/x509/x_pubkey.c @@ -72,57 +72,54 @@ /* Minor tweak to operation: free up EVP_PKEY */ static int pubkey_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it, - void *exarg) -{ - if (operation == ASN1_OP_FREE_POST) { - X509_PUBKEY *pubkey = (X509_PUBKEY *)*pval; - EVP_PKEY_free(pubkey->pkey); - } - return 1; + void *exarg) { + if (operation == ASN1_OP_FREE_POST) { + X509_PUBKEY *pubkey = (X509_PUBKEY *)*pval; + EVP_PKEY_free(pubkey->pkey); + } + return 1; } ASN1_SEQUENCE_cb(X509_PUBKEY, pubkey_cb) = { - ASN1_SIMPLE(X509_PUBKEY, algor, X509_ALGOR), - ASN1_SIMPLE(X509_PUBKEY, public_key, ASN1_BIT_STRING), + ASN1_SIMPLE(X509_PUBKEY, algor, X509_ALGOR), + ASN1_SIMPLE(X509_PUBKEY, public_key, ASN1_BIT_STRING), } ASN1_SEQUENCE_END_cb(X509_PUBKEY, X509_PUBKEY) IMPLEMENT_ASN1_FUNCTIONS(X509_PUBKEY) -int X509_PUBKEY_set(X509_PUBKEY **x, EVP_PKEY *pkey) -{ - X509_PUBKEY *pk = NULL; - uint8_t *spki = NULL; - size_t spki_len; - - if (x == NULL) - return (0); - - CBB cbb; - if (!CBB_init(&cbb, 0) || - !EVP_marshal_public_key(&cbb, pkey) || - !CBB_finish(&cbb, &spki, &spki_len) || - spki_len > LONG_MAX) { - CBB_cleanup(&cbb); - OPENSSL_PUT_ERROR(X509, X509_R_PUBLIC_KEY_ENCODE_ERROR); - goto error; - } - - const uint8_t *p = spki; - pk = d2i_X509_PUBKEY(NULL, &p, (long)spki_len); - if (pk == NULL || p != spki + spki_len) { - OPENSSL_PUT_ERROR(X509, X509_R_PUBLIC_KEY_DECODE_ERROR); - goto error; - } - - OPENSSL_free(spki); - X509_PUBKEY_free(*x); - *x = pk; - - return 1; - error: - X509_PUBKEY_free(pk); - OPENSSL_free(spki); - return 0; +int X509_PUBKEY_set(X509_PUBKEY **x, EVP_PKEY *pkey) { + X509_PUBKEY *pk = NULL; + uint8_t *spki = NULL; + size_t spki_len; + + if (x == NULL) { + return (0); + } + + CBB cbb; + if (!CBB_init(&cbb, 0) || !EVP_marshal_public_key(&cbb, pkey) || + !CBB_finish(&cbb, &spki, &spki_len) || spki_len > LONG_MAX) { + CBB_cleanup(&cbb); + OPENSSL_PUT_ERROR(X509, X509_R_PUBLIC_KEY_ENCODE_ERROR); + goto error; + } + + const uint8_t *p = spki; + pk = d2i_X509_PUBKEY(NULL, &p, (long)spki_len); + if (pk == NULL || p != spki + spki_len) { + OPENSSL_PUT_ERROR(X509, X509_R_PUBLIC_KEY_DECODE_ERROR); + goto error; + } + + OPENSSL_free(spki); + X509_PUBKEY_free(*x); + *x = pk; + + return 1; +error: + X509_PUBKEY_free(pk); + OPENSSL_free(spki); + return 0; } /* g_pubkey_lock is used to protect the initialisation of the |pkey| member of @@ -131,87 +128,85 @@ int X509_PUBKEY_set(X509_PUBKEY **x, EVP_PKEY *pkey) * not. */ static struct CRYPTO_STATIC_MUTEX g_pubkey_lock = CRYPTO_STATIC_MUTEX_INIT; -EVP_PKEY *X509_PUBKEY_get(X509_PUBKEY *key) -{ - EVP_PKEY *ret = NULL; - uint8_t *spki = NULL; +EVP_PKEY *X509_PUBKEY_get(X509_PUBKEY *key) { + EVP_PKEY *ret = NULL; + uint8_t *spki = NULL; - if (key == NULL) - goto error; + if (key == NULL) { + goto error; + } - CRYPTO_STATIC_MUTEX_lock_read(&g_pubkey_lock); - if (key->pkey != NULL) { - CRYPTO_STATIC_MUTEX_unlock_read(&g_pubkey_lock); - EVP_PKEY_up_ref(key->pkey); - return key->pkey; - } + CRYPTO_STATIC_MUTEX_lock_read(&g_pubkey_lock); + if (key->pkey != NULL) { CRYPTO_STATIC_MUTEX_unlock_read(&g_pubkey_lock); - - /* Re-encode the |X509_PUBKEY| to DER and parse it. */ - int spki_len = i2d_X509_PUBKEY(key, &spki); - if (spki_len < 0) { - goto error; - } - CBS cbs; - CBS_init(&cbs, spki, (size_t)spki_len); - ret = EVP_parse_public_key(&cbs); - if (ret == NULL || CBS_len(&cbs) != 0) { - OPENSSL_PUT_ERROR(X509, X509_R_PUBLIC_KEY_DECODE_ERROR); - goto error; - } - - /* Check to see if another thread set key->pkey first */ - CRYPTO_STATIC_MUTEX_lock_write(&g_pubkey_lock); - if (key->pkey) { - CRYPTO_STATIC_MUTEX_unlock_write(&g_pubkey_lock); - EVP_PKEY_free(ret); - ret = key->pkey; - } else { - key->pkey = ret; - CRYPTO_STATIC_MUTEX_unlock_write(&g_pubkey_lock); - } - - OPENSSL_free(spki); - EVP_PKEY_up_ref(ret); - return ret; - - error: - OPENSSL_free(spki); + EVP_PKEY_up_ref(key->pkey); + return key->pkey; + } + CRYPTO_STATIC_MUTEX_unlock_read(&g_pubkey_lock); + + /* Re-encode the |X509_PUBKEY| to DER and parse it. */ + int spki_len = i2d_X509_PUBKEY(key, &spki); + if (spki_len < 0) { + goto error; + } + CBS cbs; + CBS_init(&cbs, spki, (size_t)spki_len); + ret = EVP_parse_public_key(&cbs); + if (ret == NULL || CBS_len(&cbs) != 0) { + OPENSSL_PUT_ERROR(X509, X509_R_PUBLIC_KEY_DECODE_ERROR); + goto error; + } + + /* Check to see if another thread set key->pkey first */ + CRYPTO_STATIC_MUTEX_lock_write(&g_pubkey_lock); + if (key->pkey) { + CRYPTO_STATIC_MUTEX_unlock_write(&g_pubkey_lock); EVP_PKEY_free(ret); - return NULL; + ret = key->pkey; + } else { + key->pkey = ret; + CRYPTO_STATIC_MUTEX_unlock_write(&g_pubkey_lock); + } + + OPENSSL_free(spki); + EVP_PKEY_up_ref(ret); + return ret; + +error: + OPENSSL_free(spki); + EVP_PKEY_free(ret); + return NULL; } int X509_PUBKEY_set0_param(X509_PUBKEY *pub, ASN1_OBJECT *obj, int param_type, - void *param_value, uint8_t *key, int key_len) -{ - if (!X509_ALGOR_set0(pub->algor, obj, param_type, param_value)) { - return 0; - } - - ASN1_STRING_set0(pub->public_key, key, key_len); - /* Set the number of unused bits to zero. */ - pub->public_key->flags &= ~(ASN1_STRING_FLAG_BITS_LEFT | 0x07); - pub->public_key->flags |= ASN1_STRING_FLAG_BITS_LEFT; - return 1; + void *param_value, uint8_t *key, int key_len) { + if (!X509_ALGOR_set0(pub->algor, obj, param_type, param_value)) { + return 0; + } + + ASN1_STRING_set0(pub->public_key, key, key_len); + /* Set the number of unused bits to zero. */ + pub->public_key->flags &= ~(ASN1_STRING_FLAG_BITS_LEFT | 0x07); + pub->public_key->flags |= ASN1_STRING_FLAG_BITS_LEFT; + return 1; } int X509_PUBKEY_get0_param(ASN1_OBJECT **out_obj, const uint8_t **out_key, int *out_key_len, X509_ALGOR **out_alg, - X509_PUBKEY *pub) -{ - if (out_obj != NULL) { - *out_obj = pub->algor->algorithm; - } - if (out_key != NULL) { - *out_key = pub->public_key->data; - *out_key_len = pub->public_key->length; - } - if (out_alg != NULL) { - *out_alg = pub->algor; - } - return 1; + X509_PUBKEY *pub) { + if (out_obj != NULL) { + *out_obj = pub->algor->algorithm; + } + if (out_key != NULL) { + *out_key = pub->public_key->data; + *out_key_len = pub->public_key->length; + } + if (out_alg != NULL) { + *out_alg = pub->algor; + } + return 1; } const ASN1_BIT_STRING *X509_PUBKEY_get0_public_key(const X509_PUBKEY *pub) { - return pub->public_key; + return pub->public_key; } diff --git a/crypto/x509/x_req.c b/crypto/x509/x_req.c index 4c4c0920b4..42e94965f0 100644 --- a/crypto/x509/x_req.c +++ b/crypto/x509/x_req.c @@ -73,40 +73,40 @@ */ static int rinf_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it, - void *exarg) -{ - X509_REQ_INFO *rinf = (X509_REQ_INFO *)*pval; + void *exarg) { + X509_REQ_INFO *rinf = (X509_REQ_INFO *)*pval; - if (operation == ASN1_OP_NEW_POST) { - rinf->attributes = sk_X509_ATTRIBUTE_new_null(); - if (!rinf->attributes) - return 0; + if (operation == ASN1_OP_NEW_POST) { + rinf->attributes = sk_X509_ATTRIBUTE_new_null(); + if (!rinf->attributes) { + return 0; } + } - if (operation == ASN1_OP_D2I_POST) { - if (ASN1_INTEGER_get(rinf->version) != X509_REQ_VERSION_1) { - OPENSSL_PUT_ERROR(X509, X509_R_INVALID_VERSION); - return 0; - } + if (operation == ASN1_OP_D2I_POST) { + if (ASN1_INTEGER_get(rinf->version) != X509_REQ_VERSION_1) { + OPENSSL_PUT_ERROR(X509, X509_R_INVALID_VERSION); + return 0; } + } - return 1; + return 1; } ASN1_SEQUENCE_enc(X509_REQ_INFO, enc, rinf_cb) = { - ASN1_SIMPLE(X509_REQ_INFO, version, ASN1_INTEGER), - ASN1_SIMPLE(X509_REQ_INFO, subject, X509_NAME), - ASN1_SIMPLE(X509_REQ_INFO, pubkey, X509_PUBKEY), - /* This isn't really OPTIONAL but it gets around invalid encodings. */ - ASN1_IMP_SET_OF_OPT(X509_REQ_INFO, attributes, X509_ATTRIBUTE, 0), + ASN1_SIMPLE(X509_REQ_INFO, version, ASN1_INTEGER), + ASN1_SIMPLE(X509_REQ_INFO, subject, X509_NAME), + ASN1_SIMPLE(X509_REQ_INFO, pubkey, X509_PUBKEY), + /* This isn't really OPTIONAL but it gets around invalid encodings. */ + ASN1_IMP_SET_OF_OPT(X509_REQ_INFO, attributes, X509_ATTRIBUTE, 0), } ASN1_SEQUENCE_END_enc(X509_REQ_INFO, X509_REQ_INFO) IMPLEMENT_ASN1_FUNCTIONS(X509_REQ_INFO) ASN1_SEQUENCE_ref(X509_REQ, 0) = { - ASN1_SIMPLE(X509_REQ, req_info, X509_REQ_INFO), - ASN1_SIMPLE(X509_REQ, sig_alg, X509_ALGOR), - ASN1_SIMPLE(X509_REQ, signature, ASN1_BIT_STRING), + ASN1_SIMPLE(X509_REQ, req_info, X509_REQ_INFO), + ASN1_SIMPLE(X509_REQ, sig_alg, X509_ALGOR), + ASN1_SIMPLE(X509_REQ, signature, ASN1_BIT_STRING), } ASN1_SEQUENCE_END_ref(X509_REQ, X509_REQ) IMPLEMENT_ASN1_FUNCTIONS(X509_REQ) diff --git a/crypto/x509/x_sig.c b/crypto/x509/x_sig.c index 905af6a14e..b68cb9ef4c 100644 --- a/crypto/x509/x_sig.c +++ b/crypto/x509/x_sig.c @@ -67,8 +67,8 @@ struct X509_sig_st { } /* X509_SIG */; ASN1_SEQUENCE(X509_SIG) = { - ASN1_SIMPLE(X509_SIG, algor, X509_ALGOR), - ASN1_SIMPLE(X509_SIG, digest, ASN1_OCTET_STRING), + ASN1_SIMPLE(X509_SIG, algor, X509_ALGOR), + ASN1_SIMPLE(X509_SIG, digest, ASN1_OCTET_STRING), } ASN1_SEQUENCE_END(X509_SIG) IMPLEMENT_ASN1_FUNCTIONS(X509_SIG) diff --git a/crypto/x509/x_spki.c b/crypto/x509/x_spki.c index e2e418741a..5e582f5f4e 100644 --- a/crypto/x509/x_spki.c +++ b/crypto/x509/x_spki.c @@ -55,26 +55,26 @@ * copied and put under another distribution licence * [including the GNU Public Licence.] */ - /* - * This module was send to me my Pat Richards who wrote it. - * It is under my Copyright with his permission. - */ +/* + * This module was send to me my Pat Richards who wrote it. + * It is under my Copyright with his permission. + */ -#include #include +#include ASN1_SEQUENCE(NETSCAPE_SPKAC) = { - ASN1_SIMPLE(NETSCAPE_SPKAC, pubkey, X509_PUBKEY), - ASN1_SIMPLE(NETSCAPE_SPKAC, challenge, ASN1_IA5STRING), + ASN1_SIMPLE(NETSCAPE_SPKAC, pubkey, X509_PUBKEY), + ASN1_SIMPLE(NETSCAPE_SPKAC, challenge, ASN1_IA5STRING), } ASN1_SEQUENCE_END(NETSCAPE_SPKAC) IMPLEMENT_ASN1_FUNCTIONS(NETSCAPE_SPKAC) ASN1_SEQUENCE(NETSCAPE_SPKI) = { - ASN1_SIMPLE(NETSCAPE_SPKI, spkac, NETSCAPE_SPKAC), - ASN1_SIMPLE(NETSCAPE_SPKI, sig_algor, X509_ALGOR), - ASN1_SIMPLE(NETSCAPE_SPKI, signature, ASN1_BIT_STRING), + ASN1_SIMPLE(NETSCAPE_SPKI, spkac, NETSCAPE_SPKAC), + ASN1_SIMPLE(NETSCAPE_SPKI, sig_algor, X509_ALGOR), + ASN1_SIMPLE(NETSCAPE_SPKI, signature, ASN1_BIT_STRING), } ASN1_SEQUENCE_END(NETSCAPE_SPKI) IMPLEMENT_ASN1_FUNCTIONS(NETSCAPE_SPKI) diff --git a/crypto/x509/x_val.c b/crypto/x509/x_val.c index 4004ab536e..e317a7053a 100644 --- a/crypto/x509/x_val.c +++ b/crypto/x509/x_val.c @@ -64,8 +64,8 @@ ASN1_SEQUENCE(X509_VAL) = { - ASN1_SIMPLE(X509_VAL, notBefore, ASN1_TIME), - ASN1_SIMPLE(X509_VAL, notAfter, ASN1_TIME), + ASN1_SIMPLE(X509_VAL, notBefore, ASN1_TIME), + ASN1_SIMPLE(X509_VAL, notAfter, ASN1_TIME), } ASN1_SEQUENCE_END(X509_VAL) IMPLEMENT_ASN1_FUNCTIONS(X509_VAL) diff --git a/crypto/x509/x_x509.c b/crypto/x509/x_x509.c index 37ee975219..743fd80a00 100644 --- a/crypto/x509/x_x509.c +++ b/crypto/x509/x_x509.c @@ -74,16 +74,16 @@ static CRYPTO_EX_DATA_CLASS g_ex_data_class = CRYPTO_EX_DATA_CLASS_INIT; ASN1_SEQUENCE_enc(X509_CINF, enc, 0) = { - ASN1_EXP_OPT(X509_CINF, version, ASN1_INTEGER, 0), - ASN1_SIMPLE(X509_CINF, serialNumber, ASN1_INTEGER), - ASN1_SIMPLE(X509_CINF, signature, X509_ALGOR), - ASN1_SIMPLE(X509_CINF, issuer, X509_NAME), - ASN1_SIMPLE(X509_CINF, validity, X509_VAL), - ASN1_SIMPLE(X509_CINF, subject, X509_NAME), - ASN1_SIMPLE(X509_CINF, key, X509_PUBKEY), - ASN1_IMP_OPT(X509_CINF, issuerUID, ASN1_BIT_STRING, 1), - ASN1_IMP_OPT(X509_CINF, subjectUID, ASN1_BIT_STRING, 2), - ASN1_EXP_SEQUENCE_OF_OPT(X509_CINF, extensions, X509_EXTENSION, 3), + ASN1_EXP_OPT(X509_CINF, version, ASN1_INTEGER, 0), + ASN1_SIMPLE(X509_CINF, serialNumber, ASN1_INTEGER), + ASN1_SIMPLE(X509_CINF, signature, X509_ALGOR), + ASN1_SIMPLE(X509_CINF, issuer, X509_NAME), + ASN1_SIMPLE(X509_CINF, validity, X509_VAL), + ASN1_SIMPLE(X509_CINF, subject, X509_NAME), + ASN1_SIMPLE(X509_CINF, key, X509_PUBKEY), + ASN1_IMP_OPT(X509_CINF, issuerUID, ASN1_BIT_STRING, 1), + ASN1_IMP_OPT(X509_CINF, subjectUID, ASN1_BIT_STRING, 2), + ASN1_EXP_SEQUENCE_OF_OPT(X509_CINF, extensions, X509_EXTENSION, 3), } ASN1_SEQUENCE_END_enc(X509_CINF, X509_CINF) IMPLEMENT_ASN1_FUNCTIONS(X509_CINF) @@ -92,82 +92,78 @@ IMPLEMENT_ASN1_FUNCTIONS(X509_CINF) extern void policy_cache_free(X509_POLICY_CACHE *cache); static int x509_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it, - void *exarg) -{ - X509 *ret = (X509 *)*pval; - - switch (operation) { + void *exarg) { + X509 *ret = (X509 *)*pval; + switch (operation) { case ASN1_OP_NEW_POST: - ret->ex_flags = 0; - ret->ex_pathlen = -1; - ret->skid = NULL; - ret->akid = NULL; - ret->aux = NULL; - ret->crldp = NULL; - ret->buf = NULL; - CRYPTO_new_ex_data(&ret->ex_data); - CRYPTO_MUTEX_init(&ret->lock); - break; + ret->ex_flags = 0; + ret->ex_pathlen = -1; + ret->skid = NULL; + ret->akid = NULL; + ret->aux = NULL; + ret->crldp = NULL; + ret->buf = NULL; + CRYPTO_new_ex_data(&ret->ex_data); + CRYPTO_MUTEX_init(&ret->lock); + break; case ASN1_OP_D2I_PRE: - CRYPTO_BUFFER_free(ret->buf); - ret->buf = NULL; - break; + CRYPTO_BUFFER_free(ret->buf); + ret->buf = NULL; + break; case ASN1_OP_D2I_POST: { - /* The version must be one of v1(0), v2(1), or v3(2). */ - long version = X509_VERSION_1; - if (ret->cert_info->version != NULL) { - version = ASN1_INTEGER_get(ret->cert_info->version); - /* TODO(https://crbug.com/boringssl/364): |X509_VERSION_1| should - * also be rejected here. This means an explicitly-encoded X.509v1 - * version. v1 is DEFAULT, so DER requires it be omitted. */ - if (version < X509_VERSION_1 || version > X509_VERSION_3) { - OPENSSL_PUT_ERROR(X509, X509_R_INVALID_VERSION); - return 0; - } + /* The version must be one of v1(0), v2(1), or v3(2). */ + long version = X509_VERSION_1; + if (ret->cert_info->version != NULL) { + version = ASN1_INTEGER_get(ret->cert_info->version); + /* TODO(https://crbug.com/boringssl/364): |X509_VERSION_1| should + * also be rejected here. This means an explicitly-encoded X.509v1 + * version. v1 is DEFAULT, so DER requires it be omitted. */ + if (version < X509_VERSION_1 || version > X509_VERSION_3) { + OPENSSL_PUT_ERROR(X509, X509_R_INVALID_VERSION); + return 0; } + } - /* Per RFC 5280, section 4.1.2.8, these fields require v2 or v3. */ - if (version == X509_VERSION_1 && (ret->cert_info->issuerUID != NULL || - ret->cert_info->subjectUID != NULL)) { - OPENSSL_PUT_ERROR(X509, X509_R_INVALID_FIELD_FOR_VERSION); - return 0; - } + /* Per RFC 5280, section 4.1.2.8, these fields require v2 or v3. */ + if (version == X509_VERSION_1 && (ret->cert_info->issuerUID != NULL || + ret->cert_info->subjectUID != NULL)) { + OPENSSL_PUT_ERROR(X509, X509_R_INVALID_FIELD_FOR_VERSION); + return 0; + } - /* Per RFC 5280, section 4.1.2.9, extensions require v3. */ - if (version != X509_VERSION_3 && ret->cert_info->extensions != NULL) { - OPENSSL_PUT_ERROR(X509, X509_R_INVALID_FIELD_FOR_VERSION); - return 0; - } + /* Per RFC 5280, section 4.1.2.9, extensions require v3. */ + if (version != X509_VERSION_3 && ret->cert_info->extensions != NULL) { + OPENSSL_PUT_ERROR(X509, X509_R_INVALID_FIELD_FOR_VERSION); + return 0; + } - break; + break; } case ASN1_OP_FREE_POST: - CRYPTO_MUTEX_cleanup(&ret->lock); - CRYPTO_free_ex_data(&g_ex_data_class, ret, &ret->ex_data); - X509_CERT_AUX_free(ret->aux); - ASN1_OCTET_STRING_free(ret->skid); - AUTHORITY_KEYID_free(ret->akid); - CRL_DIST_POINTS_free(ret->crldp); - policy_cache_free(ret->policy_cache); - GENERAL_NAMES_free(ret->altname); - NAME_CONSTRAINTS_free(ret->nc); - CRYPTO_BUFFER_free(ret->buf); - break; - - } - - return 1; + CRYPTO_MUTEX_cleanup(&ret->lock); + CRYPTO_free_ex_data(&g_ex_data_class, ret, &ret->ex_data); + X509_CERT_AUX_free(ret->aux); + ASN1_OCTET_STRING_free(ret->skid); + AUTHORITY_KEYID_free(ret->akid); + CRL_DIST_POINTS_free(ret->crldp); + policy_cache_free(ret->policy_cache); + GENERAL_NAMES_free(ret->altname); + NAME_CONSTRAINTS_free(ret->nc); + CRYPTO_BUFFER_free(ret->buf); + break; + } + return 1; } ASN1_SEQUENCE_ref(X509, x509_cb) = { - ASN1_SIMPLE(X509, cert_info, X509_CINF), - ASN1_SIMPLE(X509, sig_alg, X509_ALGOR), - ASN1_SIMPLE(X509, signature, ASN1_BIT_STRING), + ASN1_SIMPLE(X509, cert_info, X509_CINF), + ASN1_SIMPLE(X509, sig_alg, X509_ALGOR), + ASN1_SIMPLE(X509, signature, ASN1_BIT_STRING), } ASN1_SEQUENCE_END_ref(X509, X509) IMPLEMENT_ASN1_FUNCTIONS(X509) @@ -204,31 +200,28 @@ X509 *X509_parse_from_buffer(CRYPTO_BUFFER *buf) { return ret; } -int X509_up_ref(X509 *x) -{ - CRYPTO_refcount_inc(&x->references); - return 1; +int X509_up_ref(X509 *x) { + CRYPTO_refcount_inc(&x->references); + return 1; } -int X509_get_ex_new_index(long argl, void *argp, CRYPTO_EX_unused * unused, - CRYPTO_EX_dup *dup_unused, CRYPTO_EX_free *free_func) -{ - int index; - if (!CRYPTO_get_ex_new_index(&g_ex_data_class, &index, argl, argp, - free_func)) { - return -1; - } - return index; +int X509_get_ex_new_index(long argl, void *argp, CRYPTO_EX_unused *unused, + CRYPTO_EX_dup *dup_unused, + CRYPTO_EX_free *free_func) { + int index; + if (!CRYPTO_get_ex_new_index(&g_ex_data_class, &index, argl, argp, + free_func)) { + return -1; + } + return index; } -int X509_set_ex_data(X509 *r, int idx, void *arg) -{ - return (CRYPTO_set_ex_data(&r->ex_data, idx, arg)); +int X509_set_ex_data(X509 *r, int idx, void *arg) { + return (CRYPTO_set_ex_data(&r->ex_data, idx, arg)); } -void *X509_get_ex_data(X509 *r, int idx) -{ - return (CRYPTO_get_ex_data(&r->ex_data, idx)); +void *X509_get_ex_data(X509 *r, int idx) { + return (CRYPTO_get_ex_data(&r->ex_data, idx)); } /* @@ -238,32 +231,35 @@ void *X509_get_ex_data(X509 *r, int idx) * reliable source such as local storage. */ -X509 *d2i_X509_AUX(X509 **a, const unsigned char **pp, long length) -{ - const unsigned char *q = *pp; - X509 *ret; - int freeret = 0; - - if (!a || *a == NULL) - freeret = 1; - ret = d2i_X509(a, &q, length); - /* If certificate unreadable then forget it */ - if (!ret) - return NULL; - /* update length */ - length -= q - *pp; - /* Parse auxiliary information if there is any. */ - if (length > 0 && !d2i_X509_CERT_AUX(&ret->aux, &q, length)) - goto err; - *pp = q; - return ret; - err: - if (freeret) { - X509_free(ret); - if (a) - *a = NULL; - } +X509 *d2i_X509_AUX(X509 **a, const unsigned char **pp, long length) { + const unsigned char *q = *pp; + X509 *ret; + int freeret = 0; + + if (!a || *a == NULL) { + freeret = 1; + } + ret = d2i_X509(a, &q, length); + /* If certificate unreadable then forget it */ + if (!ret) { return NULL; + } + /* update length */ + length -= q - *pp; + /* Parse auxiliary information if there is any. */ + if (length > 0 && !d2i_X509_CERT_AUX(&ret->aux, &q, length)) { + goto err; + } + *pp = q; + return ret; +err: + if (freeret) { + X509_free(ret); + if (a) { + *a = NULL; + } + } + return NULL; } /* @@ -272,34 +268,34 @@ X509 *d2i_X509_AUX(X509 **a, const unsigned char **pp, long length) * error path, but that depends on similar hygiene in lower-level functions. * Here we avoid compounding the problem. */ -static int i2d_x509_aux_internal(X509 *a, unsigned char **pp) -{ - int length, tmplen; - unsigned char *start = pp != NULL ? *pp : NULL; - - assert(pp == NULL || *pp != NULL); - - /* - * This might perturb *pp on error, but fixing that belongs in i2d_X509() - * not here. It should be that if a == NULL length is zero, but we check - * both just in case. - */ - length = i2d_X509(a, pp); - if (length <= 0 || a == NULL) { - return length; - } +static int i2d_x509_aux_internal(X509 *a, unsigned char **pp) { + int length, tmplen; + unsigned char *start = pp != NULL ? *pp : NULL; + + assert(pp == NULL || *pp != NULL); + + /* + * This might perturb *pp on error, but fixing that belongs in i2d_X509() + * not here. It should be that if a == NULL length is zero, but we check + * both just in case. + */ + length = i2d_X509(a, pp); + if (length <= 0 || a == NULL) { + return length; + } - if (a->aux != NULL) { - tmplen = i2d_X509_CERT_AUX(a->aux, pp); - if (tmplen < 0) { - if (start != NULL) - *pp = start; - return tmplen; - } - length += tmplen; + if (a->aux != NULL) { + tmplen = i2d_X509_CERT_AUX(a->aux, pp); + if (tmplen < 0) { + if (start != NULL) { + *pp = start; + } + return tmplen; } + length += tmplen; + } - return length; + return length; } /* @@ -311,84 +307,82 @@ static int i2d_x509_aux_internal(X509 *a, unsigned char **pp) * the allocation, nor can we allow i2d_X509_CERT_AUX() to increment the * allocated buffer. */ -int i2d_X509_AUX(X509 *a, unsigned char **pp) -{ - int length; - unsigned char *tmp; - - /* Buffer provided by caller */ - if (pp == NULL || *pp != NULL) - return i2d_x509_aux_internal(a, pp); - - /* Obtain the combined length */ - if ((length = i2d_x509_aux_internal(a, NULL)) <= 0) - return length; - - /* Allocate requisite combined storage */ - *pp = tmp = OPENSSL_malloc(length); - if (tmp == NULL) - return -1; /* Push error onto error stack? */ - - /* Encode, but keep *pp at the originally malloced pointer */ - length = i2d_x509_aux_internal(a, &tmp); - if (length <= 0) { - OPENSSL_free(*pp); - *pp = NULL; - } +int i2d_X509_AUX(X509 *a, unsigned char **pp) { + int length; + unsigned char *tmp; + + /* Buffer provided by caller */ + if (pp == NULL || *pp != NULL) { + return i2d_x509_aux_internal(a, pp); + } + + /* Obtain the combined length */ + if ((length = i2d_x509_aux_internal(a, NULL)) <= 0) { return length; + } + + /* Allocate requisite combined storage */ + *pp = tmp = OPENSSL_malloc(length); + if (tmp == NULL) { + return -1; /* Push error onto error stack? */ + } + + /* Encode, but keep *pp at the originally malloced pointer */ + length = i2d_x509_aux_internal(a, &tmp); + if (length <= 0) { + OPENSSL_free(*pp); + *pp = NULL; + } + return length; } -int i2d_re_X509_tbs(X509 *x509, unsigned char **outp) -{ - x509->cert_info->enc.modified = 1; - return i2d_X509_CINF(x509->cert_info, outp); +int i2d_re_X509_tbs(X509 *x509, unsigned char **outp) { + x509->cert_info->enc.modified = 1; + return i2d_X509_CINF(x509->cert_info, outp); } -int i2d_X509_tbs(X509 *x509, unsigned char **outp) -{ - return i2d_X509_CINF(x509->cert_info, outp); +int i2d_X509_tbs(X509 *x509, unsigned char **outp) { + return i2d_X509_CINF(x509->cert_info, outp); } -int X509_set1_signature_algo(X509 *x509, const X509_ALGOR *algo) -{ - /* TODO(https://crbug.com/boringssl/407): Generated ASN.1 dup functions - * should be const. Alternatively, when we can embed required fields - * directly in structs, import |X509_ALGOR_copy| from upstream. */ - X509_ALGOR *copy1 = X509_ALGOR_dup((X509_ALGOR *)algo); - X509_ALGOR *copy2 = X509_ALGOR_dup((X509_ALGOR *)algo); - if (copy1 == NULL || copy2 == NULL) { - X509_ALGOR_free(copy1); - X509_ALGOR_free(copy2); - return 0; - } +int X509_set1_signature_algo(X509 *x509, const X509_ALGOR *algo) { + /* TODO(https://crbug.com/boringssl/407): Generated ASN.1 dup functions + * should be const. Alternatively, when we can embed required fields + * directly in structs, import |X509_ALGOR_copy| from upstream. */ + X509_ALGOR *copy1 = X509_ALGOR_dup((X509_ALGOR *)algo); + X509_ALGOR *copy2 = X509_ALGOR_dup((X509_ALGOR *)algo); + if (copy1 == NULL || copy2 == NULL) { + X509_ALGOR_free(copy1); + X509_ALGOR_free(copy2); + return 0; + } - X509_ALGOR_free(x509->sig_alg); - x509->sig_alg = copy1; - X509_ALGOR_free(x509->cert_info->signature); - x509->cert_info->signature = copy2; - return 1; + X509_ALGOR_free(x509->sig_alg); + x509->sig_alg = copy1; + X509_ALGOR_free(x509->cert_info->signature); + x509->cert_info->signature = copy2; + return 1; } -int X509_set1_signature_value(X509 *x509, const uint8_t *sig, size_t sig_len) -{ - if (!ASN1_STRING_set(x509->signature, sig, sig_len)) { - return 0; - } - x509->signature->flags &= ~(ASN1_STRING_FLAG_BITS_LEFT | 0x07); - x509->signature->flags |= ASN1_STRING_FLAG_BITS_LEFT; - return 1; +int X509_set1_signature_value(X509 *x509, const uint8_t *sig, size_t sig_len) { + if (!ASN1_STRING_set(x509->signature, sig, sig_len)) { + return 0; + } + x509->signature->flags &= ~(ASN1_STRING_FLAG_BITS_LEFT | 0x07); + x509->signature->flags |= ASN1_STRING_FLAG_BITS_LEFT; + return 1; } void X509_get0_signature(const ASN1_BIT_STRING **psig, const X509_ALGOR **palg, - const X509 *x) -{ - if (psig) - *psig = x->signature; - if (palg) - *palg = x->sig_alg; + const X509 *x) { + if (psig) { + *psig = x->signature; + } + if (palg) { + *palg = x->sig_alg; + } } -int X509_get_signature_nid(const X509 *x) -{ - return OBJ_obj2nid(x->sig_alg->algorithm); +int X509_get_signature_nid(const X509 *x) { + return OBJ_obj2nid(x->sig_alg->algorithm); } diff --git a/crypto/x509/x_x509a.c b/crypto/x509/x_x509a.c index d0e921f2a7..96161f50dc 100644 --- a/crypto/x509/x_x509a.c +++ b/crypto/x509/x_x509a.c @@ -74,133 +74,138 @@ static X509_CERT_AUX *aux_get(X509 *x); ASN1_SEQUENCE(X509_CERT_AUX) = { - ASN1_SEQUENCE_OF_OPT(X509_CERT_AUX, trust, ASN1_OBJECT), - ASN1_IMP_SEQUENCE_OF_OPT(X509_CERT_AUX, reject, ASN1_OBJECT, 0), - ASN1_OPT(X509_CERT_AUX, alias, ASN1_UTF8STRING), - ASN1_OPT(X509_CERT_AUX, keyid, ASN1_OCTET_STRING), + ASN1_SEQUENCE_OF_OPT(X509_CERT_AUX, trust, ASN1_OBJECT), + ASN1_IMP_SEQUENCE_OF_OPT(X509_CERT_AUX, reject, ASN1_OBJECT, 0), + ASN1_OPT(X509_CERT_AUX, alias, ASN1_UTF8STRING), + ASN1_OPT(X509_CERT_AUX, keyid, ASN1_OCTET_STRING), } ASN1_SEQUENCE_END(X509_CERT_AUX) IMPLEMENT_ASN1_FUNCTIONS(X509_CERT_AUX) -static X509_CERT_AUX *aux_get(X509 *x) -{ - if (!x) - return NULL; - if (!x->aux && !(x->aux = X509_CERT_AUX_new())) - return NULL; - return x->aux; +static X509_CERT_AUX *aux_get(X509 *x) { + if (!x) { + return NULL; + } + if (!x->aux && !(x->aux = X509_CERT_AUX_new())) { + return NULL; + } + return x->aux; } -int X509_alias_set1(X509 *x, const unsigned char *name, int len) -{ - X509_CERT_AUX *aux; - /* TODO(davidben): Empty aliases are not meaningful in PKCS#12, and the - * getters cannot quite represent them. Also erase the object if |len| is - * zero. */ - if (!name) { - if (!x || !x->aux || !x->aux->alias) - return 1; - ASN1_UTF8STRING_free(x->aux->alias); - x->aux->alias = NULL; - return 1; +int X509_alias_set1(X509 *x, const unsigned char *name, int len) { + X509_CERT_AUX *aux; + /* TODO(davidben): Empty aliases are not meaningful in PKCS#12, and the + * getters cannot quite represent them. Also erase the object if |len| is + * zero. */ + if (!name) { + if (!x || !x->aux || !x->aux->alias) { + return 1; } - if (!(aux = aux_get(x))) - return 0; - if (!aux->alias && !(aux->alias = ASN1_UTF8STRING_new())) - return 0; - return ASN1_STRING_set(aux->alias, name, len); + ASN1_UTF8STRING_free(x->aux->alias); + x->aux->alias = NULL; + return 1; + } + if (!(aux = aux_get(x))) { + return 0; + } + if (!aux->alias && !(aux->alias = ASN1_UTF8STRING_new())) { + return 0; + } + return ASN1_STRING_set(aux->alias, name, len); } -int X509_keyid_set1(X509 *x, const unsigned char *id, int len) -{ - X509_CERT_AUX *aux; - /* TODO(davidben): Empty key IDs are not meaningful in PKCS#12, and the - * getters cannot quite represent them. Also erase the object if |len| is - * zero. */ - if (!id) { - if (!x || !x->aux || !x->aux->keyid) - return 1; - ASN1_OCTET_STRING_free(x->aux->keyid); - x->aux->keyid = NULL; - return 1; +int X509_keyid_set1(X509 *x, const unsigned char *id, int len) { + X509_CERT_AUX *aux; + /* TODO(davidben): Empty key IDs are not meaningful in PKCS#12, and the + * getters cannot quite represent them. Also erase the object if |len| is + * zero. */ + if (!id) { + if (!x || !x->aux || !x->aux->keyid) { + return 1; } - if (!(aux = aux_get(x))) - return 0; - if (!aux->keyid && !(aux->keyid = ASN1_OCTET_STRING_new())) - return 0; - return ASN1_STRING_set(aux->keyid, id, len); + ASN1_OCTET_STRING_free(x->aux->keyid); + x->aux->keyid = NULL; + return 1; + } + if (!(aux = aux_get(x))) { + return 0; + } + if (!aux->keyid && !(aux->keyid = ASN1_OCTET_STRING_new())) { + return 0; + } + return ASN1_STRING_set(aux->keyid, id, len); } -unsigned char *X509_alias_get0(X509 *x, int *out_len) -{ - const ASN1_UTF8STRING *alias = x->aux != NULL ? x->aux->alias : NULL; - if (out_len != NULL) { - *out_len = alias != NULL ? alias->length : 0; - } - return alias != NULL ? alias->data : NULL; +unsigned char *X509_alias_get0(X509 *x, int *out_len) { + const ASN1_UTF8STRING *alias = x->aux != NULL ? x->aux->alias : NULL; + if (out_len != NULL) { + *out_len = alias != NULL ? alias->length : 0; + } + return alias != NULL ? alias->data : NULL; } -unsigned char *X509_keyid_get0(X509 *x, int *out_len) -{ - const ASN1_OCTET_STRING *keyid = x->aux != NULL ? x->aux->keyid : NULL; - if (out_len != NULL) { - *out_len = keyid != NULL ? keyid->length : 0; - } - return keyid != NULL ? keyid->data : NULL; +unsigned char *X509_keyid_get0(X509 *x, int *out_len) { + const ASN1_OCTET_STRING *keyid = x->aux != NULL ? x->aux->keyid : NULL; + if (out_len != NULL) { + *out_len = keyid != NULL ? keyid->length : 0; + } + return keyid != NULL ? keyid->data : NULL; } -int X509_add1_trust_object(X509 *x, ASN1_OBJECT *obj) -{ - ASN1_OBJECT *objtmp = OBJ_dup(obj); - if (objtmp == NULL) - goto err; - X509_CERT_AUX *aux = aux_get(x); +int X509_add1_trust_object(X509 *x, ASN1_OBJECT *obj) { + ASN1_OBJECT *objtmp = OBJ_dup(obj); + if (objtmp == NULL) { + goto err; + } + X509_CERT_AUX *aux = aux_get(x); + if (aux->trust == NULL) { + aux->trust = sk_ASN1_OBJECT_new_null(); if (aux->trust == NULL) { - aux->trust = sk_ASN1_OBJECT_new_null(); - if (aux->trust == NULL) - goto err; + goto err; } - if (!sk_ASN1_OBJECT_push(aux->trust, objtmp)) - goto err; - return 1; - - err: - ASN1_OBJECT_free(objtmp); - return 0; + } + if (!sk_ASN1_OBJECT_push(aux->trust, objtmp)) { + goto err; + } + return 1; + +err: + ASN1_OBJECT_free(objtmp); + return 0; } -int X509_add1_reject_object(X509 *x, ASN1_OBJECT *obj) -{ - ASN1_OBJECT *objtmp = OBJ_dup(obj); - if (objtmp == NULL) - goto err; - X509_CERT_AUX *aux = aux_get(x); +int X509_add1_reject_object(X509 *x, ASN1_OBJECT *obj) { + ASN1_OBJECT *objtmp = OBJ_dup(obj); + if (objtmp == NULL) { + goto err; + } + X509_CERT_AUX *aux = aux_get(x); + if (aux->reject == NULL) { + aux->reject = sk_ASN1_OBJECT_new_null(); if (aux->reject == NULL) { - aux->reject = sk_ASN1_OBJECT_new_null(); - if (aux->reject == NULL) - goto err; + goto err; } - if (!sk_ASN1_OBJECT_push(aux->reject, objtmp)) - goto err; - return 1; - - err: - ASN1_OBJECT_free(objtmp); - return 0; + } + if (!sk_ASN1_OBJECT_push(aux->reject, objtmp)) { + goto err; + } + return 1; + +err: + ASN1_OBJECT_free(objtmp); + return 0; } -void X509_trust_clear(X509 *x) -{ - if (x->aux && x->aux->trust) { - sk_ASN1_OBJECT_pop_free(x->aux->trust, ASN1_OBJECT_free); - x->aux->trust = NULL; - } +void X509_trust_clear(X509 *x) { + if (x->aux && x->aux->trust) { + sk_ASN1_OBJECT_pop_free(x->aux->trust, ASN1_OBJECT_free); + x->aux->trust = NULL; + } } -void X509_reject_clear(X509 *x) -{ - if (x->aux && x->aux->reject) { - sk_ASN1_OBJECT_pop_free(x->aux->reject, ASN1_OBJECT_free); - x->aux->reject = NULL; - } +void X509_reject_clear(X509 *x) { + if (x->aux && x->aux->reject) { + sk_ASN1_OBJECT_pop_free(x->aux->reject, ASN1_OBJECT_free); + x->aux->reject = NULL; + } } diff --git a/crypto/x509v3/ext_dat.h b/crypto/x509v3/ext_dat.h index 7930126394..0773608726 100644 --- a/crypto/x509v3/ext_dat.h +++ b/crypto/x509v3/ext_dat.h @@ -65,10 +65,8 @@ extern const X509V3_EXT_METHOD v3_info, v3_sinfo; extern const X509V3_EXT_METHOD v3_ns_ia5_list[], v3_alt[], v3_skey_id, v3_akey_id; extern const X509V3_EXT_METHOD v3_crl_num, v3_crl_reason, v3_crl_invdate; -extern const X509V3_EXT_METHOD v3_delta_crl, v3_cpols, v3_crld, - v3_freshest_crl; -extern const X509V3_EXT_METHOD v3_ocsp_nonce, v3_ocsp_accresp, - v3_ocsp_acutoff; +extern const X509V3_EXT_METHOD v3_delta_crl, v3_cpols, v3_crld, v3_freshest_crl; +extern const X509V3_EXT_METHOD v3_ocsp_nonce, v3_ocsp_accresp, v3_ocsp_acutoff; extern const X509V3_EXT_METHOD v3_ocsp_crlid, v3_ocsp_nocheck, v3_ocsp_serviceloc; extern const X509V3_EXT_METHOD v3_crl_hold, v3_pci; @@ -131,7 +129,8 @@ static const X509V3_EXT_METHOD *const standard_exts[] = { /* Number of standard extensions */ -#define STANDARD_EXTENSION_COUNT (sizeof(standard_exts)/sizeof(X509V3_EXT_METHOD *)) +#define STANDARD_EXTENSION_COUNT \ + (sizeof(standard_exts) / sizeof(X509V3_EXT_METHOD *)) #if defined(__cplusplus) } /* extern C */ diff --git a/crypto/x509v3/internal.h b/crypto/x509v3/internal.h index 976e34d334..b26b313cfa 100644 --- a/crypto/x509v3/internal.h +++ b/crypto/x509v3/internal.h @@ -136,11 +136,11 @@ DEFINE_STACK_OF(X509_POLICY_DATA) */ struct X509_POLICY_DATA_st { - unsigned int flags; - /* Policy OID and qualifiers for this data */ - ASN1_OBJECT *valid_policy; - STACK_OF(POLICYQUALINFO) *qualifier_set; - STACK_OF(ASN1_OBJECT) *expected_policy_set; + unsigned int flags; + /* Policy OID and qualifiers for this data */ + ASN1_OBJECT *valid_policy; + STACK_OF(POLICYQUALINFO) *qualifier_set; + STACK_OF(ASN1_OBJECT) *expected_policy_set; }; /* X509_POLICY_DATA flags values */ @@ -150,50 +150,50 @@ struct X509_POLICY_DATA_st { * extension. If policy mapping is not active its references get deleted. */ -#define POLICY_DATA_FLAG_MAPPED 0x1 +#define POLICY_DATA_FLAG_MAPPED 0x1 /* * This flag indicates the data doesn't correspond to a policy in Certificate * Policies: it has been mapped to any policy. */ -#define POLICY_DATA_FLAG_MAPPED_ANY 0x2 +#define POLICY_DATA_FLAG_MAPPED_ANY 0x2 /* AND with flags to see if any mapping has occurred */ -#define POLICY_DATA_FLAG_MAP_MASK 0x3 +#define POLICY_DATA_FLAG_MAP_MASK 0x3 /* qualifiers are shared and shouldn't be freed */ -#define POLICY_DATA_FLAG_SHARED_QUALIFIERS 0x4 +#define POLICY_DATA_FLAG_SHARED_QUALIFIERS 0x4 /* Parent node is an extra node and should be freed */ -#define POLICY_DATA_FLAG_EXTRA_NODE 0x8 +#define POLICY_DATA_FLAG_EXTRA_NODE 0x8 /* Corresponding CertificatePolicies is critical */ -#define POLICY_DATA_FLAG_CRITICAL 0x10 +#define POLICY_DATA_FLAG_CRITICAL 0x10 /* This structure is cached with a certificate */ struct X509_POLICY_CACHE_st { - /* anyPolicy data or NULL if no anyPolicy */ - X509_POLICY_DATA *anyPolicy; - /* other policy data */ - STACK_OF(X509_POLICY_DATA) *data; - /* If InhibitAnyPolicy present this is its value or -1 if absent. */ - long any_skip; - /* - * If policyConstraints and requireExplicitPolicy present this is its - * value or -1 if absent. - */ - long explicit_skip; - /* - * If policyConstraints and policyMapping present this is its value or -1 - * if absent. - */ - long map_skip; + /* anyPolicy data or NULL if no anyPolicy */ + X509_POLICY_DATA *anyPolicy; + /* other policy data */ + STACK_OF(X509_POLICY_DATA) *data; + /* If InhibitAnyPolicy present this is its value or -1 if absent. */ + long any_skip; + /* + * If policyConstraints and requireExplicitPolicy present this is its + * value or -1 if absent. + */ + long explicit_skip; + /* + * If policyConstraints and policyMapping present this is its value or -1 + * if absent. + */ + long map_skip; }; /* @@ -203,45 +203,45 @@ struct X509_POLICY_CACHE_st { /* This structure represents the relationship between nodes */ struct X509_POLICY_NODE_st { - /* node data this refers to */ - const X509_POLICY_DATA *data; - /* Parent node */ - X509_POLICY_NODE *parent; - /* Number of child nodes */ - int nchild; + /* node data this refers to */ + const X509_POLICY_DATA *data; + /* Parent node */ + X509_POLICY_NODE *parent; + /* Number of child nodes */ + int nchild; }; struct X509_POLICY_LEVEL_st { - /* Cert for this level */ - X509 *cert; - /* nodes at this level */ - STACK_OF(X509_POLICY_NODE) *nodes; - /* anyPolicy node */ - X509_POLICY_NODE *anyPolicy; - /* Extra data */ - /* - * STACK_OF(X509_POLICY_DATA) *extra_data; - */ - unsigned int flags; + /* Cert for this level */ + X509 *cert; + /* nodes at this level */ + STACK_OF(X509_POLICY_NODE) *nodes; + /* anyPolicy node */ + X509_POLICY_NODE *anyPolicy; + /* Extra data */ + /* + * STACK_OF(X509_POLICY_DATA) *extra_data; + */ + unsigned int flags; }; struct X509_POLICY_TREE_st { - /* This is the tree 'level' data */ - X509_POLICY_LEVEL *levels; - int nlevel; - /* - * Extra policy data when additional nodes (not from the certificate) are - * required. - */ - STACK_OF(X509_POLICY_DATA) *extra_data; - /* This is the authority constained policy set */ - STACK_OF(X509_POLICY_NODE) *auth_policies; - STACK_OF(X509_POLICY_NODE) *user_policies; - unsigned int flags; + /* This is the tree 'level' data */ + X509_POLICY_LEVEL *levels; + int nlevel; + /* + * Extra policy data when additional nodes (not from the certificate) are + * required. + */ + STACK_OF(X509_POLICY_DATA) *extra_data; + /* This is the authority constained policy set */ + STACK_OF(X509_POLICY_NODE) *auth_policies; + STACK_OF(X509_POLICY_NODE) *user_policies; + unsigned int flags; }; /* Set if anyPolicy present in user policies */ -#define POLICY_FLAG_ANY_POLICY 0x2 +#define POLICY_FLAG_ANY_POLICY 0x2 /* Useful macros */ @@ -283,7 +283,7 @@ const X509_POLICY_CACHE *policy_cache_set(X509 *x); #if defined(__cplusplus) -} /* extern C */ +} /* extern C */ #endif -#endif /* OPENSSL_HEADER_X509V3_INTERNAL_H */ +#endif /* OPENSSL_HEADER_X509V3_INTERNAL_H */ diff --git a/crypto/x509v3/pcy_cache.c b/crypto/x509v3/pcy_cache.c index 8303664a21..f4de366b54 100644 --- a/crypto/x509v3/pcy_cache.c +++ b/crypto/x509v3/pcy_cache.c @@ -73,160 +73,177 @@ static int policy_cache_set_int(long *out, ASN1_INTEGER *value); * destroys the passed CERTIFICATEPOLICIES structure. */ -static int policy_cache_create(X509 *x, - CERTIFICATEPOLICIES *policies, int crit) -{ - size_t i; - int ret = 0; - X509_POLICY_CACHE *cache = x->policy_cache; - X509_POLICY_DATA *data = NULL; - POLICYINFO *policy; - if (sk_POLICYINFO_num(policies) == 0) - goto bad_policy; - cache->data = sk_X509_POLICY_DATA_new(policy_data_cmp); - if (!cache->data) - goto bad_policy; - for (i = 0; i < sk_POLICYINFO_num(policies); i++) { - policy = sk_POLICYINFO_value(policies, i); - data = policy_data_new(policy, NULL, crit); - if (!data) - goto bad_policy; - /* - * Duplicate policy OIDs are illegal: reject if matches found. - */ - sk_X509_POLICY_DATA_sort(cache->data); - if (OBJ_obj2nid(data->valid_policy) == NID_any_policy) { - if (cache->anyPolicy) { - ret = -1; - goto bad_policy; - } - cache->anyPolicy = data; - } else if (sk_X509_POLICY_DATA_find(cache->data, NULL, data)) { - ret = -1; - goto bad_policy; - } else if (!sk_X509_POLICY_DATA_push(cache->data, data)) - goto bad_policy; - data = NULL; +static int policy_cache_create(X509 *x, CERTIFICATEPOLICIES *policies, + int crit) { + size_t i; + int ret = 0; + X509_POLICY_CACHE *cache = x->policy_cache; + X509_POLICY_DATA *data = NULL; + POLICYINFO *policy; + if (sk_POLICYINFO_num(policies) == 0) { + goto bad_policy; + } + cache->data = sk_X509_POLICY_DATA_new(policy_data_cmp); + if (!cache->data) { + goto bad_policy; + } + for (i = 0; i < sk_POLICYINFO_num(policies); i++) { + policy = sk_POLICYINFO_value(policies, i); + data = policy_data_new(policy, NULL, crit); + if (!data) { + goto bad_policy; } - ret = 1; - bad_policy: - if (ret == -1) - x->ex_flags |= EXFLAG_INVALID_POLICY; - if (data) - policy_data_free(data); - sk_POLICYINFO_pop_free(policies, POLICYINFO_free); - if (ret <= 0) { - sk_X509_POLICY_DATA_pop_free(cache->data, policy_data_free); - cache->data = NULL; - } - return ret; -} - -static int policy_cache_new(X509 *x) -{ - X509_POLICY_CACHE *cache; - ASN1_INTEGER *ext_any = NULL; - POLICY_CONSTRAINTS *ext_pcons = NULL; - CERTIFICATEPOLICIES *ext_cpols = NULL; - POLICY_MAPPINGS *ext_pmaps = NULL; - int i; - cache = OPENSSL_malloc(sizeof(X509_POLICY_CACHE)); - if (!cache) - return 0; - cache->anyPolicy = NULL; - cache->data = NULL; - cache->any_skip = -1; - cache->explicit_skip = -1; - cache->map_skip = -1; - - x->policy_cache = cache; - /* - * Handle requireExplicitPolicy *first*. Need to process this even if we - * don't have any policies. + * Duplicate policy OIDs are illegal: reject if matches found. */ - ext_pcons = X509_get_ext_d2i(x, NID_policy_constraints, &i, NULL); - - if (!ext_pcons) { - if (i != -1) - goto bad_cache; - } else { - if (!ext_pcons->requireExplicitPolicy - && !ext_pcons->inhibitPolicyMapping) - goto bad_cache; - if (!policy_cache_set_int(&cache->explicit_skip, - ext_pcons->requireExplicitPolicy)) - goto bad_cache; - if (!policy_cache_set_int(&cache->map_skip, - ext_pcons->inhibitPolicyMapping)) - goto bad_cache; + sk_X509_POLICY_DATA_sort(cache->data); + if (OBJ_obj2nid(data->valid_policy) == NID_any_policy) { + if (cache->anyPolicy) { + ret = -1; + goto bad_policy; + } + cache->anyPolicy = data; + } else if (sk_X509_POLICY_DATA_find(cache->data, NULL, data)) { + ret = -1; + goto bad_policy; + } else if (!sk_X509_POLICY_DATA_push(cache->data, data)) { + goto bad_policy; } + data = NULL; + } + ret = 1; +bad_policy: + if (ret == -1) { + x->ex_flags |= EXFLAG_INVALID_POLICY; + } + if (data) { + policy_data_free(data); + } + sk_POLICYINFO_pop_free(policies, POLICYINFO_free); + if (ret <= 0) { + sk_X509_POLICY_DATA_pop_free(cache->data, policy_data_free); + cache->data = NULL; + } + return ret; +} - /* Process CertificatePolicies */ - - ext_cpols = X509_get_ext_d2i(x, NID_certificate_policies, &i, NULL); - /* - * If no CertificatePolicies extension or problem decoding then there is - * no point continuing because the valid policies will be NULL. - */ - if (!ext_cpols) { - /* If not absent some problem with extension */ - if (i != -1) - goto bad_cache; - return 1; +static int policy_cache_new(X509 *x) { + X509_POLICY_CACHE *cache; + ASN1_INTEGER *ext_any = NULL; + POLICY_CONSTRAINTS *ext_pcons = NULL; + CERTIFICATEPOLICIES *ext_cpols = NULL; + POLICY_MAPPINGS *ext_pmaps = NULL; + int i; + cache = OPENSSL_malloc(sizeof(X509_POLICY_CACHE)); + if (!cache) { + return 0; + } + cache->anyPolicy = NULL; + cache->data = NULL; + cache->any_skip = -1; + cache->explicit_skip = -1; + cache->map_skip = -1; + + x->policy_cache = cache; + + /* + * Handle requireExplicitPolicy *first*. Need to process this even if we + * don't have any policies. + */ + ext_pcons = X509_get_ext_d2i(x, NID_policy_constraints, &i, NULL); + + if (!ext_pcons) { + if (i != -1) { + goto bad_cache; + } + } else { + if (!ext_pcons->requireExplicitPolicy && !ext_pcons->inhibitPolicyMapping) { + goto bad_cache; + } + if (!policy_cache_set_int(&cache->explicit_skip, + ext_pcons->requireExplicitPolicy)) { + goto bad_cache; + } + if (!policy_cache_set_int(&cache->map_skip, + ext_pcons->inhibitPolicyMapping)) { + goto bad_cache; } + } + + /* Process CertificatePolicies */ + + ext_cpols = X509_get_ext_d2i(x, NID_certificate_policies, &i, NULL); + /* + * If no CertificatePolicies extension or problem decoding then there is + * no point continuing because the valid policies will be NULL. + */ + if (!ext_cpols) { + /* If not absent some problem with extension */ + if (i != -1) { + goto bad_cache; + } + return 1; + } - i = policy_cache_create(x, ext_cpols, i); + i = policy_cache_create(x, ext_cpols, i); - /* NB: ext_cpols freed by policy_cache_set_policies */ + /* NB: ext_cpols freed by policy_cache_set_policies */ - if (i <= 0) - return i; + if (i <= 0) { + return i; + } - ext_pmaps = X509_get_ext_d2i(x, NID_policy_mappings, &i, NULL); + ext_pmaps = X509_get_ext_d2i(x, NID_policy_mappings, &i, NULL); - if (!ext_pmaps) { - /* If not absent some problem with extension */ - if (i != -1) - goto bad_cache; - } else { - i = policy_cache_set_mapping(x, ext_pmaps); - if (i <= 0) - goto bad_cache; + if (!ext_pmaps) { + /* If not absent some problem with extension */ + if (i != -1) { + goto bad_cache; } + } else { + i = policy_cache_set_mapping(x, ext_pmaps); + if (i <= 0) { + goto bad_cache; + } + } - ext_any = X509_get_ext_d2i(x, NID_inhibit_any_policy, &i, NULL); - - if (!ext_any) { - if (i != -1) - goto bad_cache; - } else if (!policy_cache_set_int(&cache->any_skip, ext_any)) - goto bad_cache; + ext_any = X509_get_ext_d2i(x, NID_inhibit_any_policy, &i, NULL); - if (0) { - bad_cache: - x->ex_flags |= EXFLAG_INVALID_POLICY; + if (!ext_any) { + if (i != -1) { + goto bad_cache; } + } else if (!policy_cache_set_int(&cache->any_skip, ext_any)) { + goto bad_cache; + } - if (ext_pcons) - POLICY_CONSTRAINTS_free(ext_pcons); + if (0) { + bad_cache: + x->ex_flags |= EXFLAG_INVALID_POLICY; + } - if (ext_any) - ASN1_INTEGER_free(ext_any); + if (ext_pcons) { + POLICY_CONSTRAINTS_free(ext_pcons); + } - return 1; + if (ext_any) { + ASN1_INTEGER_free(ext_any); + } + return 1; } -void policy_cache_free(X509_POLICY_CACHE *cache) -{ - if (!cache) - return; - if (cache->anyPolicy) - policy_data_free(cache->anyPolicy); - if (cache->data) - sk_X509_POLICY_DATA_pop_free(cache->data, policy_data_free); - OPENSSL_free(cache); +void policy_cache_free(X509_POLICY_CACHE *cache) { + if (!cache) { + return; + } + if (cache->anyPolicy) { + policy_data_free(cache->anyPolicy); + } + if (cache->data) { + sk_X509_POLICY_DATA_pop_free(cache->data, policy_data_free); + } + OPENSSL_free(cache); } /* @@ -237,51 +254,52 @@ void policy_cache_free(X509_POLICY_CACHE *cache) static struct CRYPTO_STATIC_MUTEX g_x509_policy_cache_lock = CRYPTO_STATIC_MUTEX_INIT; -const X509_POLICY_CACHE *policy_cache_set(X509 *x) -{ - X509_POLICY_CACHE *cache; +const X509_POLICY_CACHE *policy_cache_set(X509 *x) { + X509_POLICY_CACHE *cache; - CRYPTO_STATIC_MUTEX_lock_read(&g_x509_policy_cache_lock); - cache = x->policy_cache; - CRYPTO_STATIC_MUTEX_unlock_read(&g_x509_policy_cache_lock); + CRYPTO_STATIC_MUTEX_lock_read(&g_x509_policy_cache_lock); + cache = x->policy_cache; + CRYPTO_STATIC_MUTEX_unlock_read(&g_x509_policy_cache_lock); - if (cache != NULL) - return cache; + if (cache != NULL) { + return cache; + } - CRYPTO_STATIC_MUTEX_lock_write(&g_x509_policy_cache_lock); - if (x->policy_cache == NULL) - policy_cache_new(x); - cache = x->policy_cache; - CRYPTO_STATIC_MUTEX_unlock_write(&g_x509_policy_cache_lock); + CRYPTO_STATIC_MUTEX_lock_write(&g_x509_policy_cache_lock); + if (x->policy_cache == NULL) { + policy_cache_new(x); + } + cache = x->policy_cache; + CRYPTO_STATIC_MUTEX_unlock_write(&g_x509_policy_cache_lock); - return cache; + return cache; } X509_POLICY_DATA *policy_cache_find_data(const X509_POLICY_CACHE *cache, - const ASN1_OBJECT *id) -{ - size_t idx; - X509_POLICY_DATA tmp; - - tmp.valid_policy = (ASN1_OBJECT *)id; - sk_X509_POLICY_DATA_sort(cache->data); - if (!sk_X509_POLICY_DATA_find(cache->data, &idx, &tmp)) - return NULL; - return sk_X509_POLICY_DATA_value(cache->data, idx); + const ASN1_OBJECT *id) { + size_t idx; + X509_POLICY_DATA tmp; + + tmp.valid_policy = (ASN1_OBJECT *)id; + sk_X509_POLICY_DATA_sort(cache->data); + if (!sk_X509_POLICY_DATA_find(cache->data, &idx, &tmp)) { + return NULL; + } + return sk_X509_POLICY_DATA_value(cache->data, idx); } static int policy_data_cmp(const X509_POLICY_DATA **a, - const X509_POLICY_DATA **b) -{ - return OBJ_cmp((*a)->valid_policy, (*b)->valid_policy); + const X509_POLICY_DATA **b) { + return OBJ_cmp((*a)->valid_policy, (*b)->valid_policy); } -static int policy_cache_set_int(long *out, ASN1_INTEGER *value) -{ - if (value == NULL) - return 1; - if (value->type == V_ASN1_NEG_INTEGER) - return 0; - *out = ASN1_INTEGER_get(value); +static int policy_cache_set_int(long *out, ASN1_INTEGER *value) { + if (value == NULL) { return 1; + } + if (value->type == V_ASN1_NEG_INTEGER) { + return 0; + } + *out = ASN1_INTEGER_get(value); + return 1; } diff --git a/crypto/x509v3/pcy_data.c b/crypto/x509v3/pcy_data.c index f83795d7f5..e2df5b243c 100644 --- a/crypto/x509v3/pcy_data.c +++ b/crypto/x509v3/pcy_data.c @@ -66,14 +66,14 @@ /* Policy Node routines */ -void policy_data_free(X509_POLICY_DATA *data) -{ - ASN1_OBJECT_free(data->valid_policy); - /* Don't free qualifiers if shared */ - if (!(data->flags & POLICY_DATA_FLAG_SHARED_QUALIFIERS)) - sk_POLICYQUALINFO_pop_free(data->qualifier_set, POLICYQUALINFO_free); - sk_ASN1_OBJECT_pop_free(data->expected_policy_set, ASN1_OBJECT_free); - OPENSSL_free(data); +void policy_data_free(X509_POLICY_DATA *data) { + ASN1_OBJECT_free(data->valid_policy); + /* Don't free qualifiers if shared */ + if (!(data->flags & POLICY_DATA_FLAG_SHARED_QUALIFIERS)) { + sk_POLICYQUALINFO_pop_free(data->qualifier_set, POLICYQUALINFO_free); + } + sk_ASN1_OBJECT_pop_free(data->expected_policy_set, ASN1_OBJECT_free); + OPENSSL_free(data); } /* @@ -84,49 +84,53 @@ void policy_data_free(X509_POLICY_DATA *data) * source. */ -X509_POLICY_DATA *policy_data_new(POLICYINFO *policy, - const ASN1_OBJECT *cid, int crit) -{ - X509_POLICY_DATA *ret; - ASN1_OBJECT *id; - if (!policy && !cid) - return NULL; - if (cid) { - id = OBJ_dup(cid); - if (!id) - return NULL; - } else - id = NULL; - ret = OPENSSL_malloc(sizeof(X509_POLICY_DATA)); - if (!ret) { - OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE); - ASN1_OBJECT_free(id); - return NULL; - } - ret->expected_policy_set = sk_ASN1_OBJECT_new_null(); - if (!ret->expected_policy_set) { - OPENSSL_free(ret); - ASN1_OBJECT_free(id); - return NULL; +X509_POLICY_DATA *policy_data_new(POLICYINFO *policy, const ASN1_OBJECT *cid, + int crit) { + X509_POLICY_DATA *ret; + ASN1_OBJECT *id; + if (!policy && !cid) { + return NULL; + } + if (cid) { + id = OBJ_dup(cid); + if (!id) { + return NULL; } + } else { + id = NULL; + } + ret = OPENSSL_malloc(sizeof(X509_POLICY_DATA)); + if (!ret) { + OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE); + ASN1_OBJECT_free(id); + return NULL; + } + ret->expected_policy_set = sk_ASN1_OBJECT_new_null(); + if (!ret->expected_policy_set) { + OPENSSL_free(ret); + ASN1_OBJECT_free(id); + return NULL; + } - if (crit) - ret->flags = POLICY_DATA_FLAG_CRITICAL; - else - ret->flags = 0; + if (crit) { + ret->flags = POLICY_DATA_FLAG_CRITICAL; + } else { + ret->flags = 0; + } - if (id) - ret->valid_policy = id; - else { - ret->valid_policy = policy->policyid; - policy->policyid = NULL; - } + if (id) { + ret->valid_policy = id; + } else { + ret->valid_policy = policy->policyid; + policy->policyid = NULL; + } - if (policy) { - ret->qualifier_set = policy->qualifiers; - policy->qualifiers = NULL; - } else - ret->qualifier_set = NULL; + if (policy) { + ret->qualifier_set = policy->qualifiers; + policy->qualifiers = NULL; + } else { + ret->qualifier_set = NULL; + } - return ret; + return ret; } diff --git a/crypto/x509v3/pcy_lib.c b/crypto/x509v3/pcy_lib.c index 3b752dd268..3775d35d48 100644 --- a/crypto/x509v3/pcy_lib.c +++ b/crypto/x509v3/pcy_lib.c @@ -64,92 +64,93 @@ /* X509_POLICY_TREE stuff */ -int X509_policy_tree_level_count(const X509_POLICY_TREE *tree) -{ - if (!tree) - return 0; - return tree->nlevel; +int X509_policy_tree_level_count(const X509_POLICY_TREE *tree) { + if (!tree) { + return 0; + } + return tree->nlevel; } X509_POLICY_LEVEL *X509_policy_tree_get0_level(const X509_POLICY_TREE *tree, - int i) -{ - if (!tree || (i < 0) || (i >= tree->nlevel)) - return NULL; - return tree->levels + i; + int i) { + if (!tree || (i < 0) || (i >= tree->nlevel)) { + return NULL; + } + return tree->levels + i; } -STACK_OF(X509_POLICY_NODE) *X509_policy_tree_get0_policies(const - X509_POLICY_TREE - *tree) -{ - if (!tree) - return NULL; - return tree->auth_policies; +STACK_OF(X509_POLICY_NODE) *X509_policy_tree_get0_policies( + const X509_POLICY_TREE *tree) { + if (!tree) { + return NULL; + } + return tree->auth_policies; } -STACK_OF(X509_POLICY_NODE) *X509_policy_tree_get0_user_policies(const - X509_POLICY_TREE - *tree) -{ - if (!tree) - return NULL; - if (tree->flags & POLICY_FLAG_ANY_POLICY) - return tree->auth_policies; - else - return tree->user_policies; +STACK_OF(X509_POLICY_NODE) *X509_policy_tree_get0_user_policies( + const X509_POLICY_TREE *tree) { + if (!tree) { + return NULL; + } + if (tree->flags & POLICY_FLAG_ANY_POLICY) { + return tree->auth_policies; + } else { + return tree->user_policies; + } } /* X509_POLICY_LEVEL stuff */ -int X509_policy_level_node_count(X509_POLICY_LEVEL *level) -{ - int n; - if (!level) - return 0; - if (level->anyPolicy) - n = 1; - else - n = 0; - if (level->nodes) - n += sk_X509_POLICY_NODE_num(level->nodes); - return n; +int X509_policy_level_node_count(X509_POLICY_LEVEL *level) { + int n; + if (!level) { + return 0; + } + if (level->anyPolicy) { + n = 1; + } else { + n = 0; + } + if (level->nodes) { + n += sk_X509_POLICY_NODE_num(level->nodes); + } + return n; } -X509_POLICY_NODE *X509_policy_level_get0_node(X509_POLICY_LEVEL *level, int i) -{ - if (!level) - return NULL; - if (level->anyPolicy) { - if (i == 0) - return level->anyPolicy; - i--; +X509_POLICY_NODE *X509_policy_level_get0_node(X509_POLICY_LEVEL *level, int i) { + if (!level) { + return NULL; + } + if (level->anyPolicy) { + if (i == 0) { + return level->anyPolicy; } - return sk_X509_POLICY_NODE_value(level->nodes, i); + i--; + } + return sk_X509_POLICY_NODE_value(level->nodes, i); } /* X509_POLICY_NODE stuff */ -const ASN1_OBJECT *X509_policy_node_get0_policy(const X509_POLICY_NODE *node) -{ - if (!node) - return NULL; - return node->data->valid_policy; +const ASN1_OBJECT *X509_policy_node_get0_policy(const X509_POLICY_NODE *node) { + if (!node) { + return NULL; + } + return node->data->valid_policy; } -STACK_OF(POLICYQUALINFO) *X509_policy_node_get0_qualifiers(const - X509_POLICY_NODE - *node) -{ - if (!node) - return NULL; - return node->data->qualifier_set; +STACK_OF(POLICYQUALINFO) *X509_policy_node_get0_qualifiers( + const X509_POLICY_NODE *node) { + if (!node) { + return NULL; + } + return node->data->qualifier_set; } -const X509_POLICY_NODE *X509_policy_node_get0_parent(const X509_POLICY_NODE - *node) -{ - if (!node) - return NULL; - return node->parent; +const X509_POLICY_NODE *X509_policy_node_get0_parent( + const X509_POLICY_NODE *node) { + if (!node) { + return NULL; + } + return node->parent; } diff --git a/crypto/x509v3/pcy_map.c b/crypto/x509v3/pcy_map.c index c96777f452..efc3ecd755 100644 --- a/crypto/x509v3/pcy_map.c +++ b/crypto/x509v3/pcy_map.c @@ -69,63 +69,65 @@ * POLICY_MAPPINGS structure */ -int policy_cache_set_mapping(X509 *x, POLICY_MAPPINGS *maps) -{ - POLICY_MAPPING *map; - X509_POLICY_DATA *data; - X509_POLICY_CACHE *cache = x->policy_cache; - size_t i; - int ret = 0; - if (sk_POLICY_MAPPING_num(maps) == 0) { - ret = -1; - goto bad_mapping; +int policy_cache_set_mapping(X509 *x, POLICY_MAPPINGS *maps) { + POLICY_MAPPING *map; + X509_POLICY_DATA *data; + X509_POLICY_CACHE *cache = x->policy_cache; + size_t i; + int ret = 0; + if (sk_POLICY_MAPPING_num(maps) == 0) { + ret = -1; + goto bad_mapping; + } + for (i = 0; i < sk_POLICY_MAPPING_num(maps); i++) { + map = sk_POLICY_MAPPING_value(maps, i); + /* Reject if map to or from anyPolicy */ + if ((OBJ_obj2nid(map->subjectDomainPolicy) == NID_any_policy) || + (OBJ_obj2nid(map->issuerDomainPolicy) == NID_any_policy)) { + ret = -1; + goto bad_mapping; } - for (i = 0; i < sk_POLICY_MAPPING_num(maps); i++) { - map = sk_POLICY_MAPPING_value(maps, i); - /* Reject if map to or from anyPolicy */ - if ((OBJ_obj2nid(map->subjectDomainPolicy) == NID_any_policy) - || (OBJ_obj2nid(map->issuerDomainPolicy) == NID_any_policy)) { - ret = -1; - goto bad_mapping; - } - - /* Attempt to find matching policy data */ - data = policy_cache_find_data(cache, map->issuerDomainPolicy); - /* If we don't have anyPolicy can't map */ - if (!data && !cache->anyPolicy) - continue; - - /* Create a NODE from anyPolicy */ - if (!data) { - data = policy_data_new(NULL, map->issuerDomainPolicy, - cache->anyPolicy->flags - & POLICY_DATA_FLAG_CRITICAL); - if (!data) - goto bad_mapping; - data->qualifier_set = cache->anyPolicy->qualifier_set; - /* - * map->issuerDomainPolicy = NULL; - */ - data->flags |= POLICY_DATA_FLAG_MAPPED_ANY; - data->flags |= POLICY_DATA_FLAG_SHARED_QUALIFIERS; - if (!sk_X509_POLICY_DATA_push(cache->data, data)) { - policy_data_free(data); - goto bad_mapping; - } - } else - data->flags |= POLICY_DATA_FLAG_MAPPED; - if (!sk_ASN1_OBJECT_push(data->expected_policy_set, - map->subjectDomainPolicy)) - goto bad_mapping; - map->subjectDomainPolicy = NULL; + /* Attempt to find matching policy data */ + data = policy_cache_find_data(cache, map->issuerDomainPolicy); + /* If we don't have anyPolicy can't map */ + if (!data && !cache->anyPolicy) { + continue; } - ret = 1; - bad_mapping: - if (ret == -1) - x->ex_flags |= EXFLAG_INVALID_POLICY; - sk_POLICY_MAPPING_pop_free(maps, POLICY_MAPPING_free); - return ret; + /* Create a NODE from anyPolicy */ + if (!data) { + data = + policy_data_new(NULL, map->issuerDomainPolicy, + cache->anyPolicy->flags & POLICY_DATA_FLAG_CRITICAL); + if (!data) { + goto bad_mapping; + } + data->qualifier_set = cache->anyPolicy->qualifier_set; + /* + * map->issuerDomainPolicy = NULL; + */ + data->flags |= POLICY_DATA_FLAG_MAPPED_ANY; + data->flags |= POLICY_DATA_FLAG_SHARED_QUALIFIERS; + if (!sk_X509_POLICY_DATA_push(cache->data, data)) { + policy_data_free(data); + goto bad_mapping; + } + } else { + data->flags |= POLICY_DATA_FLAG_MAPPED; + } + if (!sk_ASN1_OBJECT_push(data->expected_policy_set, + map->subjectDomainPolicy)) { + goto bad_mapping; + } + map->subjectDomainPolicy = NULL; + } + ret = 1; +bad_mapping: + if (ret == -1) { + x->ex_flags |= EXFLAG_INVALID_POLICY; + } + sk_POLICY_MAPPING_pop_free(maps, POLICY_MAPPING_free); + return ret; } diff --git a/crypto/x509v3/pcy_node.c b/crypto/x509v3/pcy_node.c index aa28056bcb..330194fe6b 100644 --- a/crypto/x509v3/pcy_node.c +++ b/crypto/x509v3/pcy_node.c @@ -63,102 +63,102 @@ #include "internal.h" -static int node_cmp(const X509_POLICY_NODE **a, const X509_POLICY_NODE **b) -{ - return OBJ_cmp((*a)->data->valid_policy, (*b)->data->valid_policy); +static int node_cmp(const X509_POLICY_NODE **a, const X509_POLICY_NODE **b) { + return OBJ_cmp((*a)->data->valid_policy, (*b)->data->valid_policy); } -STACK_OF(X509_POLICY_NODE) *policy_node_cmp_new(void) -{ - return sk_X509_POLICY_NODE_new(node_cmp); +STACK_OF(X509_POLICY_NODE) *policy_node_cmp_new(void) { + return sk_X509_POLICY_NODE_new(node_cmp); } X509_POLICY_NODE *tree_find_sk(STACK_OF(X509_POLICY_NODE) *nodes, - const ASN1_OBJECT *id) -{ - X509_POLICY_DATA n; - X509_POLICY_NODE l; - size_t idx; + const ASN1_OBJECT *id) { + X509_POLICY_DATA n; + X509_POLICY_NODE l; + size_t idx; - n.valid_policy = (ASN1_OBJECT *)id; - l.data = &n; + n.valid_policy = (ASN1_OBJECT *)id; + l.data = &n; - sk_X509_POLICY_NODE_sort(nodes); - if (!sk_X509_POLICY_NODE_find(nodes, &idx, &l)) - return NULL; - - return sk_X509_POLICY_NODE_value(nodes, idx); + sk_X509_POLICY_NODE_sort(nodes); + if (!sk_X509_POLICY_NODE_find(nodes, &idx, &l)) { + return NULL; + } + return sk_X509_POLICY_NODE_value(nodes, idx); } X509_POLICY_NODE *level_find_node(const X509_POLICY_LEVEL *level, const X509_POLICY_NODE *parent, - const ASN1_OBJECT *id) -{ - X509_POLICY_NODE *node; - size_t i; - for (i = 0; i < sk_X509_POLICY_NODE_num(level->nodes); i++) { - node = sk_X509_POLICY_NODE_value(level->nodes, i); - if (node->parent == parent) { - if (!OBJ_cmp(node->data->valid_policy, id)) - return node; - } + const ASN1_OBJECT *id) { + X509_POLICY_NODE *node; + size_t i; + for (i = 0; i < sk_X509_POLICY_NODE_num(level->nodes); i++) { + node = sk_X509_POLICY_NODE_value(level->nodes, i); + if (node->parent == parent) { + if (!OBJ_cmp(node->data->valid_policy, id)) { + return node; + } } - return NULL; + } + return NULL; } X509_POLICY_NODE *level_add_node(X509_POLICY_LEVEL *level, X509_POLICY_DATA *data, X509_POLICY_NODE *parent, - X509_POLICY_TREE *tree) -{ - X509_POLICY_NODE *node; - node = OPENSSL_malloc(sizeof(X509_POLICY_NODE)); - if (!node) - return NULL; - node->data = data; - node->parent = parent; - node->nchild = 0; - if (level) { - if (OBJ_obj2nid(data->valid_policy) == NID_any_policy) { - if (level->anyPolicy) - goto node_error; - level->anyPolicy = node; - } else { - - if (!level->nodes) - level->nodes = policy_node_cmp_new(); - if (!level->nodes) - goto node_error; - if (!sk_X509_POLICY_NODE_push(level->nodes, node)) - goto node_error; - } + X509_POLICY_TREE *tree) { + X509_POLICY_NODE *node; + node = OPENSSL_malloc(sizeof(X509_POLICY_NODE)); + if (!node) { + return NULL; + } + node->data = data; + node->parent = parent; + node->nchild = 0; + if (level) { + if (OBJ_obj2nid(data->valid_policy) == NID_any_policy) { + if (level->anyPolicy) { + goto node_error; + } + level->anyPolicy = node; + } else { + if (!level->nodes) { + level->nodes = policy_node_cmp_new(); + } + if (!level->nodes) { + goto node_error; + } + if (!sk_X509_POLICY_NODE_push(level->nodes, node)) { + goto node_error; + } } + } - if (tree) { - if (!tree->extra_data) - tree->extra_data = sk_X509_POLICY_DATA_new_null(); - if (!tree->extra_data) - goto node_error; - if (!sk_X509_POLICY_DATA_push(tree->extra_data, data)) - goto node_error; + if (tree) { + if (!tree->extra_data) { + tree->extra_data = sk_X509_POLICY_DATA_new_null(); } + if (!tree->extra_data) { + goto node_error; + } + if (!sk_X509_POLICY_DATA_push(tree->extra_data, data)) { + goto node_error; + } + } - if (parent) - parent->nchild++; - - return node; + if (parent) { + parent->nchild++; + } - node_error: - policy_node_free(node); - return 0; + return node; +node_error: + policy_node_free(node); + return 0; } -void policy_node_free(X509_POLICY_NODE *node) -{ - OPENSSL_free(node); -} +void policy_node_free(X509_POLICY_NODE *node) { OPENSSL_free(node); } /* * See if a policy node matches a policy OID. If mapping enabled look through @@ -166,24 +166,24 @@ void policy_node_free(X509_POLICY_NODE *node) */ int policy_node_match(const X509_POLICY_LEVEL *lvl, - const X509_POLICY_NODE *node, const ASN1_OBJECT *oid) -{ - size_t i; - ASN1_OBJECT *policy_oid; - const X509_POLICY_DATA *x = node->data; - - if ((lvl->flags & X509_V_FLAG_INHIBIT_MAP) - || !(x->flags & POLICY_DATA_FLAG_MAP_MASK)) { - if (!OBJ_cmp(x->valid_policy, oid)) - return 1; - return 0; - } - - for (i = 0; i < sk_ASN1_OBJECT_num(x->expected_policy_set); i++) { - policy_oid = sk_ASN1_OBJECT_value(x->expected_policy_set, i); - if (!OBJ_cmp(policy_oid, oid)) - return 1; + const X509_POLICY_NODE *node, const ASN1_OBJECT *oid) { + size_t i; + ASN1_OBJECT *policy_oid; + const X509_POLICY_DATA *x = node->data; + + if ((lvl->flags & X509_V_FLAG_INHIBIT_MAP) || + !(x->flags & POLICY_DATA_FLAG_MAP_MASK)) { + if (!OBJ_cmp(x->valid_policy, oid)) { + return 1; } return 0; + } + for (i = 0; i < sk_ASN1_OBJECT_num(x->expected_policy_set); i++) { + policy_oid = sk_ASN1_OBJECT_value(x->expected_policy_set, i); + if (!OBJ_cmp(policy_oid, oid)) { + return 1; + } + } + return 0; } diff --git a/crypto/x509v3/pcy_tree.c b/crypto/x509v3/pcy_tree.c index 9e65528661..db7704e3b4 100644 --- a/crypto/x509v3/pcy_tree.c +++ b/crypto/x509v3/pcy_tree.c @@ -81,59 +81,59 @@ #ifdef OPENSSL_POLICY_DEBUG static void expected_print(BIO *err, X509_POLICY_LEVEL *lev, - X509_POLICY_NODE *node, int indent) -{ - if ((lev->flags & X509_V_FLAG_INHIBIT_MAP) - || !(node->data->flags & POLICY_DATA_FLAG_MAP_MASK)) - BIO_puts(err, " Not Mapped\n"); - else { - int i; - STACK_OF(ASN1_OBJECT) *pset = node->data->expected_policy_set; - ASN1_OBJECT *oid; - BIO_puts(err, " Expected: "); - for (i = 0; i < sk_ASN1_OBJECT_num(pset); i++) { - oid = sk_ASN1_OBJECT_value(pset, i); - if (i) - BIO_puts(err, ", "); - i2a_ASN1_OBJECT(err, oid); - } - BIO_puts(err, "\n"); + X509_POLICY_NODE *node, int indent) { + if ((lev->flags & X509_V_FLAG_INHIBIT_MAP) || + !(node->data->flags & POLICY_DATA_FLAG_MAP_MASK)) { + BIO_puts(err, " Not Mapped\n"); + } else { + int i; + STACK_OF(ASN1_OBJECT) *pset = node->data->expected_policy_set; + ASN1_OBJECT *oid; + BIO_puts(err, " Expected: "); + for (i = 0; i < sk_ASN1_OBJECT_num(pset); i++) { + oid = sk_ASN1_OBJECT_value(pset, i); + if (i) { + BIO_puts(err, ", "); + } + i2a_ASN1_OBJECT(err, oid); } + BIO_puts(err, "\n"); + } } static void tree_print(char *str, X509_POLICY_TREE *tree, - X509_POLICY_LEVEL *curr) -{ - X509_POLICY_LEVEL *plev; - X509_POLICY_NODE *node; - int i; - BIO *err; - err = BIO_new_fp(stderr, BIO_NOCLOSE); - if (!curr) - curr = tree->levels + tree->nlevel; - else - curr++; - BIO_printf(err, "Level print after %s\n", str); - BIO_printf(err, "Printing Up to Level %ld\n", curr - tree->levels); - for (plev = tree->levels; plev != curr; plev++) { - BIO_printf(err, "Level %ld, flags = %x\n", - plev - tree->levels, plev->flags); - for (i = 0; i < sk_X509_POLICY_NODE_num(plev->nodes); i++) { - node = sk_X509_POLICY_NODE_value(plev->nodes, i); - X509_POLICY_NODE_print(err, node, 2); - expected_print(err, plev, node, 2); - BIO_printf(err, " Flags: %x\n", node->data->flags); - } - if (plev->anyPolicy) - X509_POLICY_NODE_print(err, plev->anyPolicy, 2); + X509_POLICY_LEVEL *curr) { + X509_POLICY_LEVEL *plev; + X509_POLICY_NODE *node; + int i; + BIO *err; + err = BIO_new_fp(stderr, BIO_NOCLOSE); + if (!curr) { + curr = tree->levels + tree->nlevel; + } else { + curr++; + } + BIO_printf(err, "Level print after %s\n", str); + BIO_printf(err, "Printing Up to Level %ld\n", curr - tree->levels); + for (plev = tree->levels; plev != curr; plev++) { + BIO_printf(err, "Level %ld, flags = %x\n", plev - tree->levels, + plev->flags); + for (i = 0; i < sk_X509_POLICY_NODE_num(plev->nodes); i++) { + node = sk_X509_POLICY_NODE_value(plev->nodes, i); + X509_POLICY_NODE_print(err, node, 2); + expected_print(err, plev, node, 2); + BIO_printf(err, " Flags: %x\n", node->data->flags); } + if (plev->anyPolicy) { + X509_POLICY_NODE_print(err, plev->anyPolicy, 2); + } + } - BIO_free(err); - + BIO_free(err); } #else -# define tree_print(a,b,c) /* */ +#define tree_print(a, b, c) /* */ #endif @@ -148,188 +148,203 @@ static void tree_print(char *str, X509_POLICY_TREE *tree, */ static int tree_init(X509_POLICY_TREE **ptree, STACK_OF(X509) *certs, - unsigned int flags) -{ - X509_POLICY_TREE *tree; - X509_POLICY_LEVEL *level; - const X509_POLICY_CACHE *cache; - X509_POLICY_DATA *data = NULL; - X509 *x; - int ret = 1; - int i, n; - int explicit_policy; - int any_skip; - int map_skip; - *ptree = NULL; - n = sk_X509_num(certs); + unsigned int flags) { + X509_POLICY_TREE *tree; + X509_POLICY_LEVEL *level; + const X509_POLICY_CACHE *cache; + X509_POLICY_DATA *data = NULL; + X509 *x; + int ret = 1; + int i, n; + int explicit_policy; + int any_skip; + int map_skip; + *ptree = NULL; + n = sk_X509_num(certs); #if 0 /* Disable policy mapping for now... */ flags |= X509_V_FLAG_INHIBIT_MAP; #endif - if (flags & X509_V_FLAG_EXPLICIT_POLICY) - explicit_policy = 0; - else - explicit_policy = n + 1; - - if (flags & X509_V_FLAG_INHIBIT_ANY) - any_skip = 0; - else - any_skip = n + 1; - - if (flags & X509_V_FLAG_INHIBIT_MAP) - map_skip = 0; - else - map_skip = n + 1; - - /* Can't do anything with just a trust anchor */ - if (n == 1) - return 1; + if (flags & X509_V_FLAG_EXPLICIT_POLICY) { + explicit_policy = 0; + } else { + explicit_policy = n + 1; + } + + if (flags & X509_V_FLAG_INHIBIT_ANY) { + any_skip = 0; + } else { + any_skip = n + 1; + } + + if (flags & X509_V_FLAG_INHIBIT_MAP) { + map_skip = 0; + } else { + map_skip = n + 1; + } + + /* Can't do anything with just a trust anchor */ + if (n == 1) { + return 1; + } + /* + * First setup policy cache in all certificates apart from the trust + * anchor. Note any bad cache results on the way. Also can calculate + * explicit_policy value at this point. + */ + for (i = n - 2; i >= 0; i--) { + x = sk_X509_value(certs, i); + X509_check_purpose(x, -1, -1); + cache = policy_cache_set(x); + /* If cache NULL something bad happened: return immediately */ + if (cache == NULL) { + return 0; + } /* - * First setup policy cache in all certificates apart from the trust - * anchor. Note any bad cache results on the way. Also can calculate - * explicit_policy value at this point. + * If inconsistent extensions keep a note of it but continue */ - for (i = n - 2; i >= 0; i--) { - x = sk_X509_value(certs, i); - X509_check_purpose(x, -1, -1); - cache = policy_cache_set(x); - /* If cache NULL something bad happened: return immediately */ - if (cache == NULL) - return 0; - /* - * If inconsistent extensions keep a note of it but continue - */ - if (x->ex_flags & EXFLAG_INVALID_POLICY) - ret = -1; - /* - * Otherwise if we have no data (hence no CertificatePolicies) and - * haven't already set an inconsistent code note it. - */ - else if ((ret == 1) && !cache->data) - ret = 2; - if (explicit_policy > 0) { - if (!(x->ex_flags & EXFLAG_SI)) - explicit_policy--; - if ((cache->explicit_skip != -1) - && (cache->explicit_skip < explicit_policy)) - explicit_policy = cache->explicit_skip; - } + if (x->ex_flags & EXFLAG_INVALID_POLICY) { + ret = -1; } - - if (ret != 1) { - if (ret == 2 && !explicit_policy) - return 6; - return ret; + /* + * Otherwise if we have no data (hence no CertificatePolicies) and + * haven't already set an inconsistent code note it. + */ + else if ((ret == 1) && !cache->data) { + ret = 2; + } + if (explicit_policy > 0) { + if (!(x->ex_flags & EXFLAG_SI)) { + explicit_policy--; + } + if ((cache->explicit_skip != -1) && + (cache->explicit_skip < explicit_policy)) { + explicit_policy = cache->explicit_skip; + } } + } - /* If we get this far initialize the tree */ + if (ret != 1) { + if (ret == 2 && !explicit_policy) { + return 6; + } + return ret; + } - tree = OPENSSL_malloc(sizeof(X509_POLICY_TREE)); + /* If we get this far initialize the tree */ - if (!tree) - return 0; + tree = OPENSSL_malloc(sizeof(X509_POLICY_TREE)); - tree->flags = 0; - tree->levels = OPENSSL_malloc(sizeof(X509_POLICY_LEVEL) * n); - tree->nlevel = 0; - tree->extra_data = NULL; - tree->auth_policies = NULL; - tree->user_policies = NULL; + if (!tree) { + return 0; + } - if (!tree->levels) { - OPENSSL_free(tree); - return 0; - } + tree->flags = 0; + tree->levels = OPENSSL_malloc(sizeof(X509_POLICY_LEVEL) * n); + tree->nlevel = 0; + tree->extra_data = NULL; + tree->auth_policies = NULL; + tree->user_policies = NULL; - OPENSSL_memset(tree->levels, 0, n * sizeof(X509_POLICY_LEVEL)); + if (!tree->levels) { + OPENSSL_free(tree); + return 0; + } - tree->nlevel = n; + OPENSSL_memset(tree->levels, 0, n * sizeof(X509_POLICY_LEVEL)); - level = tree->levels; + tree->nlevel = n; - /* Root data: initialize to anyPolicy */ + level = tree->levels; - data = policy_data_new(NULL, OBJ_nid2obj(NID_any_policy), 0); + /* Root data: initialize to anyPolicy */ - if (!data || !level_add_node(level, data, NULL, tree)) - goto bad_tree; + data = policy_data_new(NULL, OBJ_nid2obj(NID_any_policy), 0); - for (i = n - 2; i >= 0; i--) { - level++; - x = sk_X509_value(certs, i); - cache = policy_cache_set(x); - X509_up_ref(x); - level->cert = x; + if (!data || !level_add_node(level, data, NULL, tree)) { + goto bad_tree; + } - if (!cache->anyPolicy) - level->flags |= X509_V_FLAG_INHIBIT_ANY; + for (i = n - 2; i >= 0; i--) { + level++; + x = sk_X509_value(certs, i); + cache = policy_cache_set(x); + X509_up_ref(x); + level->cert = x; - /* Determine inhibit any and inhibit map flags */ - if (any_skip == 0) { - /* - * Any matching allowed if certificate is self issued and not the - * last in the chain. - */ - if (!(x->ex_flags & EXFLAG_SI) || (i == 0)) - level->flags |= X509_V_FLAG_INHIBIT_ANY; - } else { - if (!(x->ex_flags & EXFLAG_SI)) - any_skip--; - if ((cache->any_skip >= 0) - && (cache->any_skip < any_skip)) - any_skip = cache->any_skip; - } - - if (map_skip == 0) - level->flags |= X509_V_FLAG_INHIBIT_MAP; - else { - if (!(x->ex_flags & EXFLAG_SI)) - map_skip--; - if ((cache->map_skip >= 0) - && (cache->map_skip < map_skip)) - map_skip = cache->map_skip; - } + if (!cache->anyPolicy) { + level->flags |= X509_V_FLAG_INHIBIT_ANY; + } + /* Determine inhibit any and inhibit map flags */ + if (any_skip == 0) { + /* + * Any matching allowed if certificate is self issued and not the + * last in the chain. + */ + if (!(x->ex_flags & EXFLAG_SI) || (i == 0)) { + level->flags |= X509_V_FLAG_INHIBIT_ANY; + } + } else { + if (!(x->ex_flags & EXFLAG_SI)) { + any_skip--; + } + if ((cache->any_skip >= 0) && (cache->any_skip < any_skip)) { + any_skip = cache->any_skip; + } } - *ptree = tree; + if (map_skip == 0) { + level->flags |= X509_V_FLAG_INHIBIT_MAP; + } else { + if (!(x->ex_flags & EXFLAG_SI)) { + map_skip--; + } + if ((cache->map_skip >= 0) && (cache->map_skip < map_skip)) { + map_skip = cache->map_skip; + } + } + } - if (explicit_policy) - return 1; - else - return 5; + *ptree = tree; - bad_tree: + if (explicit_policy) { + return 1; + } else { + return 5; + } - X509_policy_tree_free(tree); +bad_tree: - return 0; + X509_policy_tree_free(tree); + return 0; } static int tree_link_matching_nodes(X509_POLICY_LEVEL *curr, - X509_POLICY_DATA *data) -{ - X509_POLICY_LEVEL *last = curr - 1; - X509_POLICY_NODE *node; - int matched = 0; - size_t i; - /* Iterate through all in nodes linking matches */ - for (i = 0; i < sk_X509_POLICY_NODE_num(last->nodes); i++) { - node = sk_X509_POLICY_NODE_value(last->nodes, i); - if (policy_node_match(last, node, data->valid_policy)) { - if (!level_add_node(curr, data, node, NULL)) - return 0; - matched = 1; - } + X509_POLICY_DATA *data) { + X509_POLICY_LEVEL *last = curr - 1; + X509_POLICY_NODE *node; + int matched = 0; + size_t i; + /* Iterate through all in nodes linking matches */ + for (i = 0; i < sk_X509_POLICY_NODE_num(last->nodes); i++) { + node = sk_X509_POLICY_NODE_value(last->nodes, i); + if (policy_node_match(last, node, data->valid_policy)) { + if (!level_add_node(curr, data, node, NULL)) { + return 0; + } + matched = 1; } - if (!matched && last->anyPolicy) { - if (!level_add_node(curr, data, last->anyPolicy, NULL)) - return 0; + } + if (!matched && last->anyPolicy) { + if (!level_add_node(curr, data, last->anyPolicy, NULL)) { + return 0; } - return 1; + } + return 1; } /* @@ -338,31 +353,31 @@ static int tree_link_matching_nodes(X509_POLICY_LEVEL *curr, */ static int tree_link_nodes(X509_POLICY_LEVEL *curr, - const X509_POLICY_CACHE *cache) -{ - size_t i; - X509_POLICY_DATA *data; + const X509_POLICY_CACHE *cache) { + size_t i; + X509_POLICY_DATA *data; - for (i = 0; i < sk_X509_POLICY_DATA_num(cache->data); i++) { - data = sk_X509_POLICY_DATA_value(cache->data, i); - /* - * If a node is mapped any it doesn't have a corresponding - * CertificatePolicies entry. However such an identical node would - * be created if anyPolicy matching is enabled because there would be - * no match with the parent valid_policy_set. So we create link - * because then it will have the mapping flags right and we can prune - * it later. - */ + for (i = 0; i < sk_X509_POLICY_DATA_num(cache->data); i++) { + data = sk_X509_POLICY_DATA_value(cache->data, i); + /* + * If a node is mapped any it doesn't have a corresponding + * CertificatePolicies entry. However such an identical node would + * be created if anyPolicy matching is enabled because there would be + * no match with the parent valid_policy_set. So we create link + * because then it will have the mapping flags right and we can prune + * it later. + */ #if 0 if ((data->flags & POLICY_DATA_FLAG_MAPPED_ANY) && !(curr->flags & X509_V_FLAG_INHIBIT_ANY)) continue; #endif - /* Look for matching nodes in previous level */ - if (!tree_link_matching_nodes(curr, data)) - return 0; + /* Look for matching nodes in previous level */ + if (!tree_link_matching_nodes(curr, data)) { + return 0; } - return 1; + } + return 1; } /* @@ -372,82 +387,85 @@ static int tree_link_nodes(X509_POLICY_LEVEL *curr, static int tree_add_unmatched(X509_POLICY_LEVEL *curr, const X509_POLICY_CACHE *cache, - const ASN1_OBJECT *id, - X509_POLICY_NODE *node, X509_POLICY_TREE *tree) -{ - X509_POLICY_DATA *data; - if (id == NULL) - id = node->data->valid_policy; - /* - * Create a new node with qualifiers from anyPolicy and id from unmatched - * node. - */ - data = policy_data_new(NULL, id, node_critical(node)); - - if (data == NULL) - return 0; - /* Curr may not have anyPolicy */ - data->qualifier_set = cache->anyPolicy->qualifier_set; - data->flags |= POLICY_DATA_FLAG_SHARED_QUALIFIERS; - if (!level_add_node(curr, data, node, tree)) { - policy_data_free(data); - return 0; - } + const ASN1_OBJECT *id, X509_POLICY_NODE *node, + X509_POLICY_TREE *tree) { + X509_POLICY_DATA *data; + if (id == NULL) { + id = node->data->valid_policy; + } + /* + * Create a new node with qualifiers from anyPolicy and id from unmatched + * node. + */ + data = policy_data_new(NULL, id, node_critical(node)); + + if (data == NULL) { + return 0; + } + /* Curr may not have anyPolicy */ + data->qualifier_set = cache->anyPolicy->qualifier_set; + data->flags |= POLICY_DATA_FLAG_SHARED_QUALIFIERS; + if (!level_add_node(curr, data, node, tree)) { + policy_data_free(data); + return 0; + } - return 1; + return 1; } static int tree_link_unmatched(X509_POLICY_LEVEL *curr, const X509_POLICY_CACHE *cache, - X509_POLICY_NODE *node, X509_POLICY_TREE *tree) -{ - const X509_POLICY_LEVEL *last = curr - 1; - size_t i; - - if ((last->flags & X509_V_FLAG_INHIBIT_MAP) - || !(node->data->flags & POLICY_DATA_FLAG_MAPPED)) { - /* If no policy mapping: matched if one child present */ - if (node->nchild) - return 1; - if (!tree_add_unmatched(curr, cache, NULL, node, tree)) - return 0; - /* Add it */ - } else { - /* If mapping: matched if one child per expected policy set */ - STACK_OF(ASN1_OBJECT) *expset = node->data->expected_policy_set; - if ((size_t)node->nchild == sk_ASN1_OBJECT_num(expset)) - return 1; - /* Locate unmatched nodes */ - for (i = 0; i < sk_ASN1_OBJECT_num(expset); i++) { - ASN1_OBJECT *oid = sk_ASN1_OBJECT_value(expset, i); - if (level_find_node(curr, node, oid)) - continue; - if (!tree_add_unmatched(curr, cache, oid, node, tree)) - return 0; - } - + X509_POLICY_NODE *node, X509_POLICY_TREE *tree) { + const X509_POLICY_LEVEL *last = curr - 1; + size_t i; + + if ((last->flags & X509_V_FLAG_INHIBIT_MAP) || + !(node->data->flags & POLICY_DATA_FLAG_MAPPED)) { + /* If no policy mapping: matched if one child present */ + if (node->nchild) { + return 1; } + if (!tree_add_unmatched(curr, cache, NULL, node, tree)) { + return 0; + } + /* Add it */ + } else { + /* If mapping: matched if one child per expected policy set */ + STACK_OF(ASN1_OBJECT) *expset = node->data->expected_policy_set; + if ((size_t)node->nchild == sk_ASN1_OBJECT_num(expset)) { + return 1; + } + /* Locate unmatched nodes */ + for (i = 0; i < sk_ASN1_OBJECT_num(expset); i++) { + ASN1_OBJECT *oid = sk_ASN1_OBJECT_value(expset, i); + if (level_find_node(curr, node, oid)) { + continue; + } + if (!tree_add_unmatched(curr, cache, oid, node, tree)) { + return 0; + } + } + } - return 1; - + return 1; } static int tree_link_any(X509_POLICY_LEVEL *curr, const X509_POLICY_CACHE *cache, - X509_POLICY_TREE *tree) -{ - size_t i; - /* - * X509_POLICY_DATA *data; - */ - X509_POLICY_NODE *node; - X509_POLICY_LEVEL *last = curr - 1; - - for (i = 0; i < sk_X509_POLICY_NODE_num(last->nodes); i++) { - node = sk_X509_POLICY_NODE_value(last->nodes, i); - - if (!tree_link_unmatched(curr, cache, node, tree)) - return 0; + X509_POLICY_TREE *tree) { + size_t i; + /* + * X509_POLICY_DATA *data; + */ + X509_POLICY_NODE *node; + X509_POLICY_LEVEL *last = curr - 1; + + for (i = 0; i < sk_X509_POLICY_NODE_num(last->nodes); i++) { + node = sk_X509_POLICY_NODE_value(last->nodes, i); + + if (!tree_link_unmatched(curr, cache, node, tree)) { + return 0; + } #if 0 @@ -476,14 +494,14 @@ static int tree_link_any(X509_POLICY_LEVEL *curr, return 0; } #endif - - } - /* Finally add link to anyPolicy */ - if (last->anyPolicy) { - if (!level_add_node(curr, cache->anyPolicy, last->anyPolicy, NULL)) - return 0; + } + /* Finally add link to anyPolicy */ + if (last->anyPolicy) { + if (!level_add_node(curr, cache->anyPolicy, last->anyPolicy, NULL)) { + return 0; } - return 1; + } + return 1; } /* @@ -492,68 +510,69 @@ static int tree_link_any(X509_POLICY_LEVEL *curr, * have no data on a level we can halt because the tree will be empty. */ -static int tree_prune(X509_POLICY_TREE *tree, X509_POLICY_LEVEL *curr) -{ - STACK_OF(X509_POLICY_NODE) *nodes; - X509_POLICY_NODE *node; - int i; - nodes = curr->nodes; - if (curr->flags & X509_V_FLAG_INHIBIT_MAP) { - for (i = sk_X509_POLICY_NODE_num(nodes) - 1; i >= 0; i--) { - node = sk_X509_POLICY_NODE_value(nodes, i); - /* Delete any mapped data: see RFC 3280 XXXX */ - if (node->data->flags & POLICY_DATA_FLAG_MAP_MASK) { - node->parent->nchild--; - OPENSSL_free(node); - (void)sk_X509_POLICY_NODE_delete(nodes, i); - } - } +static int tree_prune(X509_POLICY_TREE *tree, X509_POLICY_LEVEL *curr) { + STACK_OF(X509_POLICY_NODE) *nodes; + X509_POLICY_NODE *node; + int i; + nodes = curr->nodes; + if (curr->flags & X509_V_FLAG_INHIBIT_MAP) { + for (i = sk_X509_POLICY_NODE_num(nodes) - 1; i >= 0; i--) { + node = sk_X509_POLICY_NODE_value(nodes, i); + /* Delete any mapped data: see RFC 3280 XXXX */ + if (node->data->flags & POLICY_DATA_FLAG_MAP_MASK) { + node->parent->nchild--; + OPENSSL_free(node); + (void)sk_X509_POLICY_NODE_delete(nodes, i); + } } + } - for (;;) { - --curr; - nodes = curr->nodes; - for (i = sk_X509_POLICY_NODE_num(nodes) - 1; i >= 0; i--) { - node = sk_X509_POLICY_NODE_value(nodes, i); - if (node->nchild == 0) { - node->parent->nchild--; - OPENSSL_free(node); - (void)sk_X509_POLICY_NODE_delete(nodes, i); - } - } - if (curr->anyPolicy && !curr->anyPolicy->nchild) { - if (curr->anyPolicy->parent) - curr->anyPolicy->parent->nchild--; - OPENSSL_free(curr->anyPolicy); - curr->anyPolicy = NULL; - } - if (curr == tree->levels) { - /* If we zapped anyPolicy at top then tree is empty */ - if (!curr->anyPolicy) - return 2; - return 1; - } + for (;;) { + --curr; + nodes = curr->nodes; + for (i = sk_X509_POLICY_NODE_num(nodes) - 1; i >= 0; i--) { + node = sk_X509_POLICY_NODE_value(nodes, i); + if (node->nchild == 0) { + node->parent->nchild--; + OPENSSL_free(node); + (void)sk_X509_POLICY_NODE_delete(nodes, i); + } } - + if (curr->anyPolicy && !curr->anyPolicy->nchild) { + if (curr->anyPolicy->parent) { + curr->anyPolicy->parent->nchild--; + } + OPENSSL_free(curr->anyPolicy); + curr->anyPolicy = NULL; + } + if (curr == tree->levels) { + /* If we zapped anyPolicy at top then tree is empty */ + if (!curr->anyPolicy) { + return 2; + } + return 1; + } + } } static int tree_add_auth_node(STACK_OF(X509_POLICY_NODE) **pnodes, - X509_POLICY_NODE *pcy) -{ + X509_POLICY_NODE *pcy) { + if (!*pnodes) { + *pnodes = policy_node_cmp_new(); if (!*pnodes) { - *pnodes = policy_node_cmp_new(); - if (!*pnodes) - return 0; - } else { - sk_X509_POLICY_NODE_sort(*pnodes); - if (sk_X509_POLICY_NODE_find(*pnodes, NULL, pcy)) - return 1; + return 0; } - if (!sk_X509_POLICY_NODE_push(*pnodes, pcy)) - return 0; - - return 1; + } else { + sk_X509_POLICY_NODE_sort(*pnodes); + if (sk_X509_POLICY_NODE_find(*pnodes, NULL, pcy)) { + return 1; + } + } + if (!sk_X509_POLICY_NODE_push(*pnodes, pcy)) { + return 0; + } + return 1; } /* @@ -566,164 +585,174 @@ static int tree_add_auth_node(STACK_OF(X509_POLICY_NODE) **pnodes, */ static int tree_calculate_authority_set(X509_POLICY_TREE *tree, - STACK_OF(X509_POLICY_NODE) **pnodes) -{ - X509_POLICY_LEVEL *curr; - X509_POLICY_NODE *node, *anyptr; - STACK_OF(X509_POLICY_NODE) **addnodes; - int i; - size_t j; - curr = tree->levels + tree->nlevel - 1; - - /* If last level contains anyPolicy set is anyPolicy */ - if (curr->anyPolicy) { - if (!tree_add_auth_node(&tree->auth_policies, curr->anyPolicy)) - return 0; - addnodes = pnodes; - } else - /* Add policies to authority set */ - addnodes = &tree->auth_policies; - - curr = tree->levels; - for (i = 1; i < tree->nlevel; i++) { - /* - * If no anyPolicy node on this this level it can't appear on lower - * levels so end search. - */ - if (!(anyptr = curr->anyPolicy)) - break; - curr++; - for (j = 0; j < sk_X509_POLICY_NODE_num(curr->nodes); j++) { - node = sk_X509_POLICY_NODE_value(curr->nodes, j); - if ((node->parent == anyptr) - && !tree_add_auth_node(addnodes, node)) - return 0; - } + STACK_OF(X509_POLICY_NODE) **pnodes) { + X509_POLICY_LEVEL *curr; + X509_POLICY_NODE *node, *anyptr; + STACK_OF(X509_POLICY_NODE) **addnodes; + int i; + size_t j; + curr = tree->levels + tree->nlevel - 1; + + /* If last level contains anyPolicy set is anyPolicy */ + if (curr->anyPolicy) { + if (!tree_add_auth_node(&tree->auth_policies, curr->anyPolicy)) { + return 0; } + addnodes = pnodes; + } else { + /* Add policies to authority set */ + addnodes = &tree->auth_policies; + } + + curr = tree->levels; + for (i = 1; i < tree->nlevel; i++) { + /* + * If no anyPolicy node on this this level it can't appear on lower + * levels so end search. + */ + if (!(anyptr = curr->anyPolicy)) { + break; + } + curr++; + for (j = 0; j < sk_X509_POLICY_NODE_num(curr->nodes); j++) { + node = sk_X509_POLICY_NODE_value(curr->nodes, j); + if ((node->parent == anyptr) && !tree_add_auth_node(addnodes, node)) { + return 0; + } + } + } - if (addnodes == pnodes) - return 2; + if (addnodes == pnodes) { + return 2; + } - *pnodes = tree->auth_policies; + *pnodes = tree->auth_policies; - return 1; + return 1; } static int tree_calculate_user_set(X509_POLICY_TREE *tree, STACK_OF(ASN1_OBJECT) *policy_oids, - STACK_OF(X509_POLICY_NODE) *auth_nodes) -{ - size_t i; - X509_POLICY_NODE *node; - ASN1_OBJECT *oid; + STACK_OF(X509_POLICY_NODE) *auth_nodes) { + size_t i; + X509_POLICY_NODE *node; + ASN1_OBJECT *oid; - X509_POLICY_NODE *anyPolicy; - X509_POLICY_DATA *extra; + X509_POLICY_NODE *anyPolicy; + X509_POLICY_DATA *extra; - /* - * Check if anyPolicy present in authority constrained policy set: this - * will happen if it is a leaf node. - */ + /* + * Check if anyPolicy present in authority constrained policy set: this + * will happen if it is a leaf node. + */ - if (sk_ASN1_OBJECT_num(policy_oids) <= 0) - return 1; + if (sk_ASN1_OBJECT_num(policy_oids) <= 0) { + return 1; + } - anyPolicy = tree->levels[tree->nlevel - 1].anyPolicy; + anyPolicy = tree->levels[tree->nlevel - 1].anyPolicy; - for (i = 0; i < sk_ASN1_OBJECT_num(policy_oids); i++) { - oid = sk_ASN1_OBJECT_value(policy_oids, i); - if (OBJ_obj2nid(oid) == NID_any_policy) { - tree->flags |= POLICY_FLAG_ANY_POLICY; - return 1; - } + for (i = 0; i < sk_ASN1_OBJECT_num(policy_oids); i++) { + oid = sk_ASN1_OBJECT_value(policy_oids, i); + if (OBJ_obj2nid(oid) == NID_any_policy) { + tree->flags |= POLICY_FLAG_ANY_POLICY; + return 1; } - - for (i = 0; i < sk_ASN1_OBJECT_num(policy_oids); i++) { - oid = sk_ASN1_OBJECT_value(policy_oids, i); - node = tree_find_sk(auth_nodes, oid); - if (!node) { - if (!anyPolicy) - continue; - /* - * Create a new node with policy ID from user set and qualifiers - * from anyPolicy. - */ - extra = policy_data_new(NULL, oid, node_critical(anyPolicy)); - if (!extra) - return 0; - extra->qualifier_set = anyPolicy->data->qualifier_set; - extra->flags = POLICY_DATA_FLAG_SHARED_QUALIFIERS - | POLICY_DATA_FLAG_EXTRA_NODE; - node = level_add_node(NULL, extra, anyPolicy->parent, tree); - } - if (!tree->user_policies) { - tree->user_policies = sk_X509_POLICY_NODE_new_null(); - if (!tree->user_policies) - return 1; - } - if (!sk_X509_POLICY_NODE_push(tree->user_policies, node)) - return 0; + } + + for (i = 0; i < sk_ASN1_OBJECT_num(policy_oids); i++) { + oid = sk_ASN1_OBJECT_value(policy_oids, i); + node = tree_find_sk(auth_nodes, oid); + if (!node) { + if (!anyPolicy) { + continue; + } + /* + * Create a new node with policy ID from user set and qualifiers + * from anyPolicy. + */ + extra = policy_data_new(NULL, oid, node_critical(anyPolicy)); + if (!extra) { + return 0; + } + extra->qualifier_set = anyPolicy->data->qualifier_set; + extra->flags = + POLICY_DATA_FLAG_SHARED_QUALIFIERS | POLICY_DATA_FLAG_EXTRA_NODE; + node = level_add_node(NULL, extra, anyPolicy->parent, tree); } - return 1; - + if (!tree->user_policies) { + tree->user_policies = sk_X509_POLICY_NODE_new_null(); + if (!tree->user_policies) { + return 1; + } + } + if (!sk_X509_POLICY_NODE_push(tree->user_policies, node)) { + return 0; + } + } + return 1; } -static int tree_evaluate(X509_POLICY_TREE *tree) -{ - int ret, i; - X509_POLICY_LEVEL *curr = tree->levels + 1; - const X509_POLICY_CACHE *cache; - - for (i = 1; i < tree->nlevel; i++, curr++) { - cache = policy_cache_set(curr->cert); - if (!tree_link_nodes(curr, cache)) - return 0; +static int tree_evaluate(X509_POLICY_TREE *tree) { + int ret, i; + X509_POLICY_LEVEL *curr = tree->levels + 1; + const X509_POLICY_CACHE *cache; - if (!(curr->flags & X509_V_FLAG_INHIBIT_ANY) - && !tree_link_any(curr, cache, tree)) - return 0; - tree_print("before tree_prune()", tree, curr); - ret = tree_prune(tree, curr); - if (ret != 1) - return ret; + for (i = 1; i < tree->nlevel; i++, curr++) { + cache = policy_cache_set(curr->cert); + if (!tree_link_nodes(curr, cache)) { + return 0; } - return 1; + if (!(curr->flags & X509_V_FLAG_INHIBIT_ANY) && + !tree_link_any(curr, cache, tree)) { + return 0; + } + tree_print("before tree_prune()", tree, curr); + ret = tree_prune(tree, curr); + if (ret != 1) { + return ret; + } + } + return 1; } -static void exnode_free(X509_POLICY_NODE *node) -{ - if (node->data && (node->data->flags & POLICY_DATA_FLAG_EXTRA_NODE)) - OPENSSL_free(node); +static void exnode_free(X509_POLICY_NODE *node) { + if (node->data && (node->data->flags & POLICY_DATA_FLAG_EXTRA_NODE)) { + OPENSSL_free(node); + } } -void X509_policy_tree_free(X509_POLICY_TREE *tree) -{ - X509_POLICY_LEVEL *curr; - int i; +void X509_policy_tree_free(X509_POLICY_TREE *tree) { + X509_POLICY_LEVEL *curr; + int i; - if (!tree) - return; + if (!tree) { + return; + } - sk_X509_POLICY_NODE_free(tree->auth_policies); - sk_X509_POLICY_NODE_pop_free(tree->user_policies, exnode_free); + sk_X509_POLICY_NODE_free(tree->auth_policies); + sk_X509_POLICY_NODE_pop_free(tree->user_policies, exnode_free); - for (i = 0, curr = tree->levels; i < tree->nlevel; i++, curr++) { - if (curr->cert) - X509_free(curr->cert); - if (curr->nodes) - sk_X509_POLICY_NODE_pop_free(curr->nodes, policy_node_free); - if (curr->anyPolicy) - policy_node_free(curr->anyPolicy); + for (i = 0, curr = tree->levels; i < tree->nlevel; i++, curr++) { + if (curr->cert) { + X509_free(curr->cert); } + if (curr->nodes) { + sk_X509_POLICY_NODE_pop_free(curr->nodes, policy_node_free); + } + if (curr->anyPolicy) { + policy_node_free(curr->anyPolicy); + } + } - if (tree->extra_data) - sk_X509_POLICY_DATA_pop_free(tree->extra_data, policy_data_free); - - OPENSSL_free(tree->levels); - OPENSSL_free(tree); + if (tree->extra_data) { + sk_X509_POLICY_DATA_pop_free(tree->extra_data, policy_data_free); + } + OPENSSL_free(tree->levels); + OPENSSL_free(tree); } /*- @@ -736,108 +765,114 @@ void X509_policy_tree_free(X509_POLICY_TREE *tree) */ int X509_policy_check(X509_POLICY_TREE **ptree, int *pexplicit_policy, - STACK_OF(X509) *certs, - STACK_OF(ASN1_OBJECT) *policy_oids, unsigned int flags) -{ - int ret; - int calc_ret; - X509_POLICY_TREE *tree = NULL; - STACK_OF(X509_POLICY_NODE) *nodes, *auth_nodes = NULL; - *ptree = NULL; - - *pexplicit_policy = 0; - ret = tree_init(&tree, certs, flags); - - switch (ret) { - - /* Tree empty requireExplicit False: OK */ + STACK_OF(X509) *certs, STACK_OF(ASN1_OBJECT) *policy_oids, + unsigned int flags) { + int ret; + int calc_ret; + X509_POLICY_TREE *tree = NULL; + STACK_OF(X509_POLICY_NODE) *nodes, *auth_nodes = NULL; + *ptree = NULL; + + *pexplicit_policy = 0; + ret = tree_init(&tree, certs, flags); + + switch (ret) { + /* Tree empty requireExplicit False: OK */ case 2: - return 1; + return 1; - /* Some internal error */ + /* Some internal error */ case -1: - return -1; + return -1; - /* Some internal error */ + /* Some internal error */ case 0: - return 0; + return 0; - /* Tree empty requireExplicit True: Error */ + /* Tree empty requireExplicit True: Error */ case 6: - *pexplicit_policy = 1; - return -2; + *pexplicit_policy = 1; + return -2; - /* Tree OK requireExplicit True: OK and continue */ + /* Tree OK requireExplicit True: OK and continue */ case 5: - *pexplicit_policy = 1; - break; + *pexplicit_policy = 1; + break; - /* Tree OK: continue */ + /* Tree OK: continue */ case 1: - if (!tree) - /* - * tree_init() returns success and a null tree - * if it's just looking at a trust anchor. - * I'm not sure that returning success here is - * correct, but I'm sure that reporting this - * as an internal error which our caller - * interprets as a malloc failure is wrong. - */ - return 1; - break; - } + if (!tree) { + /* + * tree_init() returns success and a null tree + * if it's just looking at a trust anchor. + * I'm not sure that returning success here is + * correct, but I'm sure that reporting this + * as an internal error which our caller + * interprets as a malloc failure is wrong. + */ + return 1; + } + break; + } - if (!tree) - goto error; - ret = tree_evaluate(tree); + if (!tree) { + goto error; + } + ret = tree_evaluate(tree); - tree_print("tree_evaluate()", tree, NULL); + tree_print("tree_evaluate()", tree, NULL); - if (ret <= 0) - goto error; + if (ret <= 0) { + goto error; + } - /* Return value 2 means tree empty */ - if (ret == 2) { - X509_policy_tree_free(tree); - if (*pexplicit_policy) - return -2; - else - return 1; + /* Return value 2 means tree empty */ + if (ret == 2) { + X509_policy_tree_free(tree); + if (*pexplicit_policy) { + return -2; + } else { + return 1; } + } - /* Tree is not empty: continue */ + /* Tree is not empty: continue */ - calc_ret = tree_calculate_authority_set(tree, &auth_nodes); + calc_ret = tree_calculate_authority_set(tree, &auth_nodes); - if (!calc_ret) - goto error; + if (!calc_ret) { + goto error; + } - ret = tree_calculate_user_set(tree, policy_oids, auth_nodes); + ret = tree_calculate_user_set(tree, policy_oids, auth_nodes); - if (calc_ret == 2) - sk_X509_POLICY_NODE_free(auth_nodes); + if (calc_ret == 2) { + sk_X509_POLICY_NODE_free(auth_nodes); + } - if (!ret) - goto error; + if (!ret) { + goto error; + } - if (tree) - *ptree = tree; + if (tree) { + *ptree = tree; + } - if (*pexplicit_policy) { - nodes = X509_policy_tree_get0_user_policies(tree); - if (sk_X509_POLICY_NODE_num(nodes) <= 0) - return -2; + if (*pexplicit_policy) { + nodes = X509_policy_tree_get0_user_policies(tree); + if (sk_X509_POLICY_NODE_num(nodes) <= 0) { + return -2; } + } - return 1; + return 1; - error: +error: - X509_policy_tree_free(tree); - - return 0; + X509_policy_tree_free(tree); + return 0; } diff --git a/crypto/x509v3/v3_akey.c b/crypto/x509v3/v3_akey.c index 35dc9c24c1..e893561738 100644 --- a/crypto/x509v3/v3_akey.c +++ b/crypto/x509v3/v3_akey.c @@ -76,49 +76,53 @@ static void *v2i_AUTHORITY_KEYID(const X509V3_EXT_METHOD *method, const X509V3_EXT_METHOD v3_akey_id = { NID_authority_key_identifier, - X509V3_EXT_MULTILINE, ASN1_ITEM_ref(AUTHORITY_KEYID), - 0, 0, 0, 0, - 0, 0, + X509V3_EXT_MULTILINE, + ASN1_ITEM_ref(AUTHORITY_KEYID), + 0, + 0, + 0, + 0, + 0, + 0, i2v_AUTHORITY_KEYID, v2i_AUTHORITY_KEYID, - 0, 0, + 0, + 0, NULL, }; static STACK_OF(CONF_VALUE) *i2v_AUTHORITY_KEYID( - const X509V3_EXT_METHOD *method, void *ext, STACK_OF(CONF_VALUE) *extlist) -{ - const AUTHORITY_KEYID *akeyid = ext; - int extlist_was_null = extlist == NULL; - if (akeyid->keyid) { - char *tmp = x509v3_bytes_to_hex(akeyid->keyid->data, - akeyid->keyid->length); - int ok = tmp != NULL && X509V3_add_value("keyid", tmp, &extlist); - OPENSSL_free(tmp); - if (!ok) { - goto err; - } + const X509V3_EXT_METHOD *method, void *ext, STACK_OF(CONF_VALUE) *extlist) { + const AUTHORITY_KEYID *akeyid = ext; + int extlist_was_null = extlist == NULL; + if (akeyid->keyid) { + char *tmp = x509v3_bytes_to_hex(akeyid->keyid->data, akeyid->keyid->length); + int ok = tmp != NULL && X509V3_add_value("keyid", tmp, &extlist); + OPENSSL_free(tmp); + if (!ok) { + goto err; } - if (akeyid->issuer) { - STACK_OF(CONF_VALUE) *tmpextlist = - i2v_GENERAL_NAMES(NULL, akeyid->issuer, extlist); - if (tmpextlist == NULL) { - goto err; - } - extlist = tmpextlist; + } + if (akeyid->issuer) { + STACK_OF(CONF_VALUE) *tmpextlist = + i2v_GENERAL_NAMES(NULL, akeyid->issuer, extlist); + if (tmpextlist == NULL) { + goto err; } - if (akeyid->serial) { - if (!X509V3_add_value_int("serial", akeyid->serial, &extlist)) { - goto err; - } + extlist = tmpextlist; + } + if (akeyid->serial) { + if (!X509V3_add_value_int("serial", akeyid->serial, &extlist)) { + goto err; } - return extlist; + } + return extlist; err: - if (extlist_was_null) { - sk_CONF_VALUE_pop_free(extlist, X509V3_conf_free); - } - return NULL; + if (extlist_was_null) { + sk_CONF_VALUE_pop_free(extlist, X509V3_conf_free); + } + return NULL; } /* @@ -130,89 +134,93 @@ static STACK_OF(CONF_VALUE) *i2v_AUTHORITY_KEYID( */ static void *v2i_AUTHORITY_KEYID(const X509V3_EXT_METHOD *method, - X509V3_CTX *ctx, STACK_OF(CONF_VALUE) *values) -{ - char keyid = 0, issuer = 0; - size_t i; - int j; - CONF_VALUE *cnf; - ASN1_OCTET_STRING *ikeyid = NULL; - X509_NAME *isname = NULL; - GENERAL_NAMES *gens = NULL; - GENERAL_NAME *gen = NULL; - ASN1_INTEGER *serial = NULL; - X509_EXTENSION *ext; - X509 *cert; - AUTHORITY_KEYID *akeyid; - - for (i = 0; i < sk_CONF_VALUE_num(values); i++) { - cnf = sk_CONF_VALUE_value(values, i); - if (!strcmp(cnf->name, "keyid")) { - keyid = 1; - if (cnf->value && !strcmp(cnf->value, "always")) - keyid = 2; - } else if (!strcmp(cnf->name, "issuer")) { - issuer = 1; - if (cnf->value && !strcmp(cnf->value, "always")) - issuer = 2; - } else { - OPENSSL_PUT_ERROR(X509V3, X509V3_R_UNKNOWN_OPTION); - ERR_add_error_data(2, "name=", cnf->name); - return NULL; - } + X509V3_CTX *ctx, + STACK_OF(CONF_VALUE) *values) { + char keyid = 0, issuer = 0; + size_t i; + int j; + CONF_VALUE *cnf; + ASN1_OCTET_STRING *ikeyid = NULL; + X509_NAME *isname = NULL; + GENERAL_NAMES *gens = NULL; + GENERAL_NAME *gen = NULL; + ASN1_INTEGER *serial = NULL; + X509_EXTENSION *ext; + X509 *cert; + AUTHORITY_KEYID *akeyid; + + for (i = 0; i < sk_CONF_VALUE_num(values); i++) { + cnf = sk_CONF_VALUE_value(values, i); + if (!strcmp(cnf->name, "keyid")) { + keyid = 1; + if (cnf->value && !strcmp(cnf->value, "always")) { + keyid = 2; + } + } else if (!strcmp(cnf->name, "issuer")) { + issuer = 1; + if (cnf->value && !strcmp(cnf->value, "always")) { + issuer = 2; + } + } else { + OPENSSL_PUT_ERROR(X509V3, X509V3_R_UNKNOWN_OPTION); + ERR_add_error_data(2, "name=", cnf->name); + return NULL; } + } - if (!ctx || !ctx->issuer_cert) { - if (ctx && (ctx->flags == CTX_TEST)) - return AUTHORITY_KEYID_new(); - OPENSSL_PUT_ERROR(X509V3, X509V3_R_NO_ISSUER_CERTIFICATE); - return NULL; + if (!ctx || !ctx->issuer_cert) { + if (ctx && (ctx->flags == CTX_TEST)) { + return AUTHORITY_KEYID_new(); } + OPENSSL_PUT_ERROR(X509V3, X509V3_R_NO_ISSUER_CERTIFICATE); + return NULL; + } - cert = ctx->issuer_cert; + cert = ctx->issuer_cert; - if (keyid) { - j = X509_get_ext_by_NID(cert, NID_subject_key_identifier, -1); - if ((j >= 0) && (ext = X509_get_ext(cert, j))) - ikeyid = X509V3_EXT_d2i(ext); - if (keyid == 2 && !ikeyid) { - OPENSSL_PUT_ERROR(X509V3, X509V3_R_UNABLE_TO_GET_ISSUER_KEYID); - return NULL; - } + if (keyid) { + j = X509_get_ext_by_NID(cert, NID_subject_key_identifier, -1); + if ((j >= 0) && (ext = X509_get_ext(cert, j))) { + ikeyid = X509V3_EXT_d2i(ext); } - - if ((issuer && !ikeyid) || (issuer == 2)) { - isname = X509_NAME_dup(X509_get_issuer_name(cert)); - serial = ASN1_INTEGER_dup(X509_get_serialNumber(cert)); - if (!isname || !serial) { - OPENSSL_PUT_ERROR(X509V3, X509V3_R_UNABLE_TO_GET_ISSUER_DETAILS); - goto err; - } + if (keyid == 2 && !ikeyid) { + OPENSSL_PUT_ERROR(X509V3, X509V3_R_UNABLE_TO_GET_ISSUER_KEYID); + return NULL; } + } + + if ((issuer && !ikeyid) || (issuer == 2)) { + isname = X509_NAME_dup(X509_get_issuer_name(cert)); + serial = ASN1_INTEGER_dup(X509_get_serialNumber(cert)); + if (!isname || !serial) { + OPENSSL_PUT_ERROR(X509V3, X509V3_R_UNABLE_TO_GET_ISSUER_DETAILS); + goto err; + } + } + + if (!(akeyid = AUTHORITY_KEYID_new())) { + goto err; + } - if (!(akeyid = AUTHORITY_KEYID_new())) - goto err; - - if (isname) { - if (!(gens = sk_GENERAL_NAME_new_null()) - || !(gen = GENERAL_NAME_new()) - || !sk_GENERAL_NAME_push(gens, gen)) { - OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE); - goto err; - } - gen->type = GEN_DIRNAME; - gen->d.dirn = isname; + if (isname) { + if (!(gens = sk_GENERAL_NAME_new_null()) || !(gen = GENERAL_NAME_new()) || + !sk_GENERAL_NAME_push(gens, gen)) { + OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE); + goto err; } + gen->type = GEN_DIRNAME; + gen->d.dirn = isname; + } - akeyid->issuer = gens; - akeyid->serial = serial; - akeyid->keyid = ikeyid; + akeyid->issuer = gens; + akeyid->serial = serial; + akeyid->keyid = ikeyid; - return akeyid; + return akeyid; - err: - X509_NAME_free(isname); - ASN1_INTEGER_free(serial); - ASN1_OCTET_STRING_free(ikeyid); - return NULL; +err: + X509_NAME_free(isname); + ASN1_INTEGER_free(serial); + ASN1_OCTET_STRING_free(ikeyid); + return NULL; } diff --git a/crypto/x509v3/v3_akeya.c b/crypto/x509v3/v3_akeya.c index 4cfc099a49..f612d7c014 100644 --- a/crypto/x509v3/v3_akeya.c +++ b/crypto/x509v3/v3_akeya.c @@ -64,9 +64,9 @@ ASN1_SEQUENCE(AUTHORITY_KEYID) = { - ASN1_IMP_OPT(AUTHORITY_KEYID, keyid, ASN1_OCTET_STRING, 0), - ASN1_IMP_SEQUENCE_OF_OPT(AUTHORITY_KEYID, issuer, GENERAL_NAME, 1), - ASN1_IMP_OPT(AUTHORITY_KEYID, serial, ASN1_INTEGER, 2), + ASN1_IMP_OPT(AUTHORITY_KEYID, keyid, ASN1_OCTET_STRING, 0), + ASN1_IMP_SEQUENCE_OF_OPT(AUTHORITY_KEYID, issuer, GENERAL_NAME, 1), + ASN1_IMP_OPT(AUTHORITY_KEYID, serial, ASN1_INTEGER, 2), } ASN1_SEQUENCE_END(AUTHORITY_KEYID) IMPLEMENT_ASN1_FUNCTIONS(AUTHORITY_KEYID) diff --git a/crypto/x509v3/v3_alt.c b/crypto/x509v3/v3_alt.c index c057da1a1d..3f47901dda 100644 --- a/crypto/x509v3/v3_alt.c +++ b/crypto/x509v3/v3_alt.c @@ -78,567 +78,567 @@ static int do_othername(GENERAL_NAME *gen, const char *value, X509V3_CTX *ctx); static int do_dirname(GENERAL_NAME *gen, const char *value, X509V3_CTX *ctx); static STACK_OF(CONF_VALUE) *i2v_GENERAL_NAMES_cb( - const X509V3_EXT_METHOD *method, void *ext, STACK_OF(CONF_VALUE) *ret) -{ - return i2v_GENERAL_NAMES(method, ext, ret); + const X509V3_EXT_METHOD *method, void *ext, STACK_OF(CONF_VALUE) *ret) { + return i2v_GENERAL_NAMES(method, ext, ret); } const X509V3_EXT_METHOD v3_alt[] = { - {NID_subject_alt_name, 0, ASN1_ITEM_ref(GENERAL_NAMES), - 0, 0, 0, 0, - 0, 0, - i2v_GENERAL_NAMES_cb, - v2i_subject_alt, - NULL, NULL, NULL}, - - {NID_issuer_alt_name, 0, ASN1_ITEM_ref(GENERAL_NAMES), - 0, 0, 0, 0, - 0, 0, - i2v_GENERAL_NAMES_cb, - v2i_issuer_alt, - NULL, NULL, NULL}, - - {NID_certificate_issuer, 0, ASN1_ITEM_ref(GENERAL_NAMES), - 0, 0, 0, 0, - 0, 0, - i2v_GENERAL_NAMES_cb, - NULL, NULL, NULL, NULL}, + {NID_subject_alt_name, 0, ASN1_ITEM_ref(GENERAL_NAMES), 0, 0, 0, 0, 0, 0, + i2v_GENERAL_NAMES_cb, v2i_subject_alt, NULL, NULL, NULL}, + + {NID_issuer_alt_name, 0, ASN1_ITEM_ref(GENERAL_NAMES), 0, 0, 0, 0, 0, 0, + i2v_GENERAL_NAMES_cb, v2i_issuer_alt, NULL, NULL, NULL}, + + {NID_certificate_issuer, 0, ASN1_ITEM_ref(GENERAL_NAMES), 0, 0, 0, 0, 0, 0, + i2v_GENERAL_NAMES_cb, NULL, NULL, NULL, NULL}, }; STACK_OF(CONF_VALUE) *i2v_GENERAL_NAMES(const X509V3_EXT_METHOD *method, GENERAL_NAMES *gens, - STACK_OF(CONF_VALUE) *ret) -{ - int ret_was_null = ret == NULL; - for (size_t i = 0; i < sk_GENERAL_NAME_num(gens); i++) { - GENERAL_NAME *gen = sk_GENERAL_NAME_value(gens, i); - STACK_OF(CONF_VALUE) *tmp = i2v_GENERAL_NAME(method, gen, ret); - if (tmp == NULL) { - if (ret_was_null) { - sk_CONF_VALUE_pop_free(ret, X509V3_conf_free); - } - return NULL; - } - ret = tmp; + STACK_OF(CONF_VALUE) *ret) { + int ret_was_null = ret == NULL; + for (size_t i = 0; i < sk_GENERAL_NAME_num(gens); i++) { + GENERAL_NAME *gen = sk_GENERAL_NAME_value(gens, i); + STACK_OF(CONF_VALUE) *tmp = i2v_GENERAL_NAME(method, gen, ret); + if (tmp == NULL) { + if (ret_was_null) { + sk_CONF_VALUE_pop_free(ret, X509V3_conf_free); + } + return NULL; } - if (!ret) - return sk_CONF_VALUE_new_null(); - return ret; + ret = tmp; + } + if (!ret) { + return sk_CONF_VALUE_new_null(); + } + return ret; } STACK_OF(CONF_VALUE) *i2v_GENERAL_NAME(const X509V3_EXT_METHOD *method, GENERAL_NAME *gen, - STACK_OF(CONF_VALUE) *ret) -{ - /* Note the error-handling for this function relies on there being at most - * one |X509V3_add_value| call. If there were two and the second failed, we - * would need to sometimes free the first call's result. */ - unsigned char *p; - char oline[256], htmp[5]; - int i; - switch (gen->type) { + STACK_OF(CONF_VALUE) *ret) { + /* Note the error-handling for this function relies on there being at most + * one |X509V3_add_value| call. If there were two and the second failed, we + * would need to sometimes free the first call's result. */ + unsigned char *p; + char oline[256], htmp[5]; + int i; + switch (gen->type) { case GEN_OTHERNAME: - if (!X509V3_add_value("othername", "", &ret)) - return NULL; - break; + if (!X509V3_add_value("othername", "", &ret)) { + return NULL; + } + break; case GEN_X400: - if (!X509V3_add_value("X400Name", "", &ret)) - return NULL; - break; + if (!X509V3_add_value("X400Name", "", &ret)) { + return NULL; + } + break; case GEN_EDIPARTY: - if (!X509V3_add_value("EdiPartyName", "", &ret)) - return NULL; - break; + if (!X509V3_add_value("EdiPartyName", "", &ret)) { + return NULL; + } + break; case GEN_EMAIL: - if (!x509V3_add_value_asn1_string("email", gen->d.ia5, &ret)) - return NULL; - break; + if (!x509V3_add_value_asn1_string("email", gen->d.ia5, &ret)) { + return NULL; + } + break; case GEN_DNS: - if (!x509V3_add_value_asn1_string("DNS", gen->d.ia5, &ret)) - return NULL; - break; + if (!x509V3_add_value_asn1_string("DNS", gen->d.ia5, &ret)) { + return NULL; + } + break; case GEN_URI: - if (!x509V3_add_value_asn1_string("URI", gen->d.ia5, &ret)) - return NULL; - break; + if (!x509V3_add_value_asn1_string("URI", gen->d.ia5, &ret)) { + return NULL; + } + break; case GEN_DIRNAME: - if (X509_NAME_oneline(gen->d.dirn, oline, 256) == NULL - || !X509V3_add_value("DirName", oline, &ret)) - return NULL; - break; + if (X509_NAME_oneline(gen->d.dirn, oline, 256) == NULL || + !X509V3_add_value("DirName", oline, &ret)) { + return NULL; + } + break; case GEN_IPADD: - p = gen->d.ip->data; - if (gen->d.ip->length == 4) - BIO_snprintf(oline, sizeof(oline), - "%d.%d.%d.%d", p[0], p[1], p[2], p[3]); - else if (gen->d.ip->length == 16) { - oline[0] = 0; - for (i = 0; i < 8; i++) { - uint16_t v = ((uint16_t)p[0] << 8) | p[1]; - BIO_snprintf(htmp, sizeof(htmp), "%X", v); - p += 2; - OPENSSL_strlcat(oline, htmp, sizeof(oline)); - if (i != 7) - OPENSSL_strlcat(oline, ":", sizeof(oline)); - } - } else { - if (!X509V3_add_value("IP Address", "", &ret)) - return NULL; - break; + p = gen->d.ip->data; + if (gen->d.ip->length == 4) { + BIO_snprintf(oline, sizeof(oline), "%d.%d.%d.%d", p[0], p[1], p[2], + p[3]); + } else if (gen->d.ip->length == 16) { + oline[0] = 0; + for (i = 0; i < 8; i++) { + uint16_t v = ((uint16_t)p[0] << 8) | p[1]; + BIO_snprintf(htmp, sizeof(htmp), "%X", v); + p += 2; + OPENSSL_strlcat(oline, htmp, sizeof(oline)); + if (i != 7) { + OPENSSL_strlcat(oline, ":", sizeof(oline)); + } + } + } else { + if (!X509V3_add_value("IP Address", "", &ret)) { + return NULL; } - if (!X509V3_add_value("IP Address", oline, &ret)) - return NULL; break; + } + if (!X509V3_add_value("IP Address", oline, &ret)) { + return NULL; + } + break; case GEN_RID: - i2t_ASN1_OBJECT(oline, 256, gen->d.rid); - if (!X509V3_add_value("Registered ID", oline, &ret)) - return NULL; - break; - } - return ret; + i2t_ASN1_OBJECT(oline, 256, gen->d.rid); + if (!X509V3_add_value("Registered ID", oline, &ret)) { + return NULL; + } + break; + } + return ret; } -int GENERAL_NAME_print(BIO *out, GENERAL_NAME *gen) -{ - unsigned char *p; - int i; - switch (gen->type) { +int GENERAL_NAME_print(BIO *out, GENERAL_NAME *gen) { + unsigned char *p; + int i; + switch (gen->type) { case GEN_OTHERNAME: - BIO_printf(out, "othername:"); - break; + BIO_printf(out, "othername:"); + break; case GEN_X400: - BIO_printf(out, "X400Name:"); - break; + BIO_printf(out, "X400Name:"); + break; case GEN_EDIPARTY: - /* Maybe fix this: it is supported now */ - BIO_printf(out, "EdiPartyName:"); - break; + /* Maybe fix this: it is supported now */ + BIO_printf(out, "EdiPartyName:"); + break; case GEN_EMAIL: - BIO_printf(out, "email:"); - ASN1_STRING_print(out, gen->d.ia5); - break; + BIO_printf(out, "email:"); + ASN1_STRING_print(out, gen->d.ia5); + break; case GEN_DNS: - BIO_printf(out, "DNS:"); - ASN1_STRING_print(out, gen->d.ia5); - break; + BIO_printf(out, "DNS:"); + ASN1_STRING_print(out, gen->d.ia5); + break; case GEN_URI: - BIO_printf(out, "URI:"); - ASN1_STRING_print(out, gen->d.ia5); - break; + BIO_printf(out, "URI:"); + ASN1_STRING_print(out, gen->d.ia5); + break; case GEN_DIRNAME: - BIO_printf(out, "DirName: "); - X509_NAME_print_ex(out, gen->d.dirn, 0, XN_FLAG_ONELINE); - break; + BIO_printf(out, "DirName: "); + X509_NAME_print_ex(out, gen->d.dirn, 0, XN_FLAG_ONELINE); + break; case GEN_IPADD: - p = gen->d.ip->data; - if (gen->d.ip->length == 4) - BIO_printf(out, "IP Address:%d.%d.%d.%d", p[0], p[1], p[2], p[3]); - else if (gen->d.ip->length == 16) { - BIO_printf(out, "IP Address"); - for (i = 0; i < 8; i++) { - uint16_t v = ((uint16_t)p[0] << 8) | p[1]; - BIO_printf(out, ":%X", v); - p += 2; - } - BIO_puts(out, "\n"); - } else { - BIO_printf(out, "IP Address:"); - break; + p = gen->d.ip->data; + if (gen->d.ip->length == 4) { + BIO_printf(out, "IP Address:%d.%d.%d.%d", p[0], p[1], p[2], p[3]); + } else if (gen->d.ip->length == 16) { + BIO_printf(out, "IP Address"); + for (i = 0; i < 8; i++) { + uint16_t v = ((uint16_t)p[0] << 8) | p[1]; + BIO_printf(out, ":%X", v); + p += 2; } + BIO_puts(out, "\n"); + } else { + BIO_printf(out, "IP Address:"); break; + } + break; case GEN_RID: - BIO_printf(out, "Registered ID"); - i2a_ASN1_OBJECT(out, gen->d.rid); - break; - } - return 1; + BIO_printf(out, "Registered ID"); + i2a_ASN1_OBJECT(out, gen->d.rid); + break; + } + return 1; } static void *v2i_issuer_alt(const X509V3_EXT_METHOD *method, X509V3_CTX *ctx, - STACK_OF(CONF_VALUE) *nval) -{ - GENERAL_NAMES *gens = NULL; - CONF_VALUE *cnf; - size_t i; - if (!(gens = sk_GENERAL_NAME_new_null())) { - OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE); - return NULL; - } - for (i = 0; i < sk_CONF_VALUE_num(nval); i++) { - cnf = sk_CONF_VALUE_value(nval, i); - if (!x509v3_name_cmp(cnf->name, "issuer") && cnf->value && - !strcmp(cnf->value, "copy")) { - if (!copy_issuer(ctx, gens)) - goto err; - } else { - GENERAL_NAME *gen; - if (!(gen = v2i_GENERAL_NAME(method, ctx, cnf))) - goto err; - sk_GENERAL_NAME_push(gens, gen); - } - } - return gens; - err: - sk_GENERAL_NAME_pop_free(gens, GENERAL_NAME_free); + STACK_OF(CONF_VALUE) *nval) { + GENERAL_NAMES *gens = NULL; + CONF_VALUE *cnf; + size_t i; + if (!(gens = sk_GENERAL_NAME_new_null())) { + OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE); return NULL; + } + for (i = 0; i < sk_CONF_VALUE_num(nval); i++) { + cnf = sk_CONF_VALUE_value(nval, i); + if (!x509v3_name_cmp(cnf->name, "issuer") && cnf->value && + !strcmp(cnf->value, "copy")) { + if (!copy_issuer(ctx, gens)) { + goto err; + } + } else { + GENERAL_NAME *gen; + if (!(gen = v2i_GENERAL_NAME(method, ctx, cnf))) { + goto err; + } + sk_GENERAL_NAME_push(gens, gen); + } + } + return gens; +err: + sk_GENERAL_NAME_pop_free(gens, GENERAL_NAME_free); + return NULL; } /* Append subject altname of issuer to issuer alt name of subject */ -static int copy_issuer(X509V3_CTX *ctx, GENERAL_NAMES *gens) -{ - if (ctx && (ctx->flags == CTX_TEST)) - return 1; - if (!ctx || !ctx->issuer_cert) { - OPENSSL_PUT_ERROR(X509V3, X509V3_R_NO_ISSUER_DETAILS); - return 0; - } - int i = X509_get_ext_by_NID(ctx->issuer_cert, NID_subject_alt_name, -1); - if (i < 0) - return 1; - - int ret = 0; - GENERAL_NAMES *ialt = NULL; - X509_EXTENSION *ext; - if (!(ext = X509_get_ext(ctx->issuer_cert, i)) || - !(ialt = X509V3_EXT_d2i(ext))) { - OPENSSL_PUT_ERROR(X509V3, X509V3_R_ISSUER_DECODE_ERROR); - goto err; - } - - for (size_t j = 0; j < sk_GENERAL_NAME_num(ialt); j++) { - GENERAL_NAME *gen = sk_GENERAL_NAME_value(ialt, j); - if (!sk_GENERAL_NAME_push(gens, gen)) { - OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE); - goto err; - } - /* Ownership of |gen| has moved from |ialt| to |gens|. */ - sk_GENERAL_NAME_set(ialt, j, NULL); +static int copy_issuer(X509V3_CTX *ctx, GENERAL_NAMES *gens) { + if (ctx && (ctx->flags == CTX_TEST)) { + return 1; + } + if (!ctx || !ctx->issuer_cert) { + OPENSSL_PUT_ERROR(X509V3, X509V3_R_NO_ISSUER_DETAILS); + return 0; + } + int i = X509_get_ext_by_NID(ctx->issuer_cert, NID_subject_alt_name, -1); + if (i < 0) { + return 1; + } + + int ret = 0; + GENERAL_NAMES *ialt = NULL; + X509_EXTENSION *ext; + if (!(ext = X509_get_ext(ctx->issuer_cert, i)) || + !(ialt = X509V3_EXT_d2i(ext))) { + OPENSSL_PUT_ERROR(X509V3, X509V3_R_ISSUER_DECODE_ERROR); + goto err; + } + + for (size_t j = 0; j < sk_GENERAL_NAME_num(ialt); j++) { + GENERAL_NAME *gen = sk_GENERAL_NAME_value(ialt, j); + if (!sk_GENERAL_NAME_push(gens, gen)) { + OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE); + goto err; } + /* Ownership of |gen| has moved from |ialt| to |gens|. */ + sk_GENERAL_NAME_set(ialt, j, NULL); + } - ret = 1; + ret = 1; err: - GENERAL_NAMES_free(ialt); - return ret; + GENERAL_NAMES_free(ialt); + return ret; } static void *v2i_subject_alt(const X509V3_EXT_METHOD *method, X509V3_CTX *ctx, - STACK_OF(CONF_VALUE) *nval) -{ - GENERAL_NAMES *gens = NULL; - CONF_VALUE *cnf; - size_t i; - if (!(gens = sk_GENERAL_NAME_new_null())) { - OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE); - return NULL; - } - for (i = 0; i < sk_CONF_VALUE_num(nval); i++) { - cnf = sk_CONF_VALUE_value(nval, i); - if (!x509v3_name_cmp(cnf->name, "email") && cnf->value && - !strcmp(cnf->value, "copy")) { - if (!copy_email(ctx, gens, 0)) - goto err; - } else if (!x509v3_name_cmp(cnf->name, "email") && cnf->value && - !strcmp(cnf->value, "move")) { - if (!copy_email(ctx, gens, 1)) - goto err; - } else { - GENERAL_NAME *gen; - if (!(gen = v2i_GENERAL_NAME(method, ctx, cnf))) - goto err; - sk_GENERAL_NAME_push(gens, gen); - } - } - return gens; - err: - sk_GENERAL_NAME_pop_free(gens, GENERAL_NAME_free); + STACK_OF(CONF_VALUE) *nval) { + GENERAL_NAMES *gens = NULL; + CONF_VALUE *cnf; + size_t i; + if (!(gens = sk_GENERAL_NAME_new_null())) { + OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE); return NULL; + } + for (i = 0; i < sk_CONF_VALUE_num(nval); i++) { + cnf = sk_CONF_VALUE_value(nval, i); + if (!x509v3_name_cmp(cnf->name, "email") && cnf->value && + !strcmp(cnf->value, "copy")) { + if (!copy_email(ctx, gens, 0)) { + goto err; + } + } else if (!x509v3_name_cmp(cnf->name, "email") && cnf->value && + !strcmp(cnf->value, "move")) { + if (!copy_email(ctx, gens, 1)) { + goto err; + } + } else { + GENERAL_NAME *gen; + if (!(gen = v2i_GENERAL_NAME(method, ctx, cnf))) { + goto err; + } + sk_GENERAL_NAME_push(gens, gen); + } + } + return gens; +err: + sk_GENERAL_NAME_pop_free(gens, GENERAL_NAME_free); + return NULL; } /* * Copy any email addresses in a certificate or request to GENERAL_NAMES */ -static int copy_email(X509V3_CTX *ctx, GENERAL_NAMES *gens, int move_p) -{ - X509_NAME *nm; - ASN1_IA5STRING *email = NULL; - X509_NAME_ENTRY *ne; - GENERAL_NAME *gen = NULL; - int i; - if (ctx != NULL && ctx->flags == CTX_TEST) - return 1; - if (!ctx || (!ctx->subject_cert && !ctx->subject_req)) { - OPENSSL_PUT_ERROR(X509V3, X509V3_R_NO_SUBJECT_DETAILS); - goto err; +static int copy_email(X509V3_CTX *ctx, GENERAL_NAMES *gens, int move_p) { + X509_NAME *nm; + ASN1_IA5STRING *email = NULL; + X509_NAME_ENTRY *ne; + GENERAL_NAME *gen = NULL; + int i; + if (ctx != NULL && ctx->flags == CTX_TEST) { + return 1; + } + if (!ctx || (!ctx->subject_cert && !ctx->subject_req)) { + OPENSSL_PUT_ERROR(X509V3, X509V3_R_NO_SUBJECT_DETAILS); + goto err; + } + /* Find the subject name */ + if (ctx->subject_cert) { + nm = X509_get_subject_name(ctx->subject_cert); + } else { + nm = X509_REQ_get_subject_name(ctx->subject_req); + } + + /* Now add any email address(es) to STACK */ + i = -1; + while ((i = X509_NAME_get_index_by_NID(nm, NID_pkcs9_emailAddress, i)) >= 0) { + ne = X509_NAME_get_entry(nm, i); + email = ASN1_STRING_dup(X509_NAME_ENTRY_get_data(ne)); + if (move_p) { + X509_NAME_delete_entry(nm, i); + X509_NAME_ENTRY_free(ne); + i--; } - /* Find the subject name */ - if (ctx->subject_cert) - nm = X509_get_subject_name(ctx->subject_cert); - else - nm = X509_REQ_get_subject_name(ctx->subject_req); - - /* Now add any email address(es) to STACK */ - i = -1; - while ((i = X509_NAME_get_index_by_NID(nm, - NID_pkcs9_emailAddress, i)) >= 0) { - ne = X509_NAME_get_entry(nm, i); - email = ASN1_STRING_dup(X509_NAME_ENTRY_get_data(ne)); - if (move_p) { - X509_NAME_delete_entry(nm, i); - X509_NAME_ENTRY_free(ne); - i--; - } - if (!email || !(gen = GENERAL_NAME_new())) { - OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE); - goto err; - } - gen->d.ia5 = email; - email = NULL; - gen->type = GEN_EMAIL; - if (!sk_GENERAL_NAME_push(gens, gen)) { - OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE); - goto err; - } - gen = NULL; + if (!email || !(gen = GENERAL_NAME_new())) { + OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE); + goto err; } + gen->d.ia5 = email; + email = NULL; + gen->type = GEN_EMAIL; + if (!sk_GENERAL_NAME_push(gens, gen)) { + OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE); + goto err; + } + gen = NULL; + } - return 1; - - err: - GENERAL_NAME_free(gen); - ASN1_IA5STRING_free(email); - return 0; + return 1; +err: + GENERAL_NAME_free(gen); + ASN1_IA5STRING_free(email); + return 0; } GENERAL_NAMES *v2i_GENERAL_NAMES(const X509V3_EXT_METHOD *method, - X509V3_CTX *ctx, STACK_OF(CONF_VALUE) *nval) -{ - GENERAL_NAME *gen; - GENERAL_NAMES *gens = NULL; - CONF_VALUE *cnf; - size_t i; - if (!(gens = sk_GENERAL_NAME_new_null())) { - OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE); - return NULL; - } - for (i = 0; i < sk_CONF_VALUE_num(nval); i++) { - cnf = sk_CONF_VALUE_value(nval, i); - if (!(gen = v2i_GENERAL_NAME(method, ctx, cnf))) - goto err; - sk_GENERAL_NAME_push(gens, gen); - } - return gens; - err: - sk_GENERAL_NAME_pop_free(gens, GENERAL_NAME_free); + X509V3_CTX *ctx, STACK_OF(CONF_VALUE) *nval) { + GENERAL_NAME *gen; + GENERAL_NAMES *gens = NULL; + CONF_VALUE *cnf; + size_t i; + if (!(gens = sk_GENERAL_NAME_new_null())) { + OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE); return NULL; + } + for (i = 0; i < sk_CONF_VALUE_num(nval); i++) { + cnf = sk_CONF_VALUE_value(nval, i); + if (!(gen = v2i_GENERAL_NAME(method, ctx, cnf))) { + goto err; + } + sk_GENERAL_NAME_push(gens, gen); + } + return gens; +err: + sk_GENERAL_NAME_pop_free(gens, GENERAL_NAME_free); + return NULL; } -GENERAL_NAME *v2i_GENERAL_NAME(const X509V3_EXT_METHOD *method, - X509V3_CTX *ctx, CONF_VALUE *cnf) -{ - return v2i_GENERAL_NAME_ex(NULL, method, ctx, cnf, 0); +GENERAL_NAME *v2i_GENERAL_NAME(const X509V3_EXT_METHOD *method, X509V3_CTX *ctx, + CONF_VALUE *cnf) { + return v2i_GENERAL_NAME_ex(NULL, method, ctx, cnf, 0); } GENERAL_NAME *a2i_GENERAL_NAME(GENERAL_NAME *out, - const X509V3_EXT_METHOD *method, - X509V3_CTX *ctx, int gen_type, - const char *value, int is_nc) -{ - char is_string = 0; - GENERAL_NAME *gen = NULL; - - if (!value) { - OPENSSL_PUT_ERROR(X509V3, X509V3_R_MISSING_VALUE); - return NULL; - } + const X509V3_EXT_METHOD *method, X509V3_CTX *ctx, + int gen_type, const char *value, int is_nc) { + char is_string = 0; + GENERAL_NAME *gen = NULL; - if (out) - gen = out; - else { - gen = GENERAL_NAME_new(); - if (gen == NULL) { - OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE); - return NULL; - } + if (!value) { + OPENSSL_PUT_ERROR(X509V3, X509V3_R_MISSING_VALUE); + return NULL; + } + + if (out) { + gen = out; + } else { + gen = GENERAL_NAME_new(); + if (gen == NULL) { + OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE); + return NULL; } + } - switch (gen_type) { + switch (gen_type) { case GEN_URI: case GEN_EMAIL: case GEN_DNS: - is_string = 1; - break; - - case GEN_RID: - { - ASN1_OBJECT *obj; - if (!(obj = OBJ_txt2obj(value, 0))) { - OPENSSL_PUT_ERROR(X509V3, X509V3_R_BAD_OBJECT); - ERR_add_error_data(2, "value=", value); - goto err; - } - gen->d.rid = obj; - } - break; + is_string = 1; + break; + + case GEN_RID: { + ASN1_OBJECT *obj; + if (!(obj = OBJ_txt2obj(value, 0))) { + OPENSSL_PUT_ERROR(X509V3, X509V3_R_BAD_OBJECT); + ERR_add_error_data(2, "value=", value); + goto err; + } + gen->d.rid = obj; + } break; case GEN_IPADD: - if (is_nc) - gen->d.ip = a2i_IPADDRESS_NC(value); - else - gen->d.ip = a2i_IPADDRESS(value); - if (gen->d.ip == NULL) { - OPENSSL_PUT_ERROR(X509V3, X509V3_R_BAD_IP_ADDRESS); - ERR_add_error_data(2, "value=", value); - goto err; - } - break; + if (is_nc) { + gen->d.ip = a2i_IPADDRESS_NC(value); + } else { + gen->d.ip = a2i_IPADDRESS(value); + } + if (gen->d.ip == NULL) { + OPENSSL_PUT_ERROR(X509V3, X509V3_R_BAD_IP_ADDRESS); + ERR_add_error_data(2, "value=", value); + goto err; + } + break; case GEN_DIRNAME: - if (!do_dirname(gen, value, ctx)) { - OPENSSL_PUT_ERROR(X509V3, X509V3_R_DIRNAME_ERROR); - goto err; - } - break; + if (!do_dirname(gen, value, ctx)) { + OPENSSL_PUT_ERROR(X509V3, X509V3_R_DIRNAME_ERROR); + goto err; + } + break; case GEN_OTHERNAME: - if (!do_othername(gen, value, ctx)) { - OPENSSL_PUT_ERROR(X509V3, X509V3_R_OTHERNAME_ERROR); - goto err; - } - break; - default: - OPENSSL_PUT_ERROR(X509V3, X509V3_R_UNSUPPORTED_TYPE); + if (!do_othername(gen, value, ctx)) { + OPENSSL_PUT_ERROR(X509V3, X509V3_R_OTHERNAME_ERROR); goto err; + } + break; + default: + OPENSSL_PUT_ERROR(X509V3, X509V3_R_UNSUPPORTED_TYPE); + goto err; + } + + if (is_string) { + if (!(gen->d.ia5 = ASN1_IA5STRING_new()) || + !ASN1_STRING_set(gen->d.ia5, (unsigned char *)value, strlen(value))) { + OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE); + goto err; } + } - if (is_string) { - if (!(gen->d.ia5 = ASN1_IA5STRING_new()) || - !ASN1_STRING_set(gen->d.ia5, (unsigned char *)value, - strlen(value))) { - OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE); - goto err; - } - } - - gen->type = gen_type; + gen->type = gen_type; - return gen; + return gen; - err: - if (!out) - GENERAL_NAME_free(gen); - return NULL; +err: + if (!out) { + GENERAL_NAME_free(gen); + } + return NULL; } GENERAL_NAME *v2i_GENERAL_NAME_ex(GENERAL_NAME *out, const X509V3_EXT_METHOD *method, - X509V3_CTX *ctx, CONF_VALUE *cnf, int is_nc) -{ - int type; - - char *name, *value; + X509V3_CTX *ctx, CONF_VALUE *cnf, int is_nc) { + int type; - name = cnf->name; - value = cnf->value; + char *name, *value; - if (!value) { - OPENSSL_PUT_ERROR(X509V3, X509V3_R_MISSING_VALUE); - return NULL; - } - - if (!x509v3_name_cmp(name, "email")) - type = GEN_EMAIL; - else if (!x509v3_name_cmp(name, "URI")) - type = GEN_URI; - else if (!x509v3_name_cmp(name, "DNS")) - type = GEN_DNS; - else if (!x509v3_name_cmp(name, "RID")) - type = GEN_RID; - else if (!x509v3_name_cmp(name, "IP")) - type = GEN_IPADD; - else if (!x509v3_name_cmp(name, "dirName")) - type = GEN_DIRNAME; - else if (!x509v3_name_cmp(name, "otherName")) - type = GEN_OTHERNAME; - else { - OPENSSL_PUT_ERROR(X509V3, X509V3_R_UNSUPPORTED_OPTION); - ERR_add_error_data(2, "name=", name); - return NULL; - } + name = cnf->name; + value = cnf->value; - return a2i_GENERAL_NAME(out, method, ctx, type, value, is_nc); + if (!value) { + OPENSSL_PUT_ERROR(X509V3, X509V3_R_MISSING_VALUE); + return NULL; + } + + if (!x509v3_name_cmp(name, "email")) { + type = GEN_EMAIL; + } else if (!x509v3_name_cmp(name, "URI")) { + type = GEN_URI; + } else if (!x509v3_name_cmp(name, "DNS")) { + type = GEN_DNS; + } else if (!x509v3_name_cmp(name, "RID")) { + type = GEN_RID; + } else if (!x509v3_name_cmp(name, "IP")) { + type = GEN_IPADD; + } else if (!x509v3_name_cmp(name, "dirName")) { + type = GEN_DIRNAME; + } else if (!x509v3_name_cmp(name, "otherName")) { + type = GEN_OTHERNAME; + } else { + OPENSSL_PUT_ERROR(X509V3, X509V3_R_UNSUPPORTED_OPTION); + ERR_add_error_data(2, "name=", name); + return NULL; + } + return a2i_GENERAL_NAME(out, method, ctx, type, value, is_nc); } -static int do_othername(GENERAL_NAME *gen, const char *value, X509V3_CTX *ctx) -{ - char *objtmp = NULL; - const char *p; - int objlen; - if (!(p = strchr(value, ';'))) - return 0; - if (!(gen->d.otherName = OTHERNAME_new())) - return 0; - /* - * Free this up because we will overwrite it. no need to free type_id - * because it is static - */ - ASN1_TYPE_free(gen->d.otherName->value); - if (!(gen->d.otherName->value = ASN1_generate_v3(p + 1, ctx))) - return 0; - objlen = p - value; - objtmp = OPENSSL_malloc(objlen + 1); - if (objtmp == NULL) - return 0; - OPENSSL_strlcpy(objtmp, value, objlen + 1); - gen->d.otherName->type_id = OBJ_txt2obj(objtmp, 0); - OPENSSL_free(objtmp); - if (!gen->d.otherName->type_id) - return 0; - return 1; +static int do_othername(GENERAL_NAME *gen, const char *value, X509V3_CTX *ctx) { + char *objtmp = NULL; + const char *p; + int objlen; + if (!(p = strchr(value, ';'))) { + return 0; + } + if (!(gen->d.otherName = OTHERNAME_new())) { + return 0; + } + /* + * Free this up because we will overwrite it. no need to free type_id + * because it is static + */ + ASN1_TYPE_free(gen->d.otherName->value); + if (!(gen->d.otherName->value = ASN1_generate_v3(p + 1, ctx))) { + return 0; + } + objlen = p - value; + objtmp = OPENSSL_malloc(objlen + 1); + if (objtmp == NULL) { + return 0; + } + OPENSSL_strlcpy(objtmp, value, objlen + 1); + gen->d.otherName->type_id = OBJ_txt2obj(objtmp, 0); + OPENSSL_free(objtmp); + if (!gen->d.otherName->type_id) { + return 0; + } + return 1; } -static int do_dirname(GENERAL_NAME *gen, const char *value, X509V3_CTX *ctx) -{ - int ret = 0; - STACK_OF(CONF_VALUE) *sk = NULL; - X509_NAME *nm = X509_NAME_new(); - if (nm == NULL) - goto err; - sk = X509V3_get_section(ctx, value); - if (sk == NULL) { - OPENSSL_PUT_ERROR(X509V3, X509V3_R_SECTION_NOT_FOUND); - ERR_add_error_data(2, "section=", value); - goto err; - } - /* FIXME: should allow other character types... */ - if (!X509V3_NAME_from_section(nm, sk, MBSTRING_ASC)) - goto err; - gen->d.dirn = nm; - ret = 1; - - err: - if (!ret) - X509_NAME_free(nm); - X509V3_section_free(ctx, sk); - return ret; +static int do_dirname(GENERAL_NAME *gen, const char *value, X509V3_CTX *ctx) { + int ret = 0; + STACK_OF(CONF_VALUE) *sk = NULL; + X509_NAME *nm = X509_NAME_new(); + if (nm == NULL) { + goto err; + } + sk = X509V3_get_section(ctx, value); + if (sk == NULL) { + OPENSSL_PUT_ERROR(X509V3, X509V3_R_SECTION_NOT_FOUND); + ERR_add_error_data(2, "section=", value); + goto err; + } + /* FIXME: should allow other character types... */ + if (!X509V3_NAME_from_section(nm, sk, MBSTRING_ASC)) { + goto err; + } + gen->d.dirn = nm; + ret = 1; + +err: + if (!ret) { + X509_NAME_free(nm); + } + X509V3_section_free(ctx, sk); + return ret; } diff --git a/crypto/x509v3/v3_bcons.c b/crypto/x509v3/v3_bcons.c index c35204f2c2..db55f0623c 100644 --- a/crypto/x509v3/v3_bcons.c +++ b/crypto/x509v3/v3_bcons.c @@ -72,59 +72,65 @@ static void *v2i_BASIC_CONSTRAINTS(const X509V3_EXT_METHOD *method, STACK_OF(CONF_VALUE) *values); const X509V3_EXT_METHOD v3_bcons = { - NID_basic_constraints, 0, + NID_basic_constraints, + 0, ASN1_ITEM_ref(BASIC_CONSTRAINTS), - 0, 0, 0, 0, - 0, 0, + 0, + 0, + 0, + 0, + 0, + 0, i2v_BASIC_CONSTRAINTS, v2i_BASIC_CONSTRAINTS, - NULL, NULL, + NULL, + NULL, NULL, }; ASN1_SEQUENCE(BASIC_CONSTRAINTS) = { - ASN1_OPT(BASIC_CONSTRAINTS, ca, ASN1_FBOOLEAN), - ASN1_OPT(BASIC_CONSTRAINTS, pathlen, ASN1_INTEGER), + ASN1_OPT(BASIC_CONSTRAINTS, ca, ASN1_FBOOLEAN), + ASN1_OPT(BASIC_CONSTRAINTS, pathlen, ASN1_INTEGER), } ASN1_SEQUENCE_END(BASIC_CONSTRAINTS) IMPLEMENT_ASN1_FUNCTIONS(BASIC_CONSTRAINTS) static STACK_OF(CONF_VALUE) *i2v_BASIC_CONSTRAINTS( - const X509V3_EXT_METHOD *method, void *ext, STACK_OF(CONF_VALUE) *extlist) -{ - const BASIC_CONSTRAINTS *bcons = ext; - X509V3_add_value_bool("CA", bcons->ca, &extlist); - X509V3_add_value_int("pathlen", bcons->pathlen, &extlist); - return extlist; + const X509V3_EXT_METHOD *method, void *ext, STACK_OF(CONF_VALUE) *extlist) { + const BASIC_CONSTRAINTS *bcons = ext; + X509V3_add_value_bool("CA", bcons->ca, &extlist); + X509V3_add_value_int("pathlen", bcons->pathlen, &extlist); + return extlist; } static void *v2i_BASIC_CONSTRAINTS(const X509V3_EXT_METHOD *method, X509V3_CTX *ctx, - STACK_OF(CONF_VALUE) *values) -{ - BASIC_CONSTRAINTS *bcons = NULL; - CONF_VALUE *val; - size_t i; - if (!(bcons = BASIC_CONSTRAINTS_new())) { - OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE); - return NULL; - } - for (i = 0; i < sk_CONF_VALUE_num(values); i++) { - val = sk_CONF_VALUE_value(values, i); - if (!strcmp(val->name, "CA")) { - if (!X509V3_get_value_bool(val, &bcons->ca)) - goto err; - } else if (!strcmp(val->name, "pathlen")) { - if (!X509V3_get_value_int(val, &bcons->pathlen)) - goto err; - } else { - OPENSSL_PUT_ERROR(X509V3, X509V3_R_INVALID_NAME); - X509V3_conf_err(val); - goto err; - } - } - return bcons; - err: - BASIC_CONSTRAINTS_free(bcons); + STACK_OF(CONF_VALUE) *values) { + BASIC_CONSTRAINTS *bcons = NULL; + CONF_VALUE *val; + size_t i; + if (!(bcons = BASIC_CONSTRAINTS_new())) { + OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE); return NULL; + } + for (i = 0; i < sk_CONF_VALUE_num(values); i++) { + val = sk_CONF_VALUE_value(values, i); + if (!strcmp(val->name, "CA")) { + if (!X509V3_get_value_bool(val, &bcons->ca)) { + goto err; + } + } else if (!strcmp(val->name, "pathlen")) { + if (!X509V3_get_value_int(val, &bcons->pathlen)) { + goto err; + } + } else { + OPENSSL_PUT_ERROR(X509V3, X509V3_R_INVALID_NAME); + X509V3_conf_err(val); + goto err; + } + } + return bcons; +err: + BASIC_CONSTRAINTS_free(bcons); + return NULL; } diff --git a/crypto/x509v3/v3_bitst.c b/crypto/x509v3/v3_bitst.c index 3420b126be..9562826fbe 100644 --- a/crypto/x509v3/v3_bitst.c +++ b/crypto/x509v3/v3_bitst.c @@ -75,8 +75,7 @@ static const BIT_STRING_BITNAME ns_cert_type_table[] = { {5, "SSL CA", "sslCA"}, {6, "S/MIME CA", "emailCA"}, {7, "Object Signing CA", "objCA"}, - {-1, NULL, NULL} -}; + {-1, NULL, NULL}}; static const BIT_STRING_BITNAME key_usage_type_table[] = { {0, "Digital Signature", "digitalSignature"}, @@ -88,53 +87,50 @@ static const BIT_STRING_BITNAME key_usage_type_table[] = { {6, "CRL Sign", "cRLSign"}, {7, "Encipher Only", "encipherOnly"}, {8, "Decipher Only", "decipherOnly"}, - {-1, NULL, NULL} -}; + {-1, NULL, NULL}}; static STACK_OF(CONF_VALUE) *i2v_ASN1_BIT_STRING( - const X509V3_EXT_METHOD *method, void *ext, STACK_OF(CONF_VALUE) *ret) -{ - const ASN1_BIT_STRING *bits = ext; - const BIT_STRING_BITNAME *bnam; - for (bnam = method->usr_data; bnam->lname; bnam++) { - if (ASN1_BIT_STRING_get_bit(bits, bnam->bitnum)) - X509V3_add_value(bnam->lname, NULL, &ret); + const X509V3_EXT_METHOD *method, void *ext, STACK_OF(CONF_VALUE) *ret) { + const ASN1_BIT_STRING *bits = ext; + const BIT_STRING_BITNAME *bnam; + for (bnam = method->usr_data; bnam->lname; bnam++) { + if (ASN1_BIT_STRING_get_bit(bits, bnam->bitnum)) { + X509V3_add_value(bnam->lname, NULL, &ret); } - return ret; + } + return ret; } static void *v2i_ASN1_BIT_STRING(const X509V3_EXT_METHOD *method, - X509V3_CTX *ctx, STACK_OF(CONF_VALUE) *nval) -{ - CONF_VALUE *val; - ASN1_BIT_STRING *bs; - size_t i; - const BIT_STRING_BITNAME *bnam; - if (!(bs = ASN1_BIT_STRING_new())) { - OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE); - return NULL; - } - for (i = 0; i < sk_CONF_VALUE_num(nval); i++) { - val = sk_CONF_VALUE_value(nval, i); - for (bnam = method->usr_data; bnam->lname; bnam++) { - if (!strcmp(bnam->sname, val->name) || - !strcmp(bnam->lname, val->name)) { - if (!ASN1_BIT_STRING_set_bit(bs, bnam->bitnum, 1)) { - OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE); - ASN1_BIT_STRING_free(bs); - return NULL; - } - break; - } - } - if (!bnam->lname) { - OPENSSL_PUT_ERROR(X509V3, X509V3_R_UNKNOWN_BIT_STRING_ARGUMENT); - X509V3_conf_err(val); - ASN1_BIT_STRING_free(bs); - return NULL; + X509V3_CTX *ctx, STACK_OF(CONF_VALUE) *nval) { + CONF_VALUE *val; + ASN1_BIT_STRING *bs; + size_t i; + const BIT_STRING_BITNAME *bnam; + if (!(bs = ASN1_BIT_STRING_new())) { + OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE); + return NULL; + } + for (i = 0; i < sk_CONF_VALUE_num(nval); i++) { + val = sk_CONF_VALUE_value(nval, i); + for (bnam = method->usr_data; bnam->lname; bnam++) { + if (!strcmp(bnam->sname, val->name) || !strcmp(bnam->lname, val->name)) { + if (!ASN1_BIT_STRING_set_bit(bs, bnam->bitnum, 1)) { + OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE); + ASN1_BIT_STRING_free(bs); + return NULL; } + break; + } } - return bs; + if (!bnam->lname) { + OPENSSL_PUT_ERROR(X509V3, X509V3_R_UNKNOWN_BIT_STRING_ARGUMENT); + X509V3_conf_err(val); + ASN1_BIT_STRING_free(bs); + return NULL; + } + } + return bs; } #define EXT_BITSTRING(nid, table) \ @@ -144,6 +140,6 @@ static void *v2i_ASN1_BIT_STRING(const X509V3_EXT_METHOD *method, } const X509V3_EXT_METHOD v3_nscert = -EXT_BITSTRING(NID_netscape_cert_type, ns_cert_type_table); + EXT_BITSTRING(NID_netscape_cert_type, ns_cert_type_table); const X509V3_EXT_METHOD v3_key_usage = -EXT_BITSTRING(NID_key_usage, key_usage_type_table); + EXT_BITSTRING(NID_key_usage, key_usage_type_table); diff --git a/crypto/x509v3/v3_conf.c b/crypto/x509v3/v3_conf.c index 3192752301..1c10158e66 100644 --- a/crypto/x509v3/v3_conf.c +++ b/crypto/x509v3/v3_conf.c @@ -79,248 +79,254 @@ static X509_EXTENSION *do_ext_nconf(CONF *conf, X509V3_CTX *ctx, int ext_nid, static X509_EXTENSION *v3_generic_extension(const char *ext, const char *value, int crit, int type, X509V3_CTX *ctx); -static X509_EXTENSION *do_ext_i2d(const X509V3_EXT_METHOD *method, - int ext_nid, int crit, void *ext_struc); +static X509_EXTENSION *do_ext_i2d(const X509V3_EXT_METHOD *method, int ext_nid, + int crit, void *ext_struc); static unsigned char *generic_asn1(const char *value, X509V3_CTX *ctx, long *ext_len); /* CONF *conf: Config file */ /* char *name: Name */ /* char *value: Value */ X509_EXTENSION *X509V3_EXT_nconf(CONF *conf, X509V3_CTX *ctx, const char *name, - const char *value) -{ - int crit; - int ext_type; - X509_EXTENSION *ret; - crit = v3_check_critical(&value); - if ((ext_type = v3_check_generic(&value))) - return v3_generic_extension(name, value, crit, ext_type, ctx); - ret = do_ext_nconf(conf, ctx, OBJ_sn2nid(name), crit, value); - if (!ret) { - OPENSSL_PUT_ERROR(X509V3, X509V3_R_ERROR_IN_EXTENSION); - ERR_add_error_data(4, "name=", name, ", value=", value); - } - return ret; + const char *value) { + int crit; + int ext_type; + X509_EXTENSION *ret; + crit = v3_check_critical(&value); + if ((ext_type = v3_check_generic(&value))) { + return v3_generic_extension(name, value, crit, ext_type, ctx); + } + ret = do_ext_nconf(conf, ctx, OBJ_sn2nid(name), crit, value); + if (!ret) { + OPENSSL_PUT_ERROR(X509V3, X509V3_R_ERROR_IN_EXTENSION); + ERR_add_error_data(4, "name=", name, ", value=", value); + } + return ret; } /* CONF *conf: Config file */ /* char *value: Value */ X509_EXTENSION *X509V3_EXT_nconf_nid(CONF *conf, X509V3_CTX *ctx, int ext_nid, - const char *value) -{ - int crit; - int ext_type; - crit = v3_check_critical(&value); - if ((ext_type = v3_check_generic(&value))) - return v3_generic_extension(OBJ_nid2sn(ext_nid), - value, crit, ext_type, ctx); - return do_ext_nconf(conf, ctx, ext_nid, crit, value); + const char *value) { + int crit; + int ext_type; + crit = v3_check_critical(&value); + if ((ext_type = v3_check_generic(&value))) { + return v3_generic_extension(OBJ_nid2sn(ext_nid), value, crit, ext_type, + ctx); + } + return do_ext_nconf(conf, ctx, ext_nid, crit, value); } /* CONF *conf: Config file */ /* char *value: Value */ static X509_EXTENSION *do_ext_nconf(CONF *conf, X509V3_CTX *ctx, int ext_nid, - int crit, const char *value) -{ - const X509V3_EXT_METHOD *method; - X509_EXTENSION *ext; - STACK_OF(CONF_VALUE) *nval; - void *ext_struc; - if (ext_nid == NID_undef) { - OPENSSL_PUT_ERROR(X509V3, X509V3_R_UNKNOWN_EXTENSION_NAME); - return NULL; + int crit, const char *value) { + const X509V3_EXT_METHOD *method; + X509_EXTENSION *ext; + STACK_OF(CONF_VALUE) *nval; + void *ext_struc; + if (ext_nid == NID_undef) { + OPENSSL_PUT_ERROR(X509V3, X509V3_R_UNKNOWN_EXTENSION_NAME); + return NULL; + } + if (!(method = X509V3_EXT_get_nid(ext_nid))) { + OPENSSL_PUT_ERROR(X509V3, X509V3_R_UNKNOWN_EXTENSION); + return NULL; + } + /* Now get internal extension representation based on type */ + if (method->v2i) { + if (*value == '@') { + nval = NCONF_get_section(conf, value + 1); + } else { + nval = X509V3_parse_list(value); } - if (!(method = X509V3_EXT_get_nid(ext_nid))) { - OPENSSL_PUT_ERROR(X509V3, X509V3_R_UNKNOWN_EXTENSION); - return NULL; + if (nval == NULL || sk_CONF_VALUE_num(nval) <= 0) { + OPENSSL_PUT_ERROR(X509V3, X509V3_R_INVALID_EXTENSION_STRING); + ERR_add_error_data(4, "name=", OBJ_nid2sn(ext_nid), ",section=", value); + if (*value != '@') { + sk_CONF_VALUE_pop_free(nval, X509V3_conf_free); + } + return NULL; } - /* Now get internal extension representation based on type */ - if (method->v2i) { - if (*value == '@') - nval = NCONF_get_section(conf, value + 1); - else - nval = X509V3_parse_list(value); - if (nval == NULL || sk_CONF_VALUE_num(nval) <= 0) { - OPENSSL_PUT_ERROR(X509V3, X509V3_R_INVALID_EXTENSION_STRING); - ERR_add_error_data(4, "name=", OBJ_nid2sn(ext_nid), ",section=", - value); - if (*value != '@') - sk_CONF_VALUE_pop_free(nval, X509V3_conf_free); - return NULL; - } - ext_struc = method->v2i(method, ctx, nval); - if (*value != '@') - sk_CONF_VALUE_pop_free(nval, X509V3_conf_free); - if (!ext_struc) - return NULL; - } else if (method->s2i) { - if (!(ext_struc = method->s2i(method, ctx, value))) - return NULL; - } else if (method->r2i) { - if (!ctx->db || !ctx->db_meth) { - OPENSSL_PUT_ERROR(X509V3, X509V3_R_NO_CONFIG_DATABASE); - return NULL; - } - if (!(ext_struc = method->r2i(method, ctx, value))) - return NULL; - } else { - OPENSSL_PUT_ERROR(X509V3, X509V3_R_EXTENSION_SETTING_NOT_SUPPORTED); - ERR_add_error_data(2, "name=", OBJ_nid2sn(ext_nid)); - return NULL; + ext_struc = method->v2i(method, ctx, nval); + if (*value != '@') { + sk_CONF_VALUE_pop_free(nval, X509V3_conf_free); } - - ext = do_ext_i2d(method, ext_nid, crit, ext_struc); - if (method->it) - ASN1_item_free(ext_struc, ASN1_ITEM_ptr(method->it)); - else - method->ext_free(ext_struc); - return ext; - -} - -static X509_EXTENSION *do_ext_i2d(const X509V3_EXT_METHOD *method, - int ext_nid, int crit, void *ext_struc) -{ - unsigned char *ext_der; - int ext_len; - ASN1_OCTET_STRING *ext_oct; - X509_EXTENSION *ext; - /* Convert internal representation to DER */ - if (method->it) { - ext_der = NULL; - ext_len = - ASN1_item_i2d(ext_struc, &ext_der, ASN1_ITEM_ptr(method->it)); - if (ext_len < 0) - goto merr; - } else { - unsigned char *p; - ext_len = method->i2d(ext_struc, NULL); - if (!(ext_der = OPENSSL_malloc(ext_len))) - goto merr; - p = ext_der; - method->i2d(ext_struc, &p); + if (!ext_struc) { + return NULL; } - if (!(ext_oct = ASN1_OCTET_STRING_new())) - goto merr; - ext_oct->data = ext_der; - ext_oct->length = ext_len; - - ext = X509_EXTENSION_create_by_NID(NULL, ext_nid, crit, ext_oct); - if (!ext) - goto merr; - ASN1_OCTET_STRING_free(ext_oct); - - return ext; - - merr: - OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE); + } else if (method->s2i) { + if (!(ext_struc = method->s2i(method, ctx, value))) { + return NULL; + } + } else if (method->r2i) { + if (!ctx->db || !ctx->db_meth) { + OPENSSL_PUT_ERROR(X509V3, X509V3_R_NO_CONFIG_DATABASE); + return NULL; + } + if (!(ext_struc = method->r2i(method, ctx, value))) { + return NULL; + } + } else { + OPENSSL_PUT_ERROR(X509V3, X509V3_R_EXTENSION_SETTING_NOT_SUPPORTED); + ERR_add_error_data(2, "name=", OBJ_nid2sn(ext_nid)); return NULL; + } + + ext = do_ext_i2d(method, ext_nid, crit, ext_struc); + if (method->it) { + ASN1_item_free(ext_struc, ASN1_ITEM_ptr(method->it)); + } else { + method->ext_free(ext_struc); + } + return ext; +} +static X509_EXTENSION *do_ext_i2d(const X509V3_EXT_METHOD *method, int ext_nid, + int crit, void *ext_struc) { + unsigned char *ext_der; + int ext_len; + ASN1_OCTET_STRING *ext_oct; + X509_EXTENSION *ext; + /* Convert internal representation to DER */ + if (method->it) { + ext_der = NULL; + ext_len = ASN1_item_i2d(ext_struc, &ext_der, ASN1_ITEM_ptr(method->it)); + if (ext_len < 0) { + goto merr; + } + } else { + unsigned char *p; + ext_len = method->i2d(ext_struc, NULL); + if (!(ext_der = OPENSSL_malloc(ext_len))) { + goto merr; + } + p = ext_der; + method->i2d(ext_struc, &p); + } + if (!(ext_oct = ASN1_OCTET_STRING_new())) { + goto merr; + } + ext_oct->data = ext_der; + ext_oct->length = ext_len; + + ext = X509_EXTENSION_create_by_NID(NULL, ext_nid, crit, ext_oct); + if (!ext) { + goto merr; + } + ASN1_OCTET_STRING_free(ext_oct); + + return ext; + +merr: + OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE); + return NULL; } /* Given an internal structure, nid and critical flag create an extension */ -X509_EXTENSION *X509V3_EXT_i2d(int ext_nid, int crit, void *ext_struc) -{ - const X509V3_EXT_METHOD *method; - if (!(method = X509V3_EXT_get_nid(ext_nid))) { - OPENSSL_PUT_ERROR(X509V3, X509V3_R_UNKNOWN_EXTENSION); - return NULL; - } - return do_ext_i2d(method, ext_nid, crit, ext_struc); +X509_EXTENSION *X509V3_EXT_i2d(int ext_nid, int crit, void *ext_struc) { + const X509V3_EXT_METHOD *method; + if (!(method = X509V3_EXT_get_nid(ext_nid))) { + OPENSSL_PUT_ERROR(X509V3, X509V3_R_UNKNOWN_EXTENSION); + return NULL; + } + return do_ext_i2d(method, ext_nid, crit, ext_struc); } /* Check the extension string for critical flag */ -static int v3_check_critical(const char **value) -{ - const char *p = *value; - if ((strlen(p) < 9) || strncmp(p, "critical,", 9)) - return 0; - p += 9; - while (isspace((unsigned char)*p)) - p++; - *value = p; - return 1; +static int v3_check_critical(const char **value) { + const char *p = *value; + if ((strlen(p) < 9) || strncmp(p, "critical,", 9)) { + return 0; + } + p += 9; + while (isspace((unsigned char)*p)) { + p++; + } + *value = p; + return 1; } /* Check extension string for generic extension and return the type */ -static int v3_check_generic(const char **value) -{ - int gen_type = 0; - const char *p = *value; - if ((strlen(p) >= 4) && !strncmp(p, "DER:", 4)) { - p += 4; - gen_type = 1; - } else if ((strlen(p) >= 5) && !strncmp(p, "ASN1:", 5)) { - p += 5; - gen_type = 2; - } else - return 0; - - while (isspace((unsigned char)*p)) - p++; - *value = p; - return gen_type; +static int v3_check_generic(const char **value) { + int gen_type = 0; + const char *p = *value; + if ((strlen(p) >= 4) && !strncmp(p, "DER:", 4)) { + p += 4; + gen_type = 1; + } else if ((strlen(p) >= 5) && !strncmp(p, "ASN1:", 5)) { + p += 5; + gen_type = 2; + } else { + return 0; + } + + while (isspace((unsigned char)*p)) { + p++; + } + *value = p; + return gen_type; } /* Create a generic extension: for now just handle DER type */ static X509_EXTENSION *v3_generic_extension(const char *ext, const char *value, int crit, int gen_type, - X509V3_CTX *ctx) -{ - unsigned char *ext_der = NULL; - long ext_len = 0; - ASN1_OBJECT *obj = NULL; - ASN1_OCTET_STRING *oct = NULL; - X509_EXTENSION *extension = NULL; - if (!(obj = OBJ_txt2obj(ext, 0))) { - OPENSSL_PUT_ERROR(X509V3, X509V3_R_EXTENSION_NAME_ERROR); - ERR_add_error_data(2, "name=", ext); - goto err; - } - - if (gen_type == 1) - ext_der = x509v3_hex_to_bytes(value, &ext_len); - else if (gen_type == 2) - ext_der = generic_asn1(value, ctx, &ext_len); - - if (ext_der == NULL) { - OPENSSL_PUT_ERROR(X509V3, X509V3_R_EXTENSION_VALUE_ERROR); - ERR_add_error_data(2, "value=", value); - goto err; - } - - if (!(oct = ASN1_OCTET_STRING_new())) { - OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE); - goto err; - } - - oct->data = ext_der; - oct->length = ext_len; - ext_der = NULL; - - extension = X509_EXTENSION_create_by_OBJ(NULL, obj, crit, oct); - - err: - ASN1_OBJECT_free(obj); - ASN1_OCTET_STRING_free(oct); - if (ext_der) - OPENSSL_free(ext_der); - return extension; - + X509V3_CTX *ctx) { + unsigned char *ext_der = NULL; + long ext_len = 0; + ASN1_OBJECT *obj = NULL; + ASN1_OCTET_STRING *oct = NULL; + X509_EXTENSION *extension = NULL; + if (!(obj = OBJ_txt2obj(ext, 0))) { + OPENSSL_PUT_ERROR(X509V3, X509V3_R_EXTENSION_NAME_ERROR); + ERR_add_error_data(2, "name=", ext); + goto err; + } + + if (gen_type == 1) { + ext_der = x509v3_hex_to_bytes(value, &ext_len); + } else if (gen_type == 2) { + ext_der = generic_asn1(value, ctx, &ext_len); + } + + if (ext_der == NULL) { + OPENSSL_PUT_ERROR(X509V3, X509V3_R_EXTENSION_VALUE_ERROR); + ERR_add_error_data(2, "value=", value); + goto err; + } + + if (!(oct = ASN1_OCTET_STRING_new())) { + OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE); + goto err; + } + + oct->data = ext_der; + oct->length = ext_len; + ext_der = NULL; + + extension = X509_EXTENSION_create_by_OBJ(NULL, obj, crit, oct); + +err: + ASN1_OBJECT_free(obj); + ASN1_OCTET_STRING_free(oct); + if (ext_der) { + OPENSSL_free(ext_der); + } + return extension; } static unsigned char *generic_asn1(const char *value, X509V3_CTX *ctx, - long *ext_len) -{ - ASN1_TYPE *typ; - unsigned char *ext_der = NULL; - typ = ASN1_generate_v3(value, ctx); - if (typ == NULL) - return NULL; - *ext_len = i2d_ASN1_TYPE(typ, &ext_der); - ASN1_TYPE_free(typ); - return ext_der; + long *ext_len) { + ASN1_TYPE *typ; + unsigned char *ext_der = NULL; + typ = ASN1_generate_v3(value, ctx); + if (typ == NULL) { + return NULL; + } + *ext_len = i2d_ASN1_TYPE(typ, &ext_der); + ASN1_TYPE_free(typ); + return ext_der; } /* @@ -329,23 +335,25 @@ static unsigned char *generic_asn1(const char *value, X509V3_CTX *ctx, */ int X509V3_EXT_add_nconf_sk(CONF *conf, X509V3_CTX *ctx, const char *section, - STACK_OF(X509_EXTENSION) **sk) -{ - X509_EXTENSION *ext; - STACK_OF(CONF_VALUE) *nval; - CONF_VALUE *val; - size_t i; - if (!(nval = NCONF_get_section(conf, section))) - return 0; - for (i = 0; i < sk_CONF_VALUE_num(nval); i++) { - val = sk_CONF_VALUE_value(nval, i); - if (!(ext = X509V3_EXT_nconf(conf, ctx, val->name, val->value))) - return 0; - if (sk) - X509v3_add_ext(sk, ext, -1); - X509_EXTENSION_free(ext); + STACK_OF(X509_EXTENSION) **sk) { + X509_EXTENSION *ext; + STACK_OF(CONF_VALUE) *nval; + CONF_VALUE *val; + size_t i; + if (!(nval = NCONF_get_section(conf, section))) { + return 0; + } + for (i = 0; i < sk_CONF_VALUE_num(nval); i++) { + val = sk_CONF_VALUE_value(nval, i); + if (!(ext = X509V3_EXT_nconf(conf, ctx, val->name, val->value))) { + return 0; + } + if (sk) { + X509v3_add_ext(sk, ext, -1); } - return 1; + X509_EXTENSION_free(ext); + } + return 1; } /* @@ -353,116 +361,113 @@ int X509V3_EXT_add_nconf_sk(CONF *conf, X509V3_CTX *ctx, const char *section, */ int X509V3_EXT_add_nconf(CONF *conf, X509V3_CTX *ctx, const char *section, - X509 *cert) -{ - STACK_OF(X509_EXTENSION) **sk = NULL; - if (cert) - sk = &cert->cert_info->extensions; - return X509V3_EXT_add_nconf_sk(conf, ctx, section, sk); + X509 *cert) { + STACK_OF(X509_EXTENSION) **sk = NULL; + if (cert) { + sk = &cert->cert_info->extensions; + } + return X509V3_EXT_add_nconf_sk(conf, ctx, section, sk); } /* Same as above but for a CRL */ int X509V3_EXT_CRL_add_nconf(CONF *conf, X509V3_CTX *ctx, const char *section, - X509_CRL *crl) -{ - STACK_OF(X509_EXTENSION) **sk = NULL; - if (crl) - sk = &crl->crl->extensions; - return X509V3_EXT_add_nconf_sk(conf, ctx, section, sk); + X509_CRL *crl) { + STACK_OF(X509_EXTENSION) **sk = NULL; + if (crl) { + sk = &crl->crl->extensions; + } + return X509V3_EXT_add_nconf_sk(conf, ctx, section, sk); } /* Add extensions to certificate request */ int X509V3_EXT_REQ_add_nconf(CONF *conf, X509V3_CTX *ctx, const char *section, - X509_REQ *req) -{ - STACK_OF(X509_EXTENSION) *extlist = NULL, **sk = NULL; - int i; - if (req) - sk = &extlist; - i = X509V3_EXT_add_nconf_sk(conf, ctx, section, sk); - if (!i || !sk) - return i; - i = X509_REQ_add_extensions(req, extlist); - sk_X509_EXTENSION_pop_free(extlist, X509_EXTENSION_free); + X509_REQ *req) { + STACK_OF(X509_EXTENSION) *extlist = NULL, **sk = NULL; + int i; + if (req) { + sk = &extlist; + } + i = X509V3_EXT_add_nconf_sk(conf, ctx, section, sk); + if (!i || !sk) { return i; + } + i = X509_REQ_add_extensions(req, extlist); + sk_X509_EXTENSION_pop_free(extlist, X509_EXTENSION_free); + return i; } /* Config database functions */ -char *X509V3_get_string(X509V3_CTX *ctx, const char *name, const char *section) -{ - if (!ctx->db || !ctx->db_meth || !ctx->db_meth->get_string) { - OPENSSL_PUT_ERROR(X509V3, X509V3_R_OPERATION_NOT_DEFINED); - return NULL; - } - if (ctx->db_meth->get_string) - return ctx->db_meth->get_string(ctx->db, name, section); +char *X509V3_get_string(X509V3_CTX *ctx, const char *name, + const char *section) { + if (!ctx->db || !ctx->db_meth || !ctx->db_meth->get_string) { + OPENSSL_PUT_ERROR(X509V3, X509V3_R_OPERATION_NOT_DEFINED); return NULL; + } + if (ctx->db_meth->get_string) { + return ctx->db_meth->get_string(ctx->db, name, section); + } + return NULL; } -STACK_OF(CONF_VALUE) *X509V3_get_section(X509V3_CTX *ctx, const char *section) -{ - if (!ctx->db || !ctx->db_meth || !ctx->db_meth->get_section) { - OPENSSL_PUT_ERROR(X509V3, X509V3_R_OPERATION_NOT_DEFINED); - return NULL; - } - if (ctx->db_meth->get_section) - return ctx->db_meth->get_section(ctx->db, section); +STACK_OF(CONF_VALUE) *X509V3_get_section(X509V3_CTX *ctx, const char *section) { + if (!ctx->db || !ctx->db_meth || !ctx->db_meth->get_section) { + OPENSSL_PUT_ERROR(X509V3, X509V3_R_OPERATION_NOT_DEFINED); return NULL; + } + if (ctx->db_meth->get_section) { + return ctx->db_meth->get_section(ctx->db, section); + } + return NULL; } -void X509V3_string_free(X509V3_CTX *ctx, char *str) -{ - if (!str) - return; - if (ctx->db_meth->free_string) - ctx->db_meth->free_string(ctx->db, str); +void X509V3_string_free(X509V3_CTX *ctx, char *str) { + if (!str) { + return; + } + if (ctx->db_meth->free_string) { + ctx->db_meth->free_string(ctx->db, str); + } } -void X509V3_section_free(X509V3_CTX *ctx, STACK_OF(CONF_VALUE) *section) -{ - if (!section) - return; - if (ctx->db_meth->free_section) - ctx->db_meth->free_section(ctx->db, section); +void X509V3_section_free(X509V3_CTX *ctx, STACK_OF(CONF_VALUE) *section) { + if (!section) { + return; + } + if (ctx->db_meth->free_section) { + ctx->db_meth->free_section(ctx->db, section); + } } -static char *nconf_get_string(void *db, const char *section, const char *value) -{ - /* TODO(fork): This returns a non-const pointer because |X509V3_CONF_METHOD| - * allows |get_string| to return caller-owned pointers, provided they're - * freed by |free_string|. |nconf_method| leaves |free_string| NULL, and - * there are no other implementations of |X509V3_CONF_METHOD|, so this can - * be simplified if we make it private. */ - return (char *)NCONF_get_string(db, section, value); +static char *nconf_get_string(void *db, const char *section, + const char *value) { + /* TODO(fork): This returns a non-const pointer because |X509V3_CONF_METHOD| + * allows |get_string| to return caller-owned pointers, provided they're + * freed by |free_string|. |nconf_method| leaves |free_string| NULL, and + * there are no other implementations of |X509V3_CONF_METHOD|, so this can + * be simplified if we make it private. */ + return (char *)NCONF_get_string(db, section, value); } -static STACK_OF(CONF_VALUE) *nconf_get_section(void *db, const char *section) -{ - return NCONF_get_section(db, section); +static STACK_OF(CONF_VALUE) *nconf_get_section(void *db, const char *section) { + return NCONF_get_section(db, section); } -static const X509V3_CONF_METHOD nconf_method = { - nconf_get_string, - nconf_get_section, - NULL, - NULL -}; - -void X509V3_set_nconf(X509V3_CTX *ctx, CONF *conf) -{ - ctx->db_meth = &nconf_method; - ctx->db = conf; +static const X509V3_CONF_METHOD nconf_method = {nconf_get_string, + nconf_get_section, NULL, NULL}; + +void X509V3_set_nconf(X509V3_CTX *ctx, CONF *conf) { + ctx->db_meth = &nconf_method; + ctx->db = conf; } void X509V3_set_ctx(X509V3_CTX *ctx, X509 *issuer, X509 *subj, X509_REQ *req, - X509_CRL *crl, int flags) -{ - ctx->issuer_cert = issuer; - ctx->subject_cert = subj; - ctx->crl = crl; - ctx->subject_req = req; - ctx->flags = flags; + X509_CRL *crl, int flags) { + ctx->issuer_cert = issuer; + ctx->subject_cert = subj; + ctx->crl = crl; + ctx->subject_req = req; + ctx->flags = flags; } diff --git a/crypto/x509v3/v3_cpols.c b/crypto/x509v3/v3_cpols.c index 82731396b7..d2a674796f 100644 --- a/crypto/x509v3/v3_cpols.c +++ b/crypto/x509v3/v3_cpols.c @@ -87,410 +87,435 @@ static POLICYQUALINFO *notice_section(X509V3_CTX *ctx, static int nref_nos(STACK_OF(ASN1_INTEGER) *nnums, STACK_OF(CONF_VALUE) *nos); const X509V3_EXT_METHOD v3_cpols = { - NID_certificate_policies, 0, ASN1_ITEM_ref(CERTIFICATEPOLICIES), - 0, 0, 0, 0, - 0, 0, - 0, 0, + NID_certificate_policies, + 0, + ASN1_ITEM_ref(CERTIFICATEPOLICIES), + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, i2r_certpol, r2i_certpol, NULL, }; -ASN1_ITEM_TEMPLATE(CERTIFICATEPOLICIES) = - ASN1_EX_TEMPLATE_TYPE(ASN1_TFLG_SEQUENCE_OF, 0, CERTIFICATEPOLICIES, POLICYINFO) +ASN1_ITEM_TEMPLATE(CERTIFICATEPOLICIES) = ASN1_EX_TEMPLATE_TYPE( + ASN1_TFLG_SEQUENCE_OF, 0, CERTIFICATEPOLICIES, POLICYINFO) ASN1_ITEM_TEMPLATE_END(CERTIFICATEPOLICIES) IMPLEMENT_ASN1_FUNCTIONS(CERTIFICATEPOLICIES) ASN1_SEQUENCE(POLICYINFO) = { - ASN1_SIMPLE(POLICYINFO, policyid, ASN1_OBJECT), - ASN1_SEQUENCE_OF_OPT(POLICYINFO, qualifiers, POLICYQUALINFO), + ASN1_SIMPLE(POLICYINFO, policyid, ASN1_OBJECT), + ASN1_SEQUENCE_OF_OPT(POLICYINFO, qualifiers, POLICYQUALINFO), } ASN1_SEQUENCE_END(POLICYINFO) IMPLEMENT_ASN1_FUNCTIONS(POLICYINFO) -ASN1_ADB_TEMPLATE(policydefault) = ASN1_SIMPLE(POLICYQUALINFO, d.other, ASN1_ANY); +ASN1_ADB_TEMPLATE(policydefault) = ASN1_SIMPLE(POLICYQUALINFO, d.other, + ASN1_ANY); ASN1_ADB(POLICYQUALINFO) = { - ADB_ENTRY(NID_id_qt_cps, ASN1_SIMPLE(POLICYQUALINFO, d.cpsuri, ASN1_IA5STRING)), - ADB_ENTRY(NID_id_qt_unotice, ASN1_SIMPLE(POLICYQUALINFO, d.usernotice, USERNOTICE)), + ADB_ENTRY(NID_id_qt_cps, + ASN1_SIMPLE(POLICYQUALINFO, d.cpsuri, ASN1_IA5STRING)), + ADB_ENTRY(NID_id_qt_unotice, + ASN1_SIMPLE(POLICYQUALINFO, d.usernotice, USERNOTICE)), } ASN1_ADB_END(POLICYQUALINFO, 0, pqualid, 0, &policydefault_tt, NULL); ASN1_SEQUENCE(POLICYQUALINFO) = { - ASN1_SIMPLE(POLICYQUALINFO, pqualid, ASN1_OBJECT), - ASN1_ADB_OBJECT(POLICYQUALINFO), + ASN1_SIMPLE(POLICYQUALINFO, pqualid, ASN1_OBJECT), + ASN1_ADB_OBJECT(POLICYQUALINFO), } ASN1_SEQUENCE_END(POLICYQUALINFO) IMPLEMENT_ASN1_FUNCTIONS(POLICYQUALINFO) ASN1_SEQUENCE(USERNOTICE) = { - ASN1_OPT(USERNOTICE, noticeref, NOTICEREF), - ASN1_OPT(USERNOTICE, exptext, DISPLAYTEXT), + ASN1_OPT(USERNOTICE, noticeref, NOTICEREF), + ASN1_OPT(USERNOTICE, exptext, DISPLAYTEXT), } ASN1_SEQUENCE_END(USERNOTICE) IMPLEMENT_ASN1_FUNCTIONS(USERNOTICE) ASN1_SEQUENCE(NOTICEREF) = { - ASN1_SIMPLE(NOTICEREF, organization, DISPLAYTEXT), - ASN1_SEQUENCE_OF(NOTICEREF, noticenos, ASN1_INTEGER), + ASN1_SIMPLE(NOTICEREF, organization, DISPLAYTEXT), + ASN1_SEQUENCE_OF(NOTICEREF, noticenos, ASN1_INTEGER), } ASN1_SEQUENCE_END(NOTICEREF) IMPLEMENT_ASN1_FUNCTIONS(NOTICEREF) static void *r2i_certpol(const X509V3_EXT_METHOD *method, X509V3_CTX *ctx, - const char *value) -{ - STACK_OF(POLICYINFO) *pols = NULL; - char *pstr; - POLICYINFO *pol; - ASN1_OBJECT *pobj; - STACK_OF(CONF_VALUE) *vals; - CONF_VALUE *cnf; - size_t i; - int ia5org; - pols = sk_POLICYINFO_new_null(); - if (pols == NULL) { - OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE); - return NULL; + const char *value) { + STACK_OF(POLICYINFO) *pols = NULL; + char *pstr; + POLICYINFO *pol; + ASN1_OBJECT *pobj; + STACK_OF(CONF_VALUE) *vals; + CONF_VALUE *cnf; + size_t i; + int ia5org; + pols = sk_POLICYINFO_new_null(); + if (pols == NULL) { + OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE); + return NULL; + } + vals = X509V3_parse_list(value); + if (vals == NULL) { + OPENSSL_PUT_ERROR(X509V3, ERR_R_X509V3_LIB); + goto err; + } + ia5org = 0; + for (i = 0; i < sk_CONF_VALUE_num(vals); i++) { + cnf = sk_CONF_VALUE_value(vals, i); + if (cnf->value || !cnf->name) { + OPENSSL_PUT_ERROR(X509V3, X509V3_R_INVALID_POLICY_IDENTIFIER); + X509V3_conf_err(cnf); + goto err; } - vals = X509V3_parse_list(value); - if (vals == NULL) { - OPENSSL_PUT_ERROR(X509V3, ERR_R_X509V3_LIB); + pstr = cnf->name; + if (!strcmp(pstr, "ia5org")) { + ia5org = 1; + continue; + } else if (*pstr == '@') { + STACK_OF(CONF_VALUE) *polsect; + polsect = X509V3_get_section(ctx, pstr + 1); + if (!polsect) { + OPENSSL_PUT_ERROR(X509V3, X509V3_R_INVALID_SECTION); + + X509V3_conf_err(cnf); + goto err; + } + pol = policy_section(ctx, polsect, ia5org); + X509V3_section_free(ctx, polsect); + if (!pol) { + goto err; + } + } else { + if (!(pobj = OBJ_txt2obj(cnf->name, 0))) { + OPENSSL_PUT_ERROR(X509V3, X509V3_R_INVALID_OBJECT_IDENTIFIER); + X509V3_conf_err(cnf); + goto err; + } + pol = POLICYINFO_new(); + if (pol == NULL) { + OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE); + ASN1_OBJECT_free(pobj); goto err; + } + pol->policyid = pobj; } - ia5org = 0; - for (i = 0; i < sk_CONF_VALUE_num(vals); i++) { - cnf = sk_CONF_VALUE_value(vals, i); - if (cnf->value || !cnf->name) { - OPENSSL_PUT_ERROR(X509V3, X509V3_R_INVALID_POLICY_IDENTIFIER); - X509V3_conf_err(cnf); - goto err; - } - pstr = cnf->name; - if (!strcmp(pstr, "ia5org")) { - ia5org = 1; - continue; - } else if (*pstr == '@') { - STACK_OF(CONF_VALUE) *polsect; - polsect = X509V3_get_section(ctx, pstr + 1); - if (!polsect) { - OPENSSL_PUT_ERROR(X509V3, X509V3_R_INVALID_SECTION); - - X509V3_conf_err(cnf); - goto err; - } - pol = policy_section(ctx, polsect, ia5org); - X509V3_section_free(ctx, polsect); - if (!pol) - goto err; - } else { - if (!(pobj = OBJ_txt2obj(cnf->name, 0))) { - OPENSSL_PUT_ERROR(X509V3, X509V3_R_INVALID_OBJECT_IDENTIFIER); - X509V3_conf_err(cnf); - goto err; - } - pol = POLICYINFO_new(); - if (pol == NULL) { - OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE); - ASN1_OBJECT_free(pobj); - goto err; - } - pol->policyid = pobj; - } - if (!sk_POLICYINFO_push(pols, pol)) { - POLICYINFO_free(pol); - OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE); - goto err; - } + if (!sk_POLICYINFO_push(pols, pol)) { + POLICYINFO_free(pol); + OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE); + goto err; } - sk_CONF_VALUE_pop_free(vals, X509V3_conf_free); - return pols; - err: - sk_CONF_VALUE_pop_free(vals, X509V3_conf_free); - sk_POLICYINFO_pop_free(pols, POLICYINFO_free); - return NULL; + } + sk_CONF_VALUE_pop_free(vals, X509V3_conf_free); + return pols; +err: + sk_CONF_VALUE_pop_free(vals, X509V3_conf_free); + sk_POLICYINFO_pop_free(pols, POLICYINFO_free); + return NULL; } static POLICYINFO *policy_section(X509V3_CTX *ctx, - STACK_OF(CONF_VALUE) *polstrs, int ia5org) -{ - size_t i; - CONF_VALUE *cnf; - POLICYINFO *pol; - POLICYQUALINFO *qual; - if (!(pol = POLICYINFO_new())) + STACK_OF(CONF_VALUE) *polstrs, int ia5org) { + size_t i; + CONF_VALUE *cnf; + POLICYINFO *pol; + POLICYQUALINFO *qual; + if (!(pol = POLICYINFO_new())) { + goto merr; + } + for (i = 0; i < sk_CONF_VALUE_num(polstrs); i++) { + cnf = sk_CONF_VALUE_value(polstrs, i); + if (!strcmp(cnf->name, "policyIdentifier")) { + ASN1_OBJECT *pobj; + if (!(pobj = OBJ_txt2obj(cnf->value, 0))) { + OPENSSL_PUT_ERROR(X509V3, X509V3_R_INVALID_OBJECT_IDENTIFIER); + X509V3_conf_err(cnf); + goto err; + } + pol->policyid = pobj; + + } else if (!x509v3_name_cmp(cnf->name, "CPS")) { + if (!pol->qualifiers) { + pol->qualifiers = sk_POLICYQUALINFO_new_null(); + } + if (!(qual = POLICYQUALINFO_new())) { goto merr; - for (i = 0; i < sk_CONF_VALUE_num(polstrs); i++) { - cnf = sk_CONF_VALUE_value(polstrs, i); - if (!strcmp(cnf->name, "policyIdentifier")) { - ASN1_OBJECT *pobj; - if (!(pobj = OBJ_txt2obj(cnf->value, 0))) { - OPENSSL_PUT_ERROR(X509V3, X509V3_R_INVALID_OBJECT_IDENTIFIER); - X509V3_conf_err(cnf); - goto err; - } - pol->policyid = pobj; - - } else if (!x509v3_name_cmp(cnf->name, "CPS")) { - if (!pol->qualifiers) - pol->qualifiers = sk_POLICYQUALINFO_new_null(); - if (!(qual = POLICYQUALINFO_new())) - goto merr; - if (!sk_POLICYQUALINFO_push(pol->qualifiers, qual)) - goto merr; - qual->pqualid = OBJ_nid2obj(NID_id_qt_cps); - if (qual->pqualid == NULL) { - OPENSSL_PUT_ERROR(X509V3, ERR_R_INTERNAL_ERROR); - goto err; - } - qual->d.cpsuri = ASN1_IA5STRING_new(); - if (qual->d.cpsuri == NULL) { - goto err; - } - if (!ASN1_STRING_set(qual->d.cpsuri, cnf->value, - strlen(cnf->value))) - goto merr; - } else if (!x509v3_name_cmp(cnf->name, "userNotice")) { - STACK_OF(CONF_VALUE) *unot; - if (*cnf->value != '@') { - OPENSSL_PUT_ERROR(X509V3, X509V3_R_EXPECTED_A_SECTION_NAME); - X509V3_conf_err(cnf); - goto err; - } - unot = X509V3_get_section(ctx, cnf->value + 1); - if (!unot) { - OPENSSL_PUT_ERROR(X509V3, X509V3_R_INVALID_SECTION); - - X509V3_conf_err(cnf); - goto err; - } - qual = notice_section(ctx, unot, ia5org); - X509V3_section_free(ctx, unot); - if (!qual) - goto err; - if (!pol->qualifiers) - pol->qualifiers = sk_POLICYQUALINFO_new_null(); - if (!sk_POLICYQUALINFO_push(pol->qualifiers, qual)) - goto merr; - } else { - OPENSSL_PUT_ERROR(X509V3, X509V3_R_INVALID_OPTION); - - X509V3_conf_err(cnf); - goto err; - } - } - if (!pol->policyid) { - OPENSSL_PUT_ERROR(X509V3, X509V3_R_NO_POLICY_IDENTIFIER); + } + if (!sk_POLICYQUALINFO_push(pol->qualifiers, qual)) { + goto merr; + } + qual->pqualid = OBJ_nid2obj(NID_id_qt_cps); + if (qual->pqualid == NULL) { + OPENSSL_PUT_ERROR(X509V3, ERR_R_INTERNAL_ERROR); goto err; - } + } + qual->d.cpsuri = ASN1_IA5STRING_new(); + if (qual->d.cpsuri == NULL) { + goto err; + } + if (!ASN1_STRING_set(qual->d.cpsuri, cnf->value, strlen(cnf->value))) { + goto merr; + } + } else if (!x509v3_name_cmp(cnf->name, "userNotice")) { + STACK_OF(CONF_VALUE) *unot; + if (*cnf->value != '@') { + OPENSSL_PUT_ERROR(X509V3, X509V3_R_EXPECTED_A_SECTION_NAME); + X509V3_conf_err(cnf); + goto err; + } + unot = X509V3_get_section(ctx, cnf->value + 1); + if (!unot) { + OPENSSL_PUT_ERROR(X509V3, X509V3_R_INVALID_SECTION); - return pol; + X509V3_conf_err(cnf); + goto err; + } + qual = notice_section(ctx, unot, ia5org); + X509V3_section_free(ctx, unot); + if (!qual) { + goto err; + } + if (!pol->qualifiers) { + pol->qualifiers = sk_POLICYQUALINFO_new_null(); + } + if (!sk_POLICYQUALINFO_push(pol->qualifiers, qual)) { + goto merr; + } + } else { + OPENSSL_PUT_ERROR(X509V3, X509V3_R_INVALID_OPTION); - merr: - OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE); + X509V3_conf_err(cnf); + goto err; + } + } + if (!pol->policyid) { + OPENSSL_PUT_ERROR(X509V3, X509V3_R_NO_POLICY_IDENTIFIER); + goto err; + } - err: - POLICYINFO_free(pol); - return NULL; + return pol; +merr: + OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE); + +err: + POLICYINFO_free(pol); + return NULL; } static POLICYQUALINFO *notice_section(X509V3_CTX *ctx, - STACK_OF(CONF_VALUE) *unot, int ia5org) -{ - size_t i; - int ret; - CONF_VALUE *cnf; - USERNOTICE *not; - POLICYQUALINFO *qual; - if (!(qual = POLICYQUALINFO_new())) + STACK_OF(CONF_VALUE) *unot, int ia5org) { + size_t i; + int ret; + CONF_VALUE *cnf; + USERNOTICE * not ; + POLICYQUALINFO *qual; + if (!(qual = POLICYQUALINFO_new())) { + goto merr; + } + qual->pqualid = OBJ_nid2obj(NID_id_qt_unotice); + if (qual->pqualid == NULL) { + OPENSSL_PUT_ERROR(X509V3, ERR_R_INTERNAL_ERROR); + goto err; + } + if (!(not = USERNOTICE_new())) { + goto merr; + } + qual->d.usernotice = not ; + for (i = 0; i < sk_CONF_VALUE_num(unot); i++) { + cnf = sk_CONF_VALUE_value(unot, i); + if (!strcmp(cnf->name, "explicitText")) { + not ->exptext = ASN1_VISIBLESTRING_new(); + if (not ->exptext == NULL) { goto merr; - qual->pqualid = OBJ_nid2obj(NID_id_qt_unotice); - if (qual->pqualid == NULL) { - OPENSSL_PUT_ERROR(X509V3, ERR_R_INTERNAL_ERROR); - goto err; - } - if (!(not = USERNOTICE_new())) + } + if (!ASN1_STRING_set(not ->exptext, cnf->value, strlen(cnf->value))) { goto merr; - qual->d.usernotice = not; - for (i = 0; i < sk_CONF_VALUE_num(unot); i++) { - cnf = sk_CONF_VALUE_value(unot, i); - if (!strcmp(cnf->name, "explicitText")) { - not->exptext = ASN1_VISIBLESTRING_new(); - if (not->exptext == NULL) - goto merr; - if (!ASN1_STRING_set(not->exptext, cnf->value, - strlen(cnf->value))) - goto merr; - } else if (!strcmp(cnf->name, "organization")) { - NOTICEREF *nref; - if (!not->noticeref) { - if (!(nref = NOTICEREF_new())) - goto merr; - not->noticeref = nref; - } else - nref = not->noticeref; - if (ia5org) - nref->organization->type = V_ASN1_IA5STRING; - else - nref->organization->type = V_ASN1_VISIBLESTRING; - if (!ASN1_STRING_set(nref->organization, cnf->value, - strlen(cnf->value))) - goto merr; - } else if (!strcmp(cnf->name, "noticeNumbers")) { - NOTICEREF *nref; - STACK_OF(CONF_VALUE) *nos; - if (!not->noticeref) { - if (!(nref = NOTICEREF_new())) - goto merr; - not->noticeref = nref; - } else - nref = not->noticeref; - nos = X509V3_parse_list(cnf->value); - if (!nos || !sk_CONF_VALUE_num(nos)) { - OPENSSL_PUT_ERROR(X509V3, X509V3_R_INVALID_NUMBERS); - X509V3_conf_err(cnf); - goto err; - } - ret = nref_nos(nref->noticenos, nos); - sk_CONF_VALUE_pop_free(nos, X509V3_conf_free); - if (!ret) - goto err; - } else { - OPENSSL_PUT_ERROR(X509V3, X509V3_R_INVALID_OPTION); - X509V3_conf_err(cnf); - goto err; + } + } else if (!strcmp(cnf->name, "organization")) { + NOTICEREF *nref; + if (!not ->noticeref) { + if (!(nref = NOTICEREF_new())) { + goto merr; } - } - - if (not->noticeref && - (!not->noticeref->noticenos || !not->noticeref->organization)) { - OPENSSL_PUT_ERROR(X509V3, X509V3_R_NEED_ORGANIZATION_AND_NUMBERS); + not ->noticeref = nref; + } else { + nref = not ->noticeref; + } + if (ia5org) { + nref->organization->type = V_ASN1_IA5STRING; + } else { + nref->organization->type = V_ASN1_VISIBLESTRING; + } + if (!ASN1_STRING_set(nref->organization, cnf->value, + strlen(cnf->value))) { + goto merr; + } + } else if (!strcmp(cnf->name, "noticeNumbers")) { + NOTICEREF *nref; + STACK_OF(CONF_VALUE) *nos; + if (!not ->noticeref) { + if (!(nref = NOTICEREF_new())) { + goto merr; + } + not ->noticeref = nref; + } else { + nref = not ->noticeref; + } + nos = X509V3_parse_list(cnf->value); + if (!nos || !sk_CONF_VALUE_num(nos)) { + OPENSSL_PUT_ERROR(X509V3, X509V3_R_INVALID_NUMBERS); + X509V3_conf_err(cnf); + goto err; + } + ret = nref_nos(nref->noticenos, nos); + sk_CONF_VALUE_pop_free(nos, X509V3_conf_free); + if (!ret) { goto err; + } + } else { + OPENSSL_PUT_ERROR(X509V3, X509V3_R_INVALID_OPTION); + X509V3_conf_err(cnf); + goto err; } + } - return qual; + if (not ->noticeref && + (!not ->noticeref->noticenos || !not ->noticeref->organization)) { + OPENSSL_PUT_ERROR(X509V3, X509V3_R_NEED_ORGANIZATION_AND_NUMBERS); + goto err; + } - merr: - OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE); + return qual; - err: - POLICYQUALINFO_free(qual); - return NULL; +merr: + OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE); + +err: + POLICYQUALINFO_free(qual); + return NULL; } -static int nref_nos(STACK_OF(ASN1_INTEGER) *nnums, STACK_OF(CONF_VALUE) *nos) -{ - CONF_VALUE *cnf; - ASN1_INTEGER *aint; +static int nref_nos(STACK_OF(ASN1_INTEGER) *nnums, STACK_OF(CONF_VALUE) *nos) { + CONF_VALUE *cnf; + ASN1_INTEGER *aint; - size_t i; + size_t i; - for (i = 0; i < sk_CONF_VALUE_num(nos); i++) { - cnf = sk_CONF_VALUE_value(nos, i); - if (!(aint = s2i_ASN1_INTEGER(NULL, cnf->name))) { - OPENSSL_PUT_ERROR(X509V3, X509V3_R_INVALID_NUMBER); - goto err; - } - if (!sk_ASN1_INTEGER_push(nnums, aint)) - goto merr; + for (i = 0; i < sk_CONF_VALUE_num(nos); i++) { + cnf = sk_CONF_VALUE_value(nos, i); + if (!(aint = s2i_ASN1_INTEGER(NULL, cnf->name))) { + OPENSSL_PUT_ERROR(X509V3, X509V3_R_INVALID_NUMBER); + goto err; } - return 1; + if (!sk_ASN1_INTEGER_push(nnums, aint)) { + goto merr; + } + } + return 1; - merr: - ASN1_INTEGER_free(aint); - OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE); +merr: + ASN1_INTEGER_free(aint); + OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE); - err: - return 0; +err: + return 0; } -static int i2r_certpol(const X509V3_EXT_METHOD *method, void *ext, - BIO *out, int indent) -{ - const STACK_OF(POLICYINFO) *pol = ext; - /* First print out the policy OIDs */ - for (size_t i = 0; i < sk_POLICYINFO_num(pol); i++) { - const POLICYINFO *pinfo = sk_POLICYINFO_value(pol, i); - BIO_printf(out, "%*sPolicy: ", indent, ""); - i2a_ASN1_OBJECT(out, pinfo->policyid); - BIO_puts(out, "\n"); - if (pinfo->qualifiers) - print_qualifiers(out, pinfo->qualifiers, indent + 2); +static int i2r_certpol(const X509V3_EXT_METHOD *method, void *ext, BIO *out, + int indent) { + const STACK_OF(POLICYINFO) *pol = ext; + /* First print out the policy OIDs */ + for (size_t i = 0; i < sk_POLICYINFO_num(pol); i++) { + const POLICYINFO *pinfo = sk_POLICYINFO_value(pol, i); + BIO_printf(out, "%*sPolicy: ", indent, ""); + i2a_ASN1_OBJECT(out, pinfo->policyid); + BIO_puts(out, "\n"); + if (pinfo->qualifiers) { + print_qualifiers(out, pinfo->qualifiers, indent + 2); } - return 1; + } + return 1; } static void print_qualifiers(BIO *out, const STACK_OF(POLICYQUALINFO) *quals, - int indent) -{ - for (size_t i = 0; i < sk_POLICYQUALINFO_num(quals); i++) { - const POLICYQUALINFO *qualinfo = sk_POLICYQUALINFO_value(quals, i); - switch (OBJ_obj2nid(qualinfo->pqualid)) { - case NID_id_qt_cps: - BIO_printf(out, "%*sCPS: %.*s\n", indent, "", - qualinfo->d.cpsuri->length, qualinfo->d.cpsuri->data); - break; - - case NID_id_qt_unotice: - BIO_printf(out, "%*sUser Notice:\n", indent, ""); - print_notice(out, qualinfo->d.usernotice, indent + 2); - break; - - default: - BIO_printf(out, "%*sUnknown Qualifier: ", indent + 2, ""); - - i2a_ASN1_OBJECT(out, qualinfo->pqualid); - BIO_puts(out, "\n"); - break; - } + int indent) { + for (size_t i = 0; i < sk_POLICYQUALINFO_num(quals); i++) { + const POLICYQUALINFO *qualinfo = sk_POLICYQUALINFO_value(quals, i); + switch (OBJ_obj2nid(qualinfo->pqualid)) { + case NID_id_qt_cps: + BIO_printf(out, "%*sCPS: %.*s\n", indent, "", + qualinfo->d.cpsuri->length, qualinfo->d.cpsuri->data); + break; + + case NID_id_qt_unotice: + BIO_printf(out, "%*sUser Notice:\n", indent, ""); + print_notice(out, qualinfo->d.usernotice, indent + 2); + break; + + default: + BIO_printf(out, "%*sUnknown Qualifier: ", indent + 2, ""); + + i2a_ASN1_OBJECT(out, qualinfo->pqualid); + BIO_puts(out, "\n"); + break; } + } } -static void print_notice(BIO *out, const USERNOTICE *notice, int indent) -{ - if (notice->noticeref) { - NOTICEREF *ref; - ref = notice->noticeref; - BIO_printf(out, "%*sOrganization: %.*s\n", indent, "", - ref->organization->length, ref->organization->data); - BIO_printf(out, "%*sNumber%s: ", indent, "", - sk_ASN1_INTEGER_num(ref->noticenos) > 1 ? "s" : ""); - for (size_t i = 0; i < sk_ASN1_INTEGER_num(ref->noticenos); i++) { - ASN1_INTEGER *num; - char *tmp; - num = sk_ASN1_INTEGER_value(ref->noticenos, i); - if (i) - BIO_puts(out, ", "); - if (num == NULL) - BIO_puts(out, "(null)"); - else { - tmp = i2s_ASN1_INTEGER(NULL, num); - if (tmp == NULL) - return; - BIO_puts(out, tmp); - OPENSSL_free(tmp); - } +static void print_notice(BIO *out, const USERNOTICE *notice, int indent) { + if (notice->noticeref) { + NOTICEREF *ref; + ref = notice->noticeref; + BIO_printf(out, "%*sOrganization: %.*s\n", indent, "", + ref->organization->length, ref->organization->data); + BIO_printf(out, "%*sNumber%s: ", indent, "", + sk_ASN1_INTEGER_num(ref->noticenos) > 1 ? "s" : ""); + for (size_t i = 0; i < sk_ASN1_INTEGER_num(ref->noticenos); i++) { + ASN1_INTEGER *num; + char *tmp; + num = sk_ASN1_INTEGER_value(ref->noticenos, i); + if (i) { + BIO_puts(out, ", "); + } + if (num == NULL) { + BIO_puts(out, "(null)"); + } else { + tmp = i2s_ASN1_INTEGER(NULL, num); + if (tmp == NULL) { + return; } - BIO_puts(out, "\n"); + BIO_puts(out, tmp); + OPENSSL_free(tmp); + } } - if (notice->exptext) - BIO_printf(out, "%*sExplicit Text: %.*s\n", indent, "", - notice->exptext->length, notice->exptext->data); + BIO_puts(out, "\n"); + } + if (notice->exptext) { + BIO_printf(out, "%*sExplicit Text: %.*s\n", indent, "", + notice->exptext->length, notice->exptext->data); + } } -void X509_POLICY_NODE_print(BIO *out, X509_POLICY_NODE *node, int indent) -{ - const X509_POLICY_DATA *dat = node->data; +void X509_POLICY_NODE_print(BIO *out, X509_POLICY_NODE *node, int indent) { + const X509_POLICY_DATA *dat = node->data; - BIO_printf(out, "%*sPolicy: ", indent, ""); + BIO_printf(out, "%*sPolicy: ", indent, ""); - i2a_ASN1_OBJECT(out, dat->valid_policy); - BIO_puts(out, "\n"); - BIO_printf(out, "%*s%s\n", indent + 2, "", - node_data_critical(dat) ? "Critical" : "Non Critical"); - if (dat->qualifier_set) - print_qualifiers(out, dat->qualifier_set, indent + 2); - else - BIO_printf(out, "%*sNo Qualifiers\n", indent + 2, ""); + i2a_ASN1_OBJECT(out, dat->valid_policy); + BIO_puts(out, "\n"); + BIO_printf(out, "%*s%s\n", indent + 2, "", + node_data_critical(dat) ? "Critical" : "Non Critical"); + if (dat->qualifier_set) { + print_qualifiers(out, dat->qualifier_set, indent + 2); + } else { + BIO_printf(out, "%*sNo Qualifiers\n", indent + 2, ""); + } } diff --git a/crypto/x509v3/v3_crld.c b/crypto/x509v3/v3_crld.c index 6fafccce5c..a7b9ff3f76 100644 --- a/crypto/x509v3/v3_crld.c +++ b/crypto/x509v3/v3_crld.c @@ -66,119 +66,139 @@ #include #include -#include "internal.h" #include "../x509/internal.h" +#include "internal.h" -static void *v2i_crld(const X509V3_EXT_METHOD *method, - X509V3_CTX *ctx, STACK_OF(CONF_VALUE) *nval); +static void *v2i_crld(const X509V3_EXT_METHOD *method, X509V3_CTX *ctx, + STACK_OF(CONF_VALUE) *nval); static int i2r_crldp(const X509V3_EXT_METHOD *method, void *pcrldp, BIO *out, int indent); const X509V3_EXT_METHOD v3_crld = { - NID_crl_distribution_points, 0, ASN1_ITEM_ref(CRL_DIST_POINTS), - 0, 0, 0, 0, - 0, 0, + NID_crl_distribution_points, + 0, + ASN1_ITEM_ref(CRL_DIST_POINTS), + 0, + 0, + 0, + 0, + 0, + 0, 0, v2i_crld, - i2r_crldp, 0, + i2r_crldp, + 0, NULL, }; const X509V3_EXT_METHOD v3_freshest_crl = { - NID_freshest_crl, 0, ASN1_ITEM_ref(CRL_DIST_POINTS), - 0, 0, 0, 0, - 0, 0, + NID_freshest_crl, + 0, + ASN1_ITEM_ref(CRL_DIST_POINTS), + 0, + 0, + 0, + 0, + 0, + 0, 0, v2i_crld, - i2r_crldp, 0, + i2r_crldp, + 0, NULL, }; static STACK_OF(GENERAL_NAME) *gnames_from_sectname(X509V3_CTX *ctx, - char *sect) -{ - STACK_OF(CONF_VALUE) *gnsect; - STACK_OF(GENERAL_NAME) *gens; - if (*sect == '@') - gnsect = X509V3_get_section(ctx, sect + 1); - else - gnsect = X509V3_parse_list(sect); - if (!gnsect) { - OPENSSL_PUT_ERROR(X509V3, X509V3_R_SECTION_NOT_FOUND); - return NULL; - } - gens = v2i_GENERAL_NAMES(NULL, ctx, gnsect); - if (*sect == '@') - X509V3_section_free(ctx, gnsect); - else - sk_CONF_VALUE_pop_free(gnsect, X509V3_conf_free); - return gens; + char *sect) { + STACK_OF(CONF_VALUE) *gnsect; + STACK_OF(GENERAL_NAME) *gens; + if (*sect == '@') { + gnsect = X509V3_get_section(ctx, sect + 1); + } else { + gnsect = X509V3_parse_list(sect); + } + if (!gnsect) { + OPENSSL_PUT_ERROR(X509V3, X509V3_R_SECTION_NOT_FOUND); + return NULL; + } + gens = v2i_GENERAL_NAMES(NULL, ctx, gnsect); + if (*sect == '@') { + X509V3_section_free(ctx, gnsect); + } else { + sk_CONF_VALUE_pop_free(gnsect, X509V3_conf_free); + } + return gens; } static int set_dist_point_name(DIST_POINT_NAME **pdp, X509V3_CTX *ctx, - CONF_VALUE *cnf) -{ - STACK_OF(GENERAL_NAME) *fnm = NULL; - STACK_OF(X509_NAME_ENTRY) *rnm = NULL; - if (!strncmp(cnf->name, "fullname", 9)) { - fnm = gnames_from_sectname(ctx, cnf->value); - if (!fnm) - goto err; - } else if (!strcmp(cnf->name, "relativename")) { - int ret; - STACK_OF(CONF_VALUE) *dnsect; - X509_NAME *nm; - nm = X509_NAME_new(); - if (!nm) - return -1; - dnsect = X509V3_get_section(ctx, cnf->value); - if (!dnsect) { - OPENSSL_PUT_ERROR(X509V3, X509V3_R_SECTION_NOT_FOUND); - return -1; - } - ret = X509V3_NAME_from_section(nm, dnsect, MBSTRING_ASC); - X509V3_section_free(ctx, dnsect); - rnm = nm->entries; - nm->entries = NULL; - X509_NAME_free(nm); - if (!ret || sk_X509_NAME_ENTRY_num(rnm) <= 0) - goto err; - /* - * Since its a name fragment can't have more than one RDNSequence - */ - if (sk_X509_NAME_ENTRY_value(rnm, - sk_X509_NAME_ENTRY_num(rnm) - 1)->set) { - OPENSSL_PUT_ERROR(X509V3, X509V3_R_INVALID_MULTIPLE_RDNS); - goto err; - } - } else - return 0; - - if (*pdp) { - OPENSSL_PUT_ERROR(X509V3, X509V3_R_DISTPOINT_ALREADY_SET); - goto err; + CONF_VALUE *cnf) { + STACK_OF(GENERAL_NAME) *fnm = NULL; + STACK_OF(X509_NAME_ENTRY) *rnm = NULL; + if (!strncmp(cnf->name, "fullname", 9)) { + fnm = gnames_from_sectname(ctx, cnf->value); + if (!fnm) { + goto err; } - - *pdp = DIST_POINT_NAME_new(); - if (!*pdp) - goto err; - if (fnm) { - (*pdp)->type = 0; - (*pdp)->name.fullname = fnm; - } else { - (*pdp)->type = 1; - (*pdp)->name.relativename = rnm; + } else if (!strcmp(cnf->name, "relativename")) { + int ret; + STACK_OF(CONF_VALUE) *dnsect; + X509_NAME *nm; + nm = X509_NAME_new(); + if (!nm) { + return -1; } - - return 1; - - err: - if (fnm) - sk_GENERAL_NAME_pop_free(fnm, GENERAL_NAME_free); - if (rnm) - sk_X509_NAME_ENTRY_pop_free(rnm, X509_NAME_ENTRY_free); - return -1; + dnsect = X509V3_get_section(ctx, cnf->value); + if (!dnsect) { + OPENSSL_PUT_ERROR(X509V3, X509V3_R_SECTION_NOT_FOUND); + return -1; + } + ret = X509V3_NAME_from_section(nm, dnsect, MBSTRING_ASC); + X509V3_section_free(ctx, dnsect); + rnm = nm->entries; + nm->entries = NULL; + X509_NAME_free(nm); + if (!ret || sk_X509_NAME_ENTRY_num(rnm) <= 0) { + goto err; + } + /* + * Since its a name fragment can't have more than one RDNSequence + */ + if (sk_X509_NAME_ENTRY_value(rnm, sk_X509_NAME_ENTRY_num(rnm) - 1)->set) { + OPENSSL_PUT_ERROR(X509V3, X509V3_R_INVALID_MULTIPLE_RDNS); + goto err; + } + } else { + return 0; + } + + if (*pdp) { + OPENSSL_PUT_ERROR(X509V3, X509V3_R_DISTPOINT_ALREADY_SET); + goto err; + } + + *pdp = DIST_POINT_NAME_new(); + if (!*pdp) { + goto err; + } + if (fnm) { + (*pdp)->type = 0; + (*pdp)->name.fullname = fnm; + } else { + (*pdp)->type = 1; + (*pdp)->name.relativename = rnm; + } + + return 1; + +err: + if (fnm) { + sk_GENERAL_NAME_pop_free(fnm, GENERAL_NAME_free); + } + if (rnm) { + sk_X509_NAME_ENTRY_pop_free(rnm, X509_NAME_ENTRY_free); + } + return -1; } static const BIT_STRING_BITNAME reason_flags[] = { @@ -191,208 +211,225 @@ static const BIT_STRING_BITNAME reason_flags[] = { {6, "Certificate Hold", "certificateHold"}, {7, "Privilege Withdrawn", "privilegeWithdrawn"}, {8, "AA Compromise", "AACompromise"}, - {-1, NULL, NULL} -}; - -static int set_reasons(ASN1_BIT_STRING **preas, char *value) -{ - STACK_OF(CONF_VALUE) *rsk = NULL; - const BIT_STRING_BITNAME *pbn; - const char *bnam; - size_t i; - int ret = 0; - rsk = X509V3_parse_list(value); - if (!rsk) - return 0; - if (*preas) - return 0; - for (i = 0; i < sk_CONF_VALUE_num(rsk); i++) { - bnam = sk_CONF_VALUE_value(rsk, i)->name; - if (!*preas) { - *preas = ASN1_BIT_STRING_new(); - if (!*preas) - goto err; - } - for (pbn = reason_flags; pbn->lname; pbn++) { - if (!strcmp(pbn->sname, bnam)) { - if (!ASN1_BIT_STRING_set_bit(*preas, pbn->bitnum, 1)) - goto err; - break; - } + {-1, NULL, NULL}}; + +static int set_reasons(ASN1_BIT_STRING **preas, char *value) { + STACK_OF(CONF_VALUE) *rsk = NULL; + const BIT_STRING_BITNAME *pbn; + const char *bnam; + size_t i; + int ret = 0; + rsk = X509V3_parse_list(value); + if (!rsk) { + return 0; + } + if (*preas) { + return 0; + } + for (i = 0; i < sk_CONF_VALUE_num(rsk); i++) { + bnam = sk_CONF_VALUE_value(rsk, i)->name; + if (!*preas) { + *preas = ASN1_BIT_STRING_new(); + if (!*preas) { + goto err; + } + } + for (pbn = reason_flags; pbn->lname; pbn++) { + if (!strcmp(pbn->sname, bnam)) { + if (!ASN1_BIT_STRING_set_bit(*preas, pbn->bitnum, 1)) { + goto err; } - if (!pbn->lname) - goto err; + break; + } } - ret = 1; + if (!pbn->lname) { + goto err; + } + } + ret = 1; - err: - sk_CONF_VALUE_pop_free(rsk, X509V3_conf_free); - return ret; +err: + sk_CONF_VALUE_pop_free(rsk, X509V3_conf_free); + return ret; } -static int print_reasons(BIO *out, const char *rname, - ASN1_BIT_STRING *rflags, int indent) -{ - int first = 1; - const BIT_STRING_BITNAME *pbn; - BIO_printf(out, "%*s%s:\n%*s", indent, "", rname, indent + 2, ""); - for (pbn = reason_flags; pbn->lname; pbn++) { - if (ASN1_BIT_STRING_get_bit(rflags, pbn->bitnum)) { - if (first) - first = 0; - else - BIO_puts(out, ", "); - BIO_puts(out, pbn->lname); - } +static int print_reasons(BIO *out, const char *rname, ASN1_BIT_STRING *rflags, + int indent) { + int first = 1; + const BIT_STRING_BITNAME *pbn; + BIO_printf(out, "%*s%s:\n%*s", indent, "", rname, indent + 2, ""); + for (pbn = reason_flags; pbn->lname; pbn++) { + if (ASN1_BIT_STRING_get_bit(rflags, pbn->bitnum)) { + if (first) { + first = 0; + } else { + BIO_puts(out, ", "); + } + BIO_puts(out, pbn->lname); } - if (first) - BIO_puts(out, "\n"); - else - BIO_puts(out, "\n"); - return 1; + } + if (first) { + BIO_puts(out, "\n"); + } else { + BIO_puts(out, "\n"); + } + return 1; } static DIST_POINT *crldp_from_section(X509V3_CTX *ctx, - STACK_OF(CONF_VALUE) *nval) -{ - size_t i; - CONF_VALUE *cnf; - DIST_POINT *point = NULL; - point = DIST_POINT_new(); - if (!point) + STACK_OF(CONF_VALUE) *nval) { + size_t i; + CONF_VALUE *cnf; + DIST_POINT *point = NULL; + point = DIST_POINT_new(); + if (!point) { + goto err; + } + for (i = 0; i < sk_CONF_VALUE_num(nval); i++) { + int ret; + cnf = sk_CONF_VALUE_value(nval, i); + ret = set_dist_point_name(&point->distpoint, ctx, cnf); + if (ret > 0) { + continue; + } + if (ret < 0) { + goto err; + } + if (!strcmp(cnf->name, "reasons")) { + if (!set_reasons(&point->reasons, cnf->value)) { goto err; - for (i = 0; i < sk_CONF_VALUE_num(nval); i++) { - int ret; - cnf = sk_CONF_VALUE_value(nval, i); - ret = set_dist_point_name(&point->distpoint, ctx, cnf); - if (ret > 0) - continue; - if (ret < 0) - goto err; - if (!strcmp(cnf->name, "reasons")) { - if (!set_reasons(&point->reasons, cnf->value)) - goto err; - } else if (!strcmp(cnf->name, "CRLissuer")) { - point->CRLissuer = gnames_from_sectname(ctx, cnf->value); - if (!point->CRLissuer) - goto err; - } + } + } else if (!strcmp(cnf->name, "CRLissuer")) { + point->CRLissuer = gnames_from_sectname(ctx, cnf->value); + if (!point->CRLissuer) { + goto err; + } } + } - return point; + return point; - err: - if (point) - DIST_POINT_free(point); - return NULL; +err: + if (point) { + DIST_POINT_free(point); + } + return NULL; } -static void *v2i_crld(const X509V3_EXT_METHOD *method, - X509V3_CTX *ctx, STACK_OF(CONF_VALUE) *nval) -{ - STACK_OF(DIST_POINT) *crld = NULL; - GENERAL_NAMES *gens = NULL; - GENERAL_NAME *gen = NULL; - CONF_VALUE *cnf; - size_t i; - if (!(crld = sk_DIST_POINT_new_null())) +static void *v2i_crld(const X509V3_EXT_METHOD *method, X509V3_CTX *ctx, + STACK_OF(CONF_VALUE) *nval) { + STACK_OF(DIST_POINT) *crld = NULL; + GENERAL_NAMES *gens = NULL; + GENERAL_NAME *gen = NULL; + CONF_VALUE *cnf; + size_t i; + if (!(crld = sk_DIST_POINT_new_null())) { + goto merr; + } + for (i = 0; i < sk_CONF_VALUE_num(nval); i++) { + DIST_POINT *point; + cnf = sk_CONF_VALUE_value(nval, i); + if (!cnf->value) { + STACK_OF(CONF_VALUE) *dpsect; + dpsect = X509V3_get_section(ctx, cnf->name); + if (!dpsect) { + goto err; + } + point = crldp_from_section(ctx, dpsect); + X509V3_section_free(ctx, dpsect); + if (!point) { + goto err; + } + if (!sk_DIST_POINT_push(crld, point)) { + DIST_POINT_free(point); goto merr; - for (i = 0; i < sk_CONF_VALUE_num(nval); i++) { - DIST_POINT *point; - cnf = sk_CONF_VALUE_value(nval, i); - if (!cnf->value) { - STACK_OF(CONF_VALUE) *dpsect; - dpsect = X509V3_get_section(ctx, cnf->name); - if (!dpsect) - goto err; - point = crldp_from_section(ctx, dpsect); - X509V3_section_free(ctx, dpsect); - if (!point) - goto err; - if (!sk_DIST_POINT_push(crld, point)) { - DIST_POINT_free(point); - goto merr; - } - } else { - if (!(gen = v2i_GENERAL_NAME(method, ctx, cnf))) - goto err; - if (!(gens = GENERAL_NAMES_new())) - goto merr; - if (!sk_GENERAL_NAME_push(gens, gen)) - goto merr; - gen = NULL; - if (!(point = DIST_POINT_new())) - goto merr; - if (!sk_DIST_POINT_push(crld, point)) { - DIST_POINT_free(point); - goto merr; - } - if (!(point->distpoint = DIST_POINT_NAME_new())) - goto merr; - point->distpoint->name.fullname = gens; - point->distpoint->type = 0; - gens = NULL; - } + } + } else { + if (!(gen = v2i_GENERAL_NAME(method, ctx, cnf))) { + goto err; + } + if (!(gens = GENERAL_NAMES_new())) { + goto merr; + } + if (!sk_GENERAL_NAME_push(gens, gen)) { + goto merr; + } + gen = NULL; + if (!(point = DIST_POINT_new())) { + goto merr; + } + if (!sk_DIST_POINT_push(crld, point)) { + DIST_POINT_free(point); + goto merr; + } + if (!(point->distpoint = DIST_POINT_NAME_new())) { + goto merr; + } + point->distpoint->name.fullname = gens; + point->distpoint->type = 0; + gens = NULL; } - return crld; - - merr: - OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE); - err: - GENERAL_NAME_free(gen); - GENERAL_NAMES_free(gens); - sk_DIST_POINT_pop_free(crld, DIST_POINT_free); - return NULL; + } + return crld; + +merr: + OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE); +err: + GENERAL_NAME_free(gen); + GENERAL_NAMES_free(gens); + sk_DIST_POINT_pop_free(crld, DIST_POINT_free); + return NULL; } static int dpn_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it, - void *exarg) -{ - DIST_POINT_NAME *dpn = (DIST_POINT_NAME *)*pval; + void *exarg) { + DIST_POINT_NAME *dpn = (DIST_POINT_NAME *)*pval; - switch (operation) { + switch (operation) { case ASN1_OP_NEW_POST: - dpn->dpname = NULL; - break; + dpn->dpname = NULL; + break; case ASN1_OP_FREE_POST: - if (dpn->dpname) - X509_NAME_free(dpn->dpname); - break; - } - return 1; + if (dpn->dpname) { + X509_NAME_free(dpn->dpname); + } + break; + } + return 1; } -ASN1_CHOICE_cb(DIST_POINT_NAME, dpn_cb) = { +ASN1_CHOICE_cb(DIST_POINT_NAME, dpn_cb) = + { ASN1_IMP_SEQUENCE_OF(DIST_POINT_NAME, name.fullname, GENERAL_NAME, 0), ASN1_IMP_SET_OF(DIST_POINT_NAME, name.relativename, X509_NAME_ENTRY, 1), } ASN1_CHOICE_END_cb(DIST_POINT_NAME, DIST_POINT_NAME, type) -IMPLEMENT_ASN1_FUNCTIONS(DIST_POINT_NAME) + IMPLEMENT_ASN1_FUNCTIONS(DIST_POINT_NAME) ASN1_SEQUENCE(DIST_POINT) = { - ASN1_EXP_OPT(DIST_POINT, distpoint, DIST_POINT_NAME, 0), - ASN1_IMP_OPT(DIST_POINT, reasons, ASN1_BIT_STRING, 1), - ASN1_IMP_SEQUENCE_OF_OPT(DIST_POINT, CRLissuer, GENERAL_NAME, 2), + ASN1_EXP_OPT(DIST_POINT, distpoint, DIST_POINT_NAME, 0), + ASN1_IMP_OPT(DIST_POINT, reasons, ASN1_BIT_STRING, 1), + ASN1_IMP_SEQUENCE_OF_OPT(DIST_POINT, CRLissuer, GENERAL_NAME, 2), } ASN1_SEQUENCE_END(DIST_POINT) IMPLEMENT_ASN1_FUNCTIONS(DIST_POINT) -ASN1_ITEM_TEMPLATE(CRL_DIST_POINTS) = - ASN1_EX_TEMPLATE_TYPE(ASN1_TFLG_SEQUENCE_OF, 0, CRLDistributionPoints, DIST_POINT) +ASN1_ITEM_TEMPLATE(CRL_DIST_POINTS) = ASN1_EX_TEMPLATE_TYPE( + ASN1_TFLG_SEQUENCE_OF, 0, CRLDistributionPoints, DIST_POINT) ASN1_ITEM_TEMPLATE_END(CRL_DIST_POINTS) IMPLEMENT_ASN1_FUNCTIONS(CRL_DIST_POINTS) ASN1_SEQUENCE(ISSUING_DIST_POINT) = { - ASN1_EXP_OPT(ISSUING_DIST_POINT, distpoint, DIST_POINT_NAME, 0), - ASN1_IMP_OPT(ISSUING_DIST_POINT, onlyuser, ASN1_FBOOLEAN, 1), - ASN1_IMP_OPT(ISSUING_DIST_POINT, onlyCA, ASN1_FBOOLEAN, 2), - ASN1_IMP_OPT(ISSUING_DIST_POINT, onlysomereasons, ASN1_BIT_STRING, 3), - ASN1_IMP_OPT(ISSUING_DIST_POINT, indirectCRL, ASN1_FBOOLEAN, 4), - ASN1_IMP_OPT(ISSUING_DIST_POINT, onlyattr, ASN1_FBOOLEAN, 5), + ASN1_EXP_OPT(ISSUING_DIST_POINT, distpoint, DIST_POINT_NAME, 0), + ASN1_IMP_OPT(ISSUING_DIST_POINT, onlyuser, ASN1_FBOOLEAN, 1), + ASN1_IMP_OPT(ISSUING_DIST_POINT, onlyCA, ASN1_FBOOLEAN, 2), + ASN1_IMP_OPT(ISSUING_DIST_POINT, onlysomereasons, ASN1_BIT_STRING, 3), + ASN1_IMP_OPT(ISSUING_DIST_POINT, indirectCRL, ASN1_FBOOLEAN, 4), + ASN1_IMP_OPT(ISSUING_DIST_POINT, onlyattr, ASN1_FBOOLEAN, 5), } ASN1_SEQUENCE_END(ISSUING_DIST_POINT) IMPLEMENT_ASN1_FUNCTIONS(ISSUING_DIST_POINT) @@ -403,161 +440,180 @@ static void *v2i_idp(const X509V3_EXT_METHOD *method, X509V3_CTX *ctx, STACK_OF(CONF_VALUE) *nval); const X509V3_EXT_METHOD v3_idp = { - NID_issuing_distribution_point, X509V3_EXT_MULTILINE, + NID_issuing_distribution_point, + X509V3_EXT_MULTILINE, ASN1_ITEM_ref(ISSUING_DIST_POINT), - 0, 0, 0, 0, - 0, 0, + 0, + 0, + 0, + 0, + 0, + 0, 0, v2i_idp, - i2r_idp, 0, + i2r_idp, + 0, NULL, }; static void *v2i_idp(const X509V3_EXT_METHOD *method, X509V3_CTX *ctx, - STACK_OF(CONF_VALUE) *nval) -{ - ISSUING_DIST_POINT *idp = NULL; - CONF_VALUE *cnf; - char *name, *val; - size_t i; - int ret; - idp = ISSUING_DIST_POINT_new(); - if (!idp) - goto merr; - for (i = 0; i < sk_CONF_VALUE_num(nval); i++) { - cnf = sk_CONF_VALUE_value(nval, i); - name = cnf->name; - val = cnf->value; - ret = set_dist_point_name(&idp->distpoint, ctx, cnf); - if (ret > 0) - continue; - if (ret < 0) - goto err; - if (!strcmp(name, "onlyuser")) { - if (!X509V3_get_value_bool(cnf, &idp->onlyuser)) - goto err; - } else if (!strcmp(name, "onlyCA")) { - if (!X509V3_get_value_bool(cnf, &idp->onlyCA)) - goto err; - } else if (!strcmp(name, "onlyAA")) { - if (!X509V3_get_value_bool(cnf, &idp->onlyattr)) - goto err; - } else if (!strcmp(name, "indirectCRL")) { - if (!X509V3_get_value_bool(cnf, &idp->indirectCRL)) - goto err; - } else if (!strcmp(name, "onlysomereasons")) { - if (!set_reasons(&idp->onlysomereasons, val)) - goto err; - } else { - OPENSSL_PUT_ERROR(X509V3, X509V3_R_INVALID_NAME); - X509V3_conf_err(cnf); - goto err; - } + STACK_OF(CONF_VALUE) *nval) { + ISSUING_DIST_POINT *idp = NULL; + CONF_VALUE *cnf; + char *name, *val; + size_t i; + int ret; + idp = ISSUING_DIST_POINT_new(); + if (!idp) { + goto merr; + } + for (i = 0; i < sk_CONF_VALUE_num(nval); i++) { + cnf = sk_CONF_VALUE_value(nval, i); + name = cnf->name; + val = cnf->value; + ret = set_dist_point_name(&idp->distpoint, ctx, cnf); + if (ret > 0) { + continue; } - return idp; - - merr: - OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE); - err: - ISSUING_DIST_POINT_free(idp); - return NULL; + if (ret < 0) { + goto err; + } + if (!strcmp(name, "onlyuser")) { + if (!X509V3_get_value_bool(cnf, &idp->onlyuser)) { + goto err; + } + } else if (!strcmp(name, "onlyCA")) { + if (!X509V3_get_value_bool(cnf, &idp->onlyCA)) { + goto err; + } + } else if (!strcmp(name, "onlyAA")) { + if (!X509V3_get_value_bool(cnf, &idp->onlyattr)) { + goto err; + } + } else if (!strcmp(name, "indirectCRL")) { + if (!X509V3_get_value_bool(cnf, &idp->indirectCRL)) { + goto err; + } + } else if (!strcmp(name, "onlysomereasons")) { + if (!set_reasons(&idp->onlysomereasons, val)) { + goto err; + } + } else { + OPENSSL_PUT_ERROR(X509V3, X509V3_R_INVALID_NAME); + X509V3_conf_err(cnf); + goto err; + } + } + return idp; + +merr: + OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE); +err: + ISSUING_DIST_POINT_free(idp); + return NULL; } -static int print_gens(BIO *out, STACK_OF(GENERAL_NAME) *gens, int indent) -{ - size_t i; - for (i = 0; i < sk_GENERAL_NAME_num(gens); i++) { - BIO_printf(out, "%*s", indent + 2, ""); - GENERAL_NAME_print(out, sk_GENERAL_NAME_value(gens, i)); - BIO_puts(out, "\n"); - } - return 1; +static int print_gens(BIO *out, STACK_OF(GENERAL_NAME) *gens, int indent) { + size_t i; + for (i = 0; i < sk_GENERAL_NAME_num(gens); i++) { + BIO_printf(out, "%*s", indent + 2, ""); + GENERAL_NAME_print(out, sk_GENERAL_NAME_value(gens, i)); + BIO_puts(out, "\n"); + } + return 1; } -static int print_distpoint(BIO *out, DIST_POINT_NAME *dpn, int indent) -{ - if (dpn->type == 0) { - BIO_printf(out, "%*sFull Name:\n", indent, ""); - print_gens(out, dpn->name.fullname, indent); - } else { - X509_NAME ntmp; - ntmp.entries = dpn->name.relativename; - BIO_printf(out, "%*sRelative Name:\n%*s", indent, "", indent + 2, ""); - X509_NAME_print_ex(out, &ntmp, 0, XN_FLAG_ONELINE); - BIO_puts(out, "\n"); - } - return 1; +static int print_distpoint(BIO *out, DIST_POINT_NAME *dpn, int indent) { + if (dpn->type == 0) { + BIO_printf(out, "%*sFull Name:\n", indent, ""); + print_gens(out, dpn->name.fullname, indent); + } else { + X509_NAME ntmp; + ntmp.entries = dpn->name.relativename; + BIO_printf(out, "%*sRelative Name:\n%*s", indent, "", indent + 2, ""); + X509_NAME_print_ex(out, &ntmp, 0, XN_FLAG_ONELINE); + BIO_puts(out, "\n"); + } + return 1; } static int i2r_idp(const X509V3_EXT_METHOD *method, void *pidp, BIO *out, - int indent) -{ - ISSUING_DIST_POINT *idp = pidp; - if (idp->distpoint) - print_distpoint(out, idp->distpoint, indent); - if (idp->onlyuser > 0) - BIO_printf(out, "%*sOnly User Certificates\n", indent, ""); - if (idp->onlyCA > 0) - BIO_printf(out, "%*sOnly CA Certificates\n", indent, ""); - if (idp->indirectCRL > 0) - BIO_printf(out, "%*sIndirect CRL\n", indent, ""); - if (idp->onlysomereasons) - print_reasons(out, "Only Some Reasons", idp->onlysomereasons, indent); - if (idp->onlyattr > 0) - BIO_printf(out, "%*sOnly Attribute Certificates\n", indent, ""); - if (!idp->distpoint && (idp->onlyuser <= 0) && (idp->onlyCA <= 0) - && (idp->indirectCRL <= 0) && !idp->onlysomereasons - && (idp->onlyattr <= 0)) - BIO_printf(out, "%*s\n", indent, ""); - - return 1; + int indent) { + ISSUING_DIST_POINT *idp = pidp; + if (idp->distpoint) { + print_distpoint(out, idp->distpoint, indent); + } + if (idp->onlyuser > 0) { + BIO_printf(out, "%*sOnly User Certificates\n", indent, ""); + } + if (idp->onlyCA > 0) { + BIO_printf(out, "%*sOnly CA Certificates\n", indent, ""); + } + if (idp->indirectCRL > 0) { + BIO_printf(out, "%*sIndirect CRL\n", indent, ""); + } + if (idp->onlysomereasons) { + print_reasons(out, "Only Some Reasons", idp->onlysomereasons, indent); + } + if (idp->onlyattr > 0) { + BIO_printf(out, "%*sOnly Attribute Certificates\n", indent, ""); + } + if (!idp->distpoint && (idp->onlyuser <= 0) && (idp->onlyCA <= 0) && + (idp->indirectCRL <= 0) && !idp->onlysomereasons && + (idp->onlyattr <= 0)) { + BIO_printf(out, "%*s\n", indent, ""); + } + + return 1; } static int i2r_crldp(const X509V3_EXT_METHOD *method, void *pcrldp, BIO *out, - int indent) -{ - STACK_OF(DIST_POINT) *crld = pcrldp; - DIST_POINT *point; - size_t i; - for (i = 0; i < sk_DIST_POINT_num(crld); i++) { - BIO_puts(out, "\n"); - point = sk_DIST_POINT_value(crld, i); - if (point->distpoint) - print_distpoint(out, point->distpoint, indent); - if (point->reasons) - print_reasons(out, "Reasons", point->reasons, indent); - if (point->CRLissuer) { - BIO_printf(out, "%*sCRL Issuer:\n", indent, ""); - print_gens(out, point->CRLissuer, indent); - } + int indent) { + STACK_OF(DIST_POINT) *crld = pcrldp; + DIST_POINT *point; + size_t i; + for (i = 0; i < sk_DIST_POINT_num(crld); i++) { + BIO_puts(out, "\n"); + point = sk_DIST_POINT_value(crld, i); + if (point->distpoint) { + print_distpoint(out, point->distpoint, indent); } - return 1; -} - -int DIST_POINT_set_dpname(DIST_POINT_NAME *dpn, X509_NAME *iname) -{ - size_t i; - STACK_OF(X509_NAME_ENTRY) *frag; - X509_NAME_ENTRY *ne; - if (!dpn || (dpn->type != 1)) - return 1; - frag = dpn->name.relativename; - dpn->dpname = X509_NAME_dup(iname); - if (!dpn->dpname) - return 0; - for (i = 0; i < sk_X509_NAME_ENTRY_num(frag); i++) { - ne = sk_X509_NAME_ENTRY_value(frag, i); - if (!X509_NAME_add_entry(dpn->dpname, ne, -1, i ? 0 : 1)) { - X509_NAME_free(dpn->dpname); - dpn->dpname = NULL; - return 0; - } + if (point->reasons) { + print_reasons(out, "Reasons", point->reasons, indent); } - /* generate cached encoding of name */ - if (i2d_X509_NAME(dpn->dpname, NULL) < 0) { - X509_NAME_free(dpn->dpname); - dpn->dpname = NULL; - return 0; + if (point->CRLissuer) { + BIO_printf(out, "%*sCRL Issuer:\n", indent, ""); + print_gens(out, point->CRLissuer, indent); } + } + return 1; +} + +int DIST_POINT_set_dpname(DIST_POINT_NAME *dpn, X509_NAME *iname) { + size_t i; + STACK_OF(X509_NAME_ENTRY) *frag; + X509_NAME_ENTRY *ne; + if (!dpn || (dpn->type != 1)) { return 1; + } + frag = dpn->name.relativename; + dpn->dpname = X509_NAME_dup(iname); + if (!dpn->dpname) { + return 0; + } + for (i = 0; i < sk_X509_NAME_ENTRY_num(frag); i++) { + ne = sk_X509_NAME_ENTRY_value(frag, i); + if (!X509_NAME_add_entry(dpn->dpname, ne, -1, i ? 0 : 1)) { + X509_NAME_free(dpn->dpname); + dpn->dpname = NULL; + return 0; + } + } + /* generate cached encoding of name */ + if (i2d_X509_NAME(dpn->dpname, NULL) < 0) { + X509_NAME_free(dpn->dpname); + dpn->dpname = NULL; + return 0; + } + return 1; } diff --git a/crypto/x509v3/v3_enum.c b/crypto/x509v3/v3_enum.c index 636415bf97..cd93f30b36 100644 --- a/crypto/x509v3/v3_enum.c +++ b/crypto/x509v3/v3_enum.c @@ -57,8 +57,8 @@ #include -#include #include +#include #include #include "internal.h" @@ -73,33 +73,40 @@ static const ENUMERATED_NAMES crl_reasons[] = { {CRL_REASON_AFFILIATION_CHANGED, "Affiliation Changed", "affiliationChanged"}, {CRL_REASON_SUPERSEDED, "Superseded", "superseded"}, - {CRL_REASON_CESSATION_OF_OPERATION, - "Cessation Of Operation", "cessationOfOperation"}, + {CRL_REASON_CESSATION_OF_OPERATION, "Cessation Of Operation", + "cessationOfOperation"}, {CRL_REASON_CERTIFICATE_HOLD, "Certificate Hold", "certificateHold"}, {CRL_REASON_REMOVE_FROM_CRL, "Remove From CRL", "removeFromCRL"}, {CRL_REASON_PRIVILEGE_WITHDRAWN, "Privilege Withdrawn", "privilegeWithdrawn"}, {CRL_REASON_AA_COMPROMISE, "AA Compromise", "AACompromise"}, - {-1, NULL, NULL} -}; + {-1, NULL, NULL}}; static char *i2s_ASN1_ENUMERATED_TABLE(const X509V3_EXT_METHOD *method, - void *ext) -{ - const ASN1_ENUMERATED *e = ext; - long strval = ASN1_ENUMERATED_get(e); - for (const ENUMERATED_NAMES *enam = method->usr_data; enam->lname; enam++) { - if (strval == enam->bitnum) - return OPENSSL_strdup(enam->lname); + void *ext) { + const ASN1_ENUMERATED *e = ext; + long strval = ASN1_ENUMERATED_get(e); + for (const ENUMERATED_NAMES *enam = method->usr_data; enam->lname; enam++) { + if (strval == enam->bitnum) { + return OPENSSL_strdup(enam->lname); } - return i2s_ASN1_ENUMERATED(method, e); + } + return i2s_ASN1_ENUMERATED(method, e); } const X509V3_EXT_METHOD v3_crl_reason = { - NID_crl_reason, 0, ASN1_ITEM_ref(ASN1_ENUMERATED), - 0, 0, 0, 0, + NID_crl_reason, + 0, + ASN1_ITEM_ref(ASN1_ENUMERATED), + 0, + 0, + 0, + 0, i2s_ASN1_ENUMERATED_TABLE, 0, - 0, 0, 0, 0, + 0, + 0, + 0, + 0, (void *)crl_reasons, }; diff --git a/crypto/x509v3/v3_extku.c b/crypto/x509v3/v3_extku.c index 6171396090..9d43b0fdd9 100644 --- a/crypto/x509v3/v3_extku.c +++ b/crypto/x509v3/v3_extku.c @@ -66,83 +66,92 @@ static void *v2i_EXTENDED_KEY_USAGE(const X509V3_EXT_METHOD *method, X509V3_CTX *ctx, STACK_OF(CONF_VALUE) *nval); -static STACK_OF(CONF_VALUE) *i2v_EXTENDED_KEY_USAGE(const X509V3_EXT_METHOD - *method, void *eku, STACK_OF(CONF_VALUE) - *extlist); +static STACK_OF(CONF_VALUE) *i2v_EXTENDED_KEY_USAGE( + const X509V3_EXT_METHOD *method, void *eku, STACK_OF(CONF_VALUE) *extlist); const X509V3_EXT_METHOD v3_ext_ku = { - NID_ext_key_usage, 0, + NID_ext_key_usage, + 0, ASN1_ITEM_ref(EXTENDED_KEY_USAGE), - 0, 0, 0, 0, - 0, 0, + 0, + 0, + 0, + 0, + 0, + 0, i2v_EXTENDED_KEY_USAGE, v2i_EXTENDED_KEY_USAGE, - 0, 0, + 0, + 0, NULL, }; /* NB OCSP acceptable responses also is a SEQUENCE OF OBJECT */ const X509V3_EXT_METHOD v3_ocsp_accresp = { - NID_id_pkix_OCSP_acceptableResponses, 0, + NID_id_pkix_OCSP_acceptableResponses, + 0, ASN1_ITEM_ref(EXTENDED_KEY_USAGE), - 0, 0, 0, 0, - 0, 0, + 0, + 0, + 0, + 0, + 0, + 0, i2v_EXTENDED_KEY_USAGE, v2i_EXTENDED_KEY_USAGE, - 0, 0, + 0, + 0, NULL, }; -ASN1_ITEM_TEMPLATE(EXTENDED_KEY_USAGE) = - ASN1_EX_TEMPLATE_TYPE(ASN1_TFLG_SEQUENCE_OF, 0, EXTENDED_KEY_USAGE, ASN1_OBJECT) +ASN1_ITEM_TEMPLATE(EXTENDED_KEY_USAGE) = ASN1_EX_TEMPLATE_TYPE( + ASN1_TFLG_SEQUENCE_OF, 0, EXTENDED_KEY_USAGE, ASN1_OBJECT) ASN1_ITEM_TEMPLATE_END(EXTENDED_KEY_USAGE) IMPLEMENT_ASN1_FUNCTIONS(EXTENDED_KEY_USAGE) -static STACK_OF(CONF_VALUE) *i2v_EXTENDED_KEY_USAGE(const X509V3_EXT_METHOD - *method, void *a, STACK_OF(CONF_VALUE) - *ext_list) -{ - EXTENDED_KEY_USAGE *eku = a; - size_t i; - ASN1_OBJECT *obj; - char obj_tmp[80]; - for (i = 0; i < sk_ASN1_OBJECT_num(eku); i++) { - obj = sk_ASN1_OBJECT_value(eku, i); - i2t_ASN1_OBJECT(obj_tmp, 80, obj); - X509V3_add_value(NULL, obj_tmp, &ext_list); - } - return ext_list; +static STACK_OF(CONF_VALUE) *i2v_EXTENDED_KEY_USAGE( + const X509V3_EXT_METHOD *method, void *a, STACK_OF(CONF_VALUE) *ext_list) { + EXTENDED_KEY_USAGE *eku = a; + size_t i; + ASN1_OBJECT *obj; + char obj_tmp[80]; + for (i = 0; i < sk_ASN1_OBJECT_num(eku); i++) { + obj = sk_ASN1_OBJECT_value(eku, i); + i2t_ASN1_OBJECT(obj_tmp, 80, obj); + X509V3_add_value(NULL, obj_tmp, &ext_list); + } + return ext_list; } static void *v2i_EXTENDED_KEY_USAGE(const X509V3_EXT_METHOD *method, X509V3_CTX *ctx, - STACK_OF(CONF_VALUE) *nval) -{ - EXTENDED_KEY_USAGE *extku; - char *extval; - ASN1_OBJECT *objtmp; - CONF_VALUE *val; - size_t i; + STACK_OF(CONF_VALUE) *nval) { + EXTENDED_KEY_USAGE *extku; + char *extval; + ASN1_OBJECT *objtmp; + CONF_VALUE *val; + size_t i; - if (!(extku = sk_ASN1_OBJECT_new_null())) { - OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE); - return NULL; - } + if (!(extku = sk_ASN1_OBJECT_new_null())) { + OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE); + return NULL; + } - for (i = 0; i < sk_CONF_VALUE_num(nval); i++) { - val = sk_CONF_VALUE_value(nval, i); - if (val->value) - extval = val->value; - else - extval = val->name; - if (!(objtmp = OBJ_txt2obj(extval, 0))) { - sk_ASN1_OBJECT_pop_free(extku, ASN1_OBJECT_free); - OPENSSL_PUT_ERROR(X509V3, X509V3_R_INVALID_OBJECT_IDENTIFIER); - X509V3_conf_err(val); - return NULL; - } - sk_ASN1_OBJECT_push(extku, objtmp); + for (i = 0; i < sk_CONF_VALUE_num(nval); i++) { + val = sk_CONF_VALUE_value(nval, i); + if (val->value) { + extval = val->value; + } else { + extval = val->name; + } + if (!(objtmp = OBJ_txt2obj(extval, 0))) { + sk_ASN1_OBJECT_pop_free(extku, ASN1_OBJECT_free); + OPENSSL_PUT_ERROR(X509V3, X509V3_R_INVALID_OBJECT_IDENTIFIER); + X509V3_conf_err(val); + return NULL; } - return extku; + sk_ASN1_OBJECT_push(extku, objtmp); + } + return extku; } diff --git a/crypto/x509v3/v3_genn.c b/crypto/x509v3/v3_genn.c index a64c8b0905..4b37fc9db9 100644 --- a/crypto/x509v3/v3_genn.c +++ b/crypto/x509v3/v3_genn.c @@ -64,203 +64,206 @@ ASN1_SEQUENCE(OTHERNAME) = { - ASN1_SIMPLE(OTHERNAME, type_id, ASN1_OBJECT), - /* Maybe have a true ANY DEFINED BY later */ - ASN1_EXP(OTHERNAME, value, ASN1_ANY, 0), + ASN1_SIMPLE(OTHERNAME, type_id, ASN1_OBJECT), + /* Maybe have a true ANY DEFINED BY later */ + ASN1_EXP(OTHERNAME, value, ASN1_ANY, 0), } ASN1_SEQUENCE_END(OTHERNAME) IMPLEMENT_ASN1_FUNCTIONS(OTHERNAME) ASN1_SEQUENCE(EDIPARTYNAME) = { - /* DirectoryString is a CHOICE type, so use explicit tagging. */ - ASN1_EXP_OPT(EDIPARTYNAME, nameAssigner, DIRECTORYSTRING, 0), - ASN1_EXP(EDIPARTYNAME, partyName, DIRECTORYSTRING, 1), + /* DirectoryString is a CHOICE type, so use explicit tagging. */ + ASN1_EXP_OPT(EDIPARTYNAME, nameAssigner, DIRECTORYSTRING, 0), + ASN1_EXP(EDIPARTYNAME, partyName, DIRECTORYSTRING, 1), } ASN1_SEQUENCE_END(EDIPARTYNAME) IMPLEMENT_ASN1_FUNCTIONS(EDIPARTYNAME) ASN1_CHOICE(GENERAL_NAME) = { - ASN1_IMP(GENERAL_NAME, d.otherName, OTHERNAME, GEN_OTHERNAME), - ASN1_IMP(GENERAL_NAME, d.rfc822Name, ASN1_IA5STRING, GEN_EMAIL), - ASN1_IMP(GENERAL_NAME, d.dNSName, ASN1_IA5STRING, GEN_DNS), - /* Don't decode this */ - ASN1_IMP(GENERAL_NAME, d.x400Address, ASN1_SEQUENCE, GEN_X400), - /* X509_NAME is a CHOICE type so use EXPLICIT */ - ASN1_EXP(GENERAL_NAME, d.directoryName, X509_NAME, GEN_DIRNAME), - ASN1_IMP(GENERAL_NAME, d.ediPartyName, EDIPARTYNAME, GEN_EDIPARTY), - ASN1_IMP(GENERAL_NAME, d.uniformResourceIdentifier, ASN1_IA5STRING, GEN_URI), - ASN1_IMP(GENERAL_NAME, d.iPAddress, ASN1_OCTET_STRING, GEN_IPADD), - ASN1_IMP(GENERAL_NAME, d.registeredID, ASN1_OBJECT, GEN_RID), + ASN1_IMP(GENERAL_NAME, d.otherName, OTHERNAME, GEN_OTHERNAME), + ASN1_IMP(GENERAL_NAME, d.rfc822Name, ASN1_IA5STRING, GEN_EMAIL), + ASN1_IMP(GENERAL_NAME, d.dNSName, ASN1_IA5STRING, GEN_DNS), + /* Don't decode this */ + ASN1_IMP(GENERAL_NAME, d.x400Address, ASN1_SEQUENCE, GEN_X400), + /* X509_NAME is a CHOICE type so use EXPLICIT */ + ASN1_EXP(GENERAL_NAME, d.directoryName, X509_NAME, GEN_DIRNAME), + ASN1_IMP(GENERAL_NAME, d.ediPartyName, EDIPARTYNAME, GEN_EDIPARTY), + ASN1_IMP(GENERAL_NAME, d.uniformResourceIdentifier, ASN1_IA5STRING, + GEN_URI), + ASN1_IMP(GENERAL_NAME, d.iPAddress, ASN1_OCTET_STRING, GEN_IPADD), + ASN1_IMP(GENERAL_NAME, d.registeredID, ASN1_OBJECT, GEN_RID), } ASN1_CHOICE_END(GENERAL_NAME) IMPLEMENT_ASN1_FUNCTIONS(GENERAL_NAME) -ASN1_ITEM_TEMPLATE(GENERAL_NAMES) = - ASN1_EX_TEMPLATE_TYPE(ASN1_TFLG_SEQUENCE_OF, 0, GeneralNames, GENERAL_NAME) +ASN1_ITEM_TEMPLATE(GENERAL_NAMES) = ASN1_EX_TEMPLATE_TYPE(ASN1_TFLG_SEQUENCE_OF, + 0, GeneralNames, + GENERAL_NAME) ASN1_ITEM_TEMPLATE_END(GENERAL_NAMES) IMPLEMENT_ASN1_FUNCTIONS(GENERAL_NAMES) IMPLEMENT_ASN1_DUP_FUNCTION(GENERAL_NAME) -static int edipartyname_cmp(const EDIPARTYNAME *a, const EDIPARTYNAME *b) -{ - /* nameAssigner is optional and may be NULL. */ - if (a->nameAssigner == NULL) { - if (b->nameAssigner != NULL) { - return -1; - } - } else { - if (b->nameAssigner == NULL || - ASN1_STRING_cmp(a->nameAssigner, b->nameAssigner) != 0) { - return -1; - } +static int edipartyname_cmp(const EDIPARTYNAME *a, const EDIPARTYNAME *b) { + /* nameAssigner is optional and may be NULL. */ + if (a->nameAssigner == NULL) { + if (b->nameAssigner != NULL) { + return -1; } + } else { + if (b->nameAssigner == NULL || + ASN1_STRING_cmp(a->nameAssigner, b->nameAssigner) != 0) { + return -1; + } + } - /* partyName may not be NULL. */ - return ASN1_STRING_cmp(a->partyName, b->partyName); + /* partyName may not be NULL. */ + return ASN1_STRING_cmp(a->partyName, b->partyName); } /* Returns 0 if they are equal, != 0 otherwise. */ -int GENERAL_NAME_cmp(const GENERAL_NAME *a, const GENERAL_NAME *b) -{ - if (!a || !b || a->type != b->type) - return -1; +int GENERAL_NAME_cmp(const GENERAL_NAME *a, const GENERAL_NAME *b) { + if (!a || !b || a->type != b->type) { + return -1; + } - switch (a->type) { + switch (a->type) { case GEN_X400: - return ASN1_TYPE_cmp(a->d.x400Address, b->d.x400Address); + return ASN1_TYPE_cmp(a->d.x400Address, b->d.x400Address); case GEN_EDIPARTY: - return edipartyname_cmp(a->d.ediPartyName, b->d.ediPartyName); + return edipartyname_cmp(a->d.ediPartyName, b->d.ediPartyName); case GEN_OTHERNAME: - return OTHERNAME_cmp(a->d.otherName, b->d.otherName); + return OTHERNAME_cmp(a->d.otherName, b->d.otherName); case GEN_EMAIL: case GEN_DNS: case GEN_URI: - return ASN1_STRING_cmp(a->d.ia5, b->d.ia5); + return ASN1_STRING_cmp(a->d.ia5, b->d.ia5); case GEN_DIRNAME: - return X509_NAME_cmp(a->d.dirn, b->d.dirn); + return X509_NAME_cmp(a->d.dirn, b->d.dirn); case GEN_IPADD: - return ASN1_OCTET_STRING_cmp(a->d.ip, b->d.ip); + return ASN1_OCTET_STRING_cmp(a->d.ip, b->d.ip); case GEN_RID: - return OBJ_cmp(a->d.rid, b->d.rid); - } + return OBJ_cmp(a->d.rid, b->d.rid); + } - return -1; + return -1; } /* Returns 0 if they are equal, != 0 otherwise. */ -int OTHERNAME_cmp(OTHERNAME *a, OTHERNAME *b) -{ - int result = -1; - - if (!a || !b) - return -1; - /* Check their type first. */ - if ((result = OBJ_cmp(a->type_id, b->type_id)) != 0) - return result; - /* Check the value. */ - result = ASN1_TYPE_cmp(a->value, b->value); +int OTHERNAME_cmp(OTHERNAME *a, OTHERNAME *b) { + int result = -1; + + if (!a || !b) { + return -1; + } + /* Check their type first. */ + if ((result = OBJ_cmp(a->type_id, b->type_id)) != 0) { return result; + } + /* Check the value. */ + result = ASN1_TYPE_cmp(a->value, b->value); + return result; } -void GENERAL_NAME_set0_value(GENERAL_NAME *a, int type, void *value) -{ - switch (type) { +void GENERAL_NAME_set0_value(GENERAL_NAME *a, int type, void *value) { + switch (type) { case GEN_X400: - a->d.x400Address = value; - break; + a->d.x400Address = value; + break; case GEN_EDIPARTY: - a->d.ediPartyName = value; - break; + a->d.ediPartyName = value; + break; case GEN_OTHERNAME: - a->d.otherName = value; - break; + a->d.otherName = value; + break; case GEN_EMAIL: case GEN_DNS: case GEN_URI: - a->d.ia5 = value; - break; + a->d.ia5 = value; + break; case GEN_DIRNAME: - a->d.dirn = value; - break; + a->d.dirn = value; + break; case GEN_IPADD: - a->d.ip = value; - break; + a->d.ip = value; + break; case GEN_RID: - a->d.rid = value; - break; - } - a->type = type; + a->d.rid = value; + break; + } + a->type = type; } -void *GENERAL_NAME_get0_value(const GENERAL_NAME *a, int *ptype) -{ - if (ptype) - *ptype = a->type; - switch (a->type) { +void *GENERAL_NAME_get0_value(const GENERAL_NAME *a, int *ptype) { + if (ptype) { + *ptype = a->type; + } + switch (a->type) { case GEN_X400: - return a->d.x400Address; + return a->d.x400Address; case GEN_EDIPARTY: - return a->d.ediPartyName; + return a->d.ediPartyName; case GEN_OTHERNAME: - return a->d.otherName; + return a->d.otherName; case GEN_EMAIL: case GEN_DNS: case GEN_URI: - return a->d.ia5; + return a->d.ia5; case GEN_DIRNAME: - return a->d.dirn; + return a->d.dirn; case GEN_IPADD: - return a->d.ip; + return a->d.ip; case GEN_RID: - return a->d.rid; + return a->d.rid; default: - return NULL; - } + return NULL; + } } -int GENERAL_NAME_set0_othername(GENERAL_NAME *gen, - ASN1_OBJECT *oid, ASN1_TYPE *value) -{ - OTHERNAME *oth; - oth = OTHERNAME_new(); - if (!oth) - return 0; - ASN1_TYPE_free(oth->value); - oth->type_id = oid; - oth->value = value; - GENERAL_NAME_set0_value(gen, GEN_OTHERNAME, oth); - return 1; +int GENERAL_NAME_set0_othername(GENERAL_NAME *gen, ASN1_OBJECT *oid, + ASN1_TYPE *value) { + OTHERNAME *oth; + oth = OTHERNAME_new(); + if (!oth) { + return 0; + } + ASN1_TYPE_free(oth->value); + oth->type_id = oid; + oth->value = value; + GENERAL_NAME_set0_value(gen, GEN_OTHERNAME, oth); + return 1; } -int GENERAL_NAME_get0_otherName(const GENERAL_NAME *gen, - ASN1_OBJECT **poid, ASN1_TYPE **pvalue) -{ - if (gen->type != GEN_OTHERNAME) - return 0; - if (poid) - *poid = gen->d.otherName->type_id; - if (pvalue) - *pvalue = gen->d.otherName->value; - return 1; +int GENERAL_NAME_get0_otherName(const GENERAL_NAME *gen, ASN1_OBJECT **poid, + ASN1_TYPE **pvalue) { + if (gen->type != GEN_OTHERNAME) { + return 0; + } + if (poid) { + *poid = gen->d.otherName->type_id; + } + if (pvalue) { + *pvalue = gen->d.otherName->value; + } + return 1; } diff --git a/crypto/x509v3/v3_ia5.c b/crypto/x509v3/v3_ia5.c index 6f5ce1d7f1..8abf40ca33 100644 --- a/crypto/x509v3/v3_ia5.c +++ b/crypto/x509v3/v3_ia5.c @@ -70,39 +70,39 @@ #include "../internal.h" -static char *i2s_ASN1_IA5STRING(const X509V3_EXT_METHOD *method, void *ext) -{ - const ASN1_IA5STRING *ia5 = ext; - char *tmp; - if (!ia5 || !ia5->length) - return NULL; - if (!(tmp = OPENSSL_malloc(ia5->length + 1))) { - OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE); - return NULL; - } - OPENSSL_memcpy(tmp, ia5->data, ia5->length); - tmp[ia5->length] = 0; - return tmp; +static char *i2s_ASN1_IA5STRING(const X509V3_EXT_METHOD *method, void *ext) { + const ASN1_IA5STRING *ia5 = ext; + char *tmp; + if (!ia5 || !ia5->length) { + return NULL; + } + if (!(tmp = OPENSSL_malloc(ia5->length + 1))) { + OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE); + return NULL; + } + OPENSSL_memcpy(tmp, ia5->data, ia5->length); + tmp[ia5->length] = 0; + return tmp; } static void *s2i_ASN1_IA5STRING(const X509V3_EXT_METHOD *method, - X509V3_CTX *ctx, const char *str) -{ - ASN1_IA5STRING *ia5; - if (!str) { - OPENSSL_PUT_ERROR(X509V3, X509V3_R_INVALID_NULL_ARGUMENT); - return NULL; - } - if (!(ia5 = ASN1_IA5STRING_new())) - goto err; - if (!ASN1_STRING_set(ia5, str, strlen(str))) { - ASN1_IA5STRING_free(ia5); - goto err; - } - return ia5; - err: - OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE); + X509V3_CTX *ctx, const char *str) { + ASN1_IA5STRING *ia5; + if (!str) { + OPENSSL_PUT_ERROR(X509V3, X509V3_R_INVALID_NULL_ARGUMENT); return NULL; + } + if (!(ia5 = ASN1_IA5STRING_new())) { + goto err; + } + if (!ASN1_STRING_set(ia5, str, strlen(str))) { + ASN1_IA5STRING_free(ia5); + goto err; + } + return ia5; +err: + OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE); + return NULL; } #define EXT_IA5STRING(nid) \ @@ -122,5 +122,4 @@ const X509V3_EXT_METHOD v3_ns_ia5_list[] = { EXT_IA5STRING(NID_netscape_ca_policy_url), EXT_IA5STRING(NID_netscape_ssl_server_name), EXT_IA5STRING(NID_netscape_comment), - EXT_END -}; + EXT_END}; diff --git a/crypto/x509v3/v3_info.c b/crypto/x509v3/v3_info.c index 320c44dda5..872346acfe 100644 --- a/crypto/x509v3/v3_info.c +++ b/crypto/x509v3/v3_info.c @@ -74,133 +74,147 @@ static void *v2i_AUTHORITY_INFO_ACCESS(const X509V3_EXT_METHOD *method, X509V3_CTX *ctx, STACK_OF(CONF_VALUE) *nval); -const X509V3_EXT_METHOD v3_info = { NID_info_access, X509V3_EXT_MULTILINE, +const X509V3_EXT_METHOD v3_info = { + NID_info_access, + X509V3_EXT_MULTILINE, ASN1_ITEM_ref(AUTHORITY_INFO_ACCESS), - 0, 0, 0, 0, - 0, 0, + 0, + 0, + 0, + 0, + 0, + 0, i2v_AUTHORITY_INFO_ACCESS, v2i_AUTHORITY_INFO_ACCESS, - 0, 0, + 0, + 0, NULL, }; -const X509V3_EXT_METHOD v3_sinfo = { NID_sinfo_access, X509V3_EXT_MULTILINE, +const X509V3_EXT_METHOD v3_sinfo = { + NID_sinfo_access, + X509V3_EXT_MULTILINE, ASN1_ITEM_ref(AUTHORITY_INFO_ACCESS), - 0, 0, 0, 0, - 0, 0, + 0, + 0, + 0, + 0, + 0, + 0, i2v_AUTHORITY_INFO_ACCESS, v2i_AUTHORITY_INFO_ACCESS, - 0, 0, + 0, + 0, NULL, }; ASN1_SEQUENCE(ACCESS_DESCRIPTION) = { - ASN1_SIMPLE(ACCESS_DESCRIPTION, method, ASN1_OBJECT), - ASN1_SIMPLE(ACCESS_DESCRIPTION, location, GENERAL_NAME), + ASN1_SIMPLE(ACCESS_DESCRIPTION, method, ASN1_OBJECT), + ASN1_SIMPLE(ACCESS_DESCRIPTION, location, GENERAL_NAME), } ASN1_SEQUENCE_END(ACCESS_DESCRIPTION) IMPLEMENT_ASN1_FUNCTIONS(ACCESS_DESCRIPTION) -ASN1_ITEM_TEMPLATE(AUTHORITY_INFO_ACCESS) = - ASN1_EX_TEMPLATE_TYPE(ASN1_TFLG_SEQUENCE_OF, 0, GeneralNames, ACCESS_DESCRIPTION) +ASN1_ITEM_TEMPLATE(AUTHORITY_INFO_ACCESS) = ASN1_EX_TEMPLATE_TYPE( + ASN1_TFLG_SEQUENCE_OF, 0, GeneralNames, ACCESS_DESCRIPTION) ASN1_ITEM_TEMPLATE_END(AUTHORITY_INFO_ACCESS) IMPLEMENT_ASN1_FUNCTIONS(AUTHORITY_INFO_ACCESS) static STACK_OF(CONF_VALUE) *i2v_AUTHORITY_INFO_ACCESS( - const X509V3_EXT_METHOD *method, void *ext, STACK_OF(CONF_VALUE) *ret) -{ - const AUTHORITY_INFO_ACCESS *ainfo = ext; - ACCESS_DESCRIPTION *desc; - int nlen; - char objtmp[80], *ntmp; - CONF_VALUE *vtmp; - STACK_OF(CONF_VALUE) *tret = ret; - - for (size_t i = 0; i < sk_ACCESS_DESCRIPTION_num(ainfo); i++) { - STACK_OF(CONF_VALUE) *tmp; - - desc = sk_ACCESS_DESCRIPTION_value(ainfo, i); - tmp = i2v_GENERAL_NAME(method, desc->location, tret); - if (tmp == NULL) - goto err; - tret = tmp; - vtmp = sk_CONF_VALUE_value(tret, i); - i2t_ASN1_OBJECT(objtmp, sizeof objtmp, desc->method); - nlen = strlen(objtmp) + strlen(vtmp->name) + 5; - ntmp = OPENSSL_malloc(nlen); - if (ntmp == NULL) - goto err; - OPENSSL_strlcpy(ntmp, objtmp, nlen); - OPENSSL_strlcat(ntmp, " - ", nlen); - OPENSSL_strlcat(ntmp, vtmp->name, nlen); - OPENSSL_free(vtmp->name); - vtmp->name = ntmp; - + const X509V3_EXT_METHOD *method, void *ext, STACK_OF(CONF_VALUE) *ret) { + const AUTHORITY_INFO_ACCESS *ainfo = ext; + ACCESS_DESCRIPTION *desc; + int nlen; + char objtmp[80], *ntmp; + CONF_VALUE *vtmp; + STACK_OF(CONF_VALUE) *tret = ret; + + for (size_t i = 0; i < sk_ACCESS_DESCRIPTION_num(ainfo); i++) { + STACK_OF(CONF_VALUE) *tmp; + + desc = sk_ACCESS_DESCRIPTION_value(ainfo, i); + tmp = i2v_GENERAL_NAME(method, desc->location, tret); + if (tmp == NULL) { + goto err; } - if (ret == NULL && tret == NULL) - return sk_CONF_VALUE_new_null(); - - return tret; - err: - OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE); - if (ret == NULL && tret != NULL) - sk_CONF_VALUE_pop_free(tret, X509V3_conf_free); - return NULL; + tret = tmp; + vtmp = sk_CONF_VALUE_value(tret, i); + i2t_ASN1_OBJECT(objtmp, sizeof objtmp, desc->method); + nlen = strlen(objtmp) + strlen(vtmp->name) + 5; + ntmp = OPENSSL_malloc(nlen); + if (ntmp == NULL) { + goto err; + } + OPENSSL_strlcpy(ntmp, objtmp, nlen); + OPENSSL_strlcat(ntmp, " - ", nlen); + OPENSSL_strlcat(ntmp, vtmp->name, nlen); + OPENSSL_free(vtmp->name); + vtmp->name = ntmp; + } + if (ret == NULL && tret == NULL) { + return sk_CONF_VALUE_new_null(); + } + + return tret; +err: + OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE); + if (ret == NULL && tret != NULL) { + sk_CONF_VALUE_pop_free(tret, X509V3_conf_free); + } + return NULL; } static void *v2i_AUTHORITY_INFO_ACCESS(const X509V3_EXT_METHOD *method, X509V3_CTX *ctx, - STACK_OF(CONF_VALUE) *nval) -{ - AUTHORITY_INFO_ACCESS *ainfo = NULL; - ACCESS_DESCRIPTION *acc; - char *objtmp, *ptmp; - if (!(ainfo = sk_ACCESS_DESCRIPTION_new_null())) { - OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE); - return NULL; + STACK_OF(CONF_VALUE) *nval) { + AUTHORITY_INFO_ACCESS *ainfo = NULL; + ACCESS_DESCRIPTION *acc; + char *objtmp, *ptmp; + if (!(ainfo = sk_ACCESS_DESCRIPTION_new_null())) { + OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE); + return NULL; + } + for (size_t i = 0; i < sk_CONF_VALUE_num(nval); i++) { + CONF_VALUE *cnf = sk_CONF_VALUE_value(nval, i); + if (!(acc = ACCESS_DESCRIPTION_new()) || + !sk_ACCESS_DESCRIPTION_push(ainfo, acc)) { + OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE); + goto err; } - for (size_t i = 0; i < sk_CONF_VALUE_num(nval); i++) { - CONF_VALUE *cnf = sk_CONF_VALUE_value(nval, i); - if (!(acc = ACCESS_DESCRIPTION_new()) - || !sk_ACCESS_DESCRIPTION_push(ainfo, acc)) { - OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE); - goto err; - } - ptmp = strchr(cnf->name, ';'); - if (!ptmp) { - OPENSSL_PUT_ERROR(X509V3, X509V3_R_INVALID_SYNTAX); - goto err; - } - int objlen = ptmp - cnf->name; - CONF_VALUE ctmp; - ctmp.name = ptmp + 1; - ctmp.value = cnf->value; - if (!v2i_GENERAL_NAME_ex(acc->location, method, ctx, &ctmp, 0)) - goto err; - if (!(objtmp = OPENSSL_malloc(objlen + 1))) { - OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE); - goto err; - } - OPENSSL_strlcpy(objtmp, cnf->name, objlen + 1); - acc->method = OBJ_txt2obj(objtmp, 0); - if (!acc->method) { - OPENSSL_PUT_ERROR(X509V3, X509V3_R_BAD_OBJECT); - ERR_add_error_data(2, "value=", objtmp); - OPENSSL_free(objtmp); - goto err; - } - OPENSSL_free(objtmp); - + ptmp = strchr(cnf->name, ';'); + if (!ptmp) { + OPENSSL_PUT_ERROR(X509V3, X509V3_R_INVALID_SYNTAX); + goto err; } - return ainfo; - err: - sk_ACCESS_DESCRIPTION_pop_free(ainfo, ACCESS_DESCRIPTION_free); - return NULL; + int objlen = ptmp - cnf->name; + CONF_VALUE ctmp; + ctmp.name = ptmp + 1; + ctmp.value = cnf->value; + if (!v2i_GENERAL_NAME_ex(acc->location, method, ctx, &ctmp, 0)) { + goto err; + } + if (!(objtmp = OPENSSL_malloc(objlen + 1))) { + OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE); + goto err; + } + OPENSSL_strlcpy(objtmp, cnf->name, objlen + 1); + acc->method = OBJ_txt2obj(objtmp, 0); + if (!acc->method) { + OPENSSL_PUT_ERROR(X509V3, X509V3_R_BAD_OBJECT); + ERR_add_error_data(2, "value=", objtmp); + OPENSSL_free(objtmp); + goto err; + } + OPENSSL_free(objtmp); + } + return ainfo; +err: + sk_ACCESS_DESCRIPTION_pop_free(ainfo, ACCESS_DESCRIPTION_free); + return NULL; } -int i2a_ACCESS_DESCRIPTION(BIO *bp, const ACCESS_DESCRIPTION *a) -{ - i2a_ASN1_OBJECT(bp, a->method); - return 2; +int i2a_ACCESS_DESCRIPTION(BIO *bp, const ACCESS_DESCRIPTION *a) { + i2a_ASN1_OBJECT(bp, a->method); + return 2; } diff --git a/crypto/x509v3/v3_int.c b/crypto/x509v3/v3_int.c index a3382042d7..50cef849e6 100644 --- a/crypto/x509v3/v3_int.c +++ b/crypto/x509v3/v3_int.c @@ -61,37 +61,62 @@ #include -static char *i2s_ASN1_INTEGER_cb(const X509V3_EXT_METHOD *method, void *ext) -{ - return i2s_ASN1_INTEGER(method, ext); +static char *i2s_ASN1_INTEGER_cb(const X509V3_EXT_METHOD *method, void *ext) { + return i2s_ASN1_INTEGER(method, ext); } static void *s2i_asn1_int(const X509V3_EXT_METHOD *meth, X509V3_CTX *ctx, - const char *value) -{ - return s2i_ASN1_INTEGER(meth, value); + const char *value) { + return s2i_ASN1_INTEGER(meth, value); } const X509V3_EXT_METHOD v3_crl_num = { - NID_crl_number, 0, ASN1_ITEM_ref(ASN1_INTEGER), - 0, 0, 0, 0, + NID_crl_number, + 0, + ASN1_ITEM_ref(ASN1_INTEGER), + 0, + 0, + 0, + 0, i2s_ASN1_INTEGER_cb, 0, - 0, 0, 0, 0, NULL, + 0, + 0, + 0, + 0, + NULL, }; const X509V3_EXT_METHOD v3_delta_crl = { - NID_delta_crl, 0, ASN1_ITEM_ref(ASN1_INTEGER), - 0, 0, 0, 0, + NID_delta_crl, + 0, + ASN1_ITEM_ref(ASN1_INTEGER), + 0, + 0, + 0, + 0, i2s_ASN1_INTEGER_cb, 0, - 0, 0, 0, 0, NULL, + 0, + 0, + 0, + 0, + NULL, }; const X509V3_EXT_METHOD v3_inhibit_anyp = { - NID_inhibit_any_policy, 0, ASN1_ITEM_ref(ASN1_INTEGER), - 0, 0, 0, 0, + NID_inhibit_any_policy, + 0, + ASN1_ITEM_ref(ASN1_INTEGER), + 0, + 0, + 0, + 0, i2s_ASN1_INTEGER_cb, s2i_asn1_int, - 0, 0, 0, 0, NULL, + 0, + 0, + 0, + 0, + NULL, }; diff --git a/crypto/x509v3/v3_lib.c b/crypto/x509v3/v3_lib.c index 1b57f672c9..9434d37bda 100644 --- a/crypto/x509v3/v3_lib.c +++ b/crypto/x509v3/v3_lib.c @@ -74,123 +74,119 @@ static STACK_OF(X509V3_EXT_METHOD) *ext_list = NULL; static void ext_list_free(X509V3_EXT_METHOD *ext); static int ext_stack_cmp(const X509V3_EXT_METHOD **a, - const X509V3_EXT_METHOD **b) -{ - return ((*a)->ext_nid - (*b)->ext_nid); + const X509V3_EXT_METHOD **b) { + return ((*a)->ext_nid - (*b)->ext_nid); } -int X509V3_EXT_add(X509V3_EXT_METHOD *ext) -{ - if (!ext_list && !(ext_list = sk_X509V3_EXT_METHOD_new(ext_stack_cmp))) { - OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE); - ext_list_free(ext); - return 0; - } - if (!sk_X509V3_EXT_METHOD_push(ext_list, ext)) { - OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE); - ext_list_free(ext); - return 0; - } - return 1; +int X509V3_EXT_add(X509V3_EXT_METHOD *ext) { + if (!ext_list && !(ext_list = sk_X509V3_EXT_METHOD_new(ext_stack_cmp))) { + OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE); + ext_list_free(ext); + return 0; + } + if (!sk_X509V3_EXT_METHOD_push(ext_list, ext)) { + OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE); + ext_list_free(ext); + return 0; + } + return 1; } -static int ext_cmp(const void *void_a, const void *void_b) -{ - const X509V3_EXT_METHOD **a = (const X509V3_EXT_METHOD **)void_a; - const X509V3_EXT_METHOD **b = (const X509V3_EXT_METHOD **)void_b; - return ext_stack_cmp(a, b); +static int ext_cmp(const void *void_a, const void *void_b) { + const X509V3_EXT_METHOD **a = (const X509V3_EXT_METHOD **)void_a; + const X509V3_EXT_METHOD **b = (const X509V3_EXT_METHOD **)void_b; + return ext_stack_cmp(a, b); } -const X509V3_EXT_METHOD *X509V3_EXT_get_nid(int nid) -{ - X509V3_EXT_METHOD tmp; - const X509V3_EXT_METHOD *t = &tmp, *const *ret; - size_t idx; +const X509V3_EXT_METHOD *X509V3_EXT_get_nid(int nid) { + X509V3_EXT_METHOD tmp; + const X509V3_EXT_METHOD *t = &tmp, *const * ret; + size_t idx; - if (nid < 0) - return NULL; - tmp.ext_nid = nid; - ret = - bsearch(&t, standard_exts, STANDARD_EXTENSION_COUNT, + if (nid < 0) { + return NULL; + } + tmp.ext_nid = nid; + ret = bsearch(&t, standard_exts, STANDARD_EXTENSION_COUNT, sizeof(X509V3_EXT_METHOD *), ext_cmp); - if (ret) - return *ret; - if (!ext_list) - return NULL; + if (ret) { + return *ret; + } + if (!ext_list) { + return NULL; + } - sk_X509V3_EXT_METHOD_sort(ext_list); - if (!sk_X509V3_EXT_METHOD_find(ext_list, &idx, &tmp)) - return NULL; - return sk_X509V3_EXT_METHOD_value(ext_list, idx); + sk_X509V3_EXT_METHOD_sort(ext_list); + if (!sk_X509V3_EXT_METHOD_find(ext_list, &idx, &tmp)) { + return NULL; + } + return sk_X509V3_EXT_METHOD_value(ext_list, idx); } -const X509V3_EXT_METHOD *X509V3_EXT_get(const X509_EXTENSION *ext) -{ - int nid; - if ((nid = OBJ_obj2nid(ext->object)) == NID_undef) - return NULL; - return X509V3_EXT_get_nid(nid); +const X509V3_EXT_METHOD *X509V3_EXT_get(const X509_EXTENSION *ext) { + int nid; + if ((nid = OBJ_obj2nid(ext->object)) == NID_undef) { + return NULL; + } + return X509V3_EXT_get_nid(nid); } -int X509V3_EXT_free(int nid, void *ext_data) -{ - const X509V3_EXT_METHOD *ext_method = X509V3_EXT_get_nid(nid); - if (ext_method == NULL) { - OPENSSL_PUT_ERROR(X509V3, X509V3_R_CANNOT_FIND_FREE_FUNCTION); - return 0; - } - - if (ext_method->it != NULL) - ASN1_item_free(ext_data, ASN1_ITEM_ptr(ext_method->it)); - else if (ext_method->ext_free != NULL) - ext_method->ext_free(ext_data); - else { - OPENSSL_PUT_ERROR(X509V3, X509V3_R_CANNOT_FIND_FREE_FUNCTION); - return 0; - } +int X509V3_EXT_free(int nid, void *ext_data) { + const X509V3_EXT_METHOD *ext_method = X509V3_EXT_get_nid(nid); + if (ext_method == NULL) { + OPENSSL_PUT_ERROR(X509V3, X509V3_R_CANNOT_FIND_FREE_FUNCTION); + return 0; + } + + if (ext_method->it != NULL) { + ASN1_item_free(ext_data, ASN1_ITEM_ptr(ext_method->it)); + } else if (ext_method->ext_free != NULL) { + ext_method->ext_free(ext_data); + } else { + OPENSSL_PUT_ERROR(X509V3, X509V3_R_CANNOT_FIND_FREE_FUNCTION); + return 0; + } - return 1; + return 1; } -int X509V3_EXT_add_list(X509V3_EXT_METHOD *extlist) -{ - for (; extlist->ext_nid != -1; extlist++) - if (!X509V3_EXT_add(extlist)) - return 0; - return 1; +int X509V3_EXT_add_list(X509V3_EXT_METHOD *extlist) { + for (; extlist->ext_nid != -1; extlist++) { + if (!X509V3_EXT_add(extlist)) { + return 0; + } + } + return 1; } -int X509V3_EXT_add_alias(int nid_to, int nid_from) -{ - const X509V3_EXT_METHOD *ext; - X509V3_EXT_METHOD *tmpext; +int X509V3_EXT_add_alias(int nid_to, int nid_from) { + const X509V3_EXT_METHOD *ext; + X509V3_EXT_METHOD *tmpext; - if (!(ext = X509V3_EXT_get_nid(nid_from))) { - OPENSSL_PUT_ERROR(X509V3, X509V3_R_EXTENSION_NOT_FOUND); - return 0; - } - if (! - (tmpext = - (X509V3_EXT_METHOD *)OPENSSL_malloc(sizeof(X509V3_EXT_METHOD)))) { - OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE); - return 0; - } - *tmpext = *ext; - tmpext->ext_nid = nid_to; - tmpext->ext_flags |= X509V3_EXT_DYNAMIC; - return X509V3_EXT_add(tmpext); + if (!(ext = X509V3_EXT_get_nid(nid_from))) { + OPENSSL_PUT_ERROR(X509V3, X509V3_R_EXTENSION_NOT_FOUND); + return 0; + } + if (!(tmpext = + (X509V3_EXT_METHOD *)OPENSSL_malloc(sizeof(X509V3_EXT_METHOD)))) { + OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE); + return 0; + } + *tmpext = *ext; + tmpext->ext_nid = nid_to; + tmpext->ext_flags |= X509V3_EXT_DYNAMIC; + return X509V3_EXT_add(tmpext); } -void X509V3_EXT_cleanup(void) -{ - sk_X509V3_EXT_METHOD_pop_free(ext_list, ext_list_free); - ext_list = NULL; +void X509V3_EXT_cleanup(void) { + sk_X509V3_EXT_METHOD_pop_free(ext_list, ext_list_free); + ext_list = NULL; } -static void ext_list_free(X509V3_EXT_METHOD *ext) -{ - if (ext->ext_flags & X509V3_EXT_DYNAMIC) - OPENSSL_free(ext); +static void ext_list_free(X509V3_EXT_METHOD *ext) { + if (ext->ext_flags & X509V3_EXT_DYNAMIC) { + OPENSSL_free(ext); + } } /* @@ -198,94 +194,98 @@ static void ext_list_free(X509V3_EXT_METHOD *ext) * they are now kept in ext_dat.h. */ -int X509V3_add_standard_extensions(void) -{ - return 1; -} +int X509V3_add_standard_extensions(void) { return 1; } /* Return an extension internal structure */ -void *X509V3_EXT_d2i(const X509_EXTENSION *ext) -{ - const X509V3_EXT_METHOD *method; - const unsigned char *p; +void *X509V3_EXT_d2i(const X509_EXTENSION *ext) { + const X509V3_EXT_METHOD *method; + const unsigned char *p; - if (!(method = X509V3_EXT_get(ext))) - return NULL; - p = ext->value->data; - void *ret; + if (!(method = X509V3_EXT_get(ext))) { + return NULL; + } + p = ext->value->data; + void *ret; + if (method->it) { + ret = + ASN1_item_d2i(NULL, &p, ext->value->length, ASN1_ITEM_ptr(method->it)); + } else { + ret = method->d2i(NULL, &p, ext->value->length); + } + if (ret == NULL) { + return NULL; + } + /* Check for trailing data. */ + if (p != ext->value->data + ext->value->length) { if (method->it) { - ret = ASN1_item_d2i(NULL, &p, ext->value->length, - ASN1_ITEM_ptr(method->it)); + ASN1_item_free(ret, ASN1_ITEM_ptr(method->it)); } else { - ret = method->d2i(NULL, &p, ext->value->length); - } - if (ret == NULL) { - return NULL; - } - /* Check for trailing data. */ - if (p != ext->value->data + ext->value->length) { - if (method->it) { - ASN1_item_free(ret, ASN1_ITEM_ptr(method->it)); - } else { - method->ext_free(ret); - } - OPENSSL_PUT_ERROR(X509V3, X509V3_R_TRAILING_DATA_IN_EXTENSION); - return NULL; + method->ext_free(ret); } - return ret; + OPENSSL_PUT_ERROR(X509V3, X509V3_R_TRAILING_DATA_IN_EXTENSION); + return NULL; + } + return ret; } void *X509V3_get_d2i(const STACK_OF(X509_EXTENSION) *extensions, int nid, - int *out_critical, int *out_idx) -{ - int lastpos; - size_t i; - X509_EXTENSION *ex, *found_ex = NULL; - if (!extensions) { - if (out_idx) - *out_idx = -1; - if (out_critical) - *out_critical = -1; - return NULL; + int *out_critical, int *out_idx) { + int lastpos; + size_t i; + X509_EXTENSION *ex, *found_ex = NULL; + if (!extensions) { + if (out_idx) { + *out_idx = -1; } - if (out_idx) - lastpos = *out_idx + 1; - else - lastpos = 0; - if (lastpos < 0) - lastpos = 0; - for (i = lastpos; i < sk_X509_EXTENSION_num(extensions); i++) { - ex = sk_X509_EXTENSION_value(extensions, i); - if (OBJ_obj2nid(ex->object) == nid) { - if (out_idx) { - /* TODO(https://crbug.com/boringssl/379): Consistently reject - * duplicate extensions. */ - *out_idx = i; - found_ex = ex; - break; - } else if (found_ex) { - /* Found more than one */ - if (out_critical) - *out_critical = -2; - return NULL; - } - found_ex = ex; + if (out_critical) { + *out_critical = -1; + } + return NULL; + } + if (out_idx) { + lastpos = *out_idx + 1; + } else { + lastpos = 0; + } + if (lastpos < 0) { + lastpos = 0; + } + for (i = lastpos; i < sk_X509_EXTENSION_num(extensions); i++) { + ex = sk_X509_EXTENSION_value(extensions, i); + if (OBJ_obj2nid(ex->object) == nid) { + if (out_idx) { + /* TODO(https://crbug.com/boringssl/379): Consistently reject + * duplicate extensions. */ + *out_idx = i; + found_ex = ex; + break; + } else if (found_ex) { + /* Found more than one */ + if (out_critical) { + *out_critical = -2; } + return NULL; + } + found_ex = ex; } - if (found_ex) { - /* Found it */ - if (out_critical) - *out_critical = X509_EXTENSION_get_critical(found_ex); - return X509V3_EXT_d2i(found_ex); + } + if (found_ex) { + /* Found it */ + if (out_critical) { + *out_critical = X509_EXTENSION_get_critical(found_ex); } - - /* Extension not found */ - if (out_idx) - *out_idx = -1; - if (out_critical) - *out_critical = -1; - return NULL; + return X509V3_EXT_d2i(found_ex); + } + + /* Extension not found */ + if (out_idx) { + *out_idx = -1; + } + if (out_critical) { + *out_critical = -1; + } + return NULL; } /* @@ -295,85 +295,91 @@ void *X509V3_get_d2i(const STACK_OF(X509_EXTENSION) *extensions, int nid, */ int X509V3_add1_i2d(STACK_OF(X509_EXTENSION) **x, int nid, void *value, - int crit, unsigned long flags) -{ - int errcode, extidx = -1; - X509_EXTENSION *ext = NULL, *extmp; - STACK_OF(X509_EXTENSION) *ret = NULL; - unsigned long ext_op = flags & X509V3_ADD_OP_MASK; - - /* - * If appending we don't care if it exists, otherwise look for existing - * extension. - */ - if (ext_op != X509V3_ADD_APPEND) - extidx = X509v3_get_ext_by_NID(*x, nid, -1); - - /* See if extension exists */ - if (extidx >= 0) { - /* If keep existing, nothing to do */ - if (ext_op == X509V3_ADD_KEEP_EXISTING) - return 1; - /* If default then its an error */ - if (ext_op == X509V3_ADD_DEFAULT) { - errcode = X509V3_R_EXTENSION_EXISTS; - goto err; - } - /* If delete, just delete it */ - if (ext_op == X509V3_ADD_DELETE) { - if (!sk_X509_EXTENSION_delete(*x, extidx)) - return -1; - return 1; - } - } else { - /* - * If replace existing or delete, error since extension must exist - */ - if ((ext_op == X509V3_ADD_REPLACE_EXISTING) || - (ext_op == X509V3_ADD_DELETE)) { - errcode = X509V3_R_EXTENSION_NOT_FOUND; - goto err; - } + int crit, unsigned long flags) { + int errcode, extidx = -1; + X509_EXTENSION *ext = NULL, *extmp; + STACK_OF(X509_EXTENSION) *ret = NULL; + unsigned long ext_op = flags & X509V3_ADD_OP_MASK; + + /* + * If appending we don't care if it exists, otherwise look for existing + * extension. + */ + if (ext_op != X509V3_ADD_APPEND) { + extidx = X509v3_get_ext_by_NID(*x, nid, -1); + } + + /* See if extension exists */ + if (extidx >= 0) { + /* If keep existing, nothing to do */ + if (ext_op == X509V3_ADD_KEEP_EXISTING) { + return 1; } - + /* If default then its an error */ + if (ext_op == X509V3_ADD_DEFAULT) { + errcode = X509V3_R_EXTENSION_EXISTS; + goto err; + } + /* If delete, just delete it */ + if (ext_op == X509V3_ADD_DELETE) { + if (!sk_X509_EXTENSION_delete(*x, extidx)) { + return -1; + } + return 1; + } + } else { /* - * If we get this far then we have to create an extension: could have - * some flags for alternative encoding schemes... + * If replace existing or delete, error since extension must exist */ - - ext = X509V3_EXT_i2d(nid, crit, value); - - if (!ext) { - OPENSSL_PUT_ERROR(X509V3, X509V3_R_ERROR_CREATING_EXTENSION); - return 0; - } - - /* If extension exists replace it.. */ - if (extidx >= 0) { - extmp = sk_X509_EXTENSION_value(*x, extidx); - X509_EXTENSION_free(extmp); - if (!sk_X509_EXTENSION_set(*x, extidx, ext)) - return -1; - return 1; + if ((ext_op == X509V3_ADD_REPLACE_EXISTING) || + (ext_op == X509V3_ADD_DELETE)) { + errcode = X509V3_R_EXTENSION_NOT_FOUND; + goto err; } + } - if ((ret = *x) == NULL - && (ret = sk_X509_EXTENSION_new_null()) == NULL) - goto m_fail; - if (!sk_X509_EXTENSION_push(ret, ext)) - goto m_fail; + /* + * If we get this far then we have to create an extension: could have + * some flags for alternative encoding schemes... + */ - *x = ret; - return 1; + ext = X509V3_EXT_i2d(nid, crit, value); - m_fail: - if (ret != *x) - sk_X509_EXTENSION_free(ret); - X509_EXTENSION_free(ext); - return -1; - - err: - if (!(flags & X509V3_ADD_SILENT)) - OPENSSL_PUT_ERROR(X509V3, errcode); + if (!ext) { + OPENSSL_PUT_ERROR(X509V3, X509V3_R_ERROR_CREATING_EXTENSION); return 0; + } + + /* If extension exists replace it.. */ + if (extidx >= 0) { + extmp = sk_X509_EXTENSION_value(*x, extidx); + X509_EXTENSION_free(extmp); + if (!sk_X509_EXTENSION_set(*x, extidx, ext)) { + return -1; + } + return 1; + } + + if ((ret = *x) == NULL && (ret = sk_X509_EXTENSION_new_null()) == NULL) { + goto m_fail; + } + if (!sk_X509_EXTENSION_push(ret, ext)) { + goto m_fail; + } + + *x = ret; + return 1; + +m_fail: + if (ret != *x) { + sk_X509_EXTENSION_free(ret); + } + X509_EXTENSION_free(ext); + return -1; + +err: + if (!(flags & X509V3_ADD_SILENT)) { + OPENSSL_PUT_ERROR(X509V3, errcode); + } + return 0; } diff --git a/crypto/x509v3/v3_ncons.c b/crypto/x509v3/v3_ncons.c index e65aab5774..ce1c82e7ef 100644 --- a/crypto/x509v3/v3_ncons.c +++ b/crypto/x509v3/v3_ncons.c @@ -70,8 +70,7 @@ static void *v2i_NAME_CONSTRAINTS(const X509V3_EXT_METHOD *method, - X509V3_CTX *ctx, - STACK_OF(CONF_VALUE) *nval); + X509V3_CTX *ctx, STACK_OF(CONF_VALUE) *nval); static int i2r_NAME_CONSTRAINTS(const X509V3_EXT_METHOD *method, void *a, BIO *bp, int ind); static int do_i2r_name_constraints(const X509V3_EXT_METHOD *method, @@ -87,26 +86,33 @@ static int nc_email(ASN1_IA5STRING *sub, ASN1_IA5STRING *eml); static int nc_uri(ASN1_IA5STRING *uri, ASN1_IA5STRING *base); const X509V3_EXT_METHOD v3_name_constraints = { - NID_name_constraints, 0, + NID_name_constraints, + 0, ASN1_ITEM_ref(NAME_CONSTRAINTS), - 0, 0, 0, 0, - 0, 0, - 0, v2i_NAME_CONSTRAINTS, - i2r_NAME_CONSTRAINTS, 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + v2i_NAME_CONSTRAINTS, + i2r_NAME_CONSTRAINTS, + 0, NULL, }; ASN1_SEQUENCE(GENERAL_SUBTREE) = { - ASN1_SIMPLE(GENERAL_SUBTREE, base, GENERAL_NAME), - ASN1_IMP_OPT(GENERAL_SUBTREE, minimum, ASN1_INTEGER, 0), - ASN1_IMP_OPT(GENERAL_SUBTREE, maximum, ASN1_INTEGER, 1), + ASN1_SIMPLE(GENERAL_SUBTREE, base, GENERAL_NAME), + ASN1_IMP_OPT(GENERAL_SUBTREE, minimum, ASN1_INTEGER, 0), + ASN1_IMP_OPT(GENERAL_SUBTREE, maximum, ASN1_INTEGER, 1), } ASN1_SEQUENCE_END(GENERAL_SUBTREE) ASN1_SEQUENCE(NAME_CONSTRAINTS) = { - ASN1_IMP_SEQUENCE_OF_OPT(NAME_CONSTRAINTS, permittedSubtrees, - GENERAL_SUBTREE, 0), - ASN1_IMP_SEQUENCE_OF_OPT(NAME_CONSTRAINTS, excludedSubtrees, - GENERAL_SUBTREE, 1), + ASN1_IMP_SEQUENCE_OF_OPT(NAME_CONSTRAINTS, permittedSubtrees, + GENERAL_SUBTREE, 0), + ASN1_IMP_SEQUENCE_OF_OPT(NAME_CONSTRAINTS, excludedSubtrees, + GENERAL_SUBTREE, 1), } ASN1_SEQUENCE_END(NAME_CONSTRAINTS) @@ -114,106 +120,111 @@ IMPLEMENT_ASN1_ALLOC_FUNCTIONS(GENERAL_SUBTREE) IMPLEMENT_ASN1_ALLOC_FUNCTIONS(NAME_CONSTRAINTS) static void *v2i_NAME_CONSTRAINTS(const X509V3_EXT_METHOD *method, - X509V3_CTX *ctx, STACK_OF(CONF_VALUE) *nval) -{ - size_t i; - CONF_VALUE tval, *val; - STACK_OF(GENERAL_SUBTREE) **ptree = NULL; - NAME_CONSTRAINTS *ncons = NULL; - GENERAL_SUBTREE *sub = NULL; - ncons = NAME_CONSTRAINTS_new(); - if (!ncons) - goto memerr; - for (i = 0; i < sk_CONF_VALUE_num(nval); i++) { - val = sk_CONF_VALUE_value(nval, i); - if (!strncmp(val->name, "permitted", 9) && val->name[9]) { - ptree = &ncons->permittedSubtrees; - tval.name = val->name + 10; - } else if (!strncmp(val->name, "excluded", 8) && val->name[8]) { - ptree = &ncons->excludedSubtrees; - tval.name = val->name + 9; - } else { - OPENSSL_PUT_ERROR(X509V3, X509V3_R_INVALID_SYNTAX); - goto err; - } - tval.value = val->value; - sub = GENERAL_SUBTREE_new(); - if (!v2i_GENERAL_NAME_ex(sub->base, method, ctx, &tval, 1)) - goto err; - if (!*ptree) - *ptree = sk_GENERAL_SUBTREE_new_null(); - if (!*ptree || !sk_GENERAL_SUBTREE_push(*ptree, sub)) - goto memerr; - sub = NULL; + X509V3_CTX *ctx, STACK_OF(CONF_VALUE) *nval) { + size_t i; + CONF_VALUE tval, *val; + STACK_OF(GENERAL_SUBTREE) **ptree = NULL; + NAME_CONSTRAINTS *ncons = NULL; + GENERAL_SUBTREE *sub = NULL; + ncons = NAME_CONSTRAINTS_new(); + if (!ncons) { + goto memerr; + } + for (i = 0; i < sk_CONF_VALUE_num(nval); i++) { + val = sk_CONF_VALUE_value(nval, i); + if (!strncmp(val->name, "permitted", 9) && val->name[9]) { + ptree = &ncons->permittedSubtrees; + tval.name = val->name + 10; + } else if (!strncmp(val->name, "excluded", 8) && val->name[8]) { + ptree = &ncons->excludedSubtrees; + tval.name = val->name + 9; + } else { + OPENSSL_PUT_ERROR(X509V3, X509V3_R_INVALID_SYNTAX); + goto err; } - - return ncons; - - memerr: - OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE); - err: - if (ncons) - NAME_CONSTRAINTS_free(ncons); - if (sub) - GENERAL_SUBTREE_free(sub); - - return NULL; + tval.value = val->value; + sub = GENERAL_SUBTREE_new(); + if (!v2i_GENERAL_NAME_ex(sub->base, method, ctx, &tval, 1)) { + goto err; + } + if (!*ptree) { + *ptree = sk_GENERAL_SUBTREE_new_null(); + } + if (!*ptree || !sk_GENERAL_SUBTREE_push(*ptree, sub)) { + goto memerr; + } + sub = NULL; + } + + return ncons; + +memerr: + OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE); +err: + if (ncons) { + NAME_CONSTRAINTS_free(ncons); + } + if (sub) { + GENERAL_SUBTREE_free(sub); + } + + return NULL; } static int i2r_NAME_CONSTRAINTS(const X509V3_EXT_METHOD *method, void *a, - BIO *bp, int ind) -{ - NAME_CONSTRAINTS *ncons = a; - do_i2r_name_constraints(method, ncons->permittedSubtrees, - bp, ind, "Permitted"); - do_i2r_name_constraints(method, ncons->excludedSubtrees, - bp, ind, "Excluded"); - return 1; + BIO *bp, int ind) { + NAME_CONSTRAINTS *ncons = a; + do_i2r_name_constraints(method, ncons->permittedSubtrees, bp, ind, + "Permitted"); + do_i2r_name_constraints(method, ncons->excludedSubtrees, bp, ind, "Excluded"); + return 1; } static int do_i2r_name_constraints(const X509V3_EXT_METHOD *method, - STACK_OF(GENERAL_SUBTREE) *trees, - BIO *bp, int ind, const char *name) -{ - GENERAL_SUBTREE *tree; - size_t i; - if (sk_GENERAL_SUBTREE_num(trees) > 0) - BIO_printf(bp, "%*s%s:\n", ind, "", name); - for (i = 0; i < sk_GENERAL_SUBTREE_num(trees); i++) { - tree = sk_GENERAL_SUBTREE_value(trees, i); - BIO_printf(bp, "%*s", ind + 2, ""); - if (tree->base->type == GEN_IPADD) - print_nc_ipadd(bp, tree->base->d.ip); - else - GENERAL_NAME_print(bp, tree->base); - BIO_puts(bp, "\n"); + STACK_OF(GENERAL_SUBTREE) *trees, BIO *bp, + int ind, const char *name) { + GENERAL_SUBTREE *tree; + size_t i; + if (sk_GENERAL_SUBTREE_num(trees) > 0) { + BIO_printf(bp, "%*s%s:\n", ind, "", name); + } + for (i = 0; i < sk_GENERAL_SUBTREE_num(trees); i++) { + tree = sk_GENERAL_SUBTREE_value(trees, i); + BIO_printf(bp, "%*s", ind + 2, ""); + if (tree->base->type == GEN_IPADD) { + print_nc_ipadd(bp, tree->base->d.ip); + } else { + GENERAL_NAME_print(bp, tree->base); } - return 1; + BIO_puts(bp, "\n"); + } + return 1; } -static int print_nc_ipadd(BIO *bp, ASN1_OCTET_STRING *ip) -{ - int i, len; - unsigned char *p; - p = ip->data; - len = ip->length; - BIO_puts(bp, "IP:"); - if (len == 8) { - BIO_printf(bp, "%d.%d.%d.%d/%d.%d.%d.%d", - p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7]); - } else if (len == 32) { - for (i = 0; i < 16; i++) { - uint16_t v = ((uint16_t)p[0] << 8) | p[1]; - BIO_printf(bp, "%X", v); - p += 2; - if (i == 7) - BIO_puts(bp, "/"); - else if (i != 15) - BIO_puts(bp, ":"); - } - } else - BIO_printf(bp, "IP Address:"); - return 1; +static int print_nc_ipadd(BIO *bp, ASN1_OCTET_STRING *ip) { + int i, len; + unsigned char *p; + p = ip->data; + len = ip->length; + BIO_puts(bp, "IP:"); + if (len == 8) { + BIO_printf(bp, "%d.%d.%d.%d/%d.%d.%d.%d", p[0], p[1], p[2], p[3], p[4], + p[5], p[6], p[7]); + } else if (len == 32) { + for (i = 0; i < 16; i++) { + uint16_t v = ((uint16_t)p[0] << 8) | p[1]; + BIO_printf(bp, "%X", v); + p += 2; + if (i == 7) { + BIO_puts(bp, "/"); + } else if (i != 15) { + BIO_puts(bp, ":"); + } + } + } else { + BIO_printf(bp, "IP Address:"); + } + return 1; } /*- @@ -230,145 +241,151 @@ static int print_nc_ipadd(BIO *bp, ASN1_OCTET_STRING *ip) * X509_V_ERR_UNSUPPORTED_NAME_SYNTAX: Bad or unsupported syntax of name. */ -int NAME_CONSTRAINTS_check(X509 *x, NAME_CONSTRAINTS *nc) -{ - int r, i; - size_t j; - X509_NAME *nm; - - nm = X509_get_subject_name(x); - - /* Guard against certificates with an excessive number of names or - * constraints causing a computationally expensive name constraints - * check. */ - size_t name_count = - X509_NAME_entry_count(nm) + sk_GENERAL_NAME_num(x->altname); - size_t constraint_count = sk_GENERAL_SUBTREE_num(nc->permittedSubtrees) + - sk_GENERAL_SUBTREE_num(nc->excludedSubtrees); - size_t check_count = constraint_count * name_count; - if (name_count < (size_t)X509_NAME_entry_count(nm) || - constraint_count < sk_GENERAL_SUBTREE_num(nc->permittedSubtrees) || - (constraint_count && check_count / constraint_count != name_count) || - check_count > 1 << 20) { - return X509_V_ERR_UNSPECIFIED; +int NAME_CONSTRAINTS_check(X509 *x, NAME_CONSTRAINTS *nc) { + int r, i; + size_t j; + X509_NAME *nm; + + nm = X509_get_subject_name(x); + + /* Guard against certificates with an excessive number of names or + * constraints causing a computationally expensive name constraints + * check. */ + size_t name_count = + X509_NAME_entry_count(nm) + sk_GENERAL_NAME_num(x->altname); + size_t constraint_count = sk_GENERAL_SUBTREE_num(nc->permittedSubtrees) + + sk_GENERAL_SUBTREE_num(nc->excludedSubtrees); + size_t check_count = constraint_count * name_count; + if (name_count < (size_t)X509_NAME_entry_count(nm) || + constraint_count < sk_GENERAL_SUBTREE_num(nc->permittedSubtrees) || + (constraint_count && check_count / constraint_count != name_count) || + check_count > 1 << 20) { + return X509_V_ERR_UNSPECIFIED; + } + + if (X509_NAME_entry_count(nm) > 0) { + GENERAL_NAME gntmp; + gntmp.type = GEN_DIRNAME; + gntmp.d.directoryName = nm; + + r = nc_match(&gntmp, nc); + + if (r != X509_V_OK) { + return r; } - if (X509_NAME_entry_count(nm) > 0) { - GENERAL_NAME gntmp; - gntmp.type = GEN_DIRNAME; - gntmp.d.directoryName = nm; + gntmp.type = GEN_EMAIL; - r = nc_match(&gntmp, nc); + /* Process any email address attributes in subject name */ - if (r != X509_V_OK) - return r; - - gntmp.type = GEN_EMAIL; - - /* Process any email address attributes in subject name */ - - for (i = -1;;) { - X509_NAME_ENTRY *ne; - i = X509_NAME_get_index_by_NID(nm, NID_pkcs9_emailAddress, i); - if (i == -1) - break; - ne = X509_NAME_get_entry(nm, i); - gntmp.d.rfc822Name = X509_NAME_ENTRY_get_data(ne); - if (gntmp.d.rfc822Name->type != V_ASN1_IA5STRING) - return X509_V_ERR_UNSUPPORTED_NAME_SYNTAX; - - r = nc_match(&gntmp, nc); + for (i = -1;;) { + X509_NAME_ENTRY *ne; + i = X509_NAME_get_index_by_NID(nm, NID_pkcs9_emailAddress, i); + if (i == -1) { + break; + } + ne = X509_NAME_get_entry(nm, i); + gntmp.d.rfc822Name = X509_NAME_ENTRY_get_data(ne); + if (gntmp.d.rfc822Name->type != V_ASN1_IA5STRING) { + return X509_V_ERR_UNSUPPORTED_NAME_SYNTAX; + } - if (r != X509_V_OK) - return r; - } + r = nc_match(&gntmp, nc); + if (r != X509_V_OK) { + return r; + } } + } - for (j = 0; j < sk_GENERAL_NAME_num(x->altname); j++) { - GENERAL_NAME *gen = sk_GENERAL_NAME_value(x->altname, j); - r = nc_match(gen, nc); - if (r != X509_V_OK) - return r; + for (j = 0; j < sk_GENERAL_NAME_num(x->altname); j++) { + GENERAL_NAME *gen = sk_GENERAL_NAME_value(x->altname, j); + r = nc_match(gen, nc); + if (r != X509_V_OK) { + return r; } + } - return X509_V_OK; - + return X509_V_OK; } -static int nc_match(GENERAL_NAME *gen, NAME_CONSTRAINTS *nc) -{ - GENERAL_SUBTREE *sub; - int r, match = 0; - size_t i; - - /* - * Permitted subtrees: if any subtrees exist of matching the type at - * least one subtree must match. - */ - - for (i = 0; i < sk_GENERAL_SUBTREE_num(nc->permittedSubtrees); i++) { - sub = sk_GENERAL_SUBTREE_value(nc->permittedSubtrees, i); - if (gen->type != sub->base->type) - continue; - if (sub->minimum || sub->maximum) - return X509_V_ERR_SUBTREE_MINMAX; - /* If we already have a match don't bother trying any more */ - if (match == 2) - continue; - if (match == 0) - match = 1; - r = nc_match_single(gen, sub->base); - if (r == X509_V_OK) - match = 2; - else if (r != X509_V_ERR_PERMITTED_VIOLATION) - return r; - } +static int nc_match(GENERAL_NAME *gen, NAME_CONSTRAINTS *nc) { + GENERAL_SUBTREE *sub; + int r, match = 0; + size_t i; - if (match == 1) - return X509_V_ERR_PERMITTED_VIOLATION; + /* + * Permitted subtrees: if any subtrees exist of matching the type at + * least one subtree must match. + */ - /* Excluded subtrees: must not match any of these */ + for (i = 0; i < sk_GENERAL_SUBTREE_num(nc->permittedSubtrees); i++) { + sub = sk_GENERAL_SUBTREE_value(nc->permittedSubtrees, i); + if (gen->type != sub->base->type) { + continue; + } + if (sub->minimum || sub->maximum) { + return X509_V_ERR_SUBTREE_MINMAX; + } + /* If we already have a match don't bother trying any more */ + if (match == 2) { + continue; + } + if (match == 0) { + match = 1; + } + r = nc_match_single(gen, sub->base); + if (r == X509_V_OK) { + match = 2; + } else if (r != X509_V_ERR_PERMITTED_VIOLATION) { + return r; + } + } - for (i = 0; i < sk_GENERAL_SUBTREE_num(nc->excludedSubtrees); i++) { - sub = sk_GENERAL_SUBTREE_value(nc->excludedSubtrees, i); - if (gen->type != sub->base->type) - continue; - if (sub->minimum || sub->maximum) - return X509_V_ERR_SUBTREE_MINMAX; + if (match == 1) { + return X509_V_ERR_PERMITTED_VIOLATION; + } - r = nc_match_single(gen, sub->base); - if (r == X509_V_OK) - return X509_V_ERR_EXCLUDED_VIOLATION; - else if (r != X509_V_ERR_PERMITTED_VIOLATION) - return r; + /* Excluded subtrees: must not match any of these */ + for (i = 0; i < sk_GENERAL_SUBTREE_num(nc->excludedSubtrees); i++) { + sub = sk_GENERAL_SUBTREE_value(nc->excludedSubtrees, i); + if (gen->type != sub->base->type) { + continue; + } + if (sub->minimum || sub->maximum) { + return X509_V_ERR_SUBTREE_MINMAX; } - return X509_V_OK; + r = nc_match_single(gen, sub->base); + if (r == X509_V_OK) { + return X509_V_ERR_EXCLUDED_VIOLATION; + } else if (r != X509_V_ERR_PERMITTED_VIOLATION) { + return r; + } + } + return X509_V_OK; } -static int nc_match_single(GENERAL_NAME *gen, GENERAL_NAME *base) -{ - switch (base->type) { +static int nc_match_single(GENERAL_NAME *gen, GENERAL_NAME *base) { + switch (base->type) { case GEN_DIRNAME: - return nc_dn(gen->d.directoryName, base->d.directoryName); + return nc_dn(gen->d.directoryName, base->d.directoryName); case GEN_DNS: - return nc_dns(gen->d.dNSName, base->d.dNSName); + return nc_dns(gen->d.dNSName, base->d.dNSName); case GEN_EMAIL: - return nc_email(gen->d.rfc822Name, base->d.rfc822Name); + return nc_email(gen->d.rfc822Name, base->d.rfc822Name); case GEN_URI: - return nc_uri(gen->d.uniformResourceIdentifier, - base->d.uniformResourceIdentifier); + return nc_uri(gen->d.uniformResourceIdentifier, + base->d.uniformResourceIdentifier); default: - return X509_V_ERR_UNSUPPORTED_CONSTRAINT_TYPE; - } - + return X509_V_ERR_UNSUPPORTED_CONSTRAINT_TYPE; + } } /* @@ -377,183 +394,177 @@ static int nc_match_single(GENERAL_NAME *gen, GENERAL_NAME *base) * subset of the name. */ -static int nc_dn(X509_NAME *nm, X509_NAME *base) -{ - /* Ensure canonical encodings are up to date. */ - if (nm->modified && i2d_X509_NAME(nm, NULL) < 0) - return X509_V_ERR_OUT_OF_MEM; - if (base->modified && i2d_X509_NAME(base, NULL) < 0) - return X509_V_ERR_OUT_OF_MEM; - if (base->canon_enclen > nm->canon_enclen) - return X509_V_ERR_PERMITTED_VIOLATION; - if (OPENSSL_memcmp(base->canon_enc, nm->canon_enc, base->canon_enclen)) - return X509_V_ERR_PERMITTED_VIOLATION; - return X509_V_OK; +static int nc_dn(X509_NAME *nm, X509_NAME *base) { + /* Ensure canonical encodings are up to date. */ + if (nm->modified && i2d_X509_NAME(nm, NULL) < 0) { + return X509_V_ERR_OUT_OF_MEM; + } + if (base->modified && i2d_X509_NAME(base, NULL) < 0) { + return X509_V_ERR_OUT_OF_MEM; + } + if (base->canon_enclen > nm->canon_enclen) { + return X509_V_ERR_PERMITTED_VIOLATION; + } + if (OPENSSL_memcmp(base->canon_enc, nm->canon_enc, base->canon_enclen)) { + return X509_V_ERR_PERMITTED_VIOLATION; + } + return X509_V_OK; } -static int starts_with(const CBS *cbs, uint8_t c) -{ - return CBS_len(cbs) > 0 && CBS_data(cbs)[0] == c; +static int starts_with(const CBS *cbs, uint8_t c) { + return CBS_len(cbs) > 0 && CBS_data(cbs)[0] == c; } -static int equal_case(const CBS *a, const CBS *b) -{ - if (CBS_len(a) != CBS_len(b)) { - return 0; - } - /* Note we cannot use |OPENSSL_strncasecmp| because that would stop - * iterating at NUL. */ - const uint8_t *a_data = CBS_data(a), *b_data = CBS_data(b); - for (size_t i = 0; i < CBS_len(a); i++) { - if (OPENSSL_tolower(a_data[i]) != OPENSSL_tolower(b_data[i])) { - return 0; - } +static int equal_case(const CBS *a, const CBS *b) { + if (CBS_len(a) != CBS_len(b)) { + return 0; + } + /* Note we cannot use |OPENSSL_strncasecmp| because that would stop + * iterating at NUL. */ + const uint8_t *a_data = CBS_data(a), *b_data = CBS_data(b); + for (size_t i = 0; i < CBS_len(a); i++) { + if (OPENSSL_tolower(a_data[i]) != OPENSSL_tolower(b_data[i])) { + return 0; } - return 1; + } + return 1; } -static int has_suffix_case(const CBS *a, const CBS *b) -{ - if (CBS_len(a) < CBS_len(b)) { - return 0; - } - CBS copy = *a; - CBS_skip(©, CBS_len(a) - CBS_len(b)); - return equal_case(©, b); +static int has_suffix_case(const CBS *a, const CBS *b) { + if (CBS_len(a) < CBS_len(b)) { + return 0; + } + CBS copy = *a; + CBS_skip(©, CBS_len(a) - CBS_len(b)); + return equal_case(©, b); } -static int nc_dns(ASN1_IA5STRING *dns, ASN1_IA5STRING *base) -{ - CBS dns_cbs, base_cbs; - CBS_init(&dns_cbs, dns->data, dns->length); - CBS_init(&base_cbs, base->data, base->length); - - /* Empty matches everything */ - if (CBS_len(&base_cbs) == 0) { - return X509_V_OK; - } - - /* If |base_cbs| begins with a '.', do a simple suffix comparison. This is - * not part of RFC5280, but is part of OpenSSL's original behavior. */ - if (starts_with(&base_cbs, '.')) { - if (has_suffix_case(&dns_cbs, &base_cbs)) { - return X509_V_OK; - } - return X509_V_ERR_PERMITTED_VIOLATION; - } - - /* - * Otherwise can add zero or more components on the left so compare RHS - * and if dns is longer and expect '.' as preceding character. - */ - if (CBS_len(&dns_cbs) > CBS_len(&base_cbs)) { - uint8_t dot; - if (!CBS_skip(&dns_cbs, CBS_len(&dns_cbs) - CBS_len(&base_cbs) - 1) || - !CBS_get_u8(&dns_cbs, &dot) || - dot != '.') { - return X509_V_ERR_PERMITTED_VIOLATION; - } - } - - if (!equal_case(&dns_cbs, &base_cbs)) { - return X509_V_ERR_PERMITTED_VIOLATION; - } +static int nc_dns(ASN1_IA5STRING *dns, ASN1_IA5STRING *base) { + CBS dns_cbs, base_cbs; + CBS_init(&dns_cbs, dns->data, dns->length); + CBS_init(&base_cbs, base->data, base->length); + /* Empty matches everything */ + if (CBS_len(&base_cbs) == 0) { return X509_V_OK; + } -} - -static int nc_email(ASN1_IA5STRING *eml, ASN1_IA5STRING *base) -{ - CBS eml_cbs, base_cbs; - CBS_init(&eml_cbs, eml->data, eml->length); - CBS_init(&base_cbs, base->data, base->length); - - /* TODO(davidben): In OpenSSL 1.1.1, this switched from the first '@' to the - * last one. Match them here, or perhaps do an actual parse. Looks like - * multiple '@'s may be allowed in quoted strings. */ - CBS eml_local, base_local; - if (!CBS_get_until_first(&eml_cbs, &eml_local, '@')) { - return X509_V_ERR_UNSUPPORTED_NAME_SYNTAX; + /* If |base_cbs| begins with a '.', do a simple suffix comparison. This is + * not part of RFC5280, but is part of OpenSSL's original behavior. */ + if (starts_with(&base_cbs, '.')) { + if (has_suffix_case(&dns_cbs, &base_cbs)) { + return X509_V_OK; } - int base_has_at = CBS_get_until_first(&base_cbs, &base_local, '@'); - - /* Special case: inital '.' is RHS match */ - if (!base_has_at && starts_with(&base_cbs, '.')) { - if (has_suffix_case(&eml_cbs, &base_cbs)) { - return X509_V_OK; - } - return X509_V_ERR_PERMITTED_VIOLATION; + return X509_V_ERR_PERMITTED_VIOLATION; + } + + /* + * Otherwise can add zero or more components on the left so compare RHS + * and if dns is longer and expect '.' as preceding character. + */ + if (CBS_len(&dns_cbs) > CBS_len(&base_cbs)) { + uint8_t dot; + if (!CBS_skip(&dns_cbs, CBS_len(&dns_cbs) - CBS_len(&base_cbs) - 1) || + !CBS_get_u8(&dns_cbs, &dot) || dot != '.') { + return X509_V_ERR_PERMITTED_VIOLATION; } + } - /* If we have anything before '@' match local part */ - if (base_has_at) { - /* TODO(davidben): This interprets a constraint of "@example.com" as - * "example.com", which is not part of RFC5280. */ - if (CBS_len(&base_local) > 0) { - /* Case sensitive match of local part */ - if (!CBS_mem_equal(&base_local, CBS_data(&eml_local), - CBS_len(&eml_local))) { - return X509_V_ERR_PERMITTED_VIOLATION; - } - } - /* Position base after '@' */ - assert(starts_with(&base_cbs, '@')); - CBS_skip(&base_cbs, 1); - } - - /* Just have hostname left to match: case insensitive */ - assert(starts_with(&eml_cbs, '@')); - CBS_skip(&eml_cbs, 1); - if (!equal_case(&base_cbs, &eml_cbs)) { - return X509_V_ERR_PERMITTED_VIOLATION; - } + if (!equal_case(&dns_cbs, &base_cbs)) { + return X509_V_ERR_PERMITTED_VIOLATION; + } - return X509_V_OK; + return X509_V_OK; } -static int nc_uri(ASN1_IA5STRING *uri, ASN1_IA5STRING *base) -{ - CBS uri_cbs, base_cbs; - CBS_init(&uri_cbs, uri->data, uri->length); - CBS_init(&base_cbs, base->data, base->length); - - /* Check for foo:// and skip past it */ - CBS scheme; - uint8_t byte; - if (!CBS_get_until_first(&uri_cbs, &scheme, ':') || - !CBS_skip(&uri_cbs, 1) || // Skip the colon - !CBS_get_u8(&uri_cbs, &byte) || byte != '/' || - !CBS_get_u8(&uri_cbs, &byte) || byte != '/') { - return X509_V_ERR_UNSUPPORTED_NAME_SYNTAX; - } - - /* Look for a port indicator as end of hostname first. Otherwise look for - * trailing slash, or the end of the string. - * TODO(davidben): This is not a correct URI parser and mishandles IPv6 - * literals. */ - CBS host; - if (!CBS_get_until_first(&uri_cbs, &host, ':') && - !CBS_get_until_first(&uri_cbs, &host, '/')) { - host = uri_cbs; +static int nc_email(ASN1_IA5STRING *eml, ASN1_IA5STRING *base) { + CBS eml_cbs, base_cbs; + CBS_init(&eml_cbs, eml->data, eml->length); + CBS_init(&base_cbs, base->data, base->length); + + /* TODO(davidben): In OpenSSL 1.1.1, this switched from the first '@' to the + * last one. Match them here, or perhaps do an actual parse. Looks like + * multiple '@'s may be allowed in quoted strings. */ + CBS eml_local, base_local; + if (!CBS_get_until_first(&eml_cbs, &eml_local, '@')) { + return X509_V_ERR_UNSUPPORTED_NAME_SYNTAX; + } + int base_has_at = CBS_get_until_first(&base_cbs, &base_local, '@'); + + /* Special case: inital '.' is RHS match */ + if (!base_has_at && starts_with(&base_cbs, '.')) { + if (has_suffix_case(&eml_cbs, &base_cbs)) { + return X509_V_OK; } - - if (CBS_len(&host) == 0) { - return X509_V_ERR_UNSUPPORTED_NAME_SYNTAX; - } - - /* Special case: inital '.' is RHS match */ - if (starts_with(&base_cbs, '.')) { - if (has_suffix_case(&host, &base_cbs)) { - return X509_V_OK; - } + return X509_V_ERR_PERMITTED_VIOLATION; + } + + /* If we have anything before '@' match local part */ + if (base_has_at) { + /* TODO(davidben): This interprets a constraint of "@example.com" as + * "example.com", which is not part of RFC5280. */ + if (CBS_len(&base_local) > 0) { + /* Case sensitive match of local part */ + if (!CBS_mem_equal(&base_local, CBS_data(&eml_local), + CBS_len(&eml_local))) { return X509_V_ERR_PERMITTED_VIOLATION; + } } + /* Position base after '@' */ + assert(starts_with(&base_cbs, '@')); + CBS_skip(&base_cbs, 1); + } + + /* Just have hostname left to match: case insensitive */ + assert(starts_with(&eml_cbs, '@')); + CBS_skip(&eml_cbs, 1); + if (!equal_case(&base_cbs, &eml_cbs)) { + return X509_V_ERR_PERMITTED_VIOLATION; + } + + return X509_V_OK; +} - if (!equal_case(&base_cbs, &host)) { - return X509_V_ERR_PERMITTED_VIOLATION; +static int nc_uri(ASN1_IA5STRING *uri, ASN1_IA5STRING *base) { + CBS uri_cbs, base_cbs; + CBS_init(&uri_cbs, uri->data, uri->length); + CBS_init(&base_cbs, base->data, base->length); + + /* Check for foo:// and skip past it */ + CBS scheme; + uint8_t byte; + if (!CBS_get_until_first(&uri_cbs, &scheme, ':') || + !CBS_skip(&uri_cbs, 1) || // Skip the colon + !CBS_get_u8(&uri_cbs, &byte) || byte != '/' || + !CBS_get_u8(&uri_cbs, &byte) || byte != '/') { + return X509_V_ERR_UNSUPPORTED_NAME_SYNTAX; + } + + /* Look for a port indicator as end of hostname first. Otherwise look for + * trailing slash, or the end of the string. + * TODO(davidben): This is not a correct URI parser and mishandles IPv6 + * literals. */ + CBS host; + if (!CBS_get_until_first(&uri_cbs, &host, ':') && + !CBS_get_until_first(&uri_cbs, &host, '/')) { + host = uri_cbs; + } + + if (CBS_len(&host) == 0) { + return X509_V_ERR_UNSUPPORTED_NAME_SYNTAX; + } + + /* Special case: inital '.' is RHS match */ + if (starts_with(&base_cbs, '.')) { + if (has_suffix_case(&host, &base_cbs)) { + return X509_V_OK; } + return X509_V_ERR_PERMITTED_VIOLATION; + } - return X509_V_OK; + if (!equal_case(&base_cbs, &host)) { + return X509_V_ERR_PERMITTED_VIOLATION; + } + return X509_V_OK; } diff --git a/crypto/x509v3/v3_ocsp.c b/crypto/x509v3/v3_ocsp.c index 3b6b86c1ca..9d648f6b51 100644 --- a/crypto/x509v3/v3_ocsp.c +++ b/crypto/x509v3/v3_ocsp.c @@ -20,49 +20,64 @@ static int i2r_ocsp_acutoff(const X509V3_EXT_METHOD *method, void *nonce, BIO *out, int indent); -static int i2r_ocsp_nocheck(const X509V3_EXT_METHOD *method, - void *nocheck, BIO *out, int indent); -static void *s2i_ocsp_nocheck(const X509V3_EXT_METHOD *method, - X509V3_CTX *ctx, const char *str); +static int i2r_ocsp_nocheck(const X509V3_EXT_METHOD *method, void *nocheck, + BIO *out, int indent); +static void *s2i_ocsp_nocheck(const X509V3_EXT_METHOD *method, X509V3_CTX *ctx, + const char *str); const X509V3_EXT_METHOD v3_crl_invdate = { - NID_invalidity_date, 0, ASN1_ITEM_ref(ASN1_GENERALIZEDTIME), - 0, 0, 0, 0, - 0, 0, - 0, 0, - i2r_ocsp_acutoff, 0, + NID_invalidity_date, + 0, + ASN1_ITEM_ref(ASN1_GENERALIZEDTIME), + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + i2r_ocsp_acutoff, + 0, NULL, }; const X509V3_EXT_METHOD v3_ocsp_nocheck = { - NID_id_pkix_OCSP_noCheck, 0, ASN1_ITEM_ref(ASN1_NULL), - 0, 0, 0, 0, - 0, s2i_ocsp_nocheck, - 0, 0, - i2r_ocsp_nocheck, 0, + NID_id_pkix_OCSP_noCheck, + 0, + ASN1_ITEM_ref(ASN1_NULL), + 0, + 0, + 0, + 0, + 0, + s2i_ocsp_nocheck, + 0, + 0, + i2r_ocsp_nocheck, + 0, NULL, }; static int i2r_ocsp_acutoff(const X509V3_EXT_METHOD *method, void *cutoff, - BIO *bp, int ind) -{ - if (BIO_printf(bp, "%*s", ind, "") <= 0) - return 0; - if (!ASN1_GENERALIZEDTIME_print(bp, cutoff)) - return 0; - return 1; + BIO *bp, int ind) { + if (BIO_printf(bp, "%*s", ind, "") <= 0) { + return 0; + } + if (!ASN1_GENERALIZEDTIME_print(bp, cutoff)) { + return 0; + } + return 1; } /* Nocheck is just a single NULL. Don't print anything and always set it */ static int i2r_ocsp_nocheck(const X509V3_EXT_METHOD *method, void *nocheck, - BIO *out, int indent) -{ - return 1; + BIO *out, int indent) { + return 1; } -static void *s2i_ocsp_nocheck(const X509V3_EXT_METHOD *method, - X509V3_CTX *ctx, const char *str) -{ - return ASN1_NULL_new(); +static void *s2i_ocsp_nocheck(const X509V3_EXT_METHOD *method, X509V3_CTX *ctx, + const char *str) { + return ASN1_NULL_new(); } diff --git a/crypto/x509v3/v3_pci.c b/crypto/x509v3/v3_pci.c index b6ff148cb1..95fda039ee 100644 --- a/crypto/x509v3/v3_pci.c +++ b/crypto/x509v3/v3_pci.c @@ -52,239 +52,240 @@ static int i2r_pci(const X509V3_EXT_METHOD *method, void *ext, BIO *out, static void *r2i_pci(const X509V3_EXT_METHOD *method, X509V3_CTX *ctx, const char *str); -const X509V3_EXT_METHOD v3_pci = - { NID_proxyCertInfo, 0, ASN1_ITEM_ref(PROXY_CERT_INFO_EXTENSION), - 0, 0, 0, 0, - 0, 0, - NULL, NULL, +const X509V3_EXT_METHOD v3_pci = { + NID_proxyCertInfo, + 0, + ASN1_ITEM_ref(PROXY_CERT_INFO_EXTENSION), + 0, + 0, + 0, + 0, + 0, + 0, + NULL, + NULL, i2r_pci, r2i_pci, NULL, }; static int i2r_pci(const X509V3_EXT_METHOD *method, void *ext, BIO *out, - int indent) -{ - const PROXY_CERT_INFO_EXTENSION *pci = ext; - BIO_printf(out, "%*sPath Length Constraint: ", indent, ""); - if (pci->pcPathLengthConstraint) - i2a_ASN1_INTEGER(out, pci->pcPathLengthConstraint); - else - BIO_printf(out, "infinite"); - BIO_puts(out, "\n"); - BIO_printf(out, "%*sPolicy Language: ", indent, ""); - i2a_ASN1_OBJECT(out, pci->proxyPolicy->policyLanguage); - BIO_puts(out, "\n"); - if (pci->proxyPolicy->policy && pci->proxyPolicy->policy->data) - BIO_printf(out, "%*sPolicy Text: %.*s\n", indent, "", - pci->proxyPolicy->policy->length, - pci->proxyPolicy->policy->data); - return 1; + int indent) { + const PROXY_CERT_INFO_EXTENSION *pci = ext; + BIO_printf(out, "%*sPath Length Constraint: ", indent, ""); + if (pci->pcPathLengthConstraint) { + i2a_ASN1_INTEGER(out, pci->pcPathLengthConstraint); + } else { + BIO_printf(out, "infinite"); + } + BIO_puts(out, "\n"); + BIO_printf(out, "%*sPolicy Language: ", indent, ""); + i2a_ASN1_OBJECT(out, pci->proxyPolicy->policyLanguage); + BIO_puts(out, "\n"); + if (pci->proxyPolicy->policy && pci->proxyPolicy->policy->data) { + BIO_printf(out, "%*sPolicy Text: %.*s\n", indent, "", + pci->proxyPolicy->policy->length, + pci->proxyPolicy->policy->data); + } + return 1; } -static int process_pci_value(CONF_VALUE *val, - ASN1_OBJECT **language, ASN1_INTEGER **pathlen, - ASN1_OCTET_STRING **policy) -{ - int free_policy = 0; +static int process_pci_value(CONF_VALUE *val, ASN1_OBJECT **language, + ASN1_INTEGER **pathlen, + ASN1_OCTET_STRING **policy) { + int free_policy = 0; - if (strcmp(val->name, "language") == 0) { - if (*language) { - OPENSSL_PUT_ERROR(X509V3, - X509V3_R_POLICY_LANGUAGE_ALREADY_DEFINED); - X509V3_conf_err(val); - return 0; - } - if (!(*language = OBJ_txt2obj(val->value, 0))) { - OPENSSL_PUT_ERROR(X509V3, X509V3_R_INVALID_OBJECT_IDENTIFIER); - X509V3_conf_err(val); - return 0; - } - } else if (strcmp(val->name, "pathlen") == 0) { - if (*pathlen) { - OPENSSL_PUT_ERROR(X509V3, - X509V3_R_POLICY_PATH_LENGTH_ALREADY_DEFINED); - X509V3_conf_err(val); - return 0; - } - if (!X509V3_get_value_int(val, pathlen)) { - OPENSSL_PUT_ERROR(X509V3, X509V3_R_POLICY_PATH_LENGTH); - X509V3_conf_err(val); - return 0; - } - } else if (strcmp(val->name, "policy") == 0) { - unsigned char *tmp_data = NULL; - long val_len; - if (!*policy) { - *policy = ASN1_OCTET_STRING_new(); - if (!*policy) { - OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE); - X509V3_conf_err(val); - return 0; - } - free_policy = 1; - } - if (strncmp(val->value, "hex:", 4) == 0) { - unsigned char *tmp_data2 = - x509v3_hex_to_bytes(val->value + 4, &val_len); + if (strcmp(val->name, "language") == 0) { + if (*language) { + OPENSSL_PUT_ERROR(X509V3, X509V3_R_POLICY_LANGUAGE_ALREADY_DEFINED); + X509V3_conf_err(val); + return 0; + } + if (!(*language = OBJ_txt2obj(val->value, 0))) { + OPENSSL_PUT_ERROR(X509V3, X509V3_R_INVALID_OBJECT_IDENTIFIER); + X509V3_conf_err(val); + return 0; + } + } else if (strcmp(val->name, "pathlen") == 0) { + if (*pathlen) { + OPENSSL_PUT_ERROR(X509V3, X509V3_R_POLICY_PATH_LENGTH_ALREADY_DEFINED); + X509V3_conf_err(val); + return 0; + } + if (!X509V3_get_value_int(val, pathlen)) { + OPENSSL_PUT_ERROR(X509V3, X509V3_R_POLICY_PATH_LENGTH); + X509V3_conf_err(val); + return 0; + } + } else if (strcmp(val->name, "policy") == 0) { + unsigned char *tmp_data = NULL; + long val_len; + if (!*policy) { + *policy = ASN1_OCTET_STRING_new(); + if (!*policy) { + OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE); + X509V3_conf_err(val); + return 0; + } + free_policy = 1; + } + if (strncmp(val->value, "hex:", 4) == 0) { + unsigned char *tmp_data2 = x509v3_hex_to_bytes(val->value + 4, &val_len); - if (!tmp_data2) { - OPENSSL_PUT_ERROR(X509V3, X509V3_R_ILLEGAL_HEX_DIGIT); - X509V3_conf_err(val); - goto err; - } + if (!tmp_data2) { + OPENSSL_PUT_ERROR(X509V3, X509V3_R_ILLEGAL_HEX_DIGIT); + X509V3_conf_err(val); + goto err; + } - tmp_data = OPENSSL_realloc((*policy)->data, - (*policy)->length + val_len + 1); - if (tmp_data) { - (*policy)->data = tmp_data; - OPENSSL_memcpy(&(*policy)->data[(*policy)->length], - tmp_data2, val_len); - (*policy)->length += val_len; - (*policy)->data[(*policy)->length] = '\0'; - } else { - OPENSSL_free(tmp_data2); - /* - * realloc failure implies the original data space is b0rked - * too! - */ - (*policy)->data = NULL; - (*policy)->length = 0; - OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE); - X509V3_conf_err(val); - goto err; - } - OPENSSL_free(tmp_data2); - } else if (strncmp(val->value, "text:", 5) == 0) { - val_len = strlen(val->value + 5); - tmp_data = OPENSSL_realloc((*policy)->data, - (*policy)->length + val_len + 1); - if (tmp_data) { - (*policy)->data = tmp_data; - OPENSSL_memcpy(&(*policy)->data[(*policy)->length], - val->value + 5, val_len); - (*policy)->length += val_len; - (*policy)->data[(*policy)->length] = '\0'; - } else { - /* - * realloc failure implies the original data space is b0rked - * too! - */ - (*policy)->data = NULL; - (*policy)->length = 0; - OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE); - X509V3_conf_err(val); - goto err; - } - } else { - OPENSSL_PUT_ERROR(X509V3, X509V3_R_INCORRECT_POLICY_SYNTAX_TAG); - X509V3_conf_err(val); - goto err; - } - if (!tmp_data) { - OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE); - X509V3_conf_err(val); - goto err; - } + tmp_data = + OPENSSL_realloc((*policy)->data, (*policy)->length + val_len + 1); + if (tmp_data) { + (*policy)->data = tmp_data; + OPENSSL_memcpy(&(*policy)->data[(*policy)->length], tmp_data2, val_len); + (*policy)->length += val_len; + (*policy)->data[(*policy)->length] = '\0'; + } else { + OPENSSL_free(tmp_data2); + /* + * realloc failure implies the original data space is b0rked + * too! + */ + (*policy)->data = NULL; + (*policy)->length = 0; + OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE); + X509V3_conf_err(val); + goto err; + } + OPENSSL_free(tmp_data2); + } else if (strncmp(val->value, "text:", 5) == 0) { + val_len = strlen(val->value + 5); + tmp_data = + OPENSSL_realloc((*policy)->data, (*policy)->length + val_len + 1); + if (tmp_data) { + (*policy)->data = tmp_data; + OPENSSL_memcpy(&(*policy)->data[(*policy)->length], val->value + 5, + val_len); + (*policy)->length += val_len; + (*policy)->data[(*policy)->length] = '\0'; + } else { + /* + * realloc failure implies the original data space is b0rked + * too! + */ + (*policy)->data = NULL; + (*policy)->length = 0; + OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE); + X509V3_conf_err(val); + goto err; + } + } else { + OPENSSL_PUT_ERROR(X509V3, X509V3_R_INCORRECT_POLICY_SYNTAX_TAG); + X509V3_conf_err(val); + goto err; } - return 1; - err: - if (free_policy) { - ASN1_OCTET_STRING_free(*policy); - *policy = NULL; + if (!tmp_data) { + OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE); + X509V3_conf_err(val); + goto err; } - return 0; + } + return 1; +err: + if (free_policy) { + ASN1_OCTET_STRING_free(*policy); + *policy = NULL; + } + return 0; } static void *r2i_pci(const X509V3_EXT_METHOD *method, X509V3_CTX *ctx, - const char *value) -{ - PROXY_CERT_INFO_EXTENSION *pci = NULL; - STACK_OF(CONF_VALUE) *vals; - ASN1_OBJECT *language = NULL; - ASN1_INTEGER *pathlen = NULL; - ASN1_OCTET_STRING *policy = NULL; - size_t i, j; - int nid; + const char *value) { + PROXY_CERT_INFO_EXTENSION *pci = NULL; + STACK_OF(CONF_VALUE) *vals; + ASN1_OBJECT *language = NULL; + ASN1_INTEGER *pathlen = NULL; + ASN1_OCTET_STRING *policy = NULL; + size_t i, j; + int nid; - vals = X509V3_parse_list(value); - for (i = 0; i < sk_CONF_VALUE_num(vals); i++) { - CONF_VALUE *cnf = sk_CONF_VALUE_value(vals, i); - if (!cnf->name || (*cnf->name != '@' && !cnf->value)) { - OPENSSL_PUT_ERROR(X509V3, X509V3_R_INVALID_PROXY_POLICY_SETTING); - X509V3_conf_err(cnf); - goto err; - } - if (*cnf->name == '@') { - STACK_OF(CONF_VALUE) *sect; - int success_p = 1; - - sect = X509V3_get_section(ctx, cnf->name + 1); - if (!sect) { - OPENSSL_PUT_ERROR(X509V3, X509V3_R_INVALID_SECTION); - X509V3_conf_err(cnf); - goto err; - } - for (j = 0; success_p && j < sk_CONF_VALUE_num(sect); j++) { - success_p = - process_pci_value(sk_CONF_VALUE_value(sect, j), - &language, &pathlen, &policy); - } - X509V3_section_free(ctx, sect); - if (!success_p) - goto err; - } else { - if (!process_pci_value(cnf, &language, &pathlen, &policy)) { - X509V3_conf_err(cnf); - goto err; - } - } + vals = X509V3_parse_list(value); + for (i = 0; i < sk_CONF_VALUE_num(vals); i++) { + CONF_VALUE *cnf = sk_CONF_VALUE_value(vals, i); + if (!cnf->name || (*cnf->name != '@' && !cnf->value)) { + OPENSSL_PUT_ERROR(X509V3, X509V3_R_INVALID_PROXY_POLICY_SETTING); + X509V3_conf_err(cnf); + goto err; } + if (*cnf->name == '@') { + STACK_OF(CONF_VALUE) *sect; + int success_p = 1; - /* Language is mandatory */ - if (!language) { - OPENSSL_PUT_ERROR(X509V3, - X509V3_R_NO_PROXY_CERT_POLICY_LANGUAGE_DEFINED); + sect = X509V3_get_section(ctx, cnf->name + 1); + if (!sect) { + OPENSSL_PUT_ERROR(X509V3, X509V3_R_INVALID_SECTION); + X509V3_conf_err(cnf); goto err; - } - nid = OBJ_obj2nid(language); - if ((nid == NID_Independent || nid == NID_id_ppl_inheritAll) && policy) { - OPENSSL_PUT_ERROR(X509V3, - X509V3_R_POLICY_WHEN_PROXY_LANGUAGE_REQUIRES_NO_POLICY); + } + for (j = 0; success_p && j < sk_CONF_VALUE_num(sect); j++) { + success_p = process_pci_value(sk_CONF_VALUE_value(sect, j), &language, + &pathlen, &policy); + } + X509V3_section_free(ctx, sect); + if (!success_p) { goto err; - } - - pci = PROXY_CERT_INFO_EXTENSION_new(); - if (!pci) { - OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE); + } + } else { + if (!process_pci_value(cnf, &language, &pathlen, &policy)) { + X509V3_conf_err(cnf); goto err; + } } + } + + /* Language is mandatory */ + if (!language) { + OPENSSL_PUT_ERROR(X509V3, X509V3_R_NO_PROXY_CERT_POLICY_LANGUAGE_DEFINED); + goto err; + } + nid = OBJ_obj2nid(language); + if ((nid == NID_Independent || nid == NID_id_ppl_inheritAll) && policy) { + OPENSSL_PUT_ERROR(X509V3, + X509V3_R_POLICY_WHEN_PROXY_LANGUAGE_REQUIRES_NO_POLICY); + goto err; + } + + pci = PROXY_CERT_INFO_EXTENSION_new(); + if (!pci) { + OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE); + goto err; + } - pci->proxyPolicy->policyLanguage = language; + pci->proxyPolicy->policyLanguage = language; + language = NULL; + pci->proxyPolicy->policy = policy; + policy = NULL; + pci->pcPathLengthConstraint = pathlen; + pathlen = NULL; + goto end; +err: + if (language) { + ASN1_OBJECT_free(language); language = NULL; - pci->proxyPolicy->policy = policy; - policy = NULL; - pci->pcPathLengthConstraint = pathlen; + } + if (pathlen) { + ASN1_INTEGER_free(pathlen); pathlen = NULL; - goto end; - err: - if (language) { - ASN1_OBJECT_free(language); - language = NULL; - } - if (pathlen) { - ASN1_INTEGER_free(pathlen); - pathlen = NULL; - } - if (policy) { - ASN1_OCTET_STRING_free(policy); - policy = NULL; - } - if (pci) { - PROXY_CERT_INFO_EXTENSION_free(pci); - pci = NULL; - } - end: - sk_CONF_VALUE_pop_free(vals, X509V3_conf_free); - return pci; + } + if (policy) { + ASN1_OCTET_STRING_free(policy); + policy = NULL; + } + if (pci) { + PROXY_CERT_INFO_EXTENSION_free(pci); + pci = NULL; + } +end: + sk_CONF_VALUE_pop_free(vals, X509V3_conf_free); + return pci; } diff --git a/crypto/x509v3/v3_pcia.c b/crypto/x509v3/v3_pcia.c index 3f285f30f5..1e92ad7246 100644 --- a/crypto/x509v3/v3_pcia.c +++ b/crypto/x509v3/v3_pcia.c @@ -40,18 +40,16 @@ #include -ASN1_SEQUENCE(PROXY_POLICY) = - { - ASN1_SIMPLE(PROXY_POLICY,policyLanguage,ASN1_OBJECT), - ASN1_OPT(PROXY_POLICY,policy,ASN1_OCTET_STRING) -} ASN1_SEQUENCE_END(PROXY_POLICY) +ASN1_SEQUENCE(PROXY_POLICY) = { + ASN1_SIMPLE(PROXY_POLICY, policyLanguage, ASN1_OBJECT), + ASN1_OPT(PROXY_POLICY, policy, + ASN1_OCTET_STRING)} ASN1_SEQUENCE_END(PROXY_POLICY) IMPLEMENT_ASN1_FUNCTIONS(PROXY_POLICY) -ASN1_SEQUENCE(PROXY_CERT_INFO_EXTENSION) = - { - ASN1_OPT(PROXY_CERT_INFO_EXTENSION,pcPathLengthConstraint,ASN1_INTEGER), - ASN1_SIMPLE(PROXY_CERT_INFO_EXTENSION,proxyPolicy,PROXY_POLICY) -} ASN1_SEQUENCE_END(PROXY_CERT_INFO_EXTENSION) +ASN1_SEQUENCE(PROXY_CERT_INFO_EXTENSION) = { + ASN1_OPT(PROXY_CERT_INFO_EXTENSION, pcPathLengthConstraint, ASN1_INTEGER), + ASN1_SIMPLE(PROXY_CERT_INFO_EXTENSION, proxyPolicy, + PROXY_POLICY)} ASN1_SEQUENCE_END(PROXY_CERT_INFO_EXTENSION) IMPLEMENT_ASN1_FUNCTIONS(PROXY_CERT_INFO_EXTENSION) diff --git a/crypto/x509v3/v3_pcons.c b/crypto/x509v3/v3_pcons.c index 5054e2afcb..7ed778b1ac 100644 --- a/crypto/x509v3/v3_pcons.c +++ b/crypto/x509v3/v3_pcons.c @@ -65,75 +65,79 @@ #include #include -static STACK_OF(CONF_VALUE) *i2v_POLICY_CONSTRAINTS(const X509V3_EXT_METHOD - *method, void *bcons, STACK_OF(CONF_VALUE) - *extlist); +static STACK_OF(CONF_VALUE) *i2v_POLICY_CONSTRAINTS( + const X509V3_EXT_METHOD *method, void *bcons, + STACK_OF(CONF_VALUE) *extlist); static void *v2i_POLICY_CONSTRAINTS(const X509V3_EXT_METHOD *method, X509V3_CTX *ctx, STACK_OF(CONF_VALUE) *values); const X509V3_EXT_METHOD v3_policy_constraints = { - NID_policy_constraints, 0, + NID_policy_constraints, + 0, ASN1_ITEM_ref(POLICY_CONSTRAINTS), - 0, 0, 0, 0, - 0, 0, + 0, + 0, + 0, + 0, + 0, + 0, i2v_POLICY_CONSTRAINTS, v2i_POLICY_CONSTRAINTS, - NULL, NULL, - NULL -}; + NULL, + NULL, + NULL}; ASN1_SEQUENCE(POLICY_CONSTRAINTS) = { - ASN1_IMP_OPT(POLICY_CONSTRAINTS, requireExplicitPolicy, ASN1_INTEGER,0), - ASN1_IMP_OPT(POLICY_CONSTRAINTS, inhibitPolicyMapping, ASN1_INTEGER,1), + ASN1_IMP_OPT(POLICY_CONSTRAINTS, requireExplicitPolicy, ASN1_INTEGER, 0), + ASN1_IMP_OPT(POLICY_CONSTRAINTS, inhibitPolicyMapping, ASN1_INTEGER, 1), } ASN1_SEQUENCE_END(POLICY_CONSTRAINTS) IMPLEMENT_ASN1_ALLOC_FUNCTIONS(POLICY_CONSTRAINTS) -static STACK_OF(CONF_VALUE) *i2v_POLICY_CONSTRAINTS(const X509V3_EXT_METHOD - *method, void *a, STACK_OF(CONF_VALUE) - *extlist) -{ - POLICY_CONSTRAINTS *pcons = a; - X509V3_add_value_int("Require Explicit Policy", - pcons->requireExplicitPolicy, &extlist); - X509V3_add_value_int("Inhibit Policy Mapping", - pcons->inhibitPolicyMapping, &extlist); - return extlist; +static STACK_OF(CONF_VALUE) *i2v_POLICY_CONSTRAINTS( + const X509V3_EXT_METHOD *method, void *a, STACK_OF(CONF_VALUE) *extlist) { + POLICY_CONSTRAINTS *pcons = a; + X509V3_add_value_int("Require Explicit Policy", pcons->requireExplicitPolicy, + &extlist); + X509V3_add_value_int("Inhibit Policy Mapping", pcons->inhibitPolicyMapping, + &extlist); + return extlist; } static void *v2i_POLICY_CONSTRAINTS(const X509V3_EXT_METHOD *method, X509V3_CTX *ctx, - STACK_OF(CONF_VALUE) *values) -{ - POLICY_CONSTRAINTS *pcons = NULL; - CONF_VALUE *val; - size_t i; - if (!(pcons = POLICY_CONSTRAINTS_new())) { - OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE); - return NULL; - } - for (i = 0; i < sk_CONF_VALUE_num(values); i++) { - val = sk_CONF_VALUE_value(values, i); - if (!strcmp(val->name, "requireExplicitPolicy")) { - if (!X509V3_get_value_int(val, &pcons->requireExplicitPolicy)) - goto err; - } else if (!strcmp(val->name, "inhibitPolicyMapping")) { - if (!X509V3_get_value_int(val, &pcons->inhibitPolicyMapping)) - goto err; - } else { - OPENSSL_PUT_ERROR(X509V3, X509V3_R_INVALID_NAME); - X509V3_conf_err(val); - goto err; - } - } - if (!pcons->inhibitPolicyMapping && !pcons->requireExplicitPolicy) { - OPENSSL_PUT_ERROR(X509V3, X509V3_R_ILLEGAL_EMPTY_EXTENSION); + STACK_OF(CONF_VALUE) *values) { + POLICY_CONSTRAINTS *pcons = NULL; + CONF_VALUE *val; + size_t i; + if (!(pcons = POLICY_CONSTRAINTS_new())) { + OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE); + return NULL; + } + for (i = 0; i < sk_CONF_VALUE_num(values); i++) { + val = sk_CONF_VALUE_value(values, i); + if (!strcmp(val->name, "requireExplicitPolicy")) { + if (!X509V3_get_value_int(val, &pcons->requireExplicitPolicy)) { goto err; + } + } else if (!strcmp(val->name, "inhibitPolicyMapping")) { + if (!X509V3_get_value_int(val, &pcons->inhibitPolicyMapping)) { + goto err; + } + } else { + OPENSSL_PUT_ERROR(X509V3, X509V3_R_INVALID_NAME); + X509V3_conf_err(val); + goto err; } + } + if (!pcons->inhibitPolicyMapping && !pcons->requireExplicitPolicy) { + OPENSSL_PUT_ERROR(X509V3, X509V3_R_ILLEGAL_EMPTY_EXTENSION); + goto err; + } - return pcons; - err: - POLICY_CONSTRAINTS_free(pcons); - return NULL; + return pcons; +err: + POLICY_CONSTRAINTS_free(pcons); + return NULL; } diff --git a/crypto/x509v3/v3_pmaps.c b/crypto/x509v3/v3_pmaps.c index c26510ed43..02f971650c 100644 --- a/crypto/x509v3/v3_pmaps.c +++ b/crypto/x509v3/v3_pmaps.c @@ -65,90 +65,91 @@ static void *v2i_POLICY_MAPPINGS(const X509V3_EXT_METHOD *method, X509V3_CTX *ctx, STACK_OF(CONF_VALUE) *nval); -static STACK_OF(CONF_VALUE) *i2v_POLICY_MAPPINGS(const X509V3_EXT_METHOD - *method, void *pmps, STACK_OF(CONF_VALUE) - *extlist); +static STACK_OF(CONF_VALUE) *i2v_POLICY_MAPPINGS( + const X509V3_EXT_METHOD *method, void *pmps, STACK_OF(CONF_VALUE) *extlist); const X509V3_EXT_METHOD v3_policy_mappings = { - NID_policy_mappings, 0, + NID_policy_mappings, + 0, ASN1_ITEM_ref(POLICY_MAPPINGS), - 0, 0, 0, 0, - 0, 0, + 0, + 0, + 0, + 0, + 0, + 0, i2v_POLICY_MAPPINGS, v2i_POLICY_MAPPINGS, - 0, 0, + 0, + 0, NULL, }; ASN1_SEQUENCE(POLICY_MAPPING) = { - ASN1_SIMPLE(POLICY_MAPPING, issuerDomainPolicy, ASN1_OBJECT), - ASN1_SIMPLE(POLICY_MAPPING, subjectDomainPolicy, ASN1_OBJECT), + ASN1_SIMPLE(POLICY_MAPPING, issuerDomainPolicy, ASN1_OBJECT), + ASN1_SIMPLE(POLICY_MAPPING, subjectDomainPolicy, ASN1_OBJECT), } ASN1_SEQUENCE_END(POLICY_MAPPING) -ASN1_ITEM_TEMPLATE(POLICY_MAPPINGS) = - ASN1_EX_TEMPLATE_TYPE(ASN1_TFLG_SEQUENCE_OF, 0, POLICY_MAPPINGS, - POLICY_MAPPING) +ASN1_ITEM_TEMPLATE(POLICY_MAPPINGS) = ASN1_EX_TEMPLATE_TYPE( + ASN1_TFLG_SEQUENCE_OF, 0, POLICY_MAPPINGS, POLICY_MAPPING) ASN1_ITEM_TEMPLATE_END(POLICY_MAPPINGS) IMPLEMENT_ASN1_ALLOC_FUNCTIONS(POLICY_MAPPING) -static STACK_OF(CONF_VALUE) *i2v_POLICY_MAPPINGS(const X509V3_EXT_METHOD - *method, void *a, STACK_OF(CONF_VALUE) - *ext_list) -{ - POLICY_MAPPINGS *pmaps = a; - POLICY_MAPPING *pmap; - size_t i; - char obj_tmp1[80]; - char obj_tmp2[80]; - for (i = 0; i < sk_POLICY_MAPPING_num(pmaps); i++) { - pmap = sk_POLICY_MAPPING_value(pmaps, i); - i2t_ASN1_OBJECT(obj_tmp1, 80, pmap->issuerDomainPolicy); - i2t_ASN1_OBJECT(obj_tmp2, 80, pmap->subjectDomainPolicy); - X509V3_add_value(obj_tmp1, obj_tmp2, &ext_list); - } - return ext_list; +static STACK_OF(CONF_VALUE) *i2v_POLICY_MAPPINGS( + const X509V3_EXT_METHOD *method, void *a, STACK_OF(CONF_VALUE) *ext_list) { + POLICY_MAPPINGS *pmaps = a; + POLICY_MAPPING *pmap; + size_t i; + char obj_tmp1[80]; + char obj_tmp2[80]; + for (i = 0; i < sk_POLICY_MAPPING_num(pmaps); i++) { + pmap = sk_POLICY_MAPPING_value(pmaps, i); + i2t_ASN1_OBJECT(obj_tmp1, 80, pmap->issuerDomainPolicy); + i2t_ASN1_OBJECT(obj_tmp2, 80, pmap->subjectDomainPolicy); + X509V3_add_value(obj_tmp1, obj_tmp2, &ext_list); + } + return ext_list; } static void *v2i_POLICY_MAPPINGS(const X509V3_EXT_METHOD *method, - X509V3_CTX *ctx, STACK_OF(CONF_VALUE) *nval) -{ - POLICY_MAPPINGS *pmaps; - POLICY_MAPPING *pmap; - ASN1_OBJECT *obj1, *obj2; - CONF_VALUE *val; - size_t i; + X509V3_CTX *ctx, STACK_OF(CONF_VALUE) *nval) { + POLICY_MAPPINGS *pmaps; + POLICY_MAPPING *pmap; + ASN1_OBJECT *obj1, *obj2; + CONF_VALUE *val; + size_t i; - if (!(pmaps = sk_POLICY_MAPPING_new_null())) { - OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE); - return NULL; - } + if (!(pmaps = sk_POLICY_MAPPING_new_null())) { + OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE); + return NULL; + } - for (i = 0; i < sk_CONF_VALUE_num(nval); i++) { - val = sk_CONF_VALUE_value(nval, i); - if (!val->value || !val->name) { - sk_POLICY_MAPPING_pop_free(pmaps, POLICY_MAPPING_free); - OPENSSL_PUT_ERROR(X509V3, X509V3_R_INVALID_OBJECT_IDENTIFIER); - X509V3_conf_err(val); - return NULL; - } - obj1 = OBJ_txt2obj(val->name, 0); - obj2 = OBJ_txt2obj(val->value, 0); - if (!obj1 || !obj2) { - sk_POLICY_MAPPING_pop_free(pmaps, POLICY_MAPPING_free); - OPENSSL_PUT_ERROR(X509V3, X509V3_R_INVALID_OBJECT_IDENTIFIER); - X509V3_conf_err(val); - return NULL; - } - pmap = POLICY_MAPPING_new(); - if (!pmap) { - sk_POLICY_MAPPING_pop_free(pmaps, POLICY_MAPPING_free); - OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE); - return NULL; - } - pmap->issuerDomainPolicy = obj1; - pmap->subjectDomainPolicy = obj2; - sk_POLICY_MAPPING_push(pmaps, pmap); + for (i = 0; i < sk_CONF_VALUE_num(nval); i++) { + val = sk_CONF_VALUE_value(nval, i); + if (!val->value || !val->name) { + sk_POLICY_MAPPING_pop_free(pmaps, POLICY_MAPPING_free); + OPENSSL_PUT_ERROR(X509V3, X509V3_R_INVALID_OBJECT_IDENTIFIER); + X509V3_conf_err(val); + return NULL; + } + obj1 = OBJ_txt2obj(val->name, 0); + obj2 = OBJ_txt2obj(val->value, 0); + if (!obj1 || !obj2) { + sk_POLICY_MAPPING_pop_free(pmaps, POLICY_MAPPING_free); + OPENSSL_PUT_ERROR(X509V3, X509V3_R_INVALID_OBJECT_IDENTIFIER); + X509V3_conf_err(val); + return NULL; + } + pmap = POLICY_MAPPING_new(); + if (!pmap) { + sk_POLICY_MAPPING_pop_free(pmaps, POLICY_MAPPING_free); + OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE); + return NULL; } - return pmaps; + pmap->issuerDomainPolicy = obj1; + pmap->subjectDomainPolicy = obj2; + sk_POLICY_MAPPING_push(pmaps, pmap); + } + return pmaps; } diff --git a/crypto/x509v3/v3_prn.c b/crypto/x509v3/v3_prn.c index ee4c482412..ba56c87d4b 100644 --- a/crypto/x509v3/v3_prn.c +++ b/crypto/x509v3/v3_prn.c @@ -66,165 +66,176 @@ /* Extension printing routines */ -static int unknown_ext_print(BIO *out, X509_EXTENSION *ext, - unsigned long flag, int indent, int supported); +static int unknown_ext_print(BIO *out, X509_EXTENSION *ext, unsigned long flag, + int indent, int supported); /* Print out a name+value stack */ void X509V3_EXT_val_prn(BIO *out, STACK_OF(CONF_VALUE) *val, int indent, - int ml) -{ - size_t i; - CONF_VALUE *nval; - if (!val) - return; - if (!ml || !sk_CONF_VALUE_num(val)) { - BIO_printf(out, "%*s", indent, ""); - if (!sk_CONF_VALUE_num(val)) - BIO_puts(out, "\n"); + int ml) { + size_t i; + CONF_VALUE *nval; + if (!val) { + return; + } + if (!ml || !sk_CONF_VALUE_num(val)) { + BIO_printf(out, "%*s", indent, ""); + if (!sk_CONF_VALUE_num(val)) { + BIO_puts(out, "\n"); } - for (i = 0; i < sk_CONF_VALUE_num(val); i++) { - if (ml) - BIO_printf(out, "%*s", indent, ""); - else if (i > 0) - BIO_printf(out, ", "); - nval = sk_CONF_VALUE_value(val, i); - if (!nval->name) - BIO_puts(out, nval->value); - else if (!nval->value) - BIO_puts(out, nval->name); - else - BIO_printf(out, "%s:%s", nval->name, nval->value); - if (ml) - BIO_puts(out, "\n"); + } + for (i = 0; i < sk_CONF_VALUE_num(val); i++) { + if (ml) { + BIO_printf(out, "%*s", indent, ""); + } else if (i > 0) { + BIO_printf(out, ", "); } + nval = sk_CONF_VALUE_value(val, i); + if (!nval->name) { + BIO_puts(out, nval->value); + } else if (!nval->value) { + BIO_puts(out, nval->name); + } else { + BIO_printf(out, "%s:%s", nval->name, nval->value); + } + if (ml) { + BIO_puts(out, "\n"); + } + } } /* Main routine: print out a general extension */ int X509V3_EXT_print(BIO *out, X509_EXTENSION *ext, unsigned long flag, - int indent) -{ - void *ext_str = NULL; - char *value = NULL; - const X509V3_EXT_METHOD *method; - STACK_OF(CONF_VALUE) *nval = NULL; - int ok = 1; - - if (!(method = X509V3_EXT_get(ext))) - return unknown_ext_print(out, ext, flag, indent, 0); - const ASN1_STRING *ext_data = X509_EXTENSION_get_data(ext); - const unsigned char *p = ASN1_STRING_get0_data(ext_data); - if (method->it) { - ext_str = ASN1_item_d2i(NULL, &p, ASN1_STRING_length(ext_data), - ASN1_ITEM_ptr(method->it)); - } else { - ext_str = method->d2i(NULL, &p, ASN1_STRING_length(ext_data)); + int indent) { + void *ext_str = NULL; + char *value = NULL; + const X509V3_EXT_METHOD *method; + STACK_OF(CONF_VALUE) *nval = NULL; + int ok = 1; + + if (!(method = X509V3_EXT_get(ext))) { + return unknown_ext_print(out, ext, flag, indent, 0); + } + const ASN1_STRING *ext_data = X509_EXTENSION_get_data(ext); + const unsigned char *p = ASN1_STRING_get0_data(ext_data); + if (method->it) { + ext_str = ASN1_item_d2i(NULL, &p, ASN1_STRING_length(ext_data), + ASN1_ITEM_ptr(method->it)); + } else { + ext_str = method->d2i(NULL, &p, ASN1_STRING_length(ext_data)); + } + + if (!ext_str) { + return unknown_ext_print(out, ext, flag, indent, 1); + } + + if (method->i2s) { + if (!(value = method->i2s(method, ext_str))) { + ok = 0; + goto err; } - - if (!ext_str) - return unknown_ext_print(out, ext, flag, indent, 1); - - if (method->i2s) { - if (!(value = method->i2s(method, ext_str))) { - ok = 0; - goto err; - } - BIO_printf(out, "%*s%s", indent, "", value); - } else if (method->i2v) { - if (!(nval = method->i2v(method, ext_str, NULL))) { - ok = 0; - goto err; - } - X509V3_EXT_val_prn(out, nval, indent, - method->ext_flags & X509V3_EXT_MULTILINE); - } else if (method->i2r) { - if (!method->i2r(method, ext_str, out, indent)) - ok = 0; - } else - ok = 0; - - err: - sk_CONF_VALUE_pop_free(nval, X509V3_conf_free); - if (value) - OPENSSL_free(value); - if (method->it) - ASN1_item_free(ext_str, ASN1_ITEM_ptr(method->it)); - else - method->ext_free(ext_str); - return ok; + BIO_printf(out, "%*s%s", indent, "", value); + } else if (method->i2v) { + if (!(nval = method->i2v(method, ext_str, NULL))) { + ok = 0; + goto err; + } + X509V3_EXT_val_prn(out, nval, indent, + method->ext_flags & X509V3_EXT_MULTILINE); + } else if (method->i2r) { + if (!method->i2r(method, ext_str, out, indent)) { + ok = 0; + } + } else { + ok = 0; + } + +err: + sk_CONF_VALUE_pop_free(nval, X509V3_conf_free); + if (value) { + OPENSSL_free(value); + } + if (method->it) { + ASN1_item_free(ext_str, ASN1_ITEM_ptr(method->it)); + } else { + method->ext_free(ext_str); + } + return ok; } int X509V3_extensions_print(BIO *bp, const char *title, const STACK_OF(X509_EXTENSION) *exts, - unsigned long flag, int indent) -{ - size_t i; - int j; - - if (sk_X509_EXTENSION_num(exts) <= 0) - return 1; + unsigned long flag, int indent) { + size_t i; + int j; - if (title) { - BIO_printf(bp, "%*s%s:\n", indent, "", title); - indent += 4; + if (sk_X509_EXTENSION_num(exts) <= 0) { + return 1; + } + + if (title) { + BIO_printf(bp, "%*s%s:\n", indent, "", title); + indent += 4; + } + + for (i = 0; i < sk_X509_EXTENSION_num(exts); i++) { + ASN1_OBJECT *obj; + X509_EXTENSION *ex; + ex = sk_X509_EXTENSION_value(exts, i); + if (indent && BIO_printf(bp, "%*s", indent, "") <= 0) { + return 0; } - - for (i = 0; i < sk_X509_EXTENSION_num(exts); i++) { - ASN1_OBJECT *obj; - X509_EXTENSION *ex; - ex = sk_X509_EXTENSION_value(exts, i); - if (indent && BIO_printf(bp, "%*s", indent, "") <= 0) - return 0; - obj = X509_EXTENSION_get_object(ex); - i2a_ASN1_OBJECT(bp, obj); - j = X509_EXTENSION_get_critical(ex); - if (BIO_printf(bp, ": %s\n", j ? "critical" : "") <= 0) - return 0; - if (!X509V3_EXT_print(bp, ex, flag, indent + 4)) { - BIO_printf(bp, "%*s", indent + 4, ""); - ASN1_STRING_print(bp, X509_EXTENSION_get_data(ex)); - } - if (BIO_write(bp, "\n", 1) <= 0) - return 0; + obj = X509_EXTENSION_get_object(ex); + i2a_ASN1_OBJECT(bp, obj); + j = X509_EXTENSION_get_critical(ex); + if (BIO_printf(bp, ": %s\n", j ? "critical" : "") <= 0) { + return 0; } - return 1; + if (!X509V3_EXT_print(bp, ex, flag, indent + 4)) { + BIO_printf(bp, "%*s", indent + 4, ""); + ASN1_STRING_print(bp, X509_EXTENSION_get_data(ex)); + } + if (BIO_write(bp, "\n", 1) <= 0) { + return 0; + } + } + return 1; } -static int unknown_ext_print(BIO *out, X509_EXTENSION *ext, - unsigned long flag, int indent, int supported) -{ - switch (flag & X509V3_EXT_UNKNOWN_MASK) { - +static int unknown_ext_print(BIO *out, X509_EXTENSION *ext, unsigned long flag, + int indent, int supported) { + switch (flag & X509V3_EXT_UNKNOWN_MASK) { case X509V3_EXT_DEFAULT: - return 0; + return 0; case X509V3_EXT_ERROR_UNKNOWN: - if (supported) - BIO_printf(out, "%*s", indent, ""); - else - BIO_printf(out, "%*s", indent, ""); - return 1; + if (supported) { + BIO_printf(out, "%*s", indent, ""); + } else { + BIO_printf(out, "%*s", indent, ""); + } + return 1; case X509V3_EXT_PARSE_UNKNOWN: case X509V3_EXT_DUMP_UNKNOWN: { - const ASN1_STRING *data = X509_EXTENSION_get_data(ext); - return BIO_hexdump(out, ASN1_STRING_get0_data(data), - ASN1_STRING_length(data), indent); + const ASN1_STRING *data = X509_EXTENSION_get_data(ext); + return BIO_hexdump(out, ASN1_STRING_get0_data(data), + ASN1_STRING_length(data), indent); } default: - return 1; - } + return 1; + } } -int X509V3_EXT_print_fp(FILE *fp, X509_EXTENSION *ext, int flag, int indent) -{ - BIO *bio_tmp; - int ret; - if (!(bio_tmp = BIO_new_fp(fp, BIO_NOCLOSE))) - return 0; - ret = X509V3_EXT_print(bio_tmp, ext, flag, indent); - BIO_free(bio_tmp); - return ret; +int X509V3_EXT_print_fp(FILE *fp, X509_EXTENSION *ext, int flag, int indent) { + BIO *bio_tmp; + int ret; + if (!(bio_tmp = BIO_new_fp(fp, BIO_NOCLOSE))) { + return 0; + } + ret = X509V3_EXT_print(bio_tmp, ext, flag, indent); + BIO_free(bio_tmp); + return ret; } diff --git a/crypto/x509v3/v3_purp.c b/crypto/x509v3/v3_purp.c index 909a8dbf31..0b51a07ddd 100644 --- a/crypto/x509v3/v3_purp.c +++ b/crypto/x509v3/v3_purp.c @@ -59,8 +59,8 @@ #include -#include #include +#include #include #include #include @@ -70,13 +70,13 @@ #include "../x509/internal.h" #include "internal.h" -#define V1_ROOT (EXFLAG_V1|EXFLAG_SS) +#define V1_ROOT (EXFLAG_V1 | EXFLAG_SS) #define ku_reject(x, usage) \ - (((x)->ex_flags & EXFLAG_KUSAGE) && !((x)->ex_kusage & (usage))) + (((x)->ex_flags & EXFLAG_KUSAGE) && !((x)->ex_kusage & (usage))) #define xku_reject(x, usage) \ - (((x)->ex_flags & EXFLAG_XKUSAGE) && !((x)->ex_xkusage & (usage))) + (((x)->ex_flags & EXFLAG_XKUSAGE) && !((x)->ex_xkusage & (usage))) #define ns_reject(x, usage) \ - (((x)->ex_flags & EXFLAG_NSCERT) && !((x)->ex_nscert & (usage))) + (((x)->ex_flags & EXFLAG_NSCERT) && !((x)->ex_nscert & (usage))) static int check_purpose_ssl_client(const X509_PURPOSE *xp, const X509 *x, int ca); @@ -101,11 +101,9 @@ static void xptable_free(X509_PURPOSE *p); static X509_PURPOSE xstandard[] = { {X509_PURPOSE_SSL_CLIENT, X509_TRUST_SSL_CLIENT, 0, - check_purpose_ssl_client, (char *)"SSL client", (char *)"sslclient", - NULL}, + check_purpose_ssl_client, (char *)"SSL client", (char *)"sslclient", NULL}, {X509_PURPOSE_SSL_SERVER, X509_TRUST_SSL_SERVER, 0, - check_purpose_ssl_server, (char *)"SSL server", (char *)"sslserver", - NULL}, + check_purpose_ssl_server, (char *)"SSL server", (char *)"sslserver", NULL}, {X509_PURPOSE_NS_SSL_SERVER, X509_TRUST_SSL_SERVER, 0, check_purpose_ns_ssl_server, (char *)"Netscape SSL server", (char *)"nssslserver", NULL}, @@ -125,13 +123,12 @@ static X509_PURPOSE xstandard[] = { (char *)"timestampsign", NULL}, }; -#define X509_PURPOSE_COUNT (sizeof(xstandard)/sizeof(X509_PURPOSE)) +#define X509_PURPOSE_COUNT (sizeof(xstandard) / sizeof(X509_PURPOSE)) static STACK_OF(X509_PURPOSE) *xptable = NULL; -static int xp_cmp(const X509_PURPOSE **a, const X509_PURPOSE **b) -{ - return (*a)->purpose - (*b)->purpose; +static int xp_cmp(const X509_PURPOSE **a, const X509_PURPOSE **b) { + return (*a)->purpose - (*b)->purpose; } /* @@ -139,504 +136,509 @@ static int xp_cmp(const X509_PURPOSE **a, const X509_PURPOSE **b) * really can't because it does recalculate hashes and do other non-const * things. */ -int X509_check_purpose(X509 *x, int id, int ca) -{ - int idx; - const X509_PURPOSE *pt; - if (!x509v3_cache_extensions(x)) { - return -1; - } +int X509_check_purpose(X509 *x, int id, int ca) { + int idx; + const X509_PURPOSE *pt; + if (!x509v3_cache_extensions(x)) { + return -1; + } - if (id == -1) - return 1; - idx = X509_PURPOSE_get_by_id(id); - if (idx == -1) - return -1; - pt = X509_PURPOSE_get0(idx); - return pt->check_purpose(pt, x, ca); + if (id == -1) { + return 1; + } + idx = X509_PURPOSE_get_by_id(id); + if (idx == -1) { + return -1; + } + pt = X509_PURPOSE_get0(idx); + return pt->check_purpose(pt, x, ca); } -int X509_PURPOSE_set(int *p, int purpose) -{ - if (X509_PURPOSE_get_by_id(purpose) == -1) { - OPENSSL_PUT_ERROR(X509V3, X509V3_R_INVALID_PURPOSE); - return 0; - } - *p = purpose; - return 1; +int X509_PURPOSE_set(int *p, int purpose) { + if (X509_PURPOSE_get_by_id(purpose) == -1) { + OPENSSL_PUT_ERROR(X509V3, X509V3_R_INVALID_PURPOSE); + return 0; + } + *p = purpose; + return 1; } -int X509_PURPOSE_get_count(void) -{ - if (!xptable) - return X509_PURPOSE_COUNT; - return sk_X509_PURPOSE_num(xptable) + X509_PURPOSE_COUNT; +int X509_PURPOSE_get_count(void) { + if (!xptable) { + return X509_PURPOSE_COUNT; + } + return sk_X509_PURPOSE_num(xptable) + X509_PURPOSE_COUNT; } -X509_PURPOSE *X509_PURPOSE_get0(int idx) -{ - if (idx < 0) - return NULL; - if (idx < (int)X509_PURPOSE_COUNT) - return xstandard + idx; - return sk_X509_PURPOSE_value(xptable, idx - X509_PURPOSE_COUNT); +X509_PURPOSE *X509_PURPOSE_get0(int idx) { + if (idx < 0) { + return NULL; + } + if (idx < (int)X509_PURPOSE_COUNT) { + return xstandard + idx; + } + return sk_X509_PURPOSE_value(xptable, idx - X509_PURPOSE_COUNT); } -int X509_PURPOSE_get_by_sname(char *sname) -{ - int i; - X509_PURPOSE *xptmp; - for (i = 0; i < X509_PURPOSE_get_count(); i++) { - xptmp = X509_PURPOSE_get0(i); - if (!strcmp(xptmp->sname, sname)) - return i; +int X509_PURPOSE_get_by_sname(char *sname) { + int i; + X509_PURPOSE *xptmp; + for (i = 0; i < X509_PURPOSE_get_count(); i++) { + xptmp = X509_PURPOSE_get0(i); + if (!strcmp(xptmp->sname, sname)) { + return i; } - return -1; + } + return -1; } -int X509_PURPOSE_get_by_id(int purpose) -{ - X509_PURPOSE tmp; - size_t idx; +int X509_PURPOSE_get_by_id(int purpose) { + X509_PURPOSE tmp; + size_t idx; - if ((purpose >= X509_PURPOSE_MIN) && (purpose <= X509_PURPOSE_MAX)) - return purpose - X509_PURPOSE_MIN; - tmp.purpose = purpose; - if (!xptable) - return -1; + if ((purpose >= X509_PURPOSE_MIN) && (purpose <= X509_PURPOSE_MAX)) { + return purpose - X509_PURPOSE_MIN; + } + tmp.purpose = purpose; + if (!xptable) { + return -1; + } - sk_X509_PURPOSE_sort(xptable); - if (!sk_X509_PURPOSE_find(xptable, &idx, &tmp)) - return -1; - return idx + X509_PURPOSE_COUNT; + sk_X509_PURPOSE_sort(xptable); + if (!sk_X509_PURPOSE_find(xptable, &idx, &tmp)) { + return -1; + } + return idx + X509_PURPOSE_COUNT; } int X509_PURPOSE_add(int id, int trust, int flags, - int (*ck) (const X509_PURPOSE *, const X509 *, int), - char *name, char *sname, void *arg) -{ - int idx; - X509_PURPOSE *ptmp; - char *name_dup, *sname_dup; - - /* - * This is set according to what we change: application can't set it - */ - flags &= ~X509_PURPOSE_DYNAMIC; - /* This will always be set for application modified trust entries */ - flags |= X509_PURPOSE_DYNAMIC_NAME; - /* Get existing entry if any */ - idx = X509_PURPOSE_get_by_id(id); - /* Need a new entry */ - if (idx == -1) { - if (!(ptmp = OPENSSL_malloc(sizeof(X509_PURPOSE)))) { - OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE); - return 0; - } - ptmp->flags = X509_PURPOSE_DYNAMIC; - } else - ptmp = X509_PURPOSE_get0(idx); - - /* Duplicate the supplied names. */ - name_dup = OPENSSL_strdup(name); - sname_dup = OPENSSL_strdup(sname); - if (name_dup == NULL || sname_dup == NULL) { - OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE); - if (name_dup != NULL) - OPENSSL_free(name_dup); - if (sname_dup != NULL) - OPENSSL_free(sname_dup); - if (idx == -1) - OPENSSL_free(ptmp); - return 0; - } - - /* OPENSSL_free existing name if dynamic */ - if (ptmp->flags & X509_PURPOSE_DYNAMIC_NAME) { - OPENSSL_free(ptmp->name); - OPENSSL_free(ptmp->sname); + int (*ck)(const X509_PURPOSE *, const X509 *, int), + char *name, char *sname, void *arg) { + int idx; + X509_PURPOSE *ptmp; + char *name_dup, *sname_dup; + + /* + * This is set according to what we change: application can't set it + */ + flags &= ~X509_PURPOSE_DYNAMIC; + /* This will always be set for application modified trust entries */ + flags |= X509_PURPOSE_DYNAMIC_NAME; + /* Get existing entry if any */ + idx = X509_PURPOSE_get_by_id(id); + /* Need a new entry */ + if (idx == -1) { + if (!(ptmp = OPENSSL_malloc(sizeof(X509_PURPOSE)))) { + OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE); + return 0; + } + ptmp->flags = X509_PURPOSE_DYNAMIC; + } else { + ptmp = X509_PURPOSE_get0(idx); + } + + /* Duplicate the supplied names. */ + name_dup = OPENSSL_strdup(name); + sname_dup = OPENSSL_strdup(sname); + if (name_dup == NULL || sname_dup == NULL) { + OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE); + if (name_dup != NULL) { + OPENSSL_free(name_dup); + } + if (sname_dup != NULL) { + OPENSSL_free(sname_dup); } - /* dup supplied name */ - ptmp->name = name_dup; - ptmp->sname = sname_dup; - /* Keep the dynamic flag of existing entry */ - ptmp->flags &= X509_PURPOSE_DYNAMIC; - /* Set all other flags */ - ptmp->flags |= flags; - - ptmp->purpose = id; - ptmp->trust = trust; - ptmp->check_purpose = ck; - ptmp->usr_data = arg; - - /* If its a new entry manage the dynamic table */ if (idx == -1) { - if (!xptable && !(xptable = sk_X509_PURPOSE_new(xp_cmp))) { - OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE); - xptable_free(ptmp); - return 0; - } - if (!sk_X509_PURPOSE_push(xptable, ptmp)) { - OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE); - xptable_free(ptmp); - return 0; - } + OPENSSL_free(ptmp); } - return 1; -} - -static void xptable_free(X509_PURPOSE *p) -{ - if (!p) - return; - if (p->flags & X509_PURPOSE_DYNAMIC) { - if (p->flags & X509_PURPOSE_DYNAMIC_NAME) { - OPENSSL_free(p->name); - OPENSSL_free(p->sname); - } - OPENSSL_free(p); - } -} - -void X509_PURPOSE_cleanup(void) -{ - unsigned int i; - sk_X509_PURPOSE_pop_free(xptable, xptable_free); - for (i = 0; i < X509_PURPOSE_COUNT; i++) - xptable_free(xstandard + i); - xptable = NULL; -} - -int X509_PURPOSE_get_id(const X509_PURPOSE *xp) -{ - return xp->purpose; -} - -char *X509_PURPOSE_get0_name(const X509_PURPOSE *xp) -{ - return xp->name; -} - -char *X509_PURPOSE_get0_sname(const X509_PURPOSE *xp) -{ - return xp->sname; -} - -int X509_PURPOSE_get_trust(const X509_PURPOSE *xp) -{ - return xp->trust; -} - -static int nid_cmp(const void *void_a, const void *void_b) -{ - const int *a = void_a, *b = void_b; - - return *a - *b; -} - -int X509_supported_extension(X509_EXTENSION *ex) -{ - /* - * This table is a list of the NIDs of supported extensions: that is - * those which are used by the verify process. If an extension is - * critical and doesn't appear in this list then the verify process will - * normally reject the certificate. The list must be kept in numerical - * order because it will be searched using bsearch. - */ - - static const int supported_nids[] = { - NID_netscape_cert_type, /* 71 */ - NID_key_usage, /* 83 */ - NID_subject_alt_name, /* 85 */ - NID_basic_constraints, /* 87 */ - NID_certificate_policies, /* 89 */ - NID_ext_key_usage, /* 126 */ - NID_policy_constraints, /* 401 */ - NID_proxyCertInfo, /* 663 */ - NID_name_constraints, /* 666 */ - NID_policy_mappings, /* 747 */ - NID_inhibit_any_policy /* 748 */ - }; - - int ex_nid = OBJ_obj2nid(X509_EXTENSION_get_object(ex)); - - if (ex_nid == NID_undef) - return 0; - - if (bsearch - (&ex_nid, supported_nids, sizeof(supported_nids) / sizeof(int), - sizeof(int), nid_cmp) != NULL) - return 1; return 0; -} - -static int setup_dp(X509 *x, DIST_POINT *dp) -{ - X509_NAME *iname = NULL; - size_t i; - if (dp->reasons) { - if (dp->reasons->length > 0) - dp->dp_reasons = dp->reasons->data[0]; - if (dp->reasons->length > 1) - dp->dp_reasons |= (dp->reasons->data[1] << 8); - dp->dp_reasons &= CRLDP_ALL_REASONS; - } else - dp->dp_reasons = CRLDP_ALL_REASONS; - if (!dp->distpoint || (dp->distpoint->type != 1)) - return 1; - for (i = 0; i < sk_GENERAL_NAME_num(dp->CRLissuer); i++) { - GENERAL_NAME *gen = sk_GENERAL_NAME_value(dp->CRLissuer, i); - if (gen->type == GEN_DIRNAME) { - iname = gen->d.directoryName; - break; - } - } - if (!iname) - iname = X509_get_issuer_name(x); - - return DIST_POINT_set_dpname(dp->distpoint, iname); -} + } + + /* OPENSSL_free existing name if dynamic */ + if (ptmp->flags & X509_PURPOSE_DYNAMIC_NAME) { + OPENSSL_free(ptmp->name); + OPENSSL_free(ptmp->sname); + } + /* dup supplied name */ + ptmp->name = name_dup; + ptmp->sname = sname_dup; + /* Keep the dynamic flag of existing entry */ + ptmp->flags &= X509_PURPOSE_DYNAMIC; + /* Set all other flags */ + ptmp->flags |= flags; + + ptmp->purpose = id; + ptmp->trust = trust; + ptmp->check_purpose = ck; + ptmp->usr_data = arg; + + /* If its a new entry manage the dynamic table */ + if (idx == -1) { + if (!xptable && !(xptable = sk_X509_PURPOSE_new(xp_cmp))) { + OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE); + xptable_free(ptmp); + return 0; + } + if (!sk_X509_PURPOSE_push(xptable, ptmp)) { + OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE); + xptable_free(ptmp); + return 0; + } + } + return 1; +} + +static void xptable_free(X509_PURPOSE *p) { + if (!p) { + return; + } + if (p->flags & X509_PURPOSE_DYNAMIC) { + if (p->flags & X509_PURPOSE_DYNAMIC_NAME) { + OPENSSL_free(p->name); + OPENSSL_free(p->sname); + } + OPENSSL_free(p); + } +} + +void X509_PURPOSE_cleanup(void) { + unsigned int i; + sk_X509_PURPOSE_pop_free(xptable, xptable_free); + for (i = 0; i < X509_PURPOSE_COUNT; i++) { + xptable_free(xstandard + i); + } + xptable = NULL; +} + +int X509_PURPOSE_get_id(const X509_PURPOSE *xp) { return xp->purpose; } + +char *X509_PURPOSE_get0_name(const X509_PURPOSE *xp) { return xp->name; } + +char *X509_PURPOSE_get0_sname(const X509_PURPOSE *xp) { return xp->sname; } + +int X509_PURPOSE_get_trust(const X509_PURPOSE *xp) { return xp->trust; } + +static int nid_cmp(const void *void_a, const void *void_b) { + const int *a = void_a, *b = void_b; + + return *a - *b; +} + +int X509_supported_extension(X509_EXTENSION *ex) { + /* + * This table is a list of the NIDs of supported extensions: that is + * those which are used by the verify process. If an extension is + * critical and doesn't appear in this list then the verify process will + * normally reject the certificate. The list must be kept in numerical + * order because it will be searched using bsearch. + */ + + static const int supported_nids[] = { + NID_netscape_cert_type, /* 71 */ + NID_key_usage, /* 83 */ + NID_subject_alt_name, /* 85 */ + NID_basic_constraints, /* 87 */ + NID_certificate_policies, /* 89 */ + NID_ext_key_usage, /* 126 */ + NID_policy_constraints, /* 401 */ + NID_proxyCertInfo, /* 663 */ + NID_name_constraints, /* 666 */ + NID_policy_mappings, /* 747 */ + NID_inhibit_any_policy /* 748 */ + }; + + int ex_nid = OBJ_obj2nid(X509_EXTENSION_get_object(ex)); + + if (ex_nid == NID_undef) { + return 0; + } -static int setup_crldp(X509 *x) -{ - int j; - x->crldp = X509_get_ext_d2i(x, NID_crl_distribution_points, &j, NULL); - if (x->crldp == NULL && j != -1) { - return 0; - } - for (size_t i = 0; i < sk_DIST_POINT_num(x->crldp); i++) { - if (!setup_dp(x, sk_DIST_POINT_value(x->crldp, i))) { - return 0; - } - } + if (bsearch(&ex_nid, supported_nids, sizeof(supported_nids) / sizeof(int), + sizeof(int), nid_cmp) != NULL) { return 1; + } + return 0; } -int x509v3_cache_extensions(X509 *x) -{ - BASIC_CONSTRAINTS *bs; - PROXY_CERT_INFO_EXTENSION *pci; - ASN1_BIT_STRING *usage; - ASN1_BIT_STRING *ns; - EXTENDED_KEY_USAGE *extusage; - X509_EXTENSION *ex; - size_t i; - int j; - - CRYPTO_MUTEX_lock_read(&x->lock); - const int is_set = x->ex_flags & EXFLAG_SET; - CRYPTO_MUTEX_unlock_read(&x->lock); - - if (is_set) { - return (x->ex_flags & EXFLAG_INVALID) == 0; +static int setup_dp(X509 *x, DIST_POINT *dp) { + X509_NAME *iname = NULL; + size_t i; + if (dp->reasons) { + if (dp->reasons->length > 0) { + dp->dp_reasons = dp->reasons->data[0]; } - - CRYPTO_MUTEX_lock_write(&x->lock); - if (x->ex_flags & EXFLAG_SET) { - CRYPTO_MUTEX_unlock_write(&x->lock); - return (x->ex_flags & EXFLAG_INVALID) == 0; + if (dp->reasons->length > 1) { + dp->dp_reasons |= (dp->reasons->data[1] << 8); } - - if (!X509_digest(x, EVP_sha256(), x->cert_hash, NULL)) - x->ex_flags |= EXFLAG_INVALID; - /* V1 should mean no extensions ... */ - if (X509_get_version(x) == X509_VERSION_1) - x->ex_flags |= EXFLAG_V1; - /* Handle basic constraints */ - if ((bs = X509_get_ext_d2i(x, NID_basic_constraints, &j, NULL))) { - if (bs->ca) - x->ex_flags |= EXFLAG_CA; - if (bs->pathlen) { - if ((bs->pathlen->type == V_ASN1_NEG_INTEGER) - || !bs->ca) { - x->ex_flags |= EXFLAG_INVALID; - x->ex_pathlen = 0; - } else { - /* TODO(davidben): |ASN1_INTEGER_get| returns -1 on overflow, - * which currently acts as if the constraint isn't present. This - * works (an overflowing path length constraint may as well be - * infinity), but Chromium's verifier simply treats values above - * 255 as an error. */ - x->ex_pathlen = ASN1_INTEGER_get(bs->pathlen); - } - } else - x->ex_pathlen = -1; - BASIC_CONSTRAINTS_free(bs); - x->ex_flags |= EXFLAG_BCONS; - } else if (j != -1) { - x->ex_flags |= EXFLAG_INVALID; - } - /* Handle proxy certificates */ - if ((pci = X509_get_ext_d2i(x, NID_proxyCertInfo, &j, NULL))) { - if (x->ex_flags & EXFLAG_CA - || X509_get_ext_by_NID(x, NID_subject_alt_name, -1) >= 0 - || X509_get_ext_by_NID(x, NID_issuer_alt_name, -1) >= 0) { - x->ex_flags |= EXFLAG_INVALID; - } - if (pci->pcPathLengthConstraint) { - x->ex_pcpathlen = ASN1_INTEGER_get(pci->pcPathLengthConstraint); - } else - x->ex_pcpathlen = -1; - PROXY_CERT_INFO_EXTENSION_free(pci); - x->ex_flags |= EXFLAG_PROXY; - } else if (j != -1) { - x->ex_flags |= EXFLAG_INVALID; - } - /* Handle key usage */ - if ((usage = X509_get_ext_d2i(x, NID_key_usage, &j, NULL))) { - if (usage->length > 0) { - x->ex_kusage = usage->data[0]; - if (usage->length > 1) - x->ex_kusage |= usage->data[1] << 8; - } else - x->ex_kusage = 0; - x->ex_flags |= EXFLAG_KUSAGE; - ASN1_BIT_STRING_free(usage); - } else if (j != -1) { - x->ex_flags |= EXFLAG_INVALID; - } - x->ex_xkusage = 0; - if ((extusage = X509_get_ext_d2i(x, NID_ext_key_usage, &j, NULL))) { - x->ex_flags |= EXFLAG_XKUSAGE; - for (i = 0; i < sk_ASN1_OBJECT_num(extusage); i++) { - switch (OBJ_obj2nid(sk_ASN1_OBJECT_value(extusage, i))) { - case NID_server_auth: - x->ex_xkusage |= XKU_SSL_SERVER; - break; - - case NID_client_auth: - x->ex_xkusage |= XKU_SSL_CLIENT; - break; - - case NID_email_protect: - x->ex_xkusage |= XKU_SMIME; - break; - - case NID_code_sign: - x->ex_xkusage |= XKU_CODE_SIGN; - break; - - case NID_ms_sgc: - case NID_ns_sgc: - x->ex_xkusage |= XKU_SGC; - break; - - case NID_OCSP_sign: - x->ex_xkusage |= XKU_OCSP_SIGN; - break; - - case NID_time_stamp: - x->ex_xkusage |= XKU_TIMESTAMP; - break; - - case NID_dvcs: - x->ex_xkusage |= XKU_DVCS; - break; - - case NID_anyExtendedKeyUsage: - x->ex_xkusage |= XKU_ANYEKU; - break; - } - } - sk_ASN1_OBJECT_pop_free(extusage, ASN1_OBJECT_free); - } else if (j != -1) { - x->ex_flags |= EXFLAG_INVALID; + dp->dp_reasons &= CRLDP_ALL_REASONS; + } else { + dp->dp_reasons = CRLDP_ALL_REASONS; + } + if (!dp->distpoint || (dp->distpoint->type != 1)) { + return 1; + } + for (i = 0; i < sk_GENERAL_NAME_num(dp->CRLissuer); i++) { + GENERAL_NAME *gen = sk_GENERAL_NAME_value(dp->CRLissuer, i); + if (gen->type == GEN_DIRNAME) { + iname = gen->d.directoryName; + break; } + } + if (!iname) { + iname = X509_get_issuer_name(x); + } - if ((ns = X509_get_ext_d2i(x, NID_netscape_cert_type, &j, NULL))) { - if (ns->length > 0) - x->ex_nscert = ns->data[0]; - else - x->ex_nscert = 0; - x->ex_flags |= EXFLAG_NSCERT; - ASN1_BIT_STRING_free(ns); - } else if (j != -1) { - x->ex_flags |= EXFLAG_INVALID; - } - x->skid = X509_get_ext_d2i(x, NID_subject_key_identifier, &j, NULL); - if (x->skid == NULL && j != -1) { - x->ex_flags |= EXFLAG_INVALID; - } - x->akid = X509_get_ext_d2i(x, NID_authority_key_identifier, &j, NULL); - if (x->akid == NULL && j != -1) { - x->ex_flags |= EXFLAG_INVALID; - } - /* Does subject name match issuer ? */ - if (!X509_NAME_cmp(X509_get_subject_name(x), X509_get_issuer_name(x))) { - x->ex_flags |= EXFLAG_SI; - /* If SKID matches AKID also indicate self signed */ - if (X509_check_akid(x, x->akid) == X509_V_OK && - !ku_reject(x, KU_KEY_CERT_SIGN)) - x->ex_flags |= EXFLAG_SS; - } - x->altname = X509_get_ext_d2i(x, NID_subject_alt_name, &j, NULL); - if (x->altname == NULL && j != -1) { - x->ex_flags |= EXFLAG_INVALID; - } - x->nc = X509_get_ext_d2i(x, NID_name_constraints, &j, NULL); - if (x->nc == NULL && j != -1) { - x->ex_flags |= EXFLAG_INVALID; - } - if (!setup_crldp(x)) { - x->ex_flags |= EXFLAG_INVALID; - } + return DIST_POINT_set_dpname(dp->distpoint, iname); +} - for (j = 0; j < X509_get_ext_count(x); j++) { - ex = X509_get_ext(x, j); - if (OBJ_obj2nid(X509_EXTENSION_get_object(ex)) - == NID_freshest_crl) - x->ex_flags |= EXFLAG_FRESHEST; - if (!X509_EXTENSION_get_critical(ex)) - continue; - if (!X509_supported_extension(ex)) { - x->ex_flags |= EXFLAG_CRITICAL; - break; - } - } - x->ex_flags |= EXFLAG_SET; +static int setup_crldp(X509 *x) { + int j; + x->crldp = X509_get_ext_d2i(x, NID_crl_distribution_points, &j, NULL); + if (x->crldp == NULL && j != -1) { + return 0; + } + for (size_t i = 0; i < sk_DIST_POINT_num(x->crldp); i++) { + if (!setup_dp(x, sk_DIST_POINT_value(x->crldp, i))) { + return 0; + } + } + return 1; +} + +int x509v3_cache_extensions(X509 *x) { + BASIC_CONSTRAINTS *bs; + PROXY_CERT_INFO_EXTENSION *pci; + ASN1_BIT_STRING *usage; + ASN1_BIT_STRING *ns; + EXTENDED_KEY_USAGE *extusage; + X509_EXTENSION *ex; + size_t i; + int j; + + CRYPTO_MUTEX_lock_read(&x->lock); + const int is_set = x->ex_flags & EXFLAG_SET; + CRYPTO_MUTEX_unlock_read(&x->lock); + + if (is_set) { + return (x->ex_flags & EXFLAG_INVALID) == 0; + } + CRYPTO_MUTEX_lock_write(&x->lock); + if (x->ex_flags & EXFLAG_SET) { CRYPTO_MUTEX_unlock_write(&x->lock); return (x->ex_flags & EXFLAG_INVALID) == 0; + } + + if (!X509_digest(x, EVP_sha256(), x->cert_hash, NULL)) { + x->ex_flags |= EXFLAG_INVALID; + } + /* V1 should mean no extensions ... */ + if (X509_get_version(x) == X509_VERSION_1) { + x->ex_flags |= EXFLAG_V1; + } + /* Handle basic constraints */ + if ((bs = X509_get_ext_d2i(x, NID_basic_constraints, &j, NULL))) { + if (bs->ca) { + x->ex_flags |= EXFLAG_CA; + } + if (bs->pathlen) { + if ((bs->pathlen->type == V_ASN1_NEG_INTEGER) || !bs->ca) { + x->ex_flags |= EXFLAG_INVALID; + x->ex_pathlen = 0; + } else { + /* TODO(davidben): |ASN1_INTEGER_get| returns -1 on overflow, + * which currently acts as if the constraint isn't present. This + * works (an overflowing path length constraint may as well be + * infinity), but Chromium's verifier simply treats values above + * 255 as an error. */ + x->ex_pathlen = ASN1_INTEGER_get(bs->pathlen); + } + } else { + x->ex_pathlen = -1; + } + BASIC_CONSTRAINTS_free(bs); + x->ex_flags |= EXFLAG_BCONS; + } else if (j != -1) { + x->ex_flags |= EXFLAG_INVALID; + } + /* Handle proxy certificates */ + if ((pci = X509_get_ext_d2i(x, NID_proxyCertInfo, &j, NULL))) { + if (x->ex_flags & EXFLAG_CA || + X509_get_ext_by_NID(x, NID_subject_alt_name, -1) >= 0 || + X509_get_ext_by_NID(x, NID_issuer_alt_name, -1) >= 0) { + x->ex_flags |= EXFLAG_INVALID; + } + if (pci->pcPathLengthConstraint) { + x->ex_pcpathlen = ASN1_INTEGER_get(pci->pcPathLengthConstraint); + } else { + x->ex_pcpathlen = -1; + } + PROXY_CERT_INFO_EXTENSION_free(pci); + x->ex_flags |= EXFLAG_PROXY; + } else if (j != -1) { + x->ex_flags |= EXFLAG_INVALID; + } + /* Handle key usage */ + if ((usage = X509_get_ext_d2i(x, NID_key_usage, &j, NULL))) { + if (usage->length > 0) { + x->ex_kusage = usage->data[0]; + if (usage->length > 1) { + x->ex_kusage |= usage->data[1] << 8; + } + } else { + x->ex_kusage = 0; + } + x->ex_flags |= EXFLAG_KUSAGE; + ASN1_BIT_STRING_free(usage); + } else if (j != -1) { + x->ex_flags |= EXFLAG_INVALID; + } + x->ex_xkusage = 0; + if ((extusage = X509_get_ext_d2i(x, NID_ext_key_usage, &j, NULL))) { + x->ex_flags |= EXFLAG_XKUSAGE; + for (i = 0; i < sk_ASN1_OBJECT_num(extusage); i++) { + switch (OBJ_obj2nid(sk_ASN1_OBJECT_value(extusage, i))) { + case NID_server_auth: + x->ex_xkusage |= XKU_SSL_SERVER; + break; + + case NID_client_auth: + x->ex_xkusage |= XKU_SSL_CLIENT; + break; + + case NID_email_protect: + x->ex_xkusage |= XKU_SMIME; + break; + + case NID_code_sign: + x->ex_xkusage |= XKU_CODE_SIGN; + break; + + case NID_ms_sgc: + case NID_ns_sgc: + x->ex_xkusage |= XKU_SGC; + break; + + case NID_OCSP_sign: + x->ex_xkusage |= XKU_OCSP_SIGN; + break; + + case NID_time_stamp: + x->ex_xkusage |= XKU_TIMESTAMP; + break; + + case NID_dvcs: + x->ex_xkusage |= XKU_DVCS; + break; + + case NID_anyExtendedKeyUsage: + x->ex_xkusage |= XKU_ANYEKU; + break; + } + } + sk_ASN1_OBJECT_pop_free(extusage, ASN1_OBJECT_free); + } else if (j != -1) { + x->ex_flags |= EXFLAG_INVALID; + } + + if ((ns = X509_get_ext_d2i(x, NID_netscape_cert_type, &j, NULL))) { + if (ns->length > 0) { + x->ex_nscert = ns->data[0]; + } else { + x->ex_nscert = 0; + } + x->ex_flags |= EXFLAG_NSCERT; + ASN1_BIT_STRING_free(ns); + } else if (j != -1) { + x->ex_flags |= EXFLAG_INVALID; + } + x->skid = X509_get_ext_d2i(x, NID_subject_key_identifier, &j, NULL); + if (x->skid == NULL && j != -1) { + x->ex_flags |= EXFLAG_INVALID; + } + x->akid = X509_get_ext_d2i(x, NID_authority_key_identifier, &j, NULL); + if (x->akid == NULL && j != -1) { + x->ex_flags |= EXFLAG_INVALID; + } + /* Does subject name match issuer ? */ + if (!X509_NAME_cmp(X509_get_subject_name(x), X509_get_issuer_name(x))) { + x->ex_flags |= EXFLAG_SI; + /* If SKID matches AKID also indicate self signed */ + if (X509_check_akid(x, x->akid) == X509_V_OK && + !ku_reject(x, KU_KEY_CERT_SIGN)) { + x->ex_flags |= EXFLAG_SS; + } + } + x->altname = X509_get_ext_d2i(x, NID_subject_alt_name, &j, NULL); + if (x->altname == NULL && j != -1) { + x->ex_flags |= EXFLAG_INVALID; + } + x->nc = X509_get_ext_d2i(x, NID_name_constraints, &j, NULL); + if (x->nc == NULL && j != -1) { + x->ex_flags |= EXFLAG_INVALID; + } + if (!setup_crldp(x)) { + x->ex_flags |= EXFLAG_INVALID; + } + + for (j = 0; j < X509_get_ext_count(x); j++) { + ex = X509_get_ext(x, j); + if (OBJ_obj2nid(X509_EXTENSION_get_object(ex)) == NID_freshest_crl) { + x->ex_flags |= EXFLAG_FRESHEST; + } + if (!X509_EXTENSION_get_critical(ex)) { + continue; + } + if (!X509_supported_extension(ex)) { + x->ex_flags |= EXFLAG_CRITICAL; + break; + } + } + x->ex_flags |= EXFLAG_SET; + + CRYPTO_MUTEX_unlock_write(&x->lock); + return (x->ex_flags & EXFLAG_INVALID) == 0; } /* check_ca returns one if |x| should be considered a CA certificate and zero * otherwise. */ -static int check_ca(const X509 *x) -{ - /* keyUsage if present should allow cert signing */ - if (ku_reject(x, KU_KEY_CERT_SIGN)) - return 0; - /* Version 1 certificates are considered CAs and don't have extensions. */ - if ((x->ex_flags & V1_ROOT) == V1_ROOT) { - return 1; - } - /* Otherwise, it's only a CA if basicConstraints says so. */ - return ((x->ex_flags & EXFLAG_BCONS) && - (x->ex_flags & EXFLAG_CA)); +static int check_ca(const X509 *x) { + /* keyUsage if present should allow cert signing */ + if (ku_reject(x, KU_KEY_CERT_SIGN)) { + return 0; + } + /* Version 1 certificates are considered CAs and don't have extensions. */ + if ((x->ex_flags & V1_ROOT) == V1_ROOT) { + return 1; + } + /* Otherwise, it's only a CA if basicConstraints says so. */ + return ((x->ex_flags & EXFLAG_BCONS) && (x->ex_flags & EXFLAG_CA)); } -int X509_check_ca(X509 *x) -{ - if (!x509v3_cache_extensions(x)) { - return 0; - } - return check_ca(x); +int X509_check_ca(X509 *x) { + if (!x509v3_cache_extensions(x)) { + return 0; + } + return check_ca(x); } static int check_purpose_ssl_client(const X509_PURPOSE *xp, const X509 *x, - int ca) -{ - if (xku_reject(x, XKU_SSL_CLIENT)) - return 0; - if (ca) - return check_ca(x); - /* We need to do digital signatures or key agreement */ - if (ku_reject(x, KU_DIGITAL_SIGNATURE | KU_KEY_AGREEMENT)) - return 0; - /* nsCertType if present should allow SSL client use */ - if (ns_reject(x, NS_SSL_CLIENT)) - return 0; - return 1; + int ca) { + if (xku_reject(x, XKU_SSL_CLIENT)) { + return 0; + } + if (ca) { + return check_ca(x); + } + /* We need to do digital signatures or key agreement */ + if (ku_reject(x, KU_DIGITAL_SIGNATURE | KU_KEY_AGREEMENT)) { + return 0; + } + /* nsCertType if present should allow SSL client use */ + if (ns_reject(x, NS_SSL_CLIENT)) { + return 0; + } + return 1; } /* @@ -644,93 +646,96 @@ static int check_purpose_ssl_client(const X509_PURPOSE *xp, const X509 *x, * key agreement. The ssl code can check this more thoroughly for individual * key types. */ -#define KU_TLS \ - (KU_DIGITAL_SIGNATURE|KU_KEY_ENCIPHERMENT|KU_KEY_AGREEMENT) +#define KU_TLS (KU_DIGITAL_SIGNATURE | KU_KEY_ENCIPHERMENT | KU_KEY_AGREEMENT) static int check_purpose_ssl_server(const X509_PURPOSE *xp, const X509 *x, - int ca) -{ - if (xku_reject(x, XKU_SSL_SERVER)) - return 0; - if (ca) - return check_ca(x); - - if (ns_reject(x, NS_SSL_SERVER)) - return 0; - if (ku_reject(x, KU_TLS)) - return 0; + int ca) { + if (xku_reject(x, XKU_SSL_SERVER)) { + return 0; + } + if (ca) { + return check_ca(x); + } - return 1; + if (ns_reject(x, NS_SSL_SERVER)) { + return 0; + } + if (ku_reject(x, KU_TLS)) { + return 0; + } + return 1; } static int check_purpose_ns_ssl_server(const X509_PURPOSE *xp, const X509 *x, - int ca) -{ - int ret; - ret = check_purpose_ssl_server(xp, x, ca); - if (!ret || ca) - return ret; - /* We need to encipher or Netscape complains */ - if (ku_reject(x, KU_KEY_ENCIPHERMENT)) - return 0; + int ca) { + int ret; + ret = check_purpose_ssl_server(xp, x, ca); + if (!ret || ca) { return ret; + } + /* We need to encipher or Netscape complains */ + if (ku_reject(x, KU_KEY_ENCIPHERMENT)) { + return 0; + } + return ret; } /* purpose_smime returns one if |x| is a valid S/MIME leaf (|ca| is zero) or CA * (|ca| is one) certificate, and zero otherwise. */ -static int purpose_smime(const X509 *x, int ca) -{ - if (xku_reject(x, XKU_SMIME)) - return 0; - if (ca) { - /* check nsCertType if present */ - if ((x->ex_flags & EXFLAG_NSCERT) && - (x->ex_nscert & NS_SMIME_CA) == 0) { - return 0; - } - - return check_ca(x); - } - if (x->ex_flags & EXFLAG_NSCERT) { - return (x->ex_nscert & NS_SMIME) == NS_SMIME; +static int purpose_smime(const X509 *x, int ca) { + if (xku_reject(x, XKU_SMIME)) { + return 0; + } + if (ca) { + /* check nsCertType if present */ + if ((x->ex_flags & EXFLAG_NSCERT) && (x->ex_nscert & NS_SMIME_CA) == 0) { + return 0; } - return 1; + + return check_ca(x); + } + if (x->ex_flags & EXFLAG_NSCERT) { + return (x->ex_nscert & NS_SMIME) == NS_SMIME; + } + return 1; } static int check_purpose_smime_sign(const X509_PURPOSE *xp, const X509 *x, - int ca) -{ - int ret; - ret = purpose_smime(x, ca); - if (!ret || ca) - return ret; - if (ku_reject(x, KU_DIGITAL_SIGNATURE | KU_NON_REPUDIATION)) - return 0; + int ca) { + int ret; + ret = purpose_smime(x, ca); + if (!ret || ca) { return ret; + } + if (ku_reject(x, KU_DIGITAL_SIGNATURE | KU_NON_REPUDIATION)) { + return 0; + } + return ret; } static int check_purpose_smime_encrypt(const X509_PURPOSE *xp, const X509 *x, - int ca) -{ - int ret; - ret = purpose_smime(x, ca); - if (!ret || ca) - return ret; - if (ku_reject(x, KU_KEY_ENCIPHERMENT)) - return 0; + int ca) { + int ret; + ret = purpose_smime(x, ca); + if (!ret || ca) { return ret; + } + if (ku_reject(x, KU_KEY_ENCIPHERMENT)) { + return 0; + } + return ret; } static int check_purpose_crl_sign(const X509_PURPOSE *xp, const X509 *x, - int ca) -{ - if (ca) { - return check_ca(x); - } - if (ku_reject(x, KU_CRL_SIGN)) - return 0; - return 1; + int ca) { + if (ca) { + return check_ca(x); + } + if (ku_reject(x, KU_CRL_SIGN)) { + return 0; + } + return 1; } /* @@ -738,53 +743,53 @@ static int check_purpose_crl_sign(const X509_PURPOSE *xp, const X509 *x, * is valid. Additional checks must be made on the chain. */ -static int ocsp_helper(const X509_PURPOSE *xp, const X509 *x, int ca) -{ - if (ca) - return check_ca(x); - /* leaf certificate is checked in OCSP_verify() */ - return 1; +static int ocsp_helper(const X509_PURPOSE *xp, const X509 *x, int ca) { + if (ca) { + return check_ca(x); + } + /* leaf certificate is checked in OCSP_verify() */ + return 1; } static int check_purpose_timestamp_sign(const X509_PURPOSE *xp, const X509 *x, - int ca) -{ - int i_ext; + int ca) { + int i_ext; - /* If ca is true we must return if this is a valid CA certificate. */ - if (ca) - return check_ca(x); + /* If ca is true we must return if this is a valid CA certificate. */ + if (ca) { + return check_ca(x); + } + + /* + * Check the optional key usage field: + * if Key Usage is present, it must be one of digitalSignature + * and/or nonRepudiation (other values are not consistent and shall + * be rejected). + */ + if ((x->ex_flags & EXFLAG_KUSAGE) && + ((x->ex_kusage & ~(KU_NON_REPUDIATION | KU_DIGITAL_SIGNATURE)) || + !(x->ex_kusage & (KU_NON_REPUDIATION | KU_DIGITAL_SIGNATURE)))) { + return 0; + } - /* - * Check the optional key usage field: - * if Key Usage is present, it must be one of digitalSignature - * and/or nonRepudiation (other values are not consistent and shall - * be rejected). - */ - if ((x->ex_flags & EXFLAG_KUSAGE) - && ((x->ex_kusage & ~(KU_NON_REPUDIATION | KU_DIGITAL_SIGNATURE)) || - !(x->ex_kusage & (KU_NON_REPUDIATION | KU_DIGITAL_SIGNATURE)))) - return 0; - - /* Only time stamp key usage is permitted and it's required. */ - if (!(x->ex_flags & EXFLAG_XKUSAGE) || x->ex_xkusage != XKU_TIMESTAMP) - return 0; - - /* Extended Key Usage MUST be critical */ - i_ext = X509_get_ext_by_NID((X509 *)x, NID_ext_key_usage, -1); - if (i_ext >= 0) { - X509_EXTENSION *ext = X509_get_ext((X509 *)x, i_ext); - if (!X509_EXTENSION_get_critical(ext)) - return 0; + /* Only time stamp key usage is permitted and it's required. */ + if (!(x->ex_flags & EXFLAG_XKUSAGE) || x->ex_xkusage != XKU_TIMESTAMP) { + return 0; + } + + /* Extended Key Usage MUST be critical */ + i_ext = X509_get_ext_by_NID((X509 *)x, NID_ext_key_usage, -1); + if (i_ext >= 0) { + X509_EXTENSION *ext = X509_get_ext((X509 *)x, i_ext); + if (!X509_EXTENSION_get_critical(ext)) { + return 0; } + } - return 1; + return 1; } -static int no_check(const X509_PURPOSE *xp, const X509 *x, int ca) -{ - return 1; -} +static int no_check(const X509_PURPOSE *xp, const X509 *x, int ca) { return 1; } /* * Various checks to see if one certificate issued the second. This can be @@ -796,134 +801,131 @@ static int no_check(const X509_PURPOSE *xp, const X509 *x, int ca) * reasons match codes for X509_verify_cert() */ -int X509_check_issued(X509 *issuer, X509 *subject) -{ - if (X509_NAME_cmp(X509_get_subject_name(issuer), - X509_get_issuer_name(subject))) - return X509_V_ERR_SUBJECT_ISSUER_MISMATCH; - if (!x509v3_cache_extensions(issuer) || - !x509v3_cache_extensions(subject)) { - return X509_V_ERR_UNSPECIFIED; - } +int X509_check_issued(X509 *issuer, X509 *subject) { + if (X509_NAME_cmp(X509_get_subject_name(issuer), + X509_get_issuer_name(subject))) { + return X509_V_ERR_SUBJECT_ISSUER_MISMATCH; + } + if (!x509v3_cache_extensions(issuer) || !x509v3_cache_extensions(subject)) { + return X509_V_ERR_UNSPECIFIED; + } - if (subject->akid) { - int ret = X509_check_akid(issuer, subject->akid); - if (ret != X509_V_OK) - return ret; + if (subject->akid) { + int ret = X509_check_akid(issuer, subject->akid); + if (ret != X509_V_OK) { + return ret; } + } - if (subject->ex_flags & EXFLAG_PROXY) { - if (ku_reject(issuer, KU_DIGITAL_SIGNATURE)) - return X509_V_ERR_KEYUSAGE_NO_DIGITAL_SIGNATURE; - } else if (ku_reject(issuer, KU_KEY_CERT_SIGN)) - return X509_V_ERR_KEYUSAGE_NO_CERTSIGN; - return X509_V_OK; + if (subject->ex_flags & EXFLAG_PROXY) { + if (ku_reject(issuer, KU_DIGITAL_SIGNATURE)) { + return X509_V_ERR_KEYUSAGE_NO_DIGITAL_SIGNATURE; + } + } else if (ku_reject(issuer, KU_KEY_CERT_SIGN)) { + return X509_V_ERR_KEYUSAGE_NO_CERTSIGN; + } + return X509_V_OK; } -int X509_check_akid(X509 *issuer, AUTHORITY_KEYID *akid) -{ - - if (!akid) - return X509_V_OK; - - /* Check key ids (if present) */ - if (akid->keyid && issuer->skid && - ASN1_OCTET_STRING_cmp(akid->keyid, issuer->skid)) - return X509_V_ERR_AKID_SKID_MISMATCH; - /* Check serial number */ - if (akid->serial && - ASN1_INTEGER_cmp(X509_get_serialNumber(issuer), akid->serial)) - return X509_V_ERR_AKID_ISSUER_SERIAL_MISMATCH; - /* Check issuer name */ - if (akid->issuer) { - /* - * Ugh, for some peculiar reason AKID includes SEQUENCE OF - * GeneralName. So look for a DirName. There may be more than one but - * we only take any notice of the first. - */ - GENERAL_NAMES *gens; - GENERAL_NAME *gen; - X509_NAME *nm = NULL; - size_t i; - gens = akid->issuer; - for (i = 0; i < sk_GENERAL_NAME_num(gens); i++) { - gen = sk_GENERAL_NAME_value(gens, i); - if (gen->type == GEN_DIRNAME) { - nm = gen->d.dirn; - break; - } - } - if (nm && X509_NAME_cmp(nm, X509_get_issuer_name(issuer))) - return X509_V_ERR_AKID_ISSUER_SERIAL_MISMATCH; - } +int X509_check_akid(X509 *issuer, AUTHORITY_KEYID *akid) { + if (!akid) { return X509_V_OK; + } + + /* Check key ids (if present) */ + if (akid->keyid && issuer->skid && + ASN1_OCTET_STRING_cmp(akid->keyid, issuer->skid)) { + return X509_V_ERR_AKID_SKID_MISMATCH; + } + /* Check serial number */ + if (akid->serial && + ASN1_INTEGER_cmp(X509_get_serialNumber(issuer), akid->serial)) { + return X509_V_ERR_AKID_ISSUER_SERIAL_MISMATCH; + } + /* Check issuer name */ + if (akid->issuer) { + /* + * Ugh, for some peculiar reason AKID includes SEQUENCE OF + * GeneralName. So look for a DirName. There may be more than one but + * we only take any notice of the first. + */ + GENERAL_NAMES *gens; + GENERAL_NAME *gen; + X509_NAME *nm = NULL; + size_t i; + gens = akid->issuer; + for (i = 0; i < sk_GENERAL_NAME_num(gens); i++) { + gen = sk_GENERAL_NAME_value(gens, i); + if (gen->type == GEN_DIRNAME) { + nm = gen->d.dirn; + break; + } + } + if (nm && X509_NAME_cmp(nm, X509_get_issuer_name(issuer))) { + return X509_V_ERR_AKID_ISSUER_SERIAL_MISMATCH; + } + } + return X509_V_OK; } -uint32_t X509_get_extension_flags(X509 *x) -{ - /* Ignore the return value. On failure, |x->ex_flags| will include - * |EXFLAG_INVALID|. */ - x509v3_cache_extensions(x); - return x->ex_flags; +uint32_t X509_get_extension_flags(X509 *x) { + /* Ignore the return value. On failure, |x->ex_flags| will include + * |EXFLAG_INVALID|. */ + x509v3_cache_extensions(x); + return x->ex_flags; } -uint32_t X509_get_key_usage(X509 *x) -{ - if (!x509v3_cache_extensions(x)) { - return 0; - } - if (x->ex_flags & EXFLAG_KUSAGE) - return x->ex_kusage; - return UINT32_MAX; +uint32_t X509_get_key_usage(X509 *x) { + if (!x509v3_cache_extensions(x)) { + return 0; + } + if (x->ex_flags & EXFLAG_KUSAGE) { + return x->ex_kusage; + } + return UINT32_MAX; } -uint32_t X509_get_extended_key_usage(X509 *x) -{ - if (!x509v3_cache_extensions(x)) { - return 0; - } - if (x->ex_flags & EXFLAG_XKUSAGE) - return x->ex_xkusage; - return UINT32_MAX; +uint32_t X509_get_extended_key_usage(X509 *x) { + if (!x509v3_cache_extensions(x)) { + return 0; + } + if (x->ex_flags & EXFLAG_XKUSAGE) { + return x->ex_xkusage; + } + return UINT32_MAX; } -const ASN1_OCTET_STRING *X509_get0_subject_key_id(X509 *x509) -{ - if (!x509v3_cache_extensions(x509)) { - return NULL; - } - return x509->skid; +const ASN1_OCTET_STRING *X509_get0_subject_key_id(X509 *x509) { + if (!x509v3_cache_extensions(x509)) { + return NULL; + } + return x509->skid; } -const ASN1_OCTET_STRING *X509_get0_authority_key_id(X509 *x509) -{ - if (!x509v3_cache_extensions(x509)) { - return NULL; - } - return x509->akid != NULL ? x509->akid->keyid : NULL; +const ASN1_OCTET_STRING *X509_get0_authority_key_id(X509 *x509) { + if (!x509v3_cache_extensions(x509)) { + return NULL; + } + return x509->akid != NULL ? x509->akid->keyid : NULL; } -const GENERAL_NAMES *X509_get0_authority_issuer(X509 *x509) -{ - if (!x509v3_cache_extensions(x509)) { - return NULL; - } - return x509->akid != NULL ? x509->akid->issuer : NULL; +const GENERAL_NAMES *X509_get0_authority_issuer(X509 *x509) { + if (!x509v3_cache_extensions(x509)) { + return NULL; + } + return x509->akid != NULL ? x509->akid->issuer : NULL; } -const ASN1_INTEGER *X509_get0_authority_serial(X509 *x509) -{ - if (!x509v3_cache_extensions(x509)) { - return NULL; - } - return x509->akid != NULL ? x509->akid->serial : NULL; +const ASN1_INTEGER *X509_get0_authority_serial(X509 *x509) { + if (!x509v3_cache_extensions(x509)) { + return NULL; + } + return x509->akid != NULL ? x509->akid->serial : NULL; } -long X509_get_pathlen(X509 *x509) -{ - if (!x509v3_cache_extensions(x509) || - (x509->ex_flags & EXFLAG_BCONS) == 0) { - return -1; - } - return x509->ex_pathlen; +long X509_get_pathlen(X509 *x509) { + if (!x509v3_cache_extensions(x509) || (x509->ex_flags & EXFLAG_BCONS) == 0) { + return -1; + } + return x509->ex_pathlen; } diff --git a/crypto/x509v3/v3_skey.c b/crypto/x509v3/v3_skey.c index 78e1769700..05c5050d45 100644 --- a/crypto/x509v3/v3_skey.c +++ b/crypto/x509v3/v3_skey.c @@ -68,94 +68,100 @@ char *i2s_ASN1_OCTET_STRING(const X509V3_EXT_METHOD *method, - const ASN1_OCTET_STRING *oct) -{ - return x509v3_bytes_to_hex(oct->data, oct->length); + const ASN1_OCTET_STRING *oct) { + return x509v3_bytes_to_hex(oct->data, oct->length); } ASN1_OCTET_STRING *s2i_ASN1_OCTET_STRING(const X509V3_EXT_METHOD *method, - X509V3_CTX *ctx, const char *str) -{ - ASN1_OCTET_STRING *oct; - long length; + X509V3_CTX *ctx, const char *str) { + ASN1_OCTET_STRING *oct; + long length; - if (!(oct = ASN1_OCTET_STRING_new())) { - OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE); - return NULL; - } - - if (!(oct->data = x509v3_hex_to_bytes(str, &length))) { - ASN1_OCTET_STRING_free(oct); - return NULL; - } + if (!(oct = ASN1_OCTET_STRING_new())) { + OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE); + return NULL; + } - oct->length = length; + if (!(oct->data = x509v3_hex_to_bytes(str, &length))) { + ASN1_OCTET_STRING_free(oct); + return NULL; + } - return oct; + oct->length = length; + return oct; } static char *i2s_ASN1_OCTET_STRING_cb(const X509V3_EXT_METHOD *method, - void *ext) -{ - return i2s_ASN1_OCTET_STRING(method, ext); + void *ext) { + return i2s_ASN1_OCTET_STRING(method, ext); } static void *s2i_skey_id(const X509V3_EXT_METHOD *method, X509V3_CTX *ctx, - const char *str) -{ - ASN1_OCTET_STRING *oct; - ASN1_BIT_STRING *pk; - unsigned char pkey_dig[EVP_MAX_MD_SIZE]; - unsigned int diglen; - - if (strcmp(str, "hash")) - return s2i_ASN1_OCTET_STRING(method, ctx, str); - - if (!(oct = ASN1_OCTET_STRING_new())) { - OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE); - return NULL; - } - - if (ctx && (ctx->flags == CTX_TEST)) - return oct; - - if (!ctx || (!ctx->subject_req && !ctx->subject_cert)) { - OPENSSL_PUT_ERROR(X509V3, X509V3_R_NO_PUBLIC_KEY); - goto err; - } - - if (ctx->subject_req) - pk = ctx->subject_req->req_info->pubkey->public_key; - else - pk = ctx->subject_cert->cert_info->key->public_key; - - if (!pk) { - OPENSSL_PUT_ERROR(X509V3, X509V3_R_NO_PUBLIC_KEY); - goto err; - } - - if (!EVP_Digest - (pk->data, pk->length, pkey_dig, &diglen, EVP_sha1(), NULL)) - goto err; - - if (!ASN1_OCTET_STRING_set(oct, pkey_dig, diglen)) { - OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE); - goto err; - } + const char *str) { + ASN1_OCTET_STRING *oct; + ASN1_BIT_STRING *pk; + unsigned char pkey_dig[EVP_MAX_MD_SIZE]; + unsigned int diglen; + + if (strcmp(str, "hash")) { + return s2i_ASN1_OCTET_STRING(method, ctx, str); + } + + if (!(oct = ASN1_OCTET_STRING_new())) { + OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE); + return NULL; + } + if (ctx && (ctx->flags == CTX_TEST)) { return oct; - - err: - ASN1_OCTET_STRING_free(oct); - return NULL; + } + + if (!ctx || (!ctx->subject_req && !ctx->subject_cert)) { + OPENSSL_PUT_ERROR(X509V3, X509V3_R_NO_PUBLIC_KEY); + goto err; + } + + if (ctx->subject_req) { + pk = ctx->subject_req->req_info->pubkey->public_key; + } else { + pk = ctx->subject_cert->cert_info->key->public_key; + } + + if (!pk) { + OPENSSL_PUT_ERROR(X509V3, X509V3_R_NO_PUBLIC_KEY); + goto err; + } + + if (!EVP_Digest(pk->data, pk->length, pkey_dig, &diglen, EVP_sha1(), NULL)) { + goto err; + } + + if (!ASN1_OCTET_STRING_set(oct, pkey_dig, diglen)) { + OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE); + goto err; + } + + return oct; + +err: + ASN1_OCTET_STRING_free(oct); + return NULL; } const X509V3_EXT_METHOD v3_skey_id = { - NID_subject_key_identifier, 0, ASN1_ITEM_ref(ASN1_OCTET_STRING), - 0, 0, 0, 0, + NID_subject_key_identifier, + 0, + ASN1_ITEM_ref(ASN1_OCTET_STRING), + 0, + 0, + 0, + 0, i2s_ASN1_OCTET_STRING_cb, s2i_skey_id, - 0, 0, 0, 0, + 0, + 0, + 0, + 0, NULL, }; diff --git a/crypto/x509v3/v3_utl.c b/crypto/x509v3/v3_utl.c index ae93e00411..39cddde772 100644 --- a/crypto/x509v3/v3_utl.c +++ b/crypto/x509v3/v3_utl.c @@ -76,7 +76,7 @@ static char *strip_spaces(char *name); -static int sk_strcmp(const OPENSSL_STRING *a, const OPENSSL_STRING *b); +static int sk_strcmp(const char **a, const char **b); static STACK_OF(OPENSSL_STRING) *get_email(X509_NAME *name, GENERAL_NAMES *gens); static void str_free(OPENSSL_STRING str); @@ -91,662 +91,672 @@ static int ipv6_hex(unsigned char *out, const char *in, int inlen); static int x509V3_add_len_value(const char *name, const char *value, size_t value_len, int omit_value, - STACK_OF(CONF_VALUE) **extlist) -{ - CONF_VALUE *vtmp = NULL; - char *tname = NULL, *tvalue = NULL; - int extlist_was_null = *extlist == NULL; - if (name && !(tname = OPENSSL_strdup(name))) - goto malloc_err; - if (!omit_value) { - /* |CONF_VALUE| cannot represent strings with NULs. */ - if (OPENSSL_memchr(value, 0, value_len)) { - OPENSSL_PUT_ERROR(X509V3, X509V3_R_INVALID_VALUE); - goto err; - } - tvalue = OPENSSL_strndup(value, value_len); - if (tvalue == NULL) { - goto malloc_err; - } + STACK_OF(CONF_VALUE) **extlist) { + CONF_VALUE *vtmp = NULL; + char *tname = NULL, *tvalue = NULL; + int extlist_was_null = *extlist == NULL; + if (name && !(tname = OPENSSL_strdup(name))) { + goto malloc_err; + } + if (!omit_value) { + /* |CONF_VALUE| cannot represent strings with NULs. */ + if (OPENSSL_memchr(value, 0, value_len)) { + OPENSSL_PUT_ERROR(X509V3, X509V3_R_INVALID_VALUE); + goto err; } - if (!(vtmp = CONF_VALUE_new())) - goto malloc_err; - if (!*extlist && !(*extlist = sk_CONF_VALUE_new_null())) - goto malloc_err; - vtmp->section = NULL; - vtmp->name = tname; - vtmp->value = tvalue; - if (!sk_CONF_VALUE_push(*extlist, vtmp)) - goto malloc_err; - return 1; - malloc_err: - OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE); - err: - if (extlist_was_null) { - sk_CONF_VALUE_free(*extlist); - *extlist = NULL; + tvalue = OPENSSL_strndup(value, value_len); + if (tvalue == NULL) { + goto malloc_err; } - OPENSSL_free(vtmp); - OPENSSL_free(tname); - OPENSSL_free(tvalue); - return 0; + } + if (!(vtmp = CONF_VALUE_new())) { + goto malloc_err; + } + if (!*extlist && !(*extlist = sk_CONF_VALUE_new_null())) { + goto malloc_err; + } + vtmp->section = NULL; + vtmp->name = tname; + vtmp->value = tvalue; + if (!sk_CONF_VALUE_push(*extlist, vtmp)) { + goto malloc_err; + } + return 1; +malloc_err: + OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE); +err: + if (extlist_was_null) { + sk_CONF_VALUE_free(*extlist); + *extlist = NULL; + } + OPENSSL_free(vtmp); + OPENSSL_free(tname); + OPENSSL_free(tvalue); + return 0; } int X509V3_add_value(const char *name, const char *value, - STACK_OF(CONF_VALUE) **extlist) -{ - return x509V3_add_len_value(name, value, value != NULL ? strlen(value) : 0, - /*omit_value=*/value == NULL, extlist); + STACK_OF(CONF_VALUE) **extlist) { + return x509V3_add_len_value(name, value, value != NULL ? strlen(value) : 0, + /*omit_value=*/value == NULL, extlist); } int X509V3_add_value_uchar(const char *name, const unsigned char *value, - STACK_OF(CONF_VALUE) **extlist) -{ - return X509V3_add_value(name, (const char *)value, extlist); + STACK_OF(CONF_VALUE) **extlist) { + return X509V3_add_value(name, (const char *)value, extlist); } int x509V3_add_value_asn1_string(const char *name, const ASN1_STRING *value, - STACK_OF(CONF_VALUE) **extlist) -{ - return x509V3_add_len_value(name, (const char *)value->data, value->length, - /*omit_value=*/0, extlist); + STACK_OF(CONF_VALUE) **extlist) { + return x509V3_add_len_value(name, (const char *)value->data, value->length, + /*omit_value=*/0, extlist); } /* Free function for STACK_OF(CONF_VALUE) */ -void X509V3_conf_free(CONF_VALUE *conf) -{ - if (!conf) - return; - if (conf->name) - OPENSSL_free(conf->name); - if (conf->value) - OPENSSL_free(conf->value); - if (conf->section) - OPENSSL_free(conf->section); - OPENSSL_free(conf); +void X509V3_conf_free(CONF_VALUE *conf) { + if (!conf) { + return; + } + if (conf->name) { + OPENSSL_free(conf->name); + } + if (conf->value) { + OPENSSL_free(conf->value); + } + if (conf->section) { + OPENSSL_free(conf->section); + } + OPENSSL_free(conf); } int X509V3_add_value_bool(const char *name, int asn1_bool, - STACK_OF(CONF_VALUE) **extlist) -{ - if (asn1_bool) - return X509V3_add_value(name, "TRUE", extlist); - return X509V3_add_value(name, "FALSE", extlist); + STACK_OF(CONF_VALUE) **extlist) { + if (asn1_bool) { + return X509V3_add_value(name, "TRUE", extlist); + } + return X509V3_add_value(name, "FALSE", extlist); } int X509V3_add_value_bool_nf(const char *name, int asn1_bool, - STACK_OF(CONF_VALUE) **extlist) -{ - if (asn1_bool) - return X509V3_add_value(name, "TRUE", extlist); - return 1; + STACK_OF(CONF_VALUE) **extlist) { + if (asn1_bool) { + return X509V3_add_value(name, "TRUE", extlist); + } + return 1; } -static char *bignum_to_string(const BIGNUM *bn) -{ - char *tmp, *ret; - size_t len; - - /* - * Display large numbers in hex and small numbers in decimal. Converting to - * decimal takes quadratic time and is no more useful than hex for large - * numbers. - */ - if (BN_num_bits(bn) < 32) { - return BN_bn2dec(bn); - } - - tmp = BN_bn2hex(bn); - if (tmp == NULL) { - return NULL; - } - - len = strlen(tmp) + 3; - ret = OPENSSL_malloc(len); - if (ret == NULL) { - OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE); - OPENSSL_free(tmp); - return NULL; - } +static char *bignum_to_string(const BIGNUM *bn) { + char *tmp, *ret; + size_t len; + + /* + * Display large numbers in hex and small numbers in decimal. Converting to + * decimal takes quadratic time and is no more useful than hex for large + * numbers. + */ + if (BN_num_bits(bn) < 32) { + return BN_bn2dec(bn); + } + + tmp = BN_bn2hex(bn); + if (tmp == NULL) { + return NULL; + } - /* Prepend "0x", but place it after the "-" if negative. */ - if (tmp[0] == '-') { - OPENSSL_strlcpy(ret, "-0x", len); - OPENSSL_strlcat(ret, tmp + 1, len); - } else { - OPENSSL_strlcpy(ret, "0x", len); - OPENSSL_strlcat(ret, tmp, len); - } + len = strlen(tmp) + 3; + ret = OPENSSL_malloc(len); + if (ret == NULL) { + OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE); OPENSSL_free(tmp); - return ret; + return NULL; + } + + /* Prepend "0x", but place it after the "-" if negative. */ + if (tmp[0] == '-') { + OPENSSL_strlcpy(ret, "-0x", len); + OPENSSL_strlcat(ret, tmp + 1, len); + } else { + OPENSSL_strlcpy(ret, "0x", len); + OPENSSL_strlcat(ret, tmp, len); + } + OPENSSL_free(tmp); + return ret; } char *i2s_ASN1_ENUMERATED(const X509V3_EXT_METHOD *method, - const ASN1_ENUMERATED *a) -{ - BIGNUM *bntmp = NULL; - char *strtmp = NULL; - if (!a) - return NULL; - if (!(bntmp = ASN1_ENUMERATED_to_BN(a, NULL)) || - !(strtmp = bignum_to_string(bntmp))) - OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE); - BN_free(bntmp); - return strtmp; + const ASN1_ENUMERATED *a) { + BIGNUM *bntmp = NULL; + char *strtmp = NULL; + if (!a) { + return NULL; + } + if (!(bntmp = ASN1_ENUMERATED_to_BN(a, NULL)) || + !(strtmp = bignum_to_string(bntmp))) { + OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE); + } + BN_free(bntmp); + return strtmp; } -char *i2s_ASN1_INTEGER(const X509V3_EXT_METHOD *method, const ASN1_INTEGER *a) -{ - BIGNUM *bntmp = NULL; - char *strtmp = NULL; - if (!a) - return NULL; - if (!(bntmp = ASN1_INTEGER_to_BN(a, NULL)) || - !(strtmp = bignum_to_string(bntmp))) - OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE); - BN_free(bntmp); - return strtmp; +char *i2s_ASN1_INTEGER(const X509V3_EXT_METHOD *method, const ASN1_INTEGER *a) { + BIGNUM *bntmp = NULL; + char *strtmp = NULL; + if (!a) { + return NULL; + } + if (!(bntmp = ASN1_INTEGER_to_BN(a, NULL)) || + !(strtmp = bignum_to_string(bntmp))) { + OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE); + } + BN_free(bntmp); + return strtmp; } ASN1_INTEGER *s2i_ASN1_INTEGER(const X509V3_EXT_METHOD *method, - const char *value) -{ - BIGNUM *bn = NULL; - ASN1_INTEGER *aint; - int isneg, ishex; - int ret; - if (!value) { - OPENSSL_PUT_ERROR(X509V3, X509V3_R_INVALID_NULL_VALUE); - return 0; - } - bn = BN_new(); - if (value[0] == '-') { - value++; - isneg = 1; - } else - isneg = 0; - - if (value[0] == '0' && ((value[1] == 'x') || (value[1] == 'X'))) { - value += 2; - ishex = 1; - } else - ishex = 0; - - if (ishex) - ret = BN_hex2bn(&bn, value); - else - ret = BN_dec2bn(&bn, value); - - if (!ret || value[ret]) { - BN_free(bn); - OPENSSL_PUT_ERROR(X509V3, X509V3_R_BN_DEC2BN_ERROR); - return 0; - } + const char *value) { + BIGNUM *bn = NULL; + ASN1_INTEGER *aint; + int isneg, ishex; + int ret; + if (!value) { + OPENSSL_PUT_ERROR(X509V3, X509V3_R_INVALID_NULL_VALUE); + return 0; + } + bn = BN_new(); + if (value[0] == '-') { + value++; + isneg = 1; + } else { + isneg = 0; + } + + if (value[0] == '0' && ((value[1] == 'x') || (value[1] == 'X'))) { + value += 2; + ishex = 1; + } else { + ishex = 0; + } + + if (ishex) { + ret = BN_hex2bn(&bn, value); + } else { + ret = BN_dec2bn(&bn, value); + } + + if (!ret || value[ret]) { + BN_free(bn); + OPENSSL_PUT_ERROR(X509V3, X509V3_R_BN_DEC2BN_ERROR); + return 0; + } - if (isneg && BN_is_zero(bn)) - isneg = 0; + if (isneg && BN_is_zero(bn)) { + isneg = 0; + } - aint = BN_to_ASN1_INTEGER(bn, NULL); - BN_free(bn); - if (!aint) { - OPENSSL_PUT_ERROR(X509V3, X509V3_R_BN_TO_ASN1_INTEGER_ERROR); - return 0; - } - if (isneg) - aint->type |= V_ASN1_NEG; - return aint; + aint = BN_to_ASN1_INTEGER(bn, NULL); + BN_free(bn); + if (!aint) { + OPENSSL_PUT_ERROR(X509V3, X509V3_R_BN_TO_ASN1_INTEGER_ERROR); + return 0; + } + if (isneg) { + aint->type |= V_ASN1_NEG; + } + return aint; } int X509V3_add_value_int(const char *name, const ASN1_INTEGER *aint, - STACK_OF(CONF_VALUE) **extlist) -{ - char *strtmp; - int ret; - if (!aint) - return 1; - if (!(strtmp = i2s_ASN1_INTEGER(NULL, aint))) - return 0; - ret = X509V3_add_value(name, strtmp, extlist); - OPENSSL_free(strtmp); - return ret; -} - -int X509V3_get_value_bool(const CONF_VALUE *value, int *asn1_bool) -{ - char *btmp; - if (!(btmp = value->value)) - goto err; - if (!strcmp(btmp, "TRUE") || !strcmp(btmp, "true") - || !strcmp(btmp, "Y") || !strcmp(btmp, "y") - || !strcmp(btmp, "YES") || !strcmp(btmp, "yes")) { - *asn1_bool = 0xff; - return 1; - } else if (!strcmp(btmp, "FALSE") || !strcmp(btmp, "false") - || !strcmp(btmp, "N") || !strcmp(btmp, "n") - || !strcmp(btmp, "NO") || !strcmp(btmp, "no")) { - *asn1_bool = 0; - return 1; - } - err: - OPENSSL_PUT_ERROR(X509V3, X509V3_R_INVALID_BOOLEAN_STRING); - X509V3_conf_err(value); + STACK_OF(CONF_VALUE) **extlist) { + char *strtmp; + int ret; + if (!aint) { + return 1; + } + if (!(strtmp = i2s_ASN1_INTEGER(NULL, aint))) { return 0; + } + ret = X509V3_add_value(name, strtmp, extlist); + OPENSSL_free(strtmp); + return ret; } -int X509V3_get_value_int(const CONF_VALUE *value, ASN1_INTEGER **aint) -{ - ASN1_INTEGER *itmp; - if (!(itmp = s2i_ASN1_INTEGER(NULL, value->value))) { - X509V3_conf_err(value); - return 0; - } - *aint = itmp; +int X509V3_get_value_bool(const CONF_VALUE *value, int *asn1_bool) { + char *btmp; + if (!(btmp = value->value)) { + goto err; + } + if (!strcmp(btmp, "TRUE") || !strcmp(btmp, "true") || !strcmp(btmp, "Y") || + !strcmp(btmp, "y") || !strcmp(btmp, "YES") || !strcmp(btmp, "yes")) { + *asn1_bool = 0xff; return 1; + } else if (!strcmp(btmp, "FALSE") || !strcmp(btmp, "false") || + !strcmp(btmp, "N") || !strcmp(btmp, "n") || !strcmp(btmp, "NO") || + !strcmp(btmp, "no")) { + *asn1_bool = 0; + return 1; + } +err: + OPENSSL_PUT_ERROR(X509V3, X509V3_R_INVALID_BOOLEAN_STRING); + X509V3_conf_err(value); + return 0; +} + +int X509V3_get_value_int(const CONF_VALUE *value, ASN1_INTEGER **aint) { + ASN1_INTEGER *itmp; + if (!(itmp = s2i_ASN1_INTEGER(NULL, value->value))) { + X509V3_conf_err(value); + return 0; + } + *aint = itmp; + return 1; } -#define HDR_NAME 1 -#define HDR_VALUE 2 +#define HDR_NAME 1 +#define HDR_VALUE 2 /* * #define DEBUG */ -STACK_OF(CONF_VALUE) *X509V3_parse_list(const char *line) -{ - char *p, *q, c; - char *ntmp, *vtmp; - STACK_OF(CONF_VALUE) *values = NULL; - char *linebuf; - int state; - /* We are going to modify the line so copy it first */ - linebuf = OPENSSL_strdup(line); - if (linebuf == NULL) { - OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE); - goto err; - } - state = HDR_NAME; - ntmp = NULL; - /* Go through all characters */ - for (p = linebuf, q = linebuf; (c = *p) && (c != '\r') && (c != '\n'); - p++) { - - switch (state) { - case HDR_NAME: - if (c == ':') { - state = HDR_VALUE; - *p = 0; - ntmp = strip_spaces(q); - if (!ntmp) { - OPENSSL_PUT_ERROR(X509V3, X509V3_R_INVALID_NULL_NAME); - goto err; - } - q = p + 1; - } else if (c == ',') { - *p = 0; - ntmp = strip_spaces(q); - q = p + 1; +STACK_OF(CONF_VALUE) *X509V3_parse_list(const char *line) { + char *p, *q, c; + char *ntmp, *vtmp; + STACK_OF(CONF_VALUE) *values = NULL; + char *linebuf; + int state; + /* We are going to modify the line so copy it first */ + linebuf = OPENSSL_strdup(line); + if (linebuf == NULL) { + OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE); + goto err; + } + state = HDR_NAME; + ntmp = NULL; + /* Go through all characters */ + for (p = linebuf, q = linebuf; (c = *p) && (c != '\r') && (c != '\n'); p++) { + switch (state) { + case HDR_NAME: + if (c == ':') { + state = HDR_VALUE; + *p = 0; + ntmp = strip_spaces(q); + if (!ntmp) { + OPENSSL_PUT_ERROR(X509V3, X509V3_R_INVALID_NULL_NAME); + goto err; + } + q = p + 1; + } else if (c == ',') { + *p = 0; + ntmp = strip_spaces(q); + q = p + 1; #if 0 printf("%s\n", ntmp); #endif - if (!ntmp) { - OPENSSL_PUT_ERROR(X509V3, X509V3_R_INVALID_NULL_NAME); - goto err; - } - X509V3_add_value(ntmp, NULL, &values); - } - break; - - case HDR_VALUE: - if (c == ',') { - state = HDR_NAME; - *p = 0; - vtmp = strip_spaces(q); + if (!ntmp) { + OPENSSL_PUT_ERROR(X509V3, X509V3_R_INVALID_NULL_NAME); + goto err; + } + X509V3_add_value(ntmp, NULL, &values); + } + break; + + case HDR_VALUE: + if (c == ',') { + state = HDR_NAME; + *p = 0; + vtmp = strip_spaces(q); #if 0 printf("%s\n", ntmp); #endif - if (!vtmp) { - OPENSSL_PUT_ERROR(X509V3, X509V3_R_INVALID_NULL_VALUE); - goto err; - } - X509V3_add_value(ntmp, vtmp, &values); - ntmp = NULL; - q = p + 1; - } - + if (!vtmp) { + OPENSSL_PUT_ERROR(X509V3, X509V3_R_INVALID_NULL_VALUE); + goto err; + } + X509V3_add_value(ntmp, vtmp, &values); + ntmp = NULL; + q = p + 1; } } + } - if (state == HDR_VALUE) { - vtmp = strip_spaces(q); + if (state == HDR_VALUE) { + vtmp = strip_spaces(q); #if 0 printf("%s=%s\n", ntmp, vtmp); #endif - if (!vtmp) { - OPENSSL_PUT_ERROR(X509V3, X509V3_R_INVALID_NULL_VALUE); - goto err; - } - X509V3_add_value(ntmp, vtmp, &values); - } else { - ntmp = strip_spaces(q); + if (!vtmp) { + OPENSSL_PUT_ERROR(X509V3, X509V3_R_INVALID_NULL_VALUE); + goto err; + } + X509V3_add_value(ntmp, vtmp, &values); + } else { + ntmp = strip_spaces(q); #if 0 printf("%s\n", ntmp); #endif - if (!ntmp) { - OPENSSL_PUT_ERROR(X509V3, X509V3_R_INVALID_NULL_NAME); - goto err; - } - X509V3_add_value(ntmp, NULL, &values); + if (!ntmp) { + OPENSSL_PUT_ERROR(X509V3, X509V3_R_INVALID_NULL_NAME); + goto err; } - OPENSSL_free(linebuf); - return values; - - err: - OPENSSL_free(linebuf); - sk_CONF_VALUE_pop_free(values, X509V3_conf_free); - return NULL; + X509V3_add_value(ntmp, NULL, &values); + } + OPENSSL_free(linebuf); + return values; +err: + OPENSSL_free(linebuf); + sk_CONF_VALUE_pop_free(values, X509V3_conf_free); + return NULL; } /* Delete leading and trailing spaces from a string */ -static char *strip_spaces(char *name) -{ - char *p, *q; - /* Skip over leading spaces */ - p = name; - while (*p && isspace((unsigned char)*p)) - p++; - if (!*p) - return NULL; - q = p + strlen(p) - 1; - while ((q != p) && isspace((unsigned char)*q)) - q--; - if (p != q) - q[1] = 0; - if (!*p) - return NULL; - return p; +static char *strip_spaces(char *name) { + char *p, *q; + /* Skip over leading spaces */ + p = name; + while (*p && isspace((unsigned char)*p)) { + p++; + } + if (!*p) { + return NULL; + } + q = p + strlen(p) - 1; + while ((q != p) && isspace((unsigned char)*q)) { + q--; + } + if (p != q) { + q[1] = 0; + } + if (!*p) { + return NULL; + } + return p; } /* hex string utilities */ -char *x509v3_bytes_to_hex(const uint8_t *in, size_t len) -{ - CBB cbb; - if (!CBB_init(&cbb, len * 3 + 1)) { - goto err; - } - for (size_t i = 0; i < len; i++) { - static const char hex[] = "0123456789ABCDEF"; - if ((i > 0 && !CBB_add_u8(&cbb, ':')) || - !CBB_add_u8(&cbb, hex[in[i] >> 4]) || - !CBB_add_u8(&cbb, hex[in[i] & 0xf])) { - goto err; - } - } - uint8_t *ret; - size_t unused_len; - if (!CBB_add_u8(&cbb, 0) || - !CBB_finish(&cbb, &ret, &unused_len)) { - goto err; +char *x509v3_bytes_to_hex(const uint8_t *in, size_t len) { + CBB cbb; + if (!CBB_init(&cbb, len * 3 + 1)) { + goto err; + } + for (size_t i = 0; i < len; i++) { + static const char hex[] = "0123456789ABCDEF"; + if ((i > 0 && !CBB_add_u8(&cbb, ':')) || + !CBB_add_u8(&cbb, hex[in[i] >> 4]) || + !CBB_add_u8(&cbb, hex[in[i] & 0xf])) { + goto err; } + } + uint8_t *ret; + size_t unused_len; + if (!CBB_add_u8(&cbb, 0) || !CBB_finish(&cbb, &ret, &unused_len)) { + goto err; + } - return (char *)ret; + return (char *)ret; err: - OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE); - CBB_cleanup(&cbb); - return NULL; + OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE); + CBB_cleanup(&cbb); + return NULL; } -unsigned char *x509v3_hex_to_bytes(const char *str, long *len) -{ - unsigned char *hexbuf, *q; - unsigned char ch, cl, *p; - if (!str) { - OPENSSL_PUT_ERROR(X509V3, X509V3_R_INVALID_NULL_ARGUMENT); - return NULL; +unsigned char *x509v3_hex_to_bytes(const char *str, long *len) { + unsigned char *hexbuf, *q; + unsigned char ch, cl, *p; + if (!str) { + OPENSSL_PUT_ERROR(X509V3, X509V3_R_INVALID_NULL_ARGUMENT); + return NULL; + } + if (!(hexbuf = OPENSSL_malloc(strlen(str) >> 1))) { + goto err; + } + for (p = (unsigned char *)str, q = hexbuf; *p;) { + ch = *p++; + if (ch == ':') { + continue; + } + cl = *p++; + if (!cl) { + OPENSSL_PUT_ERROR(X509V3, X509V3_R_ODD_NUMBER_OF_DIGITS); + OPENSSL_free(hexbuf); + return NULL; + } + + if ((ch >= '0') && (ch <= '9')) { + ch -= '0'; + } else if ((ch >= 'a') && (ch <= 'f')) { + ch -= 'a' - 10; + } else if ((ch >= 'A') && (ch <= 'F')) { + ch -= 'A' - 10; + } else { + goto badhex; } - if (!(hexbuf = OPENSSL_malloc(strlen(str) >> 1))) - goto err; - for (p = (unsigned char *)str, q = hexbuf; *p;) { - ch = *p++; - if (ch == ':') - continue; - cl = *p++; - if (!cl) { - OPENSSL_PUT_ERROR(X509V3, X509V3_R_ODD_NUMBER_OF_DIGITS); - OPENSSL_free(hexbuf); - return NULL; - } - if ((ch >= '0') && (ch <= '9')) - ch -= '0'; - else if ((ch >= 'a') && (ch <= 'f')) - ch -= 'a' - 10; - else if ((ch >= 'A') && (ch <= 'F')) - ch -= 'A' - 10; - else - goto badhex; - - if ((cl >= '0') && (cl <= '9')) - cl -= '0'; - else if ((cl >= 'a') && (cl <= 'f')) - cl -= 'a' - 10; - else if ((cl >= 'A') && (cl <= 'F')) - cl -= 'A' - 10; - else - goto badhex; - - *q++ = (ch << 4) | cl; + if ((cl >= '0') && (cl <= '9')) { + cl -= '0'; + } else if ((cl >= 'a') && (cl <= 'f')) { + cl -= 'a' - 10; + } else if ((cl >= 'A') && (cl <= 'F')) { + cl -= 'A' - 10; + } else { + goto badhex; } - if (len) - *len = q - hexbuf; + *q++ = (ch << 4) | cl; + } - return hexbuf; + if (len) { + *len = q - hexbuf; + } - err: - if (hexbuf) - OPENSSL_free(hexbuf); - OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE); - return NULL; + return hexbuf; - badhex: +err: + if (hexbuf) { OPENSSL_free(hexbuf); - OPENSSL_PUT_ERROR(X509V3, X509V3_R_ILLEGAL_HEX_DIGIT); - return NULL; - + } + OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE); + return NULL; + +badhex: + OPENSSL_free(hexbuf); + OPENSSL_PUT_ERROR(X509V3, X509V3_R_ILLEGAL_HEX_DIGIT); + return NULL; } -int x509v3_name_cmp(const char *name, const char *cmp) -{ - int len, ret; - char c; - len = strlen(cmp); - if ((ret = strncmp(name, cmp, len))) - return ret; - c = name[len]; - if (!c || (c == '.')) - return 0; - return 1; +int x509v3_name_cmp(const char *name, const char *cmp) { + int len, ret; + char c; + len = strlen(cmp); + if ((ret = strncmp(name, cmp, len))) { + return ret; + } + c = name[len]; + if (!c || (c == '.')) { + return 0; + } + return 1; } -static int sk_strcmp(const OPENSSL_STRING *a, const OPENSSL_STRING *b) -{ - return strcmp(*a, *b); -} +static int sk_strcmp(const char **a, const char **b) { return strcmp(*a, *b); } -STACK_OF(OPENSSL_STRING) *X509_get1_email(X509 *x) -{ - GENERAL_NAMES *gens; - STACK_OF(OPENSSL_STRING) *ret; +STACK_OF(OPENSSL_STRING) *X509_get1_email(X509 *x) { + GENERAL_NAMES *gens; + STACK_OF(OPENSSL_STRING) *ret; - gens = X509_get_ext_d2i(x, NID_subject_alt_name, NULL, NULL); - ret = get_email(X509_get_subject_name(x), gens); - sk_GENERAL_NAME_pop_free(gens, GENERAL_NAME_free); - return ret; + gens = X509_get_ext_d2i(x, NID_subject_alt_name, NULL, NULL); + ret = get_email(X509_get_subject_name(x), gens); + sk_GENERAL_NAME_pop_free(gens, GENERAL_NAME_free); + return ret; } -STACK_OF(OPENSSL_STRING) *X509_get1_ocsp(X509 *x) -{ - AUTHORITY_INFO_ACCESS *info; - STACK_OF(OPENSSL_STRING) *ret = NULL; - size_t i; +STACK_OF(OPENSSL_STRING) *X509_get1_ocsp(X509 *x) { + AUTHORITY_INFO_ACCESS *info; + STACK_OF(OPENSSL_STRING) *ret = NULL; + size_t i; - info = X509_get_ext_d2i(x, NID_info_access, NULL, NULL); - if (!info) - return NULL; - for (i = 0; i < sk_ACCESS_DESCRIPTION_num(info); i++) { - ACCESS_DESCRIPTION *ad = sk_ACCESS_DESCRIPTION_value(info, i); - if (OBJ_obj2nid(ad->method) == NID_ad_OCSP) { - if (ad->location->type == GEN_URI) { - if (!append_ia5 - (&ret, ad->location->d.uniformResourceIdentifier)) - break; - } + info = X509_get_ext_d2i(x, NID_info_access, NULL, NULL); + if (!info) { + return NULL; + } + for (i = 0; i < sk_ACCESS_DESCRIPTION_num(info); i++) { + ACCESS_DESCRIPTION *ad = sk_ACCESS_DESCRIPTION_value(info, i); + if (OBJ_obj2nid(ad->method) == NID_ad_OCSP) { + if (ad->location->type == GEN_URI) { + if (!append_ia5(&ret, ad->location->d.uniformResourceIdentifier)) { + break; } + } } - AUTHORITY_INFO_ACCESS_free(info); - return ret; + } + AUTHORITY_INFO_ACCESS_free(info); + return ret; } -STACK_OF(OPENSSL_STRING) *X509_REQ_get1_email(X509_REQ *x) -{ - GENERAL_NAMES *gens; - STACK_OF(X509_EXTENSION) *exts; - STACK_OF(OPENSSL_STRING) *ret; - - exts = X509_REQ_get_extensions(x); - gens = X509V3_get_d2i(exts, NID_subject_alt_name, NULL, NULL); - ret = get_email(X509_REQ_get_subject_name(x), gens); - sk_GENERAL_NAME_pop_free(gens, GENERAL_NAME_free); - sk_X509_EXTENSION_pop_free(exts, X509_EXTENSION_free); - return ret; +STACK_OF(OPENSSL_STRING) *X509_REQ_get1_email(X509_REQ *x) { + GENERAL_NAMES *gens; + STACK_OF(X509_EXTENSION) *exts; + STACK_OF(OPENSSL_STRING) *ret; + + exts = X509_REQ_get_extensions(x); + gens = X509V3_get_d2i(exts, NID_subject_alt_name, NULL, NULL); + ret = get_email(X509_REQ_get_subject_name(x), gens); + sk_GENERAL_NAME_pop_free(gens, GENERAL_NAME_free); + sk_X509_EXTENSION_pop_free(exts, X509_EXTENSION_free); + return ret; } static STACK_OF(OPENSSL_STRING) *get_email(X509_NAME *name, - GENERAL_NAMES *gens) -{ - STACK_OF(OPENSSL_STRING) *ret = NULL; - X509_NAME_ENTRY *ne; - ASN1_IA5STRING *email; - GENERAL_NAME *gen; - int i; - size_t j; - /* Now add any email address(es) to STACK */ - i = -1; - /* First supplied X509_NAME */ - while ((i = X509_NAME_get_index_by_NID(name, - NID_pkcs9_emailAddress, i)) >= 0) { - ne = X509_NAME_get_entry(name, i); - email = X509_NAME_ENTRY_get_data(ne); - if (!append_ia5(&ret, email)) - return NULL; + GENERAL_NAMES *gens) { + STACK_OF(OPENSSL_STRING) *ret = NULL; + X509_NAME_ENTRY *ne; + ASN1_IA5STRING *email; + GENERAL_NAME *gen; + int i; + size_t j; + /* Now add any email address(es) to STACK */ + i = -1; + /* First supplied X509_NAME */ + while ((i = X509_NAME_get_index_by_NID(name, NID_pkcs9_emailAddress, i)) >= + 0) { + ne = X509_NAME_get_entry(name, i); + email = X509_NAME_ENTRY_get_data(ne); + if (!append_ia5(&ret, email)) { + return NULL; } - for (j = 0; j < sk_GENERAL_NAME_num(gens); j++) { - gen = sk_GENERAL_NAME_value(gens, j); - if (gen->type != GEN_EMAIL) - continue; - if (!append_ia5(&ret, gen->d.ia5)) - return NULL; + } + for (j = 0; j < sk_GENERAL_NAME_num(gens); j++) { + gen = sk_GENERAL_NAME_value(gens, j); + if (gen->type != GEN_EMAIL) { + continue; } - return ret; -} - -static void str_free(OPENSSL_STRING str) -{ - OPENSSL_free(str); + if (!append_ia5(&ret, gen->d.ia5)) { + return NULL; + } + } + return ret; } -static int append_ia5(STACK_OF(OPENSSL_STRING) **sk, ASN1_IA5STRING *email) -{ - /* First some sanity checks */ - if (email->type != V_ASN1_IA5STRING) - return 1; - if (email->data == NULL || email->length == 0) - return 1; - /* |OPENSSL_STRING| cannot represent strings with embedded NULs. Do not - * report them as outputs. */ - if (OPENSSL_memchr(email->data, 0, email->length) != NULL) - return 1; - - char *emtmp = NULL; - if (!*sk) - *sk = sk_OPENSSL_STRING_new(sk_strcmp); - if (!*sk) - goto err; - - emtmp = OPENSSL_strndup((char *)email->data, email->length); - if (emtmp == NULL) { - goto err; - } +static void str_free(OPENSSL_STRING str) { OPENSSL_free(str); } - /* Don't add duplicates */ - sk_OPENSSL_STRING_sort(*sk); - if (sk_OPENSSL_STRING_find(*sk, NULL, emtmp)) { - OPENSSL_free(emtmp); - return 1; - } - if (!sk_OPENSSL_STRING_push(*sk, emtmp)) { - goto err; - } +static int append_ia5(STACK_OF(OPENSSL_STRING) **sk, ASN1_IA5STRING *email) { + /* First some sanity checks */ + if (email->type != V_ASN1_IA5STRING) { return 1; + } + if (email->data == NULL || email->length == 0) { + return 1; + } + /* |OPENSSL_STRING| cannot represent strings with embedded NULs. Do not + * report them as outputs. */ + if (OPENSSL_memchr(email->data, 0, email->length) != NULL) { + return 1; + } + + char *emtmp = NULL; + if (!*sk) { + *sk = sk_OPENSSL_STRING_new(sk_strcmp); + } + if (!*sk) { + goto err; + } + + emtmp = OPENSSL_strndup((char *)email->data, email->length); + if (emtmp == NULL) { + goto err; + } + + /* Don't add duplicates */ + sk_OPENSSL_STRING_sort(*sk); + if (sk_OPENSSL_STRING_find(*sk, NULL, emtmp)) { + OPENSSL_free(emtmp); + return 1; + } + if (!sk_OPENSSL_STRING_push(*sk, emtmp)) { + goto err; + } + return 1; err: - /* TODO(davidben): Fix the error-handling in this file. It currently relies - * on |append_ia5| leaving |*sk| at NULL on error. */ - OPENSSL_free(emtmp); - X509_email_free(*sk); - *sk = NULL; - return 0; + /* TODO(davidben): Fix the error-handling in this file. It currently relies + * on |append_ia5| leaving |*sk| at NULL on error. */ + OPENSSL_free(emtmp); + X509_email_free(*sk); + *sk = NULL; + return 0; } -void X509_email_free(STACK_OF(OPENSSL_STRING) *sk) -{ - sk_OPENSSL_STRING_pop_free(sk, str_free); +void X509_email_free(STACK_OF(OPENSSL_STRING) *sk) { + sk_OPENSSL_STRING_pop_free(sk, str_free); } -typedef int (*equal_fn) (const unsigned char *pattern, size_t pattern_len, - const unsigned char *subject, size_t subject_len, - unsigned int flags); +typedef int (*equal_fn)(const unsigned char *pattern, size_t pattern_len, + const unsigned char *subject, size_t subject_len, + unsigned int flags); /* Compare while ASCII ignoring case. */ static int equal_nocase(const unsigned char *pattern, size_t pattern_len, const unsigned char *subject, size_t subject_len, - unsigned int flags) -{ - if (pattern_len != subject_len) + unsigned int flags) { + if (pattern_len != subject_len) { + return 0; + } + while (pattern_len) { + unsigned char l = *pattern; + unsigned char r = *subject; + /* The pattern must not contain NUL characters. */ + if (l == 0) { + return 0; + } + if (l != r) { + if ('A' <= l && l <= 'Z') { + l = (l - 'A') + 'a'; + } + if ('A' <= r && r <= 'Z') { + r = (r - 'A') + 'a'; + } + if (l != r) { return 0; - while (pattern_len) { - unsigned char l = *pattern; - unsigned char r = *subject; - /* The pattern must not contain NUL characters. */ - if (l == 0) - return 0; - if (l != r) { - if ('A' <= l && l <= 'Z') - l = (l - 'A') + 'a'; - if ('A' <= r && r <= 'Z') - r = (r - 'A') + 'a'; - if (l != r) - return 0; - } - ++pattern; - ++subject; - --pattern_len; + } } - return 1; + ++pattern; + ++subject; + --pattern_len; + } + return 1; } /* Compare using OPENSSL_memcmp. */ static int equal_case(const unsigned char *pattern, size_t pattern_len, const unsigned char *subject, size_t subject_len, - unsigned int flags) -{ - if (pattern_len != subject_len) - return 0; - return !OPENSSL_memcmp(pattern, subject, pattern_len); + unsigned int flags) { + if (pattern_len != subject_len) { + return 0; + } + return !OPENSSL_memcmp(pattern, subject, pattern_len); } /* @@ -755,27 +765,29 @@ static int equal_case(const unsigned char *pattern, size_t pattern_len, */ static int equal_email(const unsigned char *a, size_t a_len, const unsigned char *b, size_t b_len, - unsigned int unused_flags) -{ - size_t i = a_len; - if (a_len != b_len) + unsigned int unused_flags) { + size_t i = a_len; + if (a_len != b_len) { + return 0; + } + /* + * We search backwards for the '@' character, so that we do not have to + * deal with quoted local-parts. The domain part is compared in a + * case-insensitive manner. + */ + while (i > 0) { + --i; + if (a[i] == '@' || b[i] == '@') { + if (!equal_nocase(a + i, a_len - i, b + i, a_len - i, 0)) { return 0; - /* - * We search backwards for the '@' character, so that we do not have to - * deal with quoted local-parts. The domain part is compared in a - * case-insensitive manner. - */ - while (i > 0) { - --i; - if (a[i] == '@' || b[i] == '@') { - if (!equal_nocase(a + i, a_len - i, b + i, a_len - i, 0)) - return 0; - break; - } + } + break; } - if (i == 0) - i = a_len; - return equal_case(a, i, b, i, 0); + } + if (i == 0) { + i = a_len; + } + return equal_case(a, i, b, i, 0); } /* @@ -785,180 +797,185 @@ static int equal_email(const unsigned char *a, size_t a_len, static int wildcard_match(const unsigned char *prefix, size_t prefix_len, const unsigned char *suffix, size_t suffix_len, const unsigned char *subject, size_t subject_len, - unsigned int flags) -{ - const unsigned char *wildcard_start; - const unsigned char *wildcard_end; - const unsigned char *p; - int allow_idna = 0; - - if (subject_len < prefix_len + suffix_len) - return 0; - if (!equal_nocase(prefix, prefix_len, subject, prefix_len, flags)) - return 0; - wildcard_start = subject + prefix_len; - wildcard_end = subject + (subject_len - suffix_len); - if (!equal_nocase(wildcard_end, suffix_len, suffix, suffix_len, flags)) - return 0; - /* - * If the wildcard makes up the entire first label, it must match at - * least one character. - */ - if (prefix_len == 0 && *suffix == '.') { - if (wildcard_start == wildcard_end) - return 0; - allow_idna = 1; + unsigned int flags) { + const unsigned char *wildcard_start; + const unsigned char *wildcard_end; + const unsigned char *p; + int allow_idna = 0; + + if (subject_len < prefix_len + suffix_len) { + return 0; + } + if (!equal_nocase(prefix, prefix_len, subject, prefix_len, flags)) { + return 0; + } + wildcard_start = subject + prefix_len; + wildcard_end = subject + (subject_len - suffix_len); + if (!equal_nocase(wildcard_end, suffix_len, suffix, suffix_len, flags)) { + return 0; + } + /* + * If the wildcard makes up the entire first label, it must match at + * least one character. + */ + if (prefix_len == 0 && *suffix == '.') { + if (wildcard_start == wildcard_end) { + return 0; } - /* IDNA labels cannot match partial wildcards */ - if (!allow_idna && - subject_len >= 4 - && OPENSSL_strncasecmp((char *)subject, "xn--", 4) == 0) - return 0; - /* The wildcard may match a literal '*' */ - if (wildcard_end == wildcard_start + 1 && *wildcard_start == '*') - return 1; - /* - * Check that the part matched by the wildcard contains only - * permitted characters and only matches a single label. - */ - for (p = wildcard_start; p != wildcard_end; ++p) - if (!(('0' <= *p && *p <= '9') || - ('A' <= *p && *p <= 'Z') || - ('a' <= *p && *p <= 'z') || - *p == '-')) - return 0; + allow_idna = 1; + } + /* IDNA labels cannot match partial wildcards */ + if (!allow_idna && subject_len >= 4 && + OPENSSL_strncasecmp((char *)subject, "xn--", 4) == 0) { + return 0; + } + /* The wildcard may match a literal '*' */ + if (wildcard_end == wildcard_start + 1 && *wildcard_start == '*') { return 1; + } + /* + * Check that the part matched by the wildcard contains only + * permitted characters and only matches a single label. + */ + for (p = wildcard_start; p != wildcard_end; ++p) { + if (!(('0' <= *p && *p <= '9') || ('A' <= *p && *p <= 'Z') || + ('a' <= *p && *p <= 'z') || *p == '-')) { + return 0; + } + } + return 1; } -#define LABEL_START (1 << 0) -#define LABEL_END (1 << 1) -#define LABEL_HYPHEN (1 << 2) -#define LABEL_IDNA (1 << 3) +#define LABEL_START (1 << 0) +#define LABEL_END (1 << 1) +#define LABEL_HYPHEN (1 << 2) +#define LABEL_IDNA (1 << 3) static const unsigned char *valid_star(const unsigned char *p, size_t len, - unsigned int flags) -{ - const unsigned char *star = 0; - size_t i; - int state = LABEL_START; - int dots = 0; - for (i = 0; i < len; ++i) { - /* - * Locate first and only legal wildcard, either at the start - * or end of a non-IDNA first and not final label. - */ - if (p[i] == '*') { - int atstart = (state & LABEL_START); - int atend = (i == len - 1 || p[i + 1] == '.'); - /* - * At most one wildcard per pattern. - * No wildcards in IDNA labels. - * No wildcards after the first label. - */ - if (star != NULL || (state & LABEL_IDNA) != 0 || dots) - return NULL; - /* Only full-label '*.example.com' wildcards. */ - if (!atstart || !atend) - return NULL; - star = &p[i]; - state &= ~LABEL_START; - } else if (('a' <= p[i] && p[i] <= 'z') - || ('A' <= p[i] && p[i] <= 'Z') - || ('0' <= p[i] && p[i] <= '9')) { - if ((state & LABEL_START) != 0 - && len - i >= 4 - && OPENSSL_strncasecmp((char *)&p[i], "xn--", 4) == 0) - state |= LABEL_IDNA; - state &= ~(LABEL_HYPHEN | LABEL_START); - } else if (p[i] == '.') { - if ((state & (LABEL_HYPHEN | LABEL_START)) != 0) - return NULL; - state = LABEL_START; - ++dots; - } else if (p[i] == '-') { - /* no domain/subdomain starts with '-' */ - if ((state & LABEL_START) != 0) - return NULL; - state |= LABEL_HYPHEN; - } else - return NULL; - } - + unsigned int flags) { + const unsigned char *star = 0; + size_t i; + int state = LABEL_START; + int dots = 0; + for (i = 0; i < len; ++i) { /* - * The final label must not end in a hyphen or ".", and - * there must be at least two dots after the star. + * Locate first and only legal wildcard, either at the start + * or end of a non-IDNA first and not final label. */ - if ((state & (LABEL_START | LABEL_HYPHEN)) != 0 || dots < 2) + if (p[i] == '*') { + int atstart = (state & LABEL_START); + int atend = (i == len - 1 || p[i + 1] == '.'); + /* + * At most one wildcard per pattern. + * No wildcards in IDNA labels. + * No wildcards after the first label. + */ + if (star != NULL || (state & LABEL_IDNA) != 0 || dots) { return NULL; - return star; + } + /* Only full-label '*.example.com' wildcards. */ + if (!atstart || !atend) { + return NULL; + } + star = &p[i]; + state &= ~LABEL_START; + } else if (('a' <= p[i] && p[i] <= 'z') || ('A' <= p[i] && p[i] <= 'Z') || + ('0' <= p[i] && p[i] <= '9')) { + if ((state & LABEL_START) != 0 && len - i >= 4 && + OPENSSL_strncasecmp((char *)&p[i], "xn--", 4) == 0) { + state |= LABEL_IDNA; + } + state &= ~(LABEL_HYPHEN | LABEL_START); + } else if (p[i] == '.') { + if ((state & (LABEL_HYPHEN | LABEL_START)) != 0) { + return NULL; + } + state = LABEL_START; + ++dots; + } else if (p[i] == '-') { + /* no domain/subdomain starts with '-' */ + if ((state & LABEL_START) != 0) { + return NULL; + } + state |= LABEL_HYPHEN; + } else { + return NULL; + } + } + + /* + * The final label must not end in a hyphen or ".", and + * there must be at least two dots after the star. + */ + if ((state & (LABEL_START | LABEL_HYPHEN)) != 0 || dots < 2) { + return NULL; + } + return star; } /* Compare using wildcards. */ static int equal_wildcard(const unsigned char *pattern, size_t pattern_len, const unsigned char *subject, size_t subject_len, - unsigned int flags) -{ - const unsigned char *star = NULL; - - /* - * Subject names starting with '.' can only match a wildcard pattern - * via a subject sub-domain pattern suffix match. - */ - if (!(subject_len > 1 && subject[0] == '.')) - star = valid_star(pattern, pattern_len, flags); - if (star == NULL) - return equal_nocase(pattern, pattern_len, - subject, subject_len, flags); - return wildcard_match(pattern, star - pattern, - star + 1, (pattern + pattern_len) - star - 1, - subject, subject_len, flags); + unsigned int flags) { + const unsigned char *star = NULL; + + /* + * Subject names starting with '.' can only match a wildcard pattern + * via a subject sub-domain pattern suffix match. + */ + if (!(subject_len > 1 && subject[0] == '.')) { + star = valid_star(pattern, pattern_len, flags); + } + if (star == NULL) { + return equal_nocase(pattern, pattern_len, subject, subject_len, flags); + } + return wildcard_match(pattern, star - pattern, star + 1, + (pattern + pattern_len) - star - 1, subject, + subject_len, flags); } int x509v3_looks_like_dns_name(const unsigned char *in, size_t len) { - /* This function is used as a heuristic for whether a common name is a - * hostname to be matched, or merely a decorative name to describe the - * subject. This heuristic must be applied to both name constraints and the - * common name fallback, so it must be loose enough to accept hostname - * common names, and tight enough to reject decorative common names. */ - - if (len > 0 && in[len - 1] == '.') { - len--; + /* This function is used as a heuristic for whether a common name is a + * hostname to be matched, or merely a decorative name to describe the + * subject. This heuristic must be applied to both name constraints and the + * common name fallback, so it must be loose enough to accept hostname + * common names, and tight enough to reject decorative common names. */ + + if (len > 0 && in[len - 1] == '.') { + len--; + } + + /* Wildcards are allowed in front. */ + if (len >= 2 && in[0] == '*' && in[1] == '.') { + in += 2; + len -= 2; + } + + if (len == 0) { + return 0; + } + + size_t label_start = 0; + for (size_t i = 0; i < len; i++) { + unsigned char c = in[i]; + if ((c >= 'a' && c <= 'z') || (c >= '0' && c <= '9') || + (c >= 'A' && c <= 'Z') || (c == '-' && i > label_start) || + /* These are not valid characters in hostnames, but commonly found + * in deployments outside the Web PKI. */ + c == '_' || c == ':') { + continue; } - /* Wildcards are allowed in front. */ - if (len >= 2 && in[0] == '*' && in[1] == '.') { - in += 2; - len -= 2; + /* Labels must not be empty. */ + if (c == '.' && i > label_start && i < len - 1) { + label_start = i + 1; + continue; } - if (len == 0) { - return 0; - } - - size_t label_start = 0; - for (size_t i = 0; i < len; i++) { - unsigned char c = in[i]; - if ((c >= 'a' && c <= 'z') || - (c >= '0' && c <= '9') || - (c >= 'A' && c <= 'Z') || - (c == '-' && i > label_start) || - /* These are not valid characters in hostnames, but commonly found - * in deployments outside the Web PKI. */ - c == '_' || - c == ':') { - continue; - } - - /* Labels must not be empty. */ - if (c == '.' && i > label_start && i < len - 1) { - label_start = i + 1; - continue; - } - - return 0; - } + return 0; + } - return 1; + return 1; } /* @@ -969,154 +986,166 @@ int x509v3_looks_like_dns_name(const unsigned char *in, size_t len) { static int do_check_string(ASN1_STRING *a, int cmp_type, equal_fn equal, unsigned int flags, int check_type, const char *b, - size_t blen, char **peername) -{ - int rv = 0; + size_t blen, char **peername) { + int rv = 0; - if (!a->data || !a->length) - return 0; - if (cmp_type > 0) { - if (cmp_type != a->type) - return 0; - if (cmp_type == V_ASN1_IA5STRING) - rv = equal(a->data, a->length, (unsigned char *)b, blen, flags); - else if (a->length == (int)blen && !OPENSSL_memcmp(a->data, b, blen)) - rv = 1; - if (rv > 0 && peername) - *peername = OPENSSL_strndup((char *)a->data, a->length); + if (!a->data || !a->length) { + return 0; + } + if (cmp_type > 0) { + if (cmp_type != a->type) { + return 0; + } + if (cmp_type == V_ASN1_IA5STRING) { + rv = equal(a->data, a->length, (unsigned char *)b, blen, flags); + } else if (a->length == (int)blen && !OPENSSL_memcmp(a->data, b, blen)) { + rv = 1; + } + if (rv > 0 && peername) { + *peername = OPENSSL_strndup((char *)a->data, a->length); + } + } else { + int astrlen; + unsigned char *astr; + astrlen = ASN1_STRING_to_UTF8(&astr, a); + if (astrlen < 0) { + return -1; + } + /* + * We check the common name against DNS name constraints if it passes + * |x509v3_looks_like_dns_name|. Thus we must not consider common names + * for DNS fallbacks if they fail this check. + */ + if (check_type == GEN_DNS && !x509v3_looks_like_dns_name(astr, astrlen)) { + rv = 0; } else { - int astrlen; - unsigned char *astr; - astrlen = ASN1_STRING_to_UTF8(&astr, a); - if (astrlen < 0) - return -1; - /* - * We check the common name against DNS name constraints if it passes - * |x509v3_looks_like_dns_name|. Thus we must not consider common names - * for DNS fallbacks if they fail this check. - */ - if (check_type == GEN_DNS && - !x509v3_looks_like_dns_name(astr, astrlen)) { - rv = 0; - } else { - rv = equal(astr, astrlen, (unsigned char *)b, blen, flags); - } - if (rv > 0 && peername) - *peername = OPENSSL_strndup((char *)astr, astrlen); - OPENSSL_free(astr); + rv = equal(astr, astrlen, (unsigned char *)b, blen, flags); } - return rv; + if (rv > 0 && peername) { + *peername = OPENSSL_strndup((char *)astr, astrlen); + } + OPENSSL_free(astr); + } + return rv; } static int do_x509_check(X509 *x, const char *chk, size_t chklen, - unsigned int flags, int check_type, char **peername) -{ - GENERAL_NAMES *gens = NULL; - X509_NAME *name = NULL; - size_t i; - int j; - int cnid = NID_undef; - int alt_type; - int rv = 0; - equal_fn equal; - - if (check_type == GEN_EMAIL) { - cnid = NID_pkcs9_emailAddress; - alt_type = V_ASN1_IA5STRING; - equal = equal_email; - } else if (check_type == GEN_DNS) { - cnid = NID_commonName; - alt_type = V_ASN1_IA5STRING; - if (flags & X509_CHECK_FLAG_NO_WILDCARDS) - equal = equal_nocase; - else - equal = equal_wildcard; + unsigned int flags, int check_type, char **peername) { + GENERAL_NAMES *gens = NULL; + X509_NAME *name = NULL; + size_t i; + int j; + int cnid = NID_undef; + int alt_type; + int rv = 0; + equal_fn equal; + + if (check_type == GEN_EMAIL) { + cnid = NID_pkcs9_emailAddress; + alt_type = V_ASN1_IA5STRING; + equal = equal_email; + } else if (check_type == GEN_DNS) { + cnid = NID_commonName; + alt_type = V_ASN1_IA5STRING; + if (flags & X509_CHECK_FLAG_NO_WILDCARDS) { + equal = equal_nocase; } else { - alt_type = V_ASN1_OCTET_STRING; - equal = equal_case; + equal = equal_wildcard; } - - gens = X509_get_ext_d2i(x, NID_subject_alt_name, NULL, NULL); - if (gens) { - for (i = 0; i < sk_GENERAL_NAME_num(gens); i++) { - GENERAL_NAME *gen; - ASN1_STRING *cstr; - gen = sk_GENERAL_NAME_value(gens, i); - if (gen->type != check_type) - continue; - if (check_type == GEN_EMAIL) - cstr = gen->d.rfc822Name; - else if (check_type == GEN_DNS) - cstr = gen->d.dNSName; - else - cstr = gen->d.iPAddress; - /* Positive on success, negative on error! */ - if ((rv = do_check_string(cstr, alt_type, equal, flags, check_type, - chk, chklen, peername)) != 0) - break; - } - GENERAL_NAMES_free(gens); - return rv; + } else { + alt_type = V_ASN1_OCTET_STRING; + equal = equal_case; + } + + gens = X509_get_ext_d2i(x, NID_subject_alt_name, NULL, NULL); + if (gens) { + for (i = 0; i < sk_GENERAL_NAME_num(gens); i++) { + GENERAL_NAME *gen; + ASN1_STRING *cstr; + gen = sk_GENERAL_NAME_value(gens, i); + if (gen->type != check_type) { + continue; + } + if (check_type == GEN_EMAIL) { + cstr = gen->d.rfc822Name; + } else if (check_type == GEN_DNS) { + cstr = gen->d.dNSName; + } else { + cstr = gen->d.iPAddress; + } + /* Positive on success, negative on error! */ + if ((rv = do_check_string(cstr, alt_type, equal, flags, check_type, chk, + chklen, peername)) != 0) { + break; + } } + GENERAL_NAMES_free(gens); + return rv; + } - /* We're done if CN-ID is not pertinent */ - if (cnid == NID_undef || (flags & X509_CHECK_FLAG_NEVER_CHECK_SUBJECT)) - return 0; + /* We're done if CN-ID is not pertinent */ + if (cnid == NID_undef || (flags & X509_CHECK_FLAG_NEVER_CHECK_SUBJECT)) { + return 0; + } - j = -1; - name = X509_get_subject_name(x); - while ((j = X509_NAME_get_index_by_NID(name, cnid, j)) >= 0) { - X509_NAME_ENTRY *ne; - ASN1_STRING *str; - ne = X509_NAME_get_entry(name, j); - str = X509_NAME_ENTRY_get_data(ne); - /* Positive on success, negative on error! */ - if ((rv = do_check_string(str, -1, equal, flags, check_type, - chk, chklen, peername)) != 0) - return rv; + j = -1; + name = X509_get_subject_name(x); + while ((j = X509_NAME_get_index_by_NID(name, cnid, j)) >= 0) { + X509_NAME_ENTRY *ne; + ASN1_STRING *str; + ne = X509_NAME_get_entry(name, j); + str = X509_NAME_ENTRY_get_data(ne); + /* Positive on success, negative on error! */ + if ((rv = do_check_string(str, -1, equal, flags, check_type, chk, chklen, + peername)) != 0) { + return rv; } - return 0; + } + return 0; } -int X509_check_host(X509 *x, const char *chk, size_t chklen, - unsigned int flags, char **peername) -{ - if (chk == NULL) - return -2; - if (OPENSSL_memchr(chk, '\0', chklen)) - return -2; - return do_x509_check(x, chk, chklen, flags, GEN_DNS, peername); +int X509_check_host(X509 *x, const char *chk, size_t chklen, unsigned int flags, + char **peername) { + if (chk == NULL) { + return -2; + } + if (OPENSSL_memchr(chk, '\0', chklen)) { + return -2; + } + return do_x509_check(x, chk, chklen, flags, GEN_DNS, peername); } int X509_check_email(X509 *x, const char *chk, size_t chklen, - unsigned int flags) -{ - if (chk == NULL) - return -2; - if (OPENSSL_memchr(chk, '\0', chklen)) - return -2; - return do_x509_check(x, chk, chklen, flags, GEN_EMAIL, NULL); + unsigned int flags) { + if (chk == NULL) { + return -2; + } + if (OPENSSL_memchr(chk, '\0', chklen)) { + return -2; + } + return do_x509_check(x, chk, chklen, flags, GEN_EMAIL, NULL); } int X509_check_ip(X509 *x, const unsigned char *chk, size_t chklen, - unsigned int flags) -{ - if (chk == NULL) - return -2; - return do_x509_check(x, (char *)chk, chklen, flags, GEN_IPADD, NULL); + unsigned int flags) { + if (chk == NULL) { + return -2; + } + return do_x509_check(x, (char *)chk, chklen, flags, GEN_IPADD, NULL); } -int X509_check_ip_asc(X509 *x, const char *ipasc, unsigned int flags) -{ - unsigned char ipout[16]; - size_t iplen; - - if (ipasc == NULL) - return -2; - iplen = (size_t)x509v3_a2i_ipadd(ipout, ipasc); - if (iplen == 0) - return -2; - return do_x509_check(x, (char *)ipout, iplen, flags, GEN_IPADD, NULL); +int X509_check_ip_asc(X509 *x, const char *ipasc, unsigned int flags) { + unsigned char ipout[16]; + size_t iplen; + + if (ipasc == NULL) { + return -2; + } + iplen = (size_t)x509v3_a2i_ipadd(ipout, ipasc); + if (iplen == 0) { + return -2; + } + return do_x509_check(x, (char *)ipout, iplen, flags, GEN_IPADD, NULL); } /* @@ -1124,276 +1153,301 @@ int X509_check_ip_asc(X509 *x, const char *ipasc, unsigned int flags) * with RFC 3280. */ -ASN1_OCTET_STRING *a2i_IPADDRESS(const char *ipasc) -{ - unsigned char ipout[16]; - ASN1_OCTET_STRING *ret; - int iplen; +ASN1_OCTET_STRING *a2i_IPADDRESS(const char *ipasc) { + unsigned char ipout[16]; + ASN1_OCTET_STRING *ret; + int iplen; - iplen = x509v3_a2i_ipadd(ipout, ipasc); - if (!iplen) - return NULL; + iplen = x509v3_a2i_ipadd(ipout, ipasc); + if (!iplen) { + return NULL; + } - ret = ASN1_OCTET_STRING_new(); - if (!ret) - return NULL; - if (!ASN1_OCTET_STRING_set(ret, ipout, iplen)) { - ASN1_OCTET_STRING_free(ret); - return NULL; - } - return ret; + ret = ASN1_OCTET_STRING_new(); + if (!ret) { + return NULL; + } + if (!ASN1_OCTET_STRING_set(ret, ipout, iplen)) { + ASN1_OCTET_STRING_free(ret); + return NULL; + } + return ret; } -ASN1_OCTET_STRING *a2i_IPADDRESS_NC(const char *ipasc) -{ - ASN1_OCTET_STRING *ret = NULL; - unsigned char ipout[32]; - char *iptmp = NULL, *p; - int iplen1, iplen2; - p = strchr(ipasc, '/'); - if (!p) - return NULL; - iptmp = OPENSSL_strdup(ipasc); - if (!iptmp) - return NULL; - p = iptmp + (p - ipasc); - *p++ = 0; +ASN1_OCTET_STRING *a2i_IPADDRESS_NC(const char *ipasc) { + ASN1_OCTET_STRING *ret = NULL; + unsigned char ipout[32]; + char *iptmp = NULL, *p; + int iplen1, iplen2; + p = strchr(ipasc, '/'); + if (!p) { + return NULL; + } + iptmp = OPENSSL_strdup(ipasc); + if (!iptmp) { + return NULL; + } + p = iptmp + (p - ipasc); + *p++ = 0; - iplen1 = x509v3_a2i_ipadd(ipout, iptmp); + iplen1 = x509v3_a2i_ipadd(ipout, iptmp); - if (!iplen1) - goto err; + if (!iplen1) { + goto err; + } - iplen2 = x509v3_a2i_ipadd(ipout + iplen1, p); + iplen2 = x509v3_a2i_ipadd(ipout + iplen1, p); - OPENSSL_free(iptmp); - iptmp = NULL; + OPENSSL_free(iptmp); + iptmp = NULL; - if (!iplen2 || (iplen1 != iplen2)) - goto err; + if (!iplen2 || (iplen1 != iplen2)) { + goto err; + } - ret = ASN1_OCTET_STRING_new(); - if (!ret) - goto err; - if (!ASN1_OCTET_STRING_set(ret, ipout, iplen1 + iplen2)) - goto err; + ret = ASN1_OCTET_STRING_new(); + if (!ret) { + goto err; + } + if (!ASN1_OCTET_STRING_set(ret, ipout, iplen1 + iplen2)) { + goto err; + } - return ret; + return ret; - err: - if (iptmp) - OPENSSL_free(iptmp); - if (ret) - ASN1_OCTET_STRING_free(ret); - return NULL; +err: + if (iptmp) { + OPENSSL_free(iptmp); + } + if (ret) { + ASN1_OCTET_STRING_free(ret); + } + return NULL; } -int x509v3_a2i_ipadd(unsigned char ipout[16], const char *ipasc) -{ - /* If string contains a ':' assume IPv6 */ +int x509v3_a2i_ipadd(unsigned char ipout[16], const char *ipasc) { + /* If string contains a ':' assume IPv6 */ - if (strchr(ipasc, ':')) { - if (!ipv6_from_asc(ipout, ipasc)) - return 0; - return 16; - } else { - if (!ipv4_from_asc(ipout, ipasc)) - return 0; - return 4; + if (strchr(ipasc, ':')) { + if (!ipv6_from_asc(ipout, ipasc)) { + return 0; } + return 16; + } else { + if (!ipv4_from_asc(ipout, ipasc)) { + return 0; + } + return 4; + } } -static int ipv4_from_asc(unsigned char v4[4], const char *in) -{ - int a0, a1, a2, a3; - if (sscanf(in, "%d.%d.%d.%d", &a0, &a1, &a2, &a3) != 4) - return 0; - if ((a0 < 0) || (a0 > 255) || (a1 < 0) || (a1 > 255) - || (a2 < 0) || (a2 > 255) || (a3 < 0) || (a3 > 255)) - return 0; - v4[0] = a0; - v4[1] = a1; - v4[2] = a2; - v4[3] = a3; - return 1; +static int ipv4_from_asc(unsigned char v4[4], const char *in) { + int a0, a1, a2, a3; + if (sscanf(in, "%d.%d.%d.%d", &a0, &a1, &a2, &a3) != 4) { + return 0; + } + if ((a0 < 0) || (a0 > 255) || (a1 < 0) || (a1 > 255) || (a2 < 0) || + (a2 > 255) || (a3 < 0) || (a3 > 255)) { + return 0; + } + v4[0] = a0; + v4[1] = a1; + v4[2] = a2; + v4[3] = a3; + return 1; } typedef struct { - /* Temporary store for IPV6 output */ - unsigned char tmp[16]; - /* Total number of bytes in tmp */ - int total; - /* The position of a zero (corresponding to '::') */ - int zero_pos; - /* Number of zeroes */ - int zero_cnt; + /* Temporary store for IPV6 output */ + unsigned char tmp[16]; + /* Total number of bytes in tmp */ + int total; + /* The position of a zero (corresponding to '::') */ + int zero_pos; + /* Number of zeroes */ + int zero_cnt; } IPV6_STAT; -static int ipv6_from_asc(unsigned char v6[16], const char *in) -{ - IPV6_STAT v6stat; - v6stat.total = 0; - v6stat.zero_pos = -1; - v6stat.zero_cnt = 0; - /* - * Treat the IPv6 representation as a list of values separated by ':'. - * The presence of a '::' will parse as one, two or three zero length - * elements. - */ - if (!CONF_parse_list(in, ':', 0, ipv6_cb, &v6stat)) - return 0; +static int ipv6_from_asc(unsigned char v6[16], const char *in) { + IPV6_STAT v6stat; + v6stat.total = 0; + v6stat.zero_pos = -1; + v6stat.zero_cnt = 0; + /* + * Treat the IPv6 representation as a list of values separated by ':'. + * The presence of a '::' will parse as one, two or three zero length + * elements. + */ + if (!CONF_parse_list(in, ':', 0, ipv6_cb, &v6stat)) { + return 0; + } - /* Now for some sanity checks */ + /* Now for some sanity checks */ - if (v6stat.zero_pos == -1) { - /* If no '::' must have exactly 16 bytes */ - if (v6stat.total != 16) - return 0; - } else { - /* If '::' must have less than 16 bytes */ - if (v6stat.total == 16) - return 0; - /* More than three zeroes is an error */ - if (v6stat.zero_cnt > 3) - return 0; - /* Can only have three zeroes if nothing else present */ - else if (v6stat.zero_cnt == 3) { - if (v6stat.total > 0) - return 0; - } - /* Can only have two zeroes if at start or end */ - else if (v6stat.zero_cnt == 2) { - if ((v6stat.zero_pos != 0) - && (v6stat.zero_pos != v6stat.total)) - return 0; - } else - /* Can only have one zero if *not* start or end */ - { - if ((v6stat.zero_pos == 0) - || (v6stat.zero_pos == v6stat.total)) - return 0; - } + if (v6stat.zero_pos == -1) { + /* If no '::' must have exactly 16 bytes */ + if (v6stat.total != 16) { + return 0; } - - /* Format result */ - - if (v6stat.zero_pos >= 0) { - /* Copy initial part */ - OPENSSL_memcpy(v6, v6stat.tmp, v6stat.zero_pos); - /* Zero middle */ - // This condition is to suppress gcc-12 warning. - // https://github.com/awslabs/aws-lc/issues/487 - if (v6stat.zero_pos >= v6stat.total) { - // This should not happen. - return 0; - } - OPENSSL_memset(v6 + v6stat.zero_pos, 0, 16 - v6stat.total); - /* Copy final part */ - if (v6stat.total != v6stat.zero_pos) - OPENSSL_memcpy(v6 + v6stat.zero_pos + 16 - v6stat.total, - v6stat.tmp + v6stat.zero_pos, - v6stat.total - v6stat.zero_pos); + } else { + /* If '::' must have less than 16 bytes */ + if (v6stat.total == 16) { + return 0; + } + /* More than three zeroes is an error */ + if (v6stat.zero_cnt > 3) { + return 0; + } + /* Can only have three zeroes if nothing else present */ + else if (v6stat.zero_cnt == 3) { + if (v6stat.total > 0) { + return 0; + } + } + /* Can only have two zeroes if at start or end */ + else if (v6stat.zero_cnt == 2) { + if ((v6stat.zero_pos != 0) && (v6stat.zero_pos != v6stat.total)) { + return 0; + } } else - OPENSSL_memcpy(v6, v6stat.tmp, 16); + /* Can only have one zero if *not* start or end */ + { + if ((v6stat.zero_pos == 0) || (v6stat.zero_pos == v6stat.total)) { + return 0; + } + } + } + + /* Format result */ + + if (v6stat.zero_pos >= 0) { + /* Copy initial part */ + OPENSSL_memcpy(v6, v6stat.tmp, v6stat.zero_pos); + /* Zero middle */ + // This condition is to suppress gcc-12 warning. + // https://github.com/awslabs/aws-lc/issues/487 + if (v6stat.zero_pos >= v6stat.total) { + // This should not happen. + return 0; + } + OPENSSL_memset(v6 + v6stat.zero_pos, 0, 16 - v6stat.total); + /* Copy final part */ + if (v6stat.total != v6stat.zero_pos) { + OPENSSL_memcpy(v6 + v6stat.zero_pos + 16 - v6stat.total, + v6stat.tmp + v6stat.zero_pos, + v6stat.total - v6stat.zero_pos); + } + } else { + OPENSSL_memcpy(v6, v6stat.tmp, 16); + } - return 1; + return 1; } -static int ipv6_cb(const char *elem, int len, void *usr) -{ - IPV6_STAT *s = usr; - /* Error if 16 bytes written */ - if (s->total == 16) +static int ipv6_cb(const char *elem, int len, void *usr) { + IPV6_STAT *s = usr; + /* Error if 16 bytes written */ + if (s->total == 16) { + return 0; + } + if (len == 0) { + /* Zero length element, corresponds to '::' */ + if (s->zero_pos == -1) { + s->zero_pos = s->total; + } + /* If we've already got a :: its an error */ + else if (s->zero_pos != s->total) { + return 0; + } + s->zero_cnt++; + } else { + /* If more than 4 characters could be final a.b.c.d form */ + if (len > 4) { + /* Need at least 4 bytes left */ + if (s->total > 12) { return 0; - if (len == 0) { - /* Zero length element, corresponds to '::' */ - if (s->zero_pos == -1) - s->zero_pos = s->total; - /* If we've already got a :: its an error */ - else if (s->zero_pos != s->total) - return 0; - s->zero_cnt++; + } + /* Must be end of string */ + if (elem[len]) { + return 0; + } + if (!ipv4_from_asc(s->tmp + s->total, elem)) { + return 0; + } + s->total += 4; } else { - /* If more than 4 characters could be final a.b.c.d form */ - if (len > 4) { - /* Need at least 4 bytes left */ - if (s->total > 12) - return 0; - /* Must be end of string */ - if (elem[len]) - return 0; - if (!ipv4_from_asc(s->tmp + s->total, elem)) - return 0; - s->total += 4; - } else { - if (!ipv6_hex(s->tmp + s->total, elem, len)) - return 0; - s->total += 2; - } + if (!ipv6_hex(s->tmp + s->total, elem, len)) { + return 0; + } + s->total += 2; } - return 1; + } + return 1; } /* * Convert a string of up to 4 hex digits into the corresponding IPv6 form. */ -static int ipv6_hex(unsigned char *out, const char *in, int inlen) -{ - unsigned char c; - unsigned int num = 0; - if (inlen > 4) - return 0; - while (inlen--) { - c = *in++; - num <<= 4; - if ((c >= '0') && (c <= '9')) - num |= c - '0'; - else if ((c >= 'A') && (c <= 'F')) - num |= c - 'A' + 10; - else if ((c >= 'a') && (c <= 'f')) - num |= c - 'a' + 10; - else - return 0; +static int ipv6_hex(unsigned char *out, const char *in, int inlen) { + unsigned char c; + unsigned int num = 0; + if (inlen > 4) { + return 0; + } + while (inlen--) { + c = *in++; + num <<= 4; + if ((c >= '0') && (c <= '9')) { + num |= c - '0'; + } else if ((c >= 'A') && (c <= 'F')) { + num |= c - 'A' + 10; + } else if ((c >= 'a') && (c <= 'f')) { + num |= c - 'a' + 10; + } else { + return 0; } - out[0] = num >> 8; - out[1] = num & 0xff; - return 1; + } + out[0] = num >> 8; + out[1] = num & 0xff; + return 1; } -int X509V3_NAME_from_section(X509_NAME *nm, STACK_OF (CONF_VALUE) * dn_sk, - unsigned long chtype) -{ - CONF_VALUE *v; - int mval; - size_t i; - char *p, *type; - if (!nm) - return 0; - - for (i = 0; i < sk_CONF_VALUE_num(dn_sk); i++) { - v = sk_CONF_VALUE_value(dn_sk, i); - type = v->name; - /* - * Skip past any leading X. X: X, etc to allow for multiple instances - */ - for (p = type; *p; p++) - if ((*p == ':') || (*p == ',') || (*p == '.')) { - p++; - if (*p) - type = p; - break; - } - if (*type == '+') { - mval = -1; - type++; - } else - mval = 0; - if (!X509_NAME_add_entry_by_txt(nm, type, chtype, - (unsigned char *)v->value, -1, -1, - mval)) - return 0; +int X509V3_NAME_from_section(X509_NAME *nm, STACK_OF(CONF_VALUE) *dn_sk, + unsigned long chtype) { + CONF_VALUE *v; + int mval; + size_t i; + char *p, *type; + if (!nm) { + return 0; + } + for (i = 0; i < sk_CONF_VALUE_num(dn_sk); i++) { + v = sk_CONF_VALUE_value(dn_sk, i); + type = v->name; + /* + * Skip past any leading X. X: X, etc to allow for multiple instances + */ + for (p = type; *p; p++) { + if ((*p == ':') || (*p == ',') || (*p == '.')) { + p++; + if (*p) { + type = p; + } + break; + } } - return 1; + if (*type == '+') { + mval = -1; + type++; + } else { + mval = 0; + } + if (!X509_NAME_add_entry_by_txt(nm, type, chtype, (unsigned char *)v->value, + -1, -1, mval)) { + return 0; + } + } + return 1; } diff --git a/include/openssl/bytestring.h b/include/openssl/bytestring.h index 68c1ba4c57..846ab24612 100644 --- a/include/openssl/bytestring.h +++ b/include/openssl/bytestring.h @@ -18,6 +18,7 @@ #include #include +#include #if defined(__cplusplus) extern "C" { @@ -353,6 +354,25 @@ OPENSSL_EXPORT int CBS_is_unsigned_asn1_integer(const CBS *cbs); OPENSSL_EXPORT char *CBS_asn1_oid_to_text(const CBS *cbs); +// CBS_parse_generalized_time returns one if |cbs| is a valid DER-encoded, ASN.1 +// GeneralizedTime body within the limitations imposed by RFC 5280, or zero +// otherwise. If |allow_timezone_offset| is non-zero, four-digit timezone +// offsets, which would not be allowed by DER, are permitted. On success, if +// |out_tm| is non-NULL, |*out_tm| will be zeroed, and then set to the +// corresponding time in UTC. This function does not compute |out_tm->tm_wday| +// or |out_tm->tm_yday|. +OPENSSL_EXPORT int CBS_parse_generalized_time(const CBS *cbs, struct tm *out_tm, + int allow_timezeone_offset); + +// CBS_parse_utc_time returns one if |cbs| is a valid DER-encoded, ASN.1 +// UTCTime body within the limitations imposed by RFC 5280, or zero otherwise. +// If |allow_timezone_offset| is non-zero, four-digit timezone offsets, which +// would not be allowed by DER, are permitted. On success, if |out_tm| is +// non-NULL, |*out_tm| will be zeroed, and then set to the corresponding time +// in UTC. This function does not compute |out_tm->tm_wday| or |out_tm->tm_yday|. +OPENSSL_EXPORT int CBS_parse_utc_time(const CBS *cbs, struct tm *out_tm, + int allow_timezeone_offset); + // CRYPTO ByteBuilder. // // |CBB| objects allow one to build length-prefixed serialisations. A |CBB| diff --git a/include/openssl/ssl.h b/include/openssl/ssl.h index a2820382ce..0f51d8a686 100644 --- a/include/openssl/ssl.h +++ b/include/openssl/ssl.h @@ -2792,7 +2792,7 @@ OPENSSL_EXPORT int SSL_CTX_add_client_CA(SSL_CTX *ctx, X509 *x509); // SSL_load_client_CA_file opens |file| and reads PEM-encoded certificates from // it. It returns a newly-allocated stack of the certificate subjects or NULL -// on error. +// on error. Duplicates in |file| are ignored. OPENSSL_EXPORT STACK_OF(X509_NAME) *SSL_load_client_CA_file(const char *file); // SSL_dup_CA_list makes a deep copy of |list|. It returns the new list on @@ -2805,6 +2805,11 @@ OPENSSL_EXPORT STACK_OF(X509_NAME) *SSL_dup_CA_list(STACK_OF(X509_NAME) *list); OPENSSL_EXPORT int SSL_add_file_cert_subjects_to_stack(STACK_OF(X509_NAME) *out, const char *file); +// SSL_add_bio_cert_subjects_to_stack behaves like +// |SSL_add_file_cert_subjects_to_stack| but reads from |bio|. +OPENSSL_EXPORT int SSL_add_bio_cert_subjects_to_stack(STACK_OF(X509_NAME) *out, + BIO *bio); + // Server name indication. // diff --git a/include/openssl/stack.h b/include/openssl/stack.h index 165d330cc6..e3624717b6 100644 --- a/include/openssl/stack.h +++ b/include/openssl/stack.h @@ -101,10 +101,20 @@ typedef void *(*stack_copy_func)(void *ptr); // extra indirection - the function is given a pointer to a pointer to the // element. This differs from the usual qsort/bsearch comparison function. // -// Note its actual type is int (*)(const T **, const T **). Low-level |sk_*| +// Note its actual type is |int (*)(const T **a, const T **b)|. Low-level |sk_*| // functions will be passed a type-specific wrapper to call it correctly. +// +// TODO(davidben): This type should be |const T *const *|. It is already fixed +// in OpenSSL 1.1.1, so hopefully we can fix this compatibly. typedef int (*stack_cmp_func)(const void **a, const void **b); +// The following function types call the above type-erased signatures with the +// true types. +typedef void (*stack_call_free_func)(stack_free_func, void *); +typedef void *(*stack_call_copy_func)(stack_copy_func, void *); +typedef int (*stack_call_cmp_func)(stack_cmp_func, const void *const *, + const void *const *); + // stack_st contains an array of pointers. It is not designed to be used // directly, rather the wrapper macros should be used. typedef struct stack_st { @@ -161,8 +171,7 @@ OPENSSL_EXPORT void sk_free(_STACK *sk); // |sk_pop_free_ex| as a workaround for existing code calling an older version // of |sk_pop_free|. OPENSSL_EXPORT void sk_pop_free_ex(_STACK *sk, - void (*call_free_func)(stack_free_func, - void *), + stack_call_free_func call_free_func, stack_free_func free_func); // sk_insert inserts |p| into the stack at index |where|, moving existing @@ -192,8 +201,7 @@ OPENSSL_EXPORT void *sk_delete_ptr(_STACK *sk, const void *p); // OpenSSL's sk_find will implicitly sort |sk| if it has a comparison function // defined. OPENSSL_EXPORT int sk_find(const _STACK *sk, size_t *out_index, const void *p, - int (*call_cmp_func)(stack_cmp_func, const void **, - const void **)); + stack_call_cmp_func call_cmp_func); // sk_shift removes and returns the first element in the stack, or returns NULL // if the stack is empty. @@ -214,7 +222,7 @@ OPENSSL_EXPORT _STACK *sk_dup(const _STACK *sk); // sk_sort sorts the elements of |sk| into ascending order based on the // comparison function. The stack maintains a |sorted| flag and sorting an // already sorted stack is a no-op. -OPENSSL_EXPORT void sk_sort(_STACK *sk); +OPENSSL_EXPORT void sk_sort(_STACK *sk, stack_call_cmp_func call_cmp_func); // sk_is_sorted returns one if |sk| is known to be sorted and zero // otherwise. @@ -227,10 +235,11 @@ OPENSSL_EXPORT stack_cmp_func sk_set_cmp_func(_STACK *sk, stack_cmp_func comp); // sk_deep_copy performs a copy of |sk| and of each of the non-NULL elements in // |sk| by using |copy_func|. If an error occurs, |free_func| is used to free // any copies already made and NULL is returned. -OPENSSL_EXPORT _STACK *sk_deep_copy( - const _STACK *sk, void *(*call_copy_func)(stack_copy_func, void *), - stack_copy_func copy_func, void (*call_free_func)(stack_free_func, void *), - stack_free_func free_func); +OPENSSL_EXPORT _STACK *sk_deep_copy(const _STACK *sk, + stack_call_copy_func call_copy_func, + stack_copy_func copy_func, + stack_call_free_func call_free_func, + stack_free_func free_func); // Deprecated functions. @@ -277,6 +286,16 @@ BSSL_NAMESPACE_END #endif #define BORINGSSL_DEFINE_STACK_OF_IMPL(name, ptrtype, constptrtype) \ + /* We disable MSVC C4191 in this macro, which warns when pointers are cast \ + * to the wrong type. While the cast itself is valid, it is often a bug \ + * because calling it through the cast is UB. However, we never actually \ + * call functions as |stack_cmp_func|. The type is just a type-erased \ + * function pointer. (C does not guarantee function pointers fit in \ + * |void*|, and GCC will warn on this.) Thus we just disable the false \ + * positive warning. */ \ + OPENSSL_MSVC_PRAGMA(warning(push)) \ + OPENSSL_MSVC_PRAGMA(warning(disable : 4191)) \ + \ DECLARE_STACK_OF(name) \ \ typedef void (*stack_##name##_free_func)(ptrtype); \ @@ -294,14 +313,17 @@ BSSL_NAMESPACE_END } \ \ OPENSSL_INLINE int sk_##name##_call_cmp_func( \ - stack_cmp_func cmp_func, const void **a, const void **b) { \ + stack_cmp_func cmp_func, const void *const *a, const void *const *b) { \ + /* The data is actually stored as |void*| pointers, so read the pointer \ + * as |void*| and then pass the corrected type into the caller-supplied \ + * function, which expects |constptrtype*|. */ \ constptrtype a_ptr = (constptrtype)*a; \ constptrtype b_ptr = (constptrtype)*b; \ return ((stack_##name##_cmp_func)cmp_func)(&a_ptr, &b_ptr); \ } \ \ - OPENSSL_INLINE STACK_OF(name) * \ - sk_##name##_new(stack_##name##_cmp_func comp) { \ + OPENSSL_INLINE STACK_OF(name) *sk_##name##_new( \ + stack_##name##_cmp_func comp) { \ return (STACK_OF(name) *)sk_new((stack_cmp_func)comp); \ } \ \ @@ -327,12 +349,12 @@ BSSL_NAMESPACE_END return (ptrtype)sk_set((_STACK *)sk, i, (void *)p); \ } \ \ - OPENSSL_INLINE void sk_##name##_free(STACK_OF(name) * sk) { \ + OPENSSL_INLINE void sk_##name##_free(STACK_OF(name) *sk) { \ sk_free((_STACK *)sk); \ } \ \ OPENSSL_INLINE void sk_##name##_pop_free( \ - STACK_OF(name) * sk, stack_##name##_free_func free_func) { \ + STACK_OF(name) *sk, stack_##name##_free_func free_func) { \ sk_pop_free_ex((_STACK *)sk, sk_##name##_call_free_func, \ (stack_free_func)free_func); \ } \ @@ -353,7 +375,7 @@ BSSL_NAMESPACE_END } \ \ OPENSSL_INLINE int sk_##name##_find(const STACK_OF(name) *sk, \ - size_t * out_index, constptrtype p) { \ + size_t *out_index, constptrtype p) { \ return sk_find((const _STACK *)sk, out_index, (const void *)p, \ sk_##name##_call_cmp_func); \ } \ @@ -370,12 +392,12 @@ BSSL_NAMESPACE_END return (ptrtype)sk_pop((_STACK *)sk); \ } \ \ - OPENSSL_INLINE STACK_OF(name) * sk_##name##_dup(const STACK_OF(name) *sk) { \ + OPENSSL_INLINE STACK_OF(name) *sk_##name##_dup(const STACK_OF(name) *sk) { \ return (STACK_OF(name) *)sk_dup((const _STACK *)sk); \ } \ \ OPENSSL_INLINE void sk_##name##_sort(STACK_OF(name) *sk) { \ - sk_sort((_STACK *)sk); \ + sk_sort((_STACK *)sk, sk_##name##_call_cmp_func); \ } \ \ OPENSSL_INLINE int sk_##name##_is_sorted(const STACK_OF(name) *sk) { \ @@ -388,15 +410,16 @@ BSSL_NAMESPACE_END (stack_cmp_func)comp); \ } \ \ - OPENSSL_INLINE STACK_OF(name) * \ - sk_##name##_deep_copy(const STACK_OF(name) *sk, \ - ptrtype(*copy_func)(ptrtype), \ - void (*free_func)(ptrtype)) { \ + OPENSSL_INLINE STACK_OF(name) *sk_##name##_deep_copy( \ + const STACK_OF(name) *sk, ptrtype (*copy_func)(ptrtype), \ + void (*free_func)(ptrtype)) { \ return (STACK_OF(name) *)sk_deep_copy( \ (const _STACK *)sk, sk_##name##_call_copy_func, \ (stack_copy_func)copy_func, sk_##name##_call_free_func, \ (stack_free_func)free_func); \ - } + } \ + \ + OPENSSL_MSVC_PRAGMA(warning(pop)) // DEFINE_NAMED_STACK_OF defines |STACK_OF(name)| to be a stack whose elements // are |type| *. @@ -414,18 +437,10 @@ BSSL_NAMESPACE_END BORINGSSL_DEFINE_STACK_OF_IMPL(type, const type *, const type *) \ BORINGSSL_DEFINE_STACK_TRAITS(type, const type, true) -// DEFINE_SPECIAL_STACK_OF defines |STACK_OF(type)| to be a stack whose elements -// are |type|, where |type| must be a typedef for a pointer. -#define DEFINE_SPECIAL_STACK_OF(type) \ - OPENSSL_STATIC_ASSERT(sizeof(type) == sizeof(void *), \ - AWSLC_CONCAT(type, is_not_a_pointer)) \ - BORINGSSL_DEFINE_STACK_OF_IMPL(type, type, const type) - - typedef char *OPENSSL_STRING; DEFINE_STACK_OF(void) -DEFINE_SPECIAL_STACK_OF(OPENSSL_STRING) +DEFINE_NAMED_STACK_OF(OPENSSL_STRING, char) #if defined(__cplusplus) diff --git a/include/openssl/trust_token.h b/include/openssl/trust_token.h index d9247f79f6..745a860b0d 100644 --- a/include/openssl/trust_token.h +++ b/include/openssl/trust_token.h @@ -78,15 +78,30 @@ OPENSSL_EXPORT void TRUST_TOKEN_free(TRUST_TOKEN *token); // to ensure success, these should be at least // |TRUST_TOKEN_MAX_PRIVATE_KEY_SIZE| and |TRUST_TOKEN_MAX_PUBLIC_KEY_SIZE|. // -// WARNING: This API is unstable and the serializations of these keys are -// subject to change. Keys generated with this function may not be persisted. -// // This function returns one on success or zero on error. OPENSSL_EXPORT int TRUST_TOKEN_generate_key( const TRUST_TOKEN_METHOD *method, uint8_t *out_priv_key, size_t *out_priv_key_len, size_t max_priv_key_len, uint8_t *out_pub_key, size_t *out_pub_key_len, size_t max_pub_key_len, uint32_t id); +// TRUST_TOKEN_derive_key_from_secret deterministically derives a new Trust +// Token keypair labeled with |id| from an input |secret| and serializes the +// private and public keys, writing the private key to |out_priv_key| and +// setting |*out_priv_key_len| to the number of bytes written, and writing the +// public key to |out_pub_key| and setting |*out_pub_key_len| to the number of +// bytes written. +// +// At most |max_priv_key_len| and |max_pub_key_len| bytes are written. In order +// to ensure success, these should be at least +// |TRUST_TOKEN_MAX_PRIVATE_KEY_SIZE| and |TRUST_TOKEN_MAX_PUBLIC_KEY_SIZE|. +// +// This function returns one on success or zero on error. +OPENSSL_EXPORT int TRUST_TOKEN_derive_key_from_secret( + const TRUST_TOKEN_METHOD *method, uint8_t *out_priv_key, + size_t *out_priv_key_len, size_t max_priv_key_len, uint8_t *out_pub_key, + size_t *out_pub_key_len, size_t max_pub_key_len, uint32_t id, + const uint8_t *secret, size_t secret_len); + // Trust Token client implementation. // diff --git a/ssl/ssl_file.cc b/ssl/ssl_file.cc index 43db37ca68..1625200101 100644 --- a/ssl/ssl_file.cc +++ b/ssl/ssl_file.cc @@ -128,125 +128,87 @@ static int xname_cmp(const X509_NAME **a, const X509_NAME **b) { return X509_NAME_cmp(*a, *b); } -// TODO(davidben): Is there any reason this doesn't call -// |SSL_add_file_cert_subjects_to_stack|? STACK_OF(X509_NAME) *SSL_load_client_CA_file(const char *file) { - BIO *in; - X509 *x = NULL; - X509_NAME *xn = NULL; - STACK_OF(X509_NAME) *ret = NULL, *sk; - - sk = sk_X509_NAME_new(xname_cmp); - in = BIO_new(BIO_s_file()); - - if (sk == NULL || in == NULL) { - OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE); - goto err; + bssl::UniquePtr ret(sk_X509_NAME_new_null()); + if (ret == nullptr || + !SSL_add_file_cert_subjects_to_stack(ret.get(), file)) { + return nullptr; } + return ret.release(); +} - if (!BIO_read_filename(in, file)) { - goto err; +int SSL_add_file_cert_subjects_to_stack(STACK_OF(X509_NAME) *out, + const char *file) { + bssl::UniquePtr in(BIO_new_file(file, "r")); + if (in == nullptr) { + return 0; } + return SSL_add_bio_cert_subjects_to_stack(out, in.get()); +} +int SSL_add_bio_cert_subjects_to_stack(STACK_OF(X509_NAME) *out, BIO *bio) { + // This function historically sorted |out| after every addition and skipped + // duplicates. This implementation preserves that behavior, but only sorts at + // the end, to avoid a quadratic running time. Existing duplicates in |out| + // are preserved, but do not introduce new duplicates. + bssl::UniquePtr to_append(sk_X509_NAME_new(xname_cmp)); + if (to_append == nullptr) { + return 0; + } + + // Temporarily switch the comparison function for |out|. + struct RestoreCmpFunc { + ~RestoreCmpFunc() { sk_X509_NAME_set_cmp_func(stack, old_cmp); } + STACK_OF(X509_NAME) *stack; + int (*old_cmp)(const X509_NAME **, const X509_NAME **); + }; + RestoreCmpFunc restore = {out, sk_X509_NAME_set_cmp_func(out, xname_cmp)}; + + sk_X509_NAME_sort(out); for (;;) { - if (PEM_read_bio_X509(in, &x, NULL, NULL) == NULL) { + bssl::UniquePtr x509( + PEM_read_bio_X509(bio, nullptr, nullptr, nullptr)); + if (x509 == nullptr) { + // TODO(davidben): This ignores PEM syntax errors. It should only succeed + // on |PEM_R_NO_START_LINE|. + ERR_clear_error(); break; } - if (ret == NULL) { - ret = sk_X509_NAME_new_null(); - if (ret == NULL) { - OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE); - goto err; - } - } - xn = X509_get_subject_name(x); - if (xn == NULL) { - goto err; - } - // Check for duplicates. - sk_X509_NAME_sort(sk); - if (sk_X509_NAME_find(sk, NULL, xn)) { + X509_NAME *subject = X509_get_subject_name(x509.get()); + // Skip if already present in |out|. Duplicates in |to_append| will be + // handled separately. + if (sk_X509_NAME_find(out, /*out_index=*/NULL, subject)) { continue; } - xn = X509_NAME_dup(xn); - if (xn == NULL || - !sk_X509_NAME_push(sk /* non-owning */, xn) || - !sk_X509_NAME_push(ret /* owning */, xn)) { - X509_NAME_free(xn); - goto err; + bssl::UniquePtr copy(X509_NAME_dup(subject)); + if (copy == nullptr || + !bssl::PushToStack(to_append.get(), std::move(copy))) { + return 0; } } - if (false) { - err: - sk_X509_NAME_pop_free(ret, X509_NAME_free); - ret = NULL; - } - - sk_X509_NAME_free(sk); - BIO_free(in); - X509_free(x); - if (ret != NULL) { - ERR_clear_error(); - } - return ret; -} - -int SSL_add_file_cert_subjects_to_stack(STACK_OF(X509_NAME) *stack, - const char *file) { - BIO *in; - X509 *x = NULL; - X509_NAME *xn = NULL; - int ret = 0; - int (*oldcmp)(const X509_NAME **a, const X509_NAME **b); - - oldcmp = sk_X509_NAME_set_cmp_func(stack, xname_cmp); - in = BIO_new(BIO_s_file()); - - if (in == NULL) { - OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE); - goto err; - } - - if (!BIO_read_filename(in, file)) { - goto err; - } - - for (;;) { - if (PEM_read_bio_X509(in, &x, NULL, NULL) == NULL) { - break; - } - xn = X509_get_subject_name(x); - if (xn == NULL) { - goto err; - } - - // Check for duplicates. - sk_X509_NAME_sort(stack); - if (sk_X509_NAME_find(stack, NULL, xn)) { + // Append |to_append| to |stack|, skipping any duplicates. + sk_X509_NAME_sort(to_append.get()); + size_t num = sk_X509_NAME_num(to_append.get()); + for (size_t i = 0; i < num; i++) { + bssl::UniquePtr name(sk_X509_NAME_value(to_append.get(), i)); + sk_X509_NAME_set(to_append.get(), i, nullptr); + if (i + 1 < num && + X509_NAME_cmp(name.get(), sk_X509_NAME_value(to_append.get(), i + 1)) == + 0) { continue; } - - xn = X509_NAME_dup(xn); - if (xn == NULL || - !sk_X509_NAME_push(stack, xn)) { - X509_NAME_free(xn); - goto err; + if (!bssl::PushToStack(out, std::move(name))) { + return 0; } } - ERR_clear_error(); - ret = 1; - -err: - BIO_free(in); - X509_free(x); - - (void) sk_X509_NAME_set_cmp_func(stack, oldcmp); - - return ret; + // Sort |out| one last time, to preserve the historical behavior of + // maintaining the sorted list. + sk_X509_NAME_sort(out); + return 1; } int SSL_use_certificate_file(SSL *ssl, const char *file, int type) { diff --git a/ssl/ssl_test.cc b/ssl/ssl_test.cc index da15f6f0df..13eda3d098 100644 --- a/ssl/ssl_test.cc +++ b/ssl/ssl_test.cc @@ -8568,5 +8568,106 @@ TEST(SSLTest, NumTickets) { EXPECT_EQ(count_tickets(), 16u); } +TEST(SSLTest, CertSubjectsToStack) { + const std::string kCert1 = R"( +-----BEGIN CERTIFICATE----- +MIIBzzCCAXagAwIBAgIJANlMBNpJfb/rMAkGByqGSM49BAEwRTELMAkGA1UEBhMC +QVUxEzARBgNVBAgMClNvbWUtU3RhdGUxITAfBgNVBAoMGEludGVybmV0IFdpZGdp +dHMgUHR5IEx0ZDAeFw0xNDA0MjMyMzIxNTdaFw0xNDA1MjMyMzIxNTdaMEUxCzAJ +BgNVBAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYDVQQKDBhJbnRlcm5l +dCBXaWRnaXRzIFB0eSBMdGQwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAATmK2ni +v2Wfl74vHg2UikzVl2u3qR4NRvvdqakendy6WgHn1peoChj5w8SjHlbifINI2xYa +HPUdfvGULUvPciLBo1AwTjAdBgNVHQ4EFgQUq4TSrKuV8IJOFngHVVdf5CaNgtEw +HwYDVR0jBBgwFoAUq4TSrKuV8IJOFngHVVdf5CaNgtEwDAYDVR0TBAUwAwEB/zAJ +BgcqhkjOPQQBA0gAMEUCIQDyoDVeUTo2w4J5m+4nUIWOcAZ0lVfSKXQA9L4Vh13E +BwIgfB55FGohg/B6dGh5XxSZmmi08cueFV7mHzJSYV51yRQ= +-----END CERTIFICATE----- +)"; + const std::vector kName1 = { + 0x30, 0x45, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x41, 0x55, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x08, + 0x0c, 0x0a, 0x53, 0x6f, 0x6d, 0x65, 0x2d, 0x53, 0x74, 0x61, 0x74, 0x65, + 0x31, 0x21, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x18, 0x49, + 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x20, 0x57, 0x69, 0x64, 0x67, + 0x69, 0x74, 0x73, 0x20, 0x50, 0x74, 0x79, 0x20, 0x4c, 0x74, 0x64}; + const std::string kCert2 = R"( +-----BEGIN CERTIFICATE----- +MIICXjCCAcegAwIBAgIIWjO48ufpunYwDQYJKoZIhvcNAQELBQAwNjEaMBgGA1UE +ChMRQm9yaW5nU1NMIFRFU1RJTkcxGDAWBgNVBAMTD0ludGVybWVkaWF0ZSBDQTAg +Fw0xNTAxMDEwMDAwMDBaGA8yMTAwMDEwMTAwMDAwMFowMjEaMBgGA1UEChMRQm9y +aW5nU1NMIFRFU1RJTkcxFDASBgNVBAMTC2V4YW1wbGUuY29tMIGfMA0GCSqGSIb3 +DQEBAQUAA4GNADCBiQKBgQDD0U0ZYgqShJ7oOjsyNKyVXEHqeafmk/bAoPqY/h1c +oPw2E8KmeqiUSoTPjG5IXSblOxcqpbAXgnjPzo8DI3GNMhAf8SYNYsoH7gc7Uy7j +5x8bUrisGnuTHqkqH6d4/e7ETJ7i3CpR8bvK16DggEvQTudLipz8FBHtYhFakfdh +TwIDAQABo3cwdTAOBgNVHQ8BAf8EBAMCBaAwHQYDVR0lBBYwFAYIKwYBBQUHAwEG +CCsGAQUFBwMCMAwGA1UdEwEB/wQCMAAwGQYDVR0OBBIEEKN5pvbur7mlXjeMEYA0 +4nUwGwYDVR0jBBQwEoAQjBpoqLV2211Xex+NFLIGozANBgkqhkiG9w0BAQsFAAOB +gQBj/p+JChp//LnXWC1k121LM/ii7hFzQzMrt70bny406SGz9jAjaPOX4S3gt38y +rhjpPukBlSzgQXFg66y6q5qp1nQTD1Cw6NkKBe9WuBlY3iYfmsf7WT8nhlT1CttU +xNCwyMX9mtdXdQicOfNjIGUCD5OLV5PgHFPRKiHHioBAhg== +-----END CERTIFICATE----- +)"; + const std::vector kName2 = { + 0x30, 0x32, 0x31, 0x1a, 0x30, 0x18, 0x06, 0x03, 0x55, 0x04, 0x0a, + 0x13, 0x11, 0x42, 0x6f, 0x72, 0x69, 0x6e, 0x67, 0x53, 0x53, 0x4c, + 0x20, 0x54, 0x45, 0x53, 0x54, 0x49, 0x4e, 0x47, 0x31, 0x14, 0x30, + 0x12, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0b, 0x65, 0x78, 0x61, + 0x6d, 0x70, 0x6c, 0x65, 0x2e, 0x63, 0x6f, 0x6d}; + + const struct { + std::vector> existing; + std::string pem; + std::vector> expected; + } kTests[] = { + // Do nothing. + {{}, "", {}}, + // Append to an empty list, skipping duplicates. + {{}, kCert1 + kCert2 + kCert1, {kName1, kName2}}, + // One of the names was already present. + {{kName1}, kCert1 + kCert2, {kName1, kName2}}, + // Both names were already present. + {{kName1, kName2}, kCert1 + kCert2, {kName1, kName2}}, + // Preserve existing duplicates. + {{kName1, kName2, kName2}, kCert1 + kCert2, {kName1, kName2, kName2}}, + }; + for (size_t i = 0; i < OPENSSL_ARRAY_SIZE(kTests); i++) { + SCOPED_TRACE(i); + const auto &t = kTests[i]; + + bssl::UniquePtr stack(sk_X509_NAME_new_null()); + ASSERT_TRUE(stack); + for (const auto& name : t.existing) { + const uint8_t *inp = name.data(); + bssl::UniquePtr name_obj( + d2i_X509_NAME(nullptr, &inp, name.size())); + ASSERT_TRUE(name_obj); + EXPECT_EQ(inp, name.data() + name.size()); + ASSERT_TRUE(bssl::PushToStack(stack.get(), std::move(name_obj))); + } + + bssl::UniquePtr bio(BIO_new_mem_buf(t.pem.data(), t.pem.size())); + ASSERT_TRUE(bio); + ASSERT_TRUE(SSL_add_bio_cert_subjects_to_stack(stack.get(), bio.get())); + + // The function should have left |stack|'s comparison function alone. + EXPECT_EQ(nullptr, sk_X509_NAME_set_cmp_func(stack.get(), nullptr)); + + std::vector> expected = t.expected, result; + for (X509_NAME *name : stack.get()) { + uint8_t *der = nullptr; + int der_len = i2d_X509_NAME(name, &der); + ASSERT_GE(der_len, 0); + result.push_back(std::vector(der, der + der_len)); + OPENSSL_free(der); + } + + // |SSL_add_bio_cert_subjects_to_stack| does not return the output in a + // well-defined order. + std::sort(expected.begin(), expected.end()); + std::sort(result.begin(), result.end()); + EXPECT_EQ(result, expected); + } +} + } // namespace BSSL_NAMESPACE_END