Run convert_comments.go on the recently-converted files

This CL is the result of the following commands:

    for d in asn1 x509 x509v3 pem; do
      go run util/convert_comments.go crypto/$d/*.h
      go run util/convert_comments.go crypto/$d/*.c
    done

Change-Id: If78433f68cb2f913b0de06ded744a5a65540e1cf
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/53087
Reviewed-by: Bob Beck <bbe@google.com>
Commit-Queue: Bob Beck <bbe@google.com>
chromium-5359
David Benjamin 3 years ago committed by Boringssl LUCI CQ
parent c0b87a04db
commit 46350487c1
  1. 38
      crypto/asn1/a_bitstr.c
  2. 6
      crypto/asn1/a_bool.c
  3. 10
      crypto/asn1/a_dup.c
  4. 60
      crypto/asn1/a_int.c
  5. 40
      crypto/asn1/a_mbstr.c
  6. 26
      crypto/asn1/a_object.c
  7. 2
      crypto/asn1/a_print.c
  8. 130
      crypto/asn1/a_strex.c
  9. 28
      crypto/asn1/a_strnid.c
  10. 18
      crypto/asn1/a_time.c
  11. 4
      crypto/asn1/a_type.c
  12. 32
      crypto/asn1/a_utf8.c
  13. 48
      crypto/asn1/asn1_lib.c
  14. 104
      crypto/asn1/internal.h
  15. 240
      crypto/asn1/tasn_dec.c
  16. 238
      crypto/asn1/tasn_enc.c
  17. 16
      crypto/asn1/tasn_fre.c
  18. 24
      crypto/asn1/tasn_new.c
  19. 10
      crypto/asn1/tasn_typ.c
  20. 44
      crypto/asn1/tasn_utl.c
  21. 26
      crypto/asn1/time_support.c
  22. 18
      crypto/pem/pem_all.c
  23. 44
      crypto/pem/pem_info.c
  24. 32
      crypto/pem/pem_lib.c
  25. 2
      crypto/pem/pem_oth.c
  26. 10
      crypto/pem/pem_pk8.c
  27. 6
      crypto/pem/pem_pkey.c
  28. 8
      crypto/x509/a_sign.c
  29. 32
      crypto/x509/algorithm.c
  30. 104
      crypto/x509/asn1_gen.c
  31. 79
      crypto/x509/by_dir.c
  32. 20
      crypto/x509/by_file.c
  33. 6
      crypto/x509/i2d_pr.c
  34. 44
      crypto/x509/internal.h
  35. 20
      crypto/x509/name_print.c
  36. 26
      crypto/x509/rsa_pss.c
  37. 16
      crypto/x509/t_x509.c
  38. 2
      crypto/x509/t_x509a.c
  39. 4
      crypto/x509/x509.c
  40. 8
      crypto/x509/x509_att.c
  41. 92
      crypto/x509/x509_cmp.c
  42. 2
      crypto/x509/x509_d2.c
  43. 2
      crypto/x509/x509_def.c
  44. 46
      crypto/x509/x509_lu.c
  45. 8
      crypto/x509/x509_obj.c
  46. 14
      crypto/x509/x509_req.c
  47. 2
      crypto/x509/x509_set.c
  48. 36
      crypto/x509/x509_trs.c
  49. 613
      crypto/x509/x509_vfy.c
  50. 173
      crypto/x509/x509_vpm.c
  51. 10
      crypto/x509/x509cset.c
  52. 20
      crypto/x509/x509name.c
  53. 6
      crypto/x509/x509rset.c
  54. 4
      crypto/x509/x509spki.c
  55. 6
      crypto/x509/x_algor.c
  56. 64
      crypto/x509/x_crl.c
  57. 86
      crypto/x509/x_name.c
  58. 16
      crypto/x509/x_pubkey.c
  59. 16
      crypto/x509/x_req.c
  60. 6
      crypto/x509/x_spki.c
  61. 80
      crypto/x509/x_x509.c
  62. 22
      crypto/x509/x_x509a.c
  63. 14
      crypto/x509v3/ext_dat.h
  64. 101
      crypto/x509v3/internal.h
  65. 38
      crypto/x509v3/pcy_cache.c
  66. 16
      crypto/x509v3/pcy_data.c
  67. 8
      crypto/x509v3/pcy_lib.c
  68. 18
      crypto/x509v3/pcy_map.c
  69. 6
      crypto/x509v3/pcy_node.c
  70. 226
      crypto/x509v3/pcy_tree.c
  71. 12
      crypto/x509v3/v3_akey.c
  72. 28
      crypto/x509v3/v3_alt.c
  73. 54
      crypto/x509v3/v3_conf.c
  74. 4
      crypto/x509v3/v3_cpols.c
  75. 6
      crypto/x509v3/v3_crld.c
  76. 2
      crypto/x509v3/v3_extku.c
  77. 20
      crypto/x509v3/v3_genn.c
  78. 54
      crypto/x509v3/v3_lib.c
  79. 101
      crypto/x509v3/v3_ncons.c
  80. 6
      crypto/x509v3/v3_ocsp.c
  81. 14
      crypto/x509v3/v3_pci.c
  82. 8
      crypto/x509v3/v3_prn.c
  83. 174
      crypto/x509v3/v3_purp.c
  84. 226
      crypto/x509v3/v3_utl.c

@ -164,19 +164,17 @@ ASN1_BIT_STRING *c2i_ASN1_BIT_STRING(ASN1_BIT_STRING **a,
goto err; goto err;
} }
/* Unused bits in a BIT STRING must be zero. */ // Unused bits in a BIT STRING must be zero.
uint8_t padding_mask = (1 << padding) - 1; uint8_t padding_mask = (1 << padding) - 1;
if (padding != 0 && (len < 1 || (p[len - 1] & padding_mask) != 0)) { if (padding != 0 && (len < 1 || (p[len - 1] & padding_mask) != 0)) {
OPENSSL_PUT_ERROR(ASN1, ASN1_R_INVALID_BIT_STRING_PADDING); OPENSSL_PUT_ERROR(ASN1, ASN1_R_INVALID_BIT_STRING_PADDING);
goto err; goto err;
} }
/* // We do this to preserve the settings. If we modify the settings, via
* We do this to preserve the settings. If we modify the settings, via // the _set_bit function, we will recalculate on output
* 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
ret->flags &= ~(ASN1_STRING_FLAG_BITS_LEFT | 0x07); /* clear */
ret->flags |= (ASN1_STRING_FLAG_BITS_LEFT | padding); /* set */
if (len > 0) { if (len > 0) {
s = OPENSSL_memdup(p, len); s = OPENSSL_memdup(p, len);
@ -205,9 +203,7 @@ err:
return (NULL); return (NULL);
} }
/* // These next 2 functions from Goetz Babin-Ebell <babinebell@trustcenter.de>
* These next 2 functions from Goetz Babin-Ebell <babinebell@trustcenter.de>
*/
int ASN1_BIT_STRING_set_bit(ASN1_BIT_STRING *a, int n, int value) { int ASN1_BIT_STRING_set_bit(ASN1_BIT_STRING *a, int n, int value) {
int w, v, iv; int w, v, iv;
unsigned char *c; unsigned char *c;
@ -223,11 +219,11 @@ int ASN1_BIT_STRING_set_bit(ASN1_BIT_STRING *a, int n, int value) {
return 0; 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 ((a->length < (w + 1)) || (a->data == NULL)) {
if (!value) { if (!value) {
return (1); /* Don't need to set */ return (1); // Don't need to set
} }
if (a->data == NULL) { if (a->data == NULL) {
c = (unsigned char *)OPENSSL_malloc(w + 1); c = (unsigned char *)OPENSSL_malloc(w + 1);
@ -262,27 +258,23 @@ int ASN1_BIT_STRING_get_bit(const ASN1_BIT_STRING *a, int n) {
return ((a->data[w] & v) != 0); return ((a->data[w] & v) != 0);
} }
/* // Checks if the given bit string contains only bits specified by
* Checks if the given bit string contains only bits specified by // the flags vector. Returns 0 if there is at least one bit set in 'a'
* the flags vector. Returns 0 if there is at least one bit set in 'a' // which is not specified in 'flags', 1 otherwise.
* which is not specified in 'flags', 1 otherwise. // 'len' is the length of 'flags'.
* 'len' is the length of 'flags'.
*/
int ASN1_BIT_STRING_check(const ASN1_BIT_STRING *a, const unsigned char *flags, int ASN1_BIT_STRING_check(const ASN1_BIT_STRING *a, const unsigned char *flags,
int flags_len) { int flags_len) {
int i, ok; int i, ok;
/* Check if there is one bit set at all. */ // Check if there is one bit set at all.
if (!a || !a->data) { if (!a || !a->data) {
return 1; return 1;
} }
/* // Check each byte of the internal representation of the bit string.
* Check each byte of the internal representation of the bit string.
*/
ok = 1; ok = 1;
for (i = 0; i < a->length && ok; ++i) { for (i = 0; i < a->length && ok; ++i) {
unsigned char mask = i < flags_len ? ~flags[i] : 0xff; unsigned char mask = i < flags_len ? ~flags[i] : 0xff;
/* We are done if there is an unneeded bit set. */ // We are done if there is an unneeded bit set.
ok = (a->data[i] & mask) == 0; ok = (a->data[i] & mask) == 0;
} }
return ok; return ok;

@ -80,10 +80,8 @@ int i2d_ASN1_BOOLEAN(ASN1_BOOLEAN a, unsigned char **pp) {
ASN1_put_object(&p, 0, 1, V_ASN1_BOOLEAN, V_ASN1_UNIVERSAL); ASN1_put_object(&p, 0, 1, V_ASN1_BOOLEAN, V_ASN1_UNIVERSAL);
*p = a ? 0xff : 0x00; *p = a ? 0xff : 0x00;
/* // If a new buffer was allocated, just return it back.
* If a new buffer was allocated, just return it back. // If not, return the incremented buffer pointer.
* If not, return the incremented buffer pointer.
*/
*pp = allocated != NULL ? allocated : p + 1; *pp = allocated != NULL ? allocated : p + 1;
return r; return r;
} }

@ -59,12 +59,10 @@
#include <openssl/err.h> #include <openssl/err.h>
#include <openssl/mem.h> #include <openssl/mem.h>
/* // ASN1_ITEM version of dup: this follows the model above except we don't
* ASN1_ITEM version of dup: this follows the model above except we don't // need to allocate the buffer. At some point this could be rewritten to
* need to allocate the buffer. At some point this could be rewritten to // directly dup the underlying structure instead of doing and encode and
* directly dup the underlying structure instead of doing and encode and // decode.
* decode.
*/
void *ASN1_item_dup(const ASN1_ITEM *it, void *x) { void *ASN1_item_dup(const ASN1_ITEM *it, void *x) {
unsigned char *b = NULL; unsigned char *b = NULL;
const unsigned char *p; const unsigned char *p;

@ -72,7 +72,7 @@ ASN1_INTEGER *ASN1_INTEGER_dup(const ASN1_INTEGER *x) {
} }
int ASN1_INTEGER_cmp(const ASN1_INTEGER *x, const ASN1_INTEGER *y) { int ASN1_INTEGER_cmp(const ASN1_INTEGER *x, const ASN1_INTEGER *y) {
/* Compare signs. */ // Compare signs.
int neg = x->type & V_ASN1_NEG; int neg = x->type & V_ASN1_NEG;
if (neg != (y->type & V_ASN1_NEG)) { if (neg != (y->type & V_ASN1_NEG)) {
return neg ? -1 : 1; return neg ? -1 : 1;
@ -80,8 +80,8 @@ int ASN1_INTEGER_cmp(const ASN1_INTEGER *x, const ASN1_INTEGER *y) {
int ret = ASN1_STRING_cmp(x, y); int ret = ASN1_STRING_cmp(x, y);
if (neg) { if (neg) {
/* This could be |-ret|, but |ASN1_STRING_cmp| is not forbidden from // This could be |-ret|, but |ASN1_STRING_cmp| is not forbidden from
* returning |INT_MIN|. */ // returning |INT_MIN|.
if (ret < 0) { if (ret < 0) {
return 1; return 1;
} else if (ret > 0) { } else if (ret > 0) {
@ -94,8 +94,8 @@ int ASN1_INTEGER_cmp(const ASN1_INTEGER *x, const ASN1_INTEGER *y) {
return ret; return ret;
} }
/* negate_twos_complement negates |len| bytes from |buf| in-place, interpreted // negate_twos_complement negates |len| bytes from |buf| in-place, interpreted
* as a signed, big-endian two's complement value. */ // as a signed, big-endian two's complement value.
static void negate_twos_complement(uint8_t *buf, size_t len) { static void negate_twos_complement(uint8_t *buf, size_t len) {
uint8_t borrow = 0; uint8_t borrow = 0;
for (size_t i = len - 1; i < len; i--) { for (size_t i = len - 1; i < len; i--) {
@ -119,9 +119,9 @@ int i2c_ASN1_INTEGER(const ASN1_INTEGER *in, unsigned char **outp) {
return 0; return 0;
} }
/* |ASN1_INTEGER|s should be represented minimally, but it is possible to // |ASN1_INTEGER|s should be represented minimally, but it is possible to
* construct invalid ones. Skip leading zeros so this does not produce an // construct invalid ones. Skip leading zeros so this does not produce an
* invalid encoding or break invariants. */ // invalid encoding or break invariants.
int start = 0; int start = 0;
while (start < in->length && in->data[start] == 0) { while (start < in->length && in->data[start] == 0) {
start++; start++;
@ -130,20 +130,20 @@ int i2c_ASN1_INTEGER(const ASN1_INTEGER *in, unsigned char **outp) {
int is_negative = (in->type & V_ASN1_NEG) != 0; int is_negative = (in->type & V_ASN1_NEG) != 0;
int pad; int pad;
if (start >= in->length) { if (start >= in->length) {
/* Zero is represented as a single byte. */ // Zero is represented as a single byte.
is_negative = 0; is_negative = 0;
pad = 1; pad = 1;
} else if (is_negative) { } else if (is_negative) {
/* 0x80...01 through 0xff...ff have a two's complement of 0x7f...ff // 0x80...01 through 0xff...ff have a two's complement of 0x7f...ff
* through 0x00...01 and need an extra byte to be negative. // through 0x00...01 and need an extra byte to be negative.
* 0x01...00 through 0x80...00 have a two's complement of 0xfe...ff // 0x01...00 through 0x80...00 have a two's complement of 0xfe...ff
* through 0x80...00 and can be negated as-is. */ // through 0x80...00 and can be negated as-is.
pad = in->data[start] > 0x80 || pad = in->data[start] > 0x80 ||
(in->data[start] == 0x80 && (in->data[start] == 0x80 &&
!is_all_zeros(in->data + start + 1, in->length - start - 1)); !is_all_zeros(in->data + start + 1, in->length - start - 1));
} else { } else {
/* If the high bit is set, the signed representation needs an extra // If the high bit is set, the signed representation needs an extra
* byte to be positive. */ // byte to be positive.
pad = (in->data[start] & 0x80) != 0; pad = (in->data[start] & 0x80) != 0;
} }
@ -173,11 +173,9 @@ int i2c_ASN1_INTEGER(const ASN1_INTEGER *in, unsigned char **outp) {
ASN1_INTEGER *c2i_ASN1_INTEGER(ASN1_INTEGER **out, const unsigned char **inp, ASN1_INTEGER *c2i_ASN1_INTEGER(ASN1_INTEGER **out, const unsigned char **inp,
long len) { long len) {
/* // This function can handle lengths up to INT_MAX - 1, but the rest of the
* 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
* legacy ASN.1 code mixes integer types, so avoid exposing it to // ASN1_INTEGERS with larger lengths.
* ASN1_INTEGERS with larger lengths.
*/
if (len < 0 || len > INT_MAX / 2) { if (len < 0 || len > INT_MAX / 2) {
OPENSSL_PUT_ERROR(ASN1, ASN1_R_TOO_LONG); OPENSSL_PUT_ERROR(ASN1, ASN1_R_TOO_LONG);
return NULL; return NULL;
@ -201,19 +199,19 @@ ASN1_INTEGER *c2i_ASN1_INTEGER(ASN1_INTEGER **out, const unsigned char **inp,
ret = *out; ret = *out;
} }
/* Convert to |ASN1_INTEGER|'s sign-and-magnitude representation. First, // Convert to |ASN1_INTEGER|'s sign-and-magnitude representation. First,
* determine the size needed for a minimal result. */ // determine the size needed for a minimal result.
if (is_negative) { if (is_negative) {
/* 0xff00...01 through 0xff7f..ff have a two's complement of 0x00ff...ff // 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 0x000100...001 and need one leading zero removed. 0x8000...00
* through 0xff00...00 have a two's complement of 0x8000...00 through // through 0xff00...00 have a two's complement of 0x8000...00 through
* 0x0100...00 and will be minimally-encoded as-is. */ // 0x0100...00 and will be minimally-encoded as-is.
if (CBS_len(&cbs) > 0 && CBS_data(&cbs)[0] == 0xff && if (CBS_len(&cbs) > 0 && CBS_data(&cbs)[0] == 0xff &&
!is_all_zeros(CBS_data(&cbs) + 1, CBS_len(&cbs) - 1)) { !is_all_zeros(CBS_data(&cbs) + 1, CBS_len(&cbs) - 1)) {
CBS_skip(&cbs, 1); CBS_skip(&cbs, 1);
} }
} else { } else {
/* Remove the leading zero byte, if any. */ // Remove the leading zero byte, if any.
if (CBS_len(&cbs) > 0 && CBS_data(&cbs)[0] == 0x00) { if (CBS_len(&cbs) > 0 && CBS_data(&cbs)[0] == 0x00) {
CBS_skip(&cbs, 1); CBS_skip(&cbs, 1);
} }
@ -230,9 +228,9 @@ ASN1_INTEGER *c2i_ASN1_INTEGER(ASN1_INTEGER **out, const unsigned char **inp,
ret->type = V_ASN1_INTEGER; ret->type = V_ASN1_INTEGER;
} }
/* The value should be minimally-encoded. */ // The value should be minimally-encoded.
assert(ret->length == 0 || ret->data[0] != 0); assert(ret->length == 0 || ret->data[0] != 0);
/* Zero is not negative. */ // Zero is not negative.
assert(!is_negative || ret->length > 0); assert(!is_negative || ret->length > 0);
*inp += len; *inp += len;
@ -347,7 +345,7 @@ static long asn1_string_get_long(const ASN1_STRING *a, int type) {
int64_t i64; int64_t i64;
int fits_in_i64; int fits_in_i64;
/* Check |v != 0| to handle manually-constructed negative zeros. */ // Check |v != 0| to handle manually-constructed negative zeros.
if ((a->type & V_ASN1_NEG) && v != 0) { if ((a->type & V_ASN1_NEG) && v != 0) {
i64 = (int64_t)(0u - v); i64 = (int64_t)(0u - v);
fits_in_i64 = i64 < 0; fits_in_i64 = i64 < 0;
@ -362,7 +360,7 @@ static long asn1_string_get_long(const ASN1_STRING *a, int type) {
} }
err: err:
/* This function's return value does not distinguish overflow from -1. */ // This function's return value does not distinguish overflow from -1.
ERR_clear_error(); ERR_clear_error();
return -1; return -1;
} }

@ -66,14 +66,12 @@
#include "../bytestring/internal.h" #include "../bytestring/internal.h"
#include "internal.h" #include "internal.h"
/* // These functions take a string in UTF8, ASCII or multibyte form and a mask
* These functions take a string in UTF8, ASCII or multibyte form and a mask // of permissible ASN1 string types. It then works out the minimal type
* of permissible ASN1 string types. It then works out the minimal type // (using the order Printable < IA5 < T61 < BMP < Universal < UTF8) and
* (using the order Printable < IA5 < T61 < BMP < Universal < UTF8) and // creates a string of the correct type with the supplied data. Yes this is
* creates a string of the correct type with the supplied data. Yes this is // horrible: it has to be :-( The 'ncopy' form checks minimum and maximum
* horrible: it has to be :-( The 'ncopy' form checks minimum and maximum // size limits too.
* size limits too.
*/
int ASN1_mbstring_copy(ASN1_STRING **out, const unsigned char *in, int len, int ASN1_mbstring_copy(ASN1_STRING **out, const unsigned char *in, int len,
int inform, unsigned long mask) { int inform, unsigned long mask) {
@ -127,7 +125,7 @@ int ASN1_mbstring_ncopy(ASN1_STRING **out, const unsigned char *in, int len,
return -1; return -1;
} }
/* Check |minsize| and |maxsize| and work out the minimal type, if any. */ // Check |minsize| and |maxsize| and work out the minimal type, if any.
CBS cbs; CBS cbs;
CBS_init(&cbs, in, len); CBS_init(&cbs, in, len);
size_t utf8_len = 0; size_t utf8_len = 0;
@ -139,17 +137,17 @@ int ASN1_mbstring_ncopy(ASN1_STRING **out, const unsigned char *in, int len,
} }
if (nchar == 0 && (inform == MBSTRING_BMP || inform == MBSTRING_UNIV) && if (nchar == 0 && (inform == MBSTRING_BMP || inform == MBSTRING_UNIV) &&
c == 0xfeff) { c == 0xfeff) {
/* Reject byte-order mark. We could drop it but that would mean // Reject byte-order mark. We could drop it but that would mean
* adding ambiguity around whether a BOM was included or not when // adding ambiguity around whether a BOM was included or not when
* matching strings. // matching strings.
* //
* For a little-endian UCS-2 string, the BOM will appear as 0xfffe // For a little-endian UCS-2 string, the BOM will appear as 0xfffe
* and will be rejected as noncharacter, below. */ // and will be rejected as noncharacter, below.
OPENSSL_PUT_ERROR(ASN1, ASN1_R_ILLEGAL_CHARACTERS); OPENSSL_PUT_ERROR(ASN1, ASN1_R_ILLEGAL_CHARACTERS);
return -1; return -1;
} }
/* Update which output formats are still possible. */ // Update which output formats are still possible.
if ((mask & B_ASN1_PRINTABLESTRING) && !asn1_is_printable(c)) { if ((mask & B_ASN1_PRINTABLESTRING) && !asn1_is_printable(c)) {
mask &= ~B_ASN1_PRINTABLESTRING; mask &= ~B_ASN1_PRINTABLESTRING;
} }
@ -185,7 +183,7 @@ int ASN1_mbstring_ncopy(ASN1_STRING **out, const unsigned char *in, int len,
return -1; return -1;
} }
/* Now work out output format and string type */ // Now work out output format and string type
int (*encode_func)(CBB *, uint32_t) = cbb_add_latin1; int (*encode_func)(CBB *, uint32_t) = cbb_add_latin1;
size_t size_estimate = nchar; size_t size_estimate = nchar;
int outform = MBSTRING_ASC; int outform = MBSTRING_ASC;
@ -237,7 +235,7 @@ int ASN1_mbstring_ncopy(ASN1_STRING **out, const unsigned char *in, int len,
*out = dest; *out = dest;
} }
/* If both the same type just copy across */ // If both the same type just copy across
if (inform == outform) { if (inform == outform) {
if (!ASN1_STRING_set(dest, in, len)) { if (!ASN1_STRING_set(dest, in, len)) {
OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE); OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
@ -261,8 +259,8 @@ int ASN1_mbstring_ncopy(ASN1_STRING **out, const unsigned char *in, int len,
} }
uint8_t *data = NULL; uint8_t *data = NULL;
size_t data_len; size_t data_len;
if (/* OpenSSL historically NUL-terminated this value with a single byte, if (// OpenSSL historically NUL-terminated this value with a single byte,
* even for |MBSTRING_BMP| and |MBSTRING_UNIV|. */ // even for |MBSTRING_BMP| and |MBSTRING_UNIV|.
!CBB_add_u8(&cbb, 0) || !CBB_finish(&cbb, &data, &data_len) || !CBB_add_u8(&cbb, 0) || !CBB_finish(&cbb, &data, &data_len) ||
data_len < 1 || data_len > INT_MAX) { data_len < 1 || data_len > INT_MAX) {
OPENSSL_PUT_ERROR(ASN1, ERR_R_INTERNAL_ERROR); OPENSSL_PUT_ERROR(ASN1, ERR_R_INTERNAL_ERROR);
@ -285,7 +283,7 @@ int asn1_is_printable(uint32_t value) {
if (value > 0x7f) { if (value > 0x7f) {
return 0; return 0;
} }
/* Note we cannot use |isalnum| because it is locale-dependent. */ // Note we cannot use |isalnum| because it is locale-dependent.
return ('a' <= value && value <= 'z') || // return ('a' <= value && value <= 'z') || //
('A' <= value && value <= 'Z') || // ('A' <= value && value <= 'Z') || //
('0' <= value && value <= '9') || // ('0' <= value && value <= '9') || //

@ -96,10 +96,8 @@ int i2d_ASN1_OBJECT(const ASN1_OBJECT *a, unsigned char **pp) {
ASN1_put_object(&p, 0, a->length, V_ASN1_OBJECT, V_ASN1_UNIVERSAL); ASN1_put_object(&p, 0, a->length, V_ASN1_OBJECT, V_ASN1_UNIVERSAL);
OPENSSL_memcpy(p, a->data, a->length); OPENSSL_memcpy(p, a->data, a->length);
/* // If a new buffer was allocated, just return it back.
* If a new buffer was allocated, just return it back. // If not, return the incremented buffer pointer.
* If not, return the incremented buffer pointer.
*/
*pp = allocated != NULL ? allocated : p + a->length; *pp = allocated != NULL ? allocated : p + a->length;
return objsize; return objsize;
} }
@ -122,7 +120,7 @@ int i2a_ASN1_OBJECT(BIO *bp, const ASN1_OBJECT *a) {
const char *str = buf; const char *str = buf;
int len = i2t_ASN1_OBJECT(buf, sizeof(buf), a); int len = i2t_ASN1_OBJECT(buf, sizeof(buf), a);
if (len > (int)sizeof(buf) - 1) { if (len > (int)sizeof(buf) - 1) {
/* The input was truncated. Allocate a buffer that fits. */ // The input was truncated. Allocate a buffer that fits.
allocated = OPENSSL_malloc(len + 1); allocated = OPENSSL_malloc(len + 1);
if (allocated == NULL) { if (allocated == NULL) {
return -1; return -1;
@ -173,17 +171,15 @@ ASN1_OBJECT *c2i_ASN1_OBJECT(ASN1_OBJECT **a, const unsigned char **pp,
unsigned char *data; unsigned char *data;
int i, length; int i, length;
/* // Sanity check OID encoding. Need at least one content octet. MSB must
* 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,
* be clear in the last octet. can't have leading 0x80 in subidentifiers, // see: X.690 8.19.2
* see: X.690 8.19.2
*/
if (len <= 0 || len > INT_MAX || pp == NULL || (p = *pp) == NULL || if (len <= 0 || len > INT_MAX || pp == NULL || (p = *pp) == NULL ||
p[len - 1] & 0x80) { p[len - 1] & 0x80) {
OPENSSL_PUT_ERROR(ASN1, ASN1_R_INVALID_OBJECT_ENCODING); OPENSSL_PUT_ERROR(ASN1, ASN1_R_INVALID_OBJECT_ENCODING);
return NULL; return NULL;
} }
/* Now 0 < len <= INT_MAX, so the cast is safe. */ // Now 0 < len <= INT_MAX, so the cast is safe.
length = (int)len; length = (int)len;
for (i = 0; i < length; i++, p++) { for (i = 0; i < length; i++, p++) {
if (*p == 0x80 && (!i || !(p[-1] & 0x80))) { if (*p == 0x80 && (!i || !(p[-1] & 0x80))) {
@ -202,10 +198,10 @@ ASN1_OBJECT *c2i_ASN1_OBJECT(ASN1_OBJECT **a, const unsigned char **pp,
} }
p = *pp; p = *pp;
/* detach data from object */ // detach data from object
data = (unsigned char *)ret->data; data = (unsigned char *)ret->data;
ret->data = NULL; ret->data = NULL;
/* once detached we can change it */ // once detached we can change it
if ((data == NULL) || (ret->length < length)) { if ((data == NULL) || (ret->length < length)) {
ret->length = 0; ret->length = 0;
if (data != NULL) { if (data != NULL) {
@ -219,13 +215,13 @@ ASN1_OBJECT *c2i_ASN1_OBJECT(ASN1_OBJECT **a, const unsigned char **pp,
ret->flags |= ASN1_OBJECT_FLAG_DYNAMIC_DATA; ret->flags |= ASN1_OBJECT_FLAG_DYNAMIC_DATA;
} }
OPENSSL_memcpy(data, p, length); OPENSSL_memcpy(data, p, length);
/* If there are dynamic strings, free them here, and clear the flag */ // If there are dynamic strings, free them here, and clear the flag
if ((ret->flags & ASN1_OBJECT_FLAG_DYNAMIC_STRINGS) != 0) { if ((ret->flags & ASN1_OBJECT_FLAG_DYNAMIC_STRINGS) != 0) {
OPENSSL_free((char *)ret->sn); OPENSSL_free((char *)ret->sn);
OPENSSL_free((char *)ret->ln); OPENSSL_free((char *)ret->ln);
ret->flags &= ~ASN1_OBJECT_FLAG_DYNAMIC_STRINGS; ret->flags &= ~ASN1_OBJECT_FLAG_DYNAMIC_STRINGS;
} }
/* reattach data to object, after which it remains const */ // reattach data to object, after which it remains const
ret->data = data; ret->data = data;
ret->length = length; ret->length = length;
ret->sn = NULL; ret->sn = NULL;

@ -70,7 +70,7 @@ int ASN1_PRINTABLE_type(const unsigned char *s, int len) {
for (int i = 0; i < len; i++) { for (int i = 0; i < len; i++) {
unsigned char c = s[i]; unsigned char c = s[i];
if (c & 0x80) { if (c & 0x80) {
/* No need to continue iterating. */ // No need to continue iterating.
return V_ASN1_T61STRING; return V_ASN1_T61STRING;
} }
if (!asn1_is_printable(c)) { if (!asn1_is_printable(c)) {

@ -72,7 +72,7 @@
ASN1_STRFLGS_ESC_MSB) ASN1_STRFLGS_ESC_MSB)
static int maybe_write(BIO *out, const void *buf, int len) { static int maybe_write(BIO *out, const void *buf, int len) {
/* If |out| is NULL, ignore the output but report the length. */ // If |out| is NULL, ignore the output but report the length.
return out == NULL || BIO_write(out, buf, len) == len; return out == NULL || BIO_write(out, buf, len) == len;
} }
@ -80,9 +80,9 @@ 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, static int do_esc_char(uint32_t c, unsigned long flags, char *do_quotes,
BIO *out, int is_first, int is_last) { BIO *out, int is_first, int is_last) {
/* |c| is a |uint32_t| because, depending on |ASN1_STRFLGS_UTF8_CONVERT|, // |c| is a |uint32_t| because, depending on |ASN1_STRFLGS_UTF8_CONVERT|,
* we may be escaping bytes or Unicode codepoints. */ // we may be escaping bytes or Unicode codepoints.
char buf[16]; /* Large enough for "\\W01234567". */ char buf[16]; // Large enough for "\\W01234567".
unsigned char u8 = (unsigned char)c; unsigned char u8 = (unsigned char)c;
if (c > 0xffff) { if (c > 0xffff) {
BIO_snprintf(buf, sizeof(buf), "\\W%08" PRIX32, c); BIO_snprintf(buf, sizeof(buf), "\\W%08" PRIX32, c);
@ -93,15 +93,15 @@ static int do_esc_char(uint32_t c, unsigned long flags, char *do_quotes,
} else if ((flags & ASN1_STRFLGS_ESC_CTRL) && is_control_character(c)) { } else if ((flags & ASN1_STRFLGS_ESC_CTRL) && is_control_character(c)) {
BIO_snprintf(buf, sizeof(buf), "\\%02X", c); BIO_snprintf(buf, sizeof(buf), "\\%02X", c);
} else if (flags & ASN1_STRFLGS_ESC_2253) { } else if (flags & ASN1_STRFLGS_ESC_2253) {
/* See RFC 2253, sections 2.4 and 4. */ // See RFC 2253, sections 2.4 and 4.
if (c == '\\' || c == '"') { if (c == '\\' || c == '"') {
/* Quotes and backslashes are always escaped, quoted or not. */ // Quotes and backslashes are always escaped, quoted or not.
BIO_snprintf(buf, sizeof(buf), "\\%c", (int)c); BIO_snprintf(buf, sizeof(buf), "\\%c", (int)c);
} else if (c == ',' || c == '+' || c == '<' || c == '>' || c == ';' || } else if (c == ',' || c == '+' || c == '<' || c == '>' || c == ';' ||
(is_first && (c == ' ' || c == '#')) || (is_first && (c == ' ' || c == '#')) ||
(is_last && (c == ' '))) { (is_last && (c == ' '))) {
if (flags & ASN1_STRFLGS_ESC_QUOTE) { if (flags & ASN1_STRFLGS_ESC_QUOTE) {
/* No need to escape, just tell the caller to quote. */ // No need to escape, just tell the caller to quote.
if (do_quotes != NULL) { if (do_quotes != NULL) {
*do_quotes = 1; *do_quotes = 1;
} }
@ -112,7 +112,7 @@ static int do_esc_char(uint32_t c, unsigned long flags, char *do_quotes,
return maybe_write(out, &u8, 1) ? 1 : -1; return maybe_write(out, &u8, 1) ? 1 : -1;
} }
} else if ((flags & ESC_FLAGS) && c == '\\') { } else if ((flags & ESC_FLAGS) && c == '\\') {
/* If any escape flags are set, also escape backslashes. */ // If any escape flags are set, also escape backslashes.
BIO_snprintf(buf, sizeof(buf), "\\%c", (int)c); BIO_snprintf(buf, sizeof(buf), "\\%c", (int)c);
} else { } else {
return maybe_write(out, &u8, 1) ? 1 : -1; return maybe_write(out, &u8, 1) ? 1 : -1;
@ -122,16 +122,14 @@ static int do_esc_char(uint32_t c, unsigned long flags, char *do_quotes,
return maybe_write(out, buf, len) ? len : -1; return maybe_write(out, buf, len) ? len : -1;
} }
/* // This function sends each character in a buffer to do_esc_char(). It
* This function sends each character in a buffer to do_esc_char(). It // interprets the content formats and converts to or from UTF8 as
* interprets the content formats and converts to or from UTF8 as // appropriate.
* appropriate.
*/
static int do_buf(const unsigned char *buf, int buflen, int encoding, static int do_buf(const unsigned char *buf, int buflen, int encoding,
int utf8_convert, unsigned long flags, char *quotes, int utf8_convert, unsigned long flags, char *quotes,
BIO *out) { BIO *out) {
/* Reject invalid UCS-4 and UCS-2 lengths without parsing. */ // Reject invalid UCS-4 and UCS-2 lengths without parsing.
switch (encoding) { switch (encoding) {
case MBSTRING_UNIV: case MBSTRING_UNIV:
if (buflen & 3) { if (buflen & 3) {
@ -152,10 +150,10 @@ static int do_buf(const unsigned char *buf, int buflen, int encoding,
int outlen = 0; int outlen = 0;
while (p != q) { while (p != q) {
const int is_first = p == buf; const int is_first = p == buf;
/* TODO(davidben): Replace this with |cbs_get_ucs2_be|, etc., to check // TODO(davidben): Replace this with |cbs_get_ucs2_be|, etc., to check
* for invalid codepoints. Before doing that, enforce it in the parser, // for invalid codepoints. Before doing that, enforce it in the parser,
* https://crbug.com/boringssl/427, so these error cases are not // https://crbug.com/boringssl/427, so these error cases are not
* reachable from parsed objects. */ // reachable from parsed objects.
uint32_t c; uint32_t c;
switch (encoding) { switch (encoding) {
case MBSTRING_UNIV: case MBSTRING_UNIV:
@ -177,7 +175,7 @@ static int do_buf(const unsigned char *buf, int buflen, int encoding,
case MBSTRING_UTF8: { case MBSTRING_UTF8: {
int consumed = UTF8_getc(p, buflen, &c); int consumed = UTF8_getc(p, buflen, &c);
if (consumed < 0) { if (consumed < 0) {
return -1; /* Invalid UTF8String */ return -1; // Invalid UTF8String
} }
buflen -= consumed; buflen -= consumed;
p += consumed; p += consumed;
@ -194,12 +192,10 @@ static int do_buf(const unsigned char *buf, int buflen, int encoding,
int utflen; int utflen;
utflen = UTF8_putc(utfbuf, sizeof utfbuf, c); utflen = UTF8_putc(utfbuf, sizeof utfbuf, c);
for (int i = 0; i < utflen; i++) { for (int i = 0; i < utflen; i++) {
/* // We don't need to worry about setting orflags correctly
* We don't need to worry about setting orflags correctly // because if utflen==1 its value will be correct anyway
* because if utflen==1 its value will be correct anyway // otherwise each character will be > 0x7f and so the
* otherwise each character will be > 0x7f and so the // character will never be escaped on first and last.
* character will never be escaped on first and last.
*/
int len = do_esc_char(utfbuf[i], flags, quotes, out, is_first, is_last); int len = do_esc_char(utfbuf[i], flags, quotes, out, is_first, is_last);
if (len < 0) { if (len < 0) {
return -1; return -1;
@ -217,7 +213,7 @@ static int do_buf(const unsigned char *buf, int buflen, int encoding,
return outlen; return outlen;
} }
/* This function hex dumps a buffer of characters */ // This function hex dumps a buffer of characters
static int do_hex_dump(BIO *out, unsigned char *buf, int buflen) { static int do_hex_dump(BIO *out, unsigned char *buf, int buflen) {
static const char hexdig[] = "0123456789ABCDEF"; static const char hexdig[] = "0123456789ABCDEF";
@ -238,18 +234,16 @@ static int do_hex_dump(BIO *out, unsigned char *buf, int buflen) {
return buflen << 1; return buflen << 1;
} }
/* // "dump" a string. This is done when the type is unknown, or the flags
* "dump" a string. This is done when the type is unknown, or the flags // request it. We can either dump the content octets or the entire DER
* request it. We can either dump the content octets or the entire DER // encoding. This uses the RFC 2253 #01234 format.
* encoding. This uses the RFC 2253 #01234 format.
*/
static int do_dump(unsigned long flags, BIO *out, const ASN1_STRING *str) { static int do_dump(unsigned long flags, BIO *out, const ASN1_STRING *str) {
if (!maybe_write(out, "#", 1)) { if (!maybe_write(out, "#", 1)) {
return -1; return -1;
} }
/* If we don't dump DER encoding just dump content octets */ // If we don't dump DER encoding just dump content octets
if (!(flags & ASN1_STRFLGS_DUMP_DER)) { if (!(flags & ASN1_STRFLGS_DUMP_DER)) {
int outlen = do_hex_dump(out, str->data, str->length); int outlen = do_hex_dump(out, str->data, str->length);
if (outlen < 0) { if (outlen < 0) {
@ -258,21 +252,19 @@ static int do_dump(unsigned long flags, BIO *out, const ASN1_STRING *str) {
return outlen + 1; return outlen + 1;
} }
/* // Placing the ASN1_STRING in a temporary ASN1_TYPE allows the DER encoding
* Placing the ASN1_STRING in a temporary ASN1_TYPE allows the DER encoding // to readily obtained.
* to readily obtained.
*/
ASN1_TYPE t; ASN1_TYPE t;
t.type = str->type; t.type = str->type;
/* Negative INTEGER and ENUMERATED values are the only case where // Negative INTEGER and ENUMERATED values are the only case where
* |ASN1_STRING| and |ASN1_TYPE| types do not match. // |ASN1_STRING| and |ASN1_TYPE| types do not match.
* //
* TODO(davidben): There are also some type fields which, in |ASN1_TYPE|, do // 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 // 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. // 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 // |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 // this is an invalid input. But this corner of the library in general
* should be more robust. */ // should be more robust.
if (t.type == V_ASN1_NEG_INTEGER) { if (t.type == V_ASN1_NEG_INTEGER) {
t.type = V_ASN1_INTEGER; t.type = V_ASN1_INTEGER;
} else if (t.type == V_ASN1_NEG_ENUMERATED) { } else if (t.type == V_ASN1_NEG_ENUMERATED) {
@ -292,12 +284,12 @@ static int do_dump(unsigned long flags, BIO *out, const ASN1_STRING *str) {
return outlen + 1; return outlen + 1;
} }
/* string_type_to_encoding returns the |MBSTRING_*| constant for the encoding // 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 // used by the |ASN1_STRING| type |type|, or -1 if |tag| is not a string
* type. */ // type.
static int string_type_to_encoding(int type) { static int string_type_to_encoding(int type) {
/* This function is sometimes passed ASN.1 universal types and sometimes // This function is sometimes passed ASN.1 universal types and sometimes
* passed |ASN1_STRING| type values */ // passed |ASN1_STRING| type values
switch (type) { switch (type) {
case V_ASN1_UTF8STRING: case V_ASN1_UTF8STRING:
return MBSTRING_UTF8; return MBSTRING_UTF8;
@ -308,7 +300,7 @@ static int string_type_to_encoding(int type) {
case V_ASN1_UTCTIME: case V_ASN1_UTCTIME:
case V_ASN1_GENERALIZEDTIME: case V_ASN1_GENERALIZEDTIME:
case V_ASN1_ISO64STRING: case V_ASN1_ISO64STRING:
/* |MBSTRING_ASC| refers to Latin-1, not ASCII. */ // |MBSTRING_ASC| refers to Latin-1, not ASCII.
return MBSTRING_ASC; return MBSTRING_ASC;
case V_ASN1_UNIVERSALSTRING: case V_ASN1_UNIVERSALSTRING:
return MBSTRING_UNIV; return MBSTRING_UNIV;
@ -318,11 +310,9 @@ static int string_type_to_encoding(int type) {
return -1; return -1;
} }
/* // This is the main function, print out an ASN1_STRING taking note of various
* This is the main function, print out an ASN1_STRING taking note of various // escape and display options. Returns number of characters written or -1 if
* escape and display options. Returns number of characters written or -1 if // an error occurred.
* an error occurred.
*/
int ASN1_STRING_print_ex(BIO *out, const ASN1_STRING *str, int ASN1_STRING_print_ex(BIO *out, const ASN1_STRING *str,
unsigned long flags) { unsigned long flags) {
@ -337,13 +327,13 @@ int ASN1_STRING_print_ex(BIO *out, const ASN1_STRING *str,
outlen++; outlen++;
} }
/* Decide what to do with |str|, either dump the contents or display it. */ // Decide what to do with |str|, either dump the contents or display it.
int encoding; int encoding;
if (flags & ASN1_STRFLGS_DUMP_ALL) { if (flags & ASN1_STRFLGS_DUMP_ALL) {
/* Dump everything. */ // Dump everything.
encoding = -1; encoding = -1;
} else if (flags & ASN1_STRFLGS_IGNORE_TYPE) { } else if (flags & ASN1_STRFLGS_IGNORE_TYPE) {
/* Ignore the string type and interpret the contents as Latin-1. */ // Ignore the string type and interpret the contents as Latin-1.
encoding = MBSTRING_ASC; encoding = MBSTRING_ASC;
} else { } else {
encoding = string_type_to_encoding(type); encoding = string_type_to_encoding(type);
@ -363,11 +353,11 @@ int ASN1_STRING_print_ex(BIO *out, const ASN1_STRING *str,
int utf8_convert = 0; int utf8_convert = 0;
if (flags & ASN1_STRFLGS_UTF8_CONVERT) { if (flags & ASN1_STRFLGS_UTF8_CONVERT) {
/* If the string is UTF-8, skip decoding and just interpret it as 1 byte // If the string is UTF-8, skip decoding and just interpret it as 1 byte
* per character to avoid converting twice. // per character to avoid converting twice.
* //
* TODO(davidben): This is not quite a valid optimization if the input // TODO(davidben): This is not quite a valid optimization if the input
* was invalid UTF-8. */ // was invalid UTF-8.
if (encoding == MBSTRING_UTF8) { if (encoding == MBSTRING_UTF8) {
encoding = MBSTRING_ASC; encoding = MBSTRING_ASC;
} else { } else {
@ -375,7 +365,7 @@ int ASN1_STRING_print_ex(BIO *out, const ASN1_STRING *str,
} }
} }
/* Measure the length. */ // Measure the length.
char quotes = 0; char quotes = 0;
int len = do_buf(str->data, str->length, encoding, utf8_convert, flags, int len = do_buf(str->data, str->length, encoding, utf8_convert, flags,
&quotes, NULL); &quotes, NULL);
@ -390,7 +380,7 @@ int ASN1_STRING_print_ex(BIO *out, const ASN1_STRING *str,
return outlen; return outlen;
} }
/* Encode the value. */ // Encode the value.
if ((quotes && !maybe_write(out, "\"", 1)) || if ((quotes && !maybe_write(out, "\"", 1)) ||
do_buf(str->data, str->length, encoding, utf8_convert, flags, NULL, out) < do_buf(str->data, str->length, encoding, utf8_convert, flags, NULL, out) <
0 || 0 ||
@ -404,8 +394,8 @@ int ASN1_STRING_print_ex_fp(FILE *fp, const ASN1_STRING *str,
unsigned long flags) { unsigned long flags) {
BIO *bio = NULL; BIO *bio = NULL;
if (fp != NULL) { if (fp != NULL) {
/* If |fp| is NULL, this function returns the number of bytes without // If |fp| is NULL, this function returns the number of bytes without
* writing. */ // writing.
bio = BIO_new_fp(fp, BIO_NOCLOSE); bio = BIO_new_fp(fp, BIO_NOCLOSE);
if (bio == NULL) { if (bio == NULL) {
return -1; return -1;
@ -518,10 +508,10 @@ int ASN1_GENERALIZEDTIME_print(BIO *bp, const ASN1_GENERALIZEDTIME *tm) {
if (tm->length >= 14 && (v[12] >= '0') && (v[12] <= '9') && (v[13] >= '0') && if (tm->length >= 14 && (v[12] >= '0') && (v[12] <= '9') && (v[13] >= '0') &&
(v[13] <= '9')) { (v[13] <= '9')) {
s = (v[12] - '0') * 10 + (v[13] - '0'); s = (v[12] - '0') * 10 + (v[13] - '0');
/* Check for fractions of seconds. */ // Check for fractions of seconds.
if (tm->length >= 15 && v[14] == '.') { if (tm->length >= 15 && v[14] == '.') {
int l = tm->length; int l = tm->length;
f = &v[14]; /* The decimal point. */ f = &v[14]; // The decimal point.
f_len = 1; f_len = 1;
while (14 + f_len < l && f[f_len] >= '0' && f[f_len] <= '9') { while (14 + f_len < l && f[f_len] >= '0' && f[f_len] <= '9') {
++f_len; ++f_len;

@ -82,11 +82,9 @@ int ASN1_STRING_set_default_mask_asc(const char *p) { return 1; }
static const ASN1_STRING_TABLE *asn1_string_table_get(int nid); static const ASN1_STRING_TABLE *asn1_string_table_get(int nid);
/* // The following function generates an ASN1_STRING based on limits in a
* The following function generates an ASN1_STRING based on limits in a // table. Frequently the types and length of an ASN1_STRING are restricted by
* table. Frequently the types and length of an ASN1_STRING are restricted by // a corresponding OID. For example certificates and certificate requests.
* a corresponding OID. For example certificates and certificate requests.
*/
ASN1_STRING *ASN1_STRING_set_by_NID(ASN1_STRING **out, const unsigned char *in, ASN1_STRING *ASN1_STRING_set_by_NID(ASN1_STRING **out, const unsigned char *in,
int len, int inform, int nid) { int len, int inform, int nid) {
@ -112,11 +110,9 @@ ASN1_STRING *ASN1_STRING_set_by_NID(ASN1_STRING **out, const unsigned char *in,
return *out; return *out;
} }
/* // Now the tables and helper functions for the string table:
* Now the tables and helper functions for the string table:
*/
/* See RFC 5280. */ // See RFC 5280.
#define ub_name 32768 #define ub_name 32768
#define ub_common_name 64 #define ub_common_name 64
#define ub_locality_name 128 #define ub_locality_name 128
@ -126,7 +122,7 @@ ASN1_STRING *ASN1_STRING_set_by_NID(ASN1_STRING **out, const unsigned char *in,
#define ub_email_address 128 #define ub_email_address 128
#define ub_serial_number 64 #define ub_serial_number 64
/* This table must be kept in NID order */ // This table must be kept in NID order
static const ASN1_STRING_TABLE tbl_standard[] = { static const ASN1_STRING_TABLE tbl_standard[] = {
{NID_commonName, 1, ub_common_name, DIRSTRING_TYPE, 0}, {NID_commonName, 1, ub_common_name, DIRSTRING_TYPE, 0},
@ -185,15 +181,15 @@ static const ASN1_STRING_TABLE *asn1_string_table_get(int nid) {
tbl = lh_ASN1_STRING_TABLE_retrieve(string_tables, &key); tbl = lh_ASN1_STRING_TABLE_retrieve(string_tables, &key);
} }
CRYPTO_STATIC_MUTEX_unlock_read(&string_tables_lock); CRYPTO_STATIC_MUTEX_unlock_read(&string_tables_lock);
/* Note returning |tbl| without the lock is only safe because // Note returning |tbl| without the lock is only safe because
* |ASN1_STRING_TABLE_add| cannot modify or delete existing entries. If we // |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. */ // wish to support that, this function must copy the result under a lock.
return tbl; return tbl;
} }
int ASN1_STRING_TABLE_add(int nid, long minsize, long maxsize, int ASN1_STRING_TABLE_add(int nid, long minsize, long maxsize,
unsigned long mask, unsigned long flags) { unsigned long mask, unsigned long flags) {
/* Existing entries cannot be overwritten. */ // Existing entries cannot be overwritten.
if (asn1_string_table_get(nid) != NULL) { if (asn1_string_table_get(nid) != NULL) {
OPENSSL_PUT_ERROR(ASN1, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); OPENSSL_PUT_ERROR(ASN1, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
return 0; return 0;
@ -208,8 +204,8 @@ int ASN1_STRING_TABLE_add(int nid, long minsize, long maxsize,
goto err; goto err;
} }
} else { } else {
/* Check again for an existing entry. One may have been added while // Check again for an existing entry. One may have been added while
* unlocked. */ // unlocked.
ASN1_STRING_TABLE key; ASN1_STRING_TABLE key;
key.nid = nid; key.nid = nid;
if (lh_ASN1_STRING_TABLE_retrieve(string_tables, &key) != NULL) { if (lh_ASN1_STRING_TABLE_retrieve(string_tables, &key) != NULL) {

@ -65,11 +65,9 @@
#include "internal.h" #include "internal.h"
/* // This is an implementation of the ASN1 Time structure which is: Time ::=
* This is an implementation of the ASN1 Time structure which is: Time ::= // CHOICE { utcTime UTCTime, generalTime GeneralizedTime } written by Steve
* CHOICE { utcTime UTCTime, generalTime GeneralizedTime } written by Steve // Henson.
* Henson.
*/
IMPLEMENT_ASN1_MSTRING(ASN1_TIME, B_ASN1_TIME) IMPLEMENT_ASN1_MSTRING(ASN1_TIME, B_ASN1_TIME)
@ -109,7 +107,7 @@ int ASN1_TIME_check(const ASN1_TIME *t) {
return 0; return 0;
} }
/* Convert an ASN1_TIME structure to GeneralizedTime */ // Convert an ASN1_TIME structure to GeneralizedTime
ASN1_GENERALIZEDTIME *ASN1_TIME_to_generalizedtime(const ASN1_TIME *t, ASN1_GENERALIZEDTIME *ASN1_TIME_to_generalizedtime(const ASN1_TIME *t,
ASN1_GENERALIZEDTIME **out) { ASN1_GENERALIZEDTIME **out) {
ASN1_GENERALIZEDTIME *ret = NULL; ASN1_GENERALIZEDTIME *ret = NULL;
@ -128,7 +126,7 @@ ASN1_GENERALIZEDTIME *ASN1_TIME_to_generalizedtime(const ASN1_TIME *t,
ret = *out; ret = *out;
} }
/* If already GeneralizedTime just copy across */ // If already GeneralizedTime just copy across
if (t->type == V_ASN1_GENERALIZEDTIME) { if (t->type == V_ASN1_GENERALIZEDTIME) {
if (!ASN1_STRING_set(ret, t->data, t->length)) { if (!ASN1_STRING_set(ret, t->data, t->length)) {
goto err; goto err;
@ -136,14 +134,14 @@ ASN1_GENERALIZEDTIME *ASN1_TIME_to_generalizedtime(const ASN1_TIME *t,
goto done; goto done;
} }
/* grow the string */ // grow the string
if (!ASN1_STRING_set(ret, NULL, t->length + 2)) { if (!ASN1_STRING_set(ret, NULL, t->length + 2)) {
goto err; goto err;
} }
/* ASN1_STRING_set() allocated 'len + 1' bytes. */ // ASN1_STRING_set() allocated 'len + 1' bytes.
newlen = t->length + 2 + 1; newlen = t->length + 2 + 1;
str = (char *)ret->data; str = (char *)ret->data;
/* Work out the century and prepend */ // Work out the century and prepend
if (t->data[0] >= '5') { if (t->data[0] >= '5') {
OPENSSL_strlcpy(str, "19", newlen); OPENSSL_strlcpy(str, "19", newlen);
} else { } else {

@ -115,7 +115,7 @@ int ASN1_TYPE_set1(ASN1_TYPE *a, int type, const void *value) {
return 1; return 1;
} }
/* Returns 0 if they are equal, != 0 otherwise. */ // Returns 0 if they are equal, != 0 otherwise.
int ASN1_TYPE_cmp(const ASN1_TYPE *a, const ASN1_TYPE *b) { int ASN1_TYPE_cmp(const ASN1_TYPE *a, const ASN1_TYPE *b) {
int result = -1; int result = -1;
@ -128,7 +128,7 @@ int ASN1_TYPE_cmp(const ASN1_TYPE *a, const ASN1_TYPE *b) {
result = OBJ_cmp(a->value.object, b->value.object); result = OBJ_cmp(a->value.object, b->value.object);
break; break;
case V_ASN1_NULL: case V_ASN1_NULL:
result = 0; /* They do not have content. */ result = 0; // They do not have content.
break; break;
case V_ASN1_BOOLEAN: case V_ASN1_BOOLEAN:
result = a->value.boolean - b->value.boolean; result = a->value.boolean - b->value.boolean;

@ -61,16 +61,14 @@
#include "internal.h" #include "internal.h"
/* UTF8 utilities */ // UTF8 utilities
/* // This parses a UTF8 string one character at a time. It is passed a pointer
* This parses a UTF8 string one character at a time. It is passed a pointer // to the string and the length of the string. It sets 'value' to the value
* to the string and the length of the string. It sets 'value' to the value // of the current character. It returns the number of characters read or a
* of the current character. It returns the number of characters read or a // negative error code: -1 = string too short -2 = illegal character -3 =
* negative error code: -1 = string too short -2 = illegal character -3 = // subsequent characters not of the form 10xxxxxx -4 = character encoded
* subsequent characters not of the form 10xxxxxx -4 = character encoded // incorrectly (not minimal length).
* incorrectly (not minimal length).
*/
int UTF8_getc(const unsigned char *str, int len, uint32_t *val) { int UTF8_getc(const unsigned char *str, int len, uint32_t *val) {
const unsigned char *p; const unsigned char *p;
@ -81,7 +79,7 @@ int UTF8_getc(const unsigned char *str, int len, uint32_t *val) {
} }
p = str; p = str;
/* Check syntax and work out the encoded value (if correct) */ // Check syntax and work out the encoded value (if correct)
if ((*p & 0x80) == 0) { if ((*p & 0x80) == 0) {
value = *p++ & 0x7f; value = *p++ & 0x7f;
ret = 1; ret = 1;
@ -171,17 +169,15 @@ int UTF8_getc(const unsigned char *str, int len, uint32_t *val) {
return ret; return ret;
} }
/* // This takes a character 'value' and writes the UTF8 encoded value in 'str'
* This takes a character 'value' and writes the UTF8 encoded value in 'str' // where 'str' is a buffer containing 'len' characters. Returns the number of
* where 'str' is a buffer containing 'len' characters. Returns the number of // characters written or -1 if 'len' is too small. 'str' can be set to NULL
* characters written or -1 if 'len' is too small. 'str' can be set to NULL // in which case it just returns the number of characters. It will need at
* in which case it just returns the number of characters. It will need at // most 6 characters.
* most 6 characters.
*/
int UTF8_putc(unsigned char *str, int len, uint32_t value) { int UTF8_putc(unsigned char *str, int len, uint32_t value) {
if (!str) { if (!str) {
len = 6; /* Maximum we will need */ len = 6; // Maximum we will need
} else if (len <= 0) { } else if (len <= 0) {
return -1; return -1;
} }

@ -67,19 +67,17 @@
#include "internal.h" #include "internal.h"
/* Cross-module errors from crypto/x509/i2d_pr.c. */ // Cross-module errors from crypto/x509/i2d_pr.c.
OPENSSL_DECLARE_ERROR_REASON(ASN1, UNSUPPORTED_PUBLIC_KEY_TYPE) OPENSSL_DECLARE_ERROR_REASON(ASN1, UNSUPPORTED_PUBLIC_KEY_TYPE)
/* Cross-module errors from crypto/x509/algorithm.c. */ // Cross-module errors from crypto/x509/algorithm.c.
OPENSSL_DECLARE_ERROR_REASON(ASN1, CONTEXT_NOT_INITIALISED) OPENSSL_DECLARE_ERROR_REASON(ASN1, CONTEXT_NOT_INITIALISED)
OPENSSL_DECLARE_ERROR_REASON(ASN1, DIGEST_AND_KEY_TYPE_NOT_SUPPORTED) OPENSSL_DECLARE_ERROR_REASON(ASN1, DIGEST_AND_KEY_TYPE_NOT_SUPPORTED)
OPENSSL_DECLARE_ERROR_REASON(ASN1, UNKNOWN_MESSAGE_DIGEST_ALGORITHM) OPENSSL_DECLARE_ERROR_REASON(ASN1, UNKNOWN_MESSAGE_DIGEST_ALGORITHM)
OPENSSL_DECLARE_ERROR_REASON(ASN1, UNKNOWN_SIGNATURE_ALGORITHM) OPENSSL_DECLARE_ERROR_REASON(ASN1, UNKNOWN_SIGNATURE_ALGORITHM)
OPENSSL_DECLARE_ERROR_REASON(ASN1, WRONG_PUBLIC_KEY_TYPE) OPENSSL_DECLARE_ERROR_REASON(ASN1, WRONG_PUBLIC_KEY_TYPE)
/* // Cross-module errors from crypto/x509/asn1_gen.c. TODO(davidben): Remove
* Cross-module errors from crypto/x509/asn1_gen.c. TODO(davidben): Remove // these once asn1_gen.c is gone.
* these once asn1_gen.c is gone.
*/
OPENSSL_DECLARE_ERROR_REASON(ASN1, DEPTH_EXCEEDED) OPENSSL_DECLARE_ERROR_REASON(ASN1, DEPTH_EXCEEDED)
OPENSSL_DECLARE_ERROR_REASON(ASN1, ILLEGAL_BITSTRING_FORMAT) OPENSSL_DECLARE_ERROR_REASON(ASN1, ILLEGAL_BITSTRING_FORMAT)
OPENSSL_DECLARE_ERROR_REASON(ASN1, ILLEGAL_BOOLEAN) OPENSSL_DECLARE_ERROR_REASON(ASN1, ILLEGAL_BOOLEAN)
@ -113,12 +111,12 @@ int ASN1_get_object(const unsigned char **inp, long *out_len, int *out_tag,
return 0x80; return 0x80;
} }
/* TODO(https://crbug.com/boringssl/354): This should use |CBS_get_asn1| to // TODO(https://crbug.com/boringssl/354): This should use |CBS_get_asn1| to
* reject non-minimal lengths, which are only allowed in BER. However, // reject non-minimal lengths, which are only allowed in BER. However,
* Android sometimes needs allow a non-minimal length in certificate // Android sometimes needs allow a non-minimal length in certificate
* signature fields (see b/18228011). Make this only apply to that field, // signature fields (see b/18228011). Make this only apply to that field,
* while requiring DER elsewhere. Better yet, it should be limited to an // while requiring DER elsewhere. Better yet, it should be limited to an
* preprocessing step in that part of Android. */ // preprocessing step in that part of Android.
unsigned tag; unsigned tag;
size_t header_len; size_t header_len;
int indefinite; int indefinite;
@ -127,19 +125,19 @@ int ASN1_get_object(const unsigned char **inp, long *out_len, int *out_tag,
if (!CBS_get_any_ber_asn1_element(&cbs, &body, &tag, &header_len, if (!CBS_get_any_ber_asn1_element(&cbs, &body, &tag, &header_len,
/*out_ber_found=*/NULL, &indefinite) || /*out_ber_found=*/NULL, &indefinite) ||
indefinite || !CBS_skip(&body, header_len) || indefinite || !CBS_skip(&body, header_len) ||
/* Bound the length to comfortably fit in an int. Lengths in this // Bound the length to comfortably fit in an int. Lengths in this
* module often switch between int and long without overflow checks. */ // module often switch between int and long without overflow checks.
CBS_len(&body) > INT_MAX / 2) { CBS_len(&body) > INT_MAX / 2) {
OPENSSL_PUT_ERROR(ASN1, ASN1_R_HEADER_TOO_LONG); OPENSSL_PUT_ERROR(ASN1, ASN1_R_HEADER_TOO_LONG);
return 0x80; return 0x80;
} }
/* Convert between tag representations. */ // Convert between tag representations.
int tag_class = (tag & CBS_ASN1_CLASS_MASK) >> CBS_ASN1_TAG_SHIFT; int tag_class = (tag & CBS_ASN1_CLASS_MASK) >> CBS_ASN1_TAG_SHIFT;
int constructed = (tag & CBS_ASN1_CONSTRUCTED) >> CBS_ASN1_TAG_SHIFT; int constructed = (tag & CBS_ASN1_CONSTRUCTED) >> CBS_ASN1_TAG_SHIFT;
int tag_number = tag & CBS_ASN1_TAG_NUMBER_MASK; int tag_number = tag & CBS_ASN1_TAG_NUMBER_MASK;
/* To avoid ambiguity with V_ASN1_NEG, impose a limit on universal tags. */ // 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) { if (tag_class == V_ASN1_UNIVERSAL && tag_number > V_ASN1_MAX_UNIVERSAL) {
OPENSSL_PUT_ERROR(ASN1, ASN1_R_HEADER_TOO_LONG); OPENSSL_PUT_ERROR(ASN1, ASN1_R_HEADER_TOO_LONG);
return 0x80; return 0x80;
@ -152,9 +150,7 @@ int ASN1_get_object(const unsigned char **inp, long *out_len, int *out_tag,
return constructed; return constructed;
} }
/* // class 0 is constructed constructed == 2 for indefinite length constructed
* class 0 is constructed constructed == 2 for indefinite length constructed
*/
void ASN1_put_object(unsigned char **pp, int constructed, int length, int tag, void ASN1_put_object(unsigned char **pp, int constructed, int length, int tag,
int xclass) { int xclass) {
unsigned char *p = *pp; unsigned char *p = *pp;
@ -188,8 +184,8 @@ void ASN1_put_object(unsigned char **pp, int constructed, int length, int tag,
} }
int ASN1_put_eoc(unsigned char **pp) { int ASN1_put_eoc(unsigned char **pp) {
/* This function is no longer used in the library, but some external code // This function is no longer used in the library, but some external code
* uses it. */ // uses it.
unsigned char *p = *pp; unsigned char *p = *pp;
*p++ = 0; *p++ = 0;
*p++ = 0; *p++ = 0;
@ -303,7 +299,7 @@ int ASN1_STRING_set(ASN1_STRING *str, const void *_data, int len) {
str->length = len; str->length = len;
if (data != NULL) { if (data != NULL) {
OPENSSL_memcpy(str->data, data, len); OPENSSL_memcpy(str->data, data, len);
/* an allowance for strings :-) */ // an allowance for strings :-)
str->data[len] = '\0'; str->data[len] = '\0';
} }
return (1); return (1);
@ -343,7 +339,7 @@ void ASN1_STRING_free(ASN1_STRING *str) {
} }
int ASN1_STRING_cmp(const ASN1_STRING *a, const ASN1_STRING *b) { int ASN1_STRING_cmp(const ASN1_STRING *a, const ASN1_STRING *b) {
/* Capture padding bits and implicit truncation in BIT STRINGs. */ // Capture padding bits and implicit truncation in BIT STRINGs.
int a_length = a->length, b_length = b->length; int a_length = a->length, b_length = b->length;
uint8_t a_padding = 0, b_padding = 0; uint8_t a_padding = 0, b_padding = 0;
if (a->type == V_ASN1_BIT_STRING) { if (a->type == V_ASN1_BIT_STRING) {
@ -359,8 +355,8 @@ int ASN1_STRING_cmp(const ASN1_STRING *a, const ASN1_STRING *b) {
if (a_length > b_length) { if (a_length > b_length) {
return 1; return 1;
} }
/* In a BIT STRING, the number of bits is 8 * length - padding. Invert this // In a BIT STRING, the number of bits is 8 * length - padding. Invert this
* comparison so we compare by lengths. */ // comparison so we compare by lengths.
if (a_padding > b_padding) { if (a_padding > b_padding) {
return -1; return -1;
} }
@ -373,7 +369,7 @@ int ASN1_STRING_cmp(const ASN1_STRING *a, const ASN1_STRING *b) {
return ret; return ret;
} }
/* Comparing the type first is more natural, but this matches OpenSSL. */ // Comparing the type first is more natural, but this matches OpenSSL.
if (a->type < b->type) { if (a->type < b->type) {
return -1; return -1;
} }

@ -69,42 +69,42 @@ extern "C" {
#endif #endif
/* Wrapper functions for time functions. */ // Wrapper functions for time functions.
/* OPENSSL_gmtime wraps |gmtime_r|. See the manual page for that function. */ // OPENSSL_gmtime wraps |gmtime_r|. See the manual page for that function.
OPENSSL_EXPORT 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| // OPENSSL_gmtime_adj updates |tm| by adding |offset_day| days and |offset_sec|
* seconds. */ // seconds.
int OPENSSL_gmtime_adj(struct tm *tm, int offset_day, long offset_sec); int OPENSSL_gmtime_adj(struct tm *tm, int offset_day, long offset_sec);
/* OPENSSL_gmtime_diff calculates the difference between |from| and |to| and // 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 // outputs the difference as a number of days and seconds in |*out_days| and
* |*out_secs|. */ // |*out_secs|.
OPENSSL_EXPORT int OPENSSL_gmtime_diff(int *out_days, int *out_secs, OPENSSL_EXPORT int OPENSSL_gmtime_diff(int *out_days, int *out_secs,
const struct tm *from, const struct tm *from,
const struct tm *to); const struct tm *to);
/* Internal ASN1 structures and functions: not for application use */ // Internal ASN1 structures and functions: not for application use
/* These are used internally in the ASN1_OBJECT to keep track of // These are used internally in the ASN1_OBJECT to keep track of
* whether the names and data need to be free()ed */ // whether the names and data need to be free()ed
#define ASN1_OBJECT_FLAG_DYNAMIC 0x01 /* internal use */ #define ASN1_OBJECT_FLAG_DYNAMIC 0x01 // internal use
#define ASN1_OBJECT_FLAG_DYNAMIC_STRINGS 0x04 /* internal use */ #define ASN1_OBJECT_FLAG_DYNAMIC_STRINGS 0x04 // internal use
#define ASN1_OBJECT_FLAG_DYNAMIC_DATA 0x08 /* internal use */ #define ASN1_OBJECT_FLAG_DYNAMIC_DATA 0x08 // internal use
/* An asn1_object_st (aka |ASN1_OBJECT|) represents an ASN.1 OBJECT IDENTIFIER. // An asn1_object_st (aka |ASN1_OBJECT|) represents an ASN.1 OBJECT IDENTIFIER.
* Note: Mutating an |ASN1_OBJECT| is only permitted when initializing it. The // Note: Mutating an |ASN1_OBJECT| is only permitted when initializing it. The
* library maintains a table of static |ASN1_OBJECT|s, which may be referenced // library maintains a table of static |ASN1_OBJECT|s, which may be referenced
* by non-const |ASN1_OBJECT| pointers. Code which receives an |ASN1_OBJECT| // by non-const |ASN1_OBJECT| pointers. Code which receives an |ASN1_OBJECT|
* pointer externally must assume it is immutable, even if the pointer is not // pointer externally must assume it is immutable, even if the pointer is not
* const. */ // const.
struct asn1_object_st { struct asn1_object_st {
const char *sn, *ln; const char *sn, *ln;
int nid; int nid;
int length; int length;
const unsigned char *data; /* data remains const after init */ const unsigned char *data; // data remains const after init
int flags; /* Should we free this one */ int flags; // Should we free this one
}; };
ASN1_OBJECT *ASN1_OBJECT_new(void); ASN1_OBJECT *ASN1_OBJECT_new(void);
@ -144,31 +144,31 @@ int ASN1_item_ex_d2i(ASN1_VALUE **pval, const unsigned char **in, long len,
const ASN1_ITEM *it, int tag, int aclass, char opt, const ASN1_ITEM *it, int tag, int aclass, char opt,
ASN1_TLC *ctx); ASN1_TLC *ctx);
/* ASN1_item_ex_i2d encodes |*pval| as a value of type |it| to |out| under the // ASN1_item_ex_i2d encodes |*pval| as a value of type |it| to |out| under the
* i2d output convention. It returns a non-zero length on success and -1 on // i2d output convention. It returns a non-zero length on success and -1 on
* error. If |tag| is -1. the tag and class come from |it|. Otherwise, the tag // error. If |tag| is -1. the tag and class come from |it|. Otherwise, the tag
* number is |tag| and the class is |aclass|. This is used for implicit tagging. // number is |tag| and the class is |aclass|. This is used for implicit tagging.
* This function treats a missing value as an error, not an optional field. */ // This function treats a missing value as an error, not an optional field.
int ASN1_item_ex_i2d(ASN1_VALUE **pval, unsigned char **out, int ASN1_item_ex_i2d(ASN1_VALUE **pval, unsigned char **out,
const ASN1_ITEM *it, int tag, int aclass); const ASN1_ITEM *it, int tag, int aclass);
void ASN1_primitive_free(ASN1_VALUE **pval, const ASN1_ITEM *it); void ASN1_primitive_free(ASN1_VALUE **pval, const ASN1_ITEM *it);
/* asn1_get_choice_selector returns the CHOICE selector value for |*pval|, which // asn1_get_choice_selector returns the CHOICE selector value for |*pval|, which
* must of type |it|. */ // must of type |it|.
int asn1_get_choice_selector(ASN1_VALUE **pval, const ASN1_ITEM *it); int asn1_get_choice_selector(ASN1_VALUE **pval, const ASN1_ITEM *it);
int asn1_set_choice_selector(ASN1_VALUE **pval, int value, const ASN1_ITEM *it); int asn1_set_choice_selector(ASN1_VALUE **pval, int value, const ASN1_ITEM *it);
/* asn1_get_field_ptr returns a pointer to the field in |*pval| corresponding to // asn1_get_field_ptr returns a pointer to the field in |*pval| corresponding to
* |tt|. */ // |tt|.
ASN1_VALUE **asn1_get_field_ptr(ASN1_VALUE **pval, const ASN1_TEMPLATE *tt); ASN1_VALUE **asn1_get_field_ptr(ASN1_VALUE **pval, const ASN1_TEMPLATE *tt);
/* asn1_do_adb returns the |ASN1_TEMPLATE| for the ANY DEFINED BY field |tt|, // asn1_do_adb returns the |ASN1_TEMPLATE| for the ANY DEFINED BY field |tt|,
* based on the selector INTEGER or OID in |*pval|. If |tt| is not an ADB field, // based on the selector INTEGER or OID in |*pval|. If |tt| is not an ADB field,
* it returns |tt|. If the selector does not match any value, it returns NULL. // it returns |tt|. If the selector does not match any value, it returns NULL.
* If |nullerr| is non-zero, it will additionally push an error to the error // If |nullerr| is non-zero, it will additionally push an error to the error
* queue when there is no match. */ // queue when there is no match.
const ASN1_TEMPLATE *asn1_do_adb(ASN1_VALUE **pval, const ASN1_TEMPLATE *tt, const ASN1_TEMPLATE *asn1_do_adb(ASN1_VALUE **pval, const ASN1_TEMPLATE *tt,
int nullerr); int nullerr);
@ -178,29 +178,29 @@ int asn1_refcount_dec_and_test_zero(ASN1_VALUE **pval, const ASN1_ITEM *it);
void asn1_enc_init(ASN1_VALUE **pval, const ASN1_ITEM *it); void asn1_enc_init(ASN1_VALUE **pval, const ASN1_ITEM *it);
void asn1_enc_free(ASN1_VALUE **pval, const ASN1_ITEM *it); void asn1_enc_free(ASN1_VALUE **pval, const ASN1_ITEM *it);
/* asn1_enc_restore, if |*pval| has a saved encoding, writes it to |out| under // asn1_enc_restore, if |*pval| has a saved encoding, writes it to |out| under
* the i2d output convention, sets |*len| to the length, and returns one. If it // the i2d output convention, sets |*len| to the length, and returns one. If it
* has no saved encoding, it returns zero. */ // has no saved encoding, it returns zero.
int asn1_enc_restore(int *len, unsigned char **out, ASN1_VALUE **pval, int asn1_enc_restore(int *len, unsigned char **out, ASN1_VALUE **pval,
const ASN1_ITEM *it); const ASN1_ITEM *it);
int asn1_enc_save(ASN1_VALUE **pval, const unsigned char *in, int inlen, int asn1_enc_save(ASN1_VALUE **pval, const unsigned char *in, int inlen,
const ASN1_ITEM *it); const ASN1_ITEM *it);
/* asn1_type_value_as_pointer returns |a|'s value in pointer form. This is // asn1_type_value_as_pointer returns |a|'s value in pointer form. This is
* usually the value object but, for BOOLEAN values, is 0 or 0xff cast to // usually the value object but, for BOOLEAN values, is 0 or 0xff cast to
* a pointer. */ // a pointer.
const void *asn1_type_value_as_pointer(const ASN1_TYPE *a); const void *asn1_type_value_as_pointer(const ASN1_TYPE *a);
/* asn1_is_printable returns one if |value| is a valid Unicode codepoint for an // asn1_is_printable returns one if |value| is a valid Unicode codepoint for an
* ASN.1 PrintableString, and zero otherwise. */ // ASN.1 PrintableString, and zero otherwise.
int asn1_is_printable(uint32_t value); int asn1_is_printable(uint32_t value);
/* asn1_bit_string_length returns the number of bytes in |str| and sets // asn1_bit_string_length returns the number of bytes in |str| and sets
* |*out_padding_bits| to the number of padding bits. // |*out_padding_bits| to the number of padding bits.
* //
* This function should be used instead of |ASN1_STRING_length| to correctly // This function should be used instead of |ASN1_STRING_length| to correctly
* handle the non-|ASN1_STRING_FLAG_BITS_LEFT| case. */ // handle the non-|ASN1_STRING_FLAG_BITS_LEFT| case.
int asn1_bit_string_length(const ASN1_BIT_STRING *str, int asn1_bit_string_length(const ASN1_BIT_STRING *str,
uint8_t *out_padding_bits); uint8_t *out_padding_bits);
@ -212,14 +212,14 @@ typedef struct {
unsigned long flags; unsigned long flags;
} ASN1_STRING_TABLE; } ASN1_STRING_TABLE;
/* asn1_get_string_table_for_testing sets |*out_ptr| and |*out_len| to the table // asn1_get_string_table_for_testing sets |*out_ptr| and |*out_len| to the table
* of built-in |ASN1_STRING_TABLE| values. It is exported for testing. */ // of built-in |ASN1_STRING_TABLE| values. It is exported for testing.
OPENSSL_EXPORT void asn1_get_string_table_for_testing( OPENSSL_EXPORT void asn1_get_string_table_for_testing(
const ASN1_STRING_TABLE **out_ptr, size_t *out_len); const ASN1_STRING_TABLE **out_ptr, size_t *out_len);
#if defined(__cplusplus) #if defined(__cplusplus)
} /* extern C */ } // extern C
#endif #endif
#endif /* OPENSSL_HEADER_ASN1_ASN1_LOCL_H */ #endif // OPENSSL_HEADER_ASN1_ASN1_LOCL_H

@ -66,12 +66,10 @@
#include "../internal.h" #include "../internal.h"
#include "internal.h" #include "internal.h"
/* // Constructed types with a recursive definition (such as can be found in PKCS7)
* Constructed types with a recursive definition (such as can be found in PKCS7) // could eventually exceed the stack given malicious input with excessive
* could eventually exceed the stack given malicious input with excessive // recursion. Therefore we limit the stack depth. This is the maximum number of
* recursion. Therefore we limit the stack depth. This is the maximum number of // recursive invocations of asn1_item_embed_d2i().
* recursive invocations of asn1_item_embed_d2i().
*/
#define ASN1_MAX_CONSTRUCTED_NEST 30 #define ASN1_MAX_CONSTRUCTED_NEST 30
static int asn1_check_tlen(long *olen, int *otag, unsigned char *oclass, static int asn1_check_tlen(long *olen, int *otag, unsigned char *oclass,
@ -93,26 +91,26 @@ static int asn1_item_ex_d2i(ASN1_VALUE **pval, const unsigned char **in,
long len, const ASN1_ITEM *it, int tag, int aclass, long len, const ASN1_ITEM *it, int tag, int aclass,
char opt, int depth); char opt, int depth);
/* Table to convert tags to bit values, used for MSTRING type */ // Table to convert tags to bit values, used for MSTRING type
static const unsigned long tag2bit[31] = { static const unsigned long tag2bit[31] = {
0, /* (reserved) */ 0, // (reserved)
0, /* BOOLEAN */ 0, // BOOLEAN
0, /* INTEGER */ 0, // INTEGER
B_ASN1_BIT_STRING, B_ASN1_BIT_STRING,
B_ASN1_OCTET_STRING, B_ASN1_OCTET_STRING,
0, /* NULL */ 0, // NULL
0, /* OBJECT IDENTIFIER */ 0, // OBJECT IDENTIFIER
B_ASN1_UNKNOWN, /* ObjectDescriptor */ B_ASN1_UNKNOWN, // ObjectDescriptor
B_ASN1_UNKNOWN, /* EXTERNAL */ B_ASN1_UNKNOWN, // EXTERNAL
B_ASN1_UNKNOWN, /* REAL */ B_ASN1_UNKNOWN, // REAL
B_ASN1_UNKNOWN, /* ENUMERATED */ B_ASN1_UNKNOWN, // ENUMERATED
B_ASN1_UNKNOWN, /* EMBEDDED PDV */ B_ASN1_UNKNOWN, // EMBEDDED PDV
B_ASN1_UTF8STRING, B_ASN1_UTF8STRING,
B_ASN1_UNKNOWN, /* RELATIVE-OID */ B_ASN1_UNKNOWN, // RELATIVE-OID
B_ASN1_UNKNOWN, /* TIME */ B_ASN1_UNKNOWN, // TIME
B_ASN1_UNKNOWN, /* (reserved) */ B_ASN1_UNKNOWN, // (reserved)
B_ASN1_SEQUENCE, B_ASN1_SEQUENCE,
0, /* SET */ 0, // SET
B_ASN1_NUMERICSTRING, B_ASN1_NUMERICSTRING,
B_ASN1_PRINTABLESTRING, B_ASN1_PRINTABLESTRING,
B_ASN1_T61STRING, B_ASN1_T61STRING,
@ -124,7 +122,7 @@ static const unsigned long tag2bit[31] = {
B_ASN1_ISO64STRING, B_ASN1_ISO64STRING,
B_ASN1_GENERALSTRING, B_ASN1_GENERALSTRING,
B_ASN1_UNIVERSALSTRING, B_ASN1_UNIVERSALSTRING,
B_ASN1_UNKNOWN, /* CHARACTER STRING */ B_ASN1_UNKNOWN, // CHARACTER STRING
B_ASN1_BMPSTRING, B_ASN1_BMPSTRING,
}; };
@ -135,14 +133,12 @@ unsigned long ASN1_tag2bit(int tag) {
return tag2bit[tag]; return tag2bit[tag];
} }
/* Macro to initialize and invalidate the cache */ // Macro to initialize and invalidate the cache
/* // Decode an ASN1 item, this currently behaves just like a standard 'd2i'
* Decode an ASN1 item, this currently behaves just like a standard 'd2i' // function. 'in' points to a buffer to read the data from, in future we
* function. 'in' points to a buffer to read the data from, in future we // will have more advanced versions that can input data a piece at a time and
* will have more advanced versions that can input data a piece at a time and // this will simply be a special case.
* this will simply be a special case.
*/
ASN1_VALUE *ASN1_item_d2i(ASN1_VALUE **pval, const unsigned char **in, long len, ASN1_VALUE *ASN1_item_d2i(ASN1_VALUE **pval, const unsigned char **in, long len,
const ASN1_ITEM *it) { const ASN1_ITEM *it) {
@ -157,10 +153,8 @@ ASN1_VALUE *ASN1_item_d2i(ASN1_VALUE **pval, const unsigned char **in, long len,
return NULL; return NULL;
} }
/* // Decode an item, taking care of IMPLICIT tagging, if any. If 'opt' set and
* Decode an item, taking care of IMPLICIT tagging, if any. If 'opt' set and // tag mismatch return -1 to handle OPTIONAL
* tag mismatch return -1 to handle OPTIONAL
*/
static int asn1_item_ex_d2i(ASN1_VALUE **pval, const unsigned char **in, static int asn1_item_ex_d2i(ASN1_VALUE **pval, const unsigned char **in,
long len, const ASN1_ITEM *it, int tag, int aclass, long len, const ASN1_ITEM *it, int tag, int aclass,
@ -180,10 +174,8 @@ static int asn1_item_ex_d2i(ASN1_VALUE **pval, const unsigned char **in,
return 0; return 0;
} }
/* // Bound |len| to comfortably fit in an int. Lengths in this module often
* Bound |len| to comfortably fit in an int. Lengths in this module often // switch between int and long without overflow checks.
* switch between int and long without overflow checks.
*/
if (len > INT_MAX / 2) { if (len > INT_MAX / 2) {
len = INT_MAX / 2; len = INT_MAX / 2;
} }
@ -196,12 +188,10 @@ static int asn1_item_ex_d2i(ASN1_VALUE **pval, const unsigned char **in,
switch (it->itype) { switch (it->itype) {
case ASN1_ITYPE_PRIMITIVE: case ASN1_ITYPE_PRIMITIVE:
if (it->templates) { if (it->templates) {
/* // tagging or OPTIONAL is currently illegal on an item template
* tagging or OPTIONAL is currently illegal on an item template // because the flags can't get passed down. In practice this
* because the flags can't get passed down. In practice this // isn't a problem: we include the relevant flags from the item
* isn't a problem: we include the relevant flags from the item // template in the template itself.
* template in the template itself.
*/
if ((tag != -1) || opt) { if ((tag != -1) || opt) {
OPENSSL_PUT_ERROR(ASN1, ASN1_R_ILLEGAL_OPTIONS_ON_ITEM_TEMPLATE); OPENSSL_PUT_ERROR(ASN1, ASN1_R_ILLEGAL_OPTIONS_ON_ITEM_TEMPLATE);
goto err; goto err;
@ -212,35 +202,33 @@ static int asn1_item_ex_d2i(ASN1_VALUE **pval, const unsigned char **in,
break; break;
case ASN1_ITYPE_MSTRING: case ASN1_ITYPE_MSTRING:
/* // It never makes sense for multi-strings to have implicit tagging, so
* 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, then this looks like an error in the template.
*/
if (tag != -1) { if (tag != -1) {
OPENSSL_PUT_ERROR(ASN1, ASN1_R_BAD_TEMPLATE); OPENSSL_PUT_ERROR(ASN1, ASN1_R_BAD_TEMPLATE);
goto err; goto err;
} }
p = *in; p = *in;
/* Just read in tag and class */ // Just read in tag and class
ret = asn1_check_tlen(NULL, &otag, &oclass, NULL, &p, len, -1, 0, 1); ret = asn1_check_tlen(NULL, &otag, &oclass, NULL, &p, len, -1, 0, 1);
if (!ret) { if (!ret) {
OPENSSL_PUT_ERROR(ASN1, ASN1_R_NESTED_ASN1_ERROR); OPENSSL_PUT_ERROR(ASN1, ASN1_R_NESTED_ASN1_ERROR);
goto err; goto err;
} }
/* Must be UNIVERSAL class */ // Must be UNIVERSAL class
if (oclass != V_ASN1_UNIVERSAL) { if (oclass != V_ASN1_UNIVERSAL) {
/* If OPTIONAL, assume this is OK */ // If OPTIONAL, assume this is OK
if (opt) { if (opt) {
return -1; return -1;
} }
OPENSSL_PUT_ERROR(ASN1, ASN1_R_MSTRING_NOT_UNIVERSAL); OPENSSL_PUT_ERROR(ASN1, ASN1_R_MSTRING_NOT_UNIVERSAL);
goto err; goto err;
} }
/* Check tag matches bit map */ // Check tag matches bit map
if (!(ASN1_tag2bit(otag) & it->utype)) { if (!(ASN1_tag2bit(otag) & it->utype)) {
/* If OPTIONAL, assume this is OK */ // If OPTIONAL, assume this is OK
if (opt) { if (opt) {
return -1; return -1;
} }
@ -250,15 +238,13 @@ static int asn1_item_ex_d2i(ASN1_VALUE **pval, const unsigned char **in,
return asn1_d2i_ex_primitive(pval, in, len, it, otag, 0, 0); return asn1_d2i_ex_primitive(pval, in, len, it, otag, 0, 0);
case ASN1_ITYPE_EXTERN: case ASN1_ITYPE_EXTERN:
/* Use new style d2i */ // Use new style d2i
ef = it->funcs; ef = it->funcs;
return ef->asn1_ex_d2i(pval, in, len, it, tag, aclass, opt, NULL); return ef->asn1_ex_d2i(pval, in, len, it, tag, aclass, opt, NULL);
case ASN1_ITYPE_CHOICE: { case ASN1_ITYPE_CHOICE: {
/* // It never makes sense for CHOICE types to have implicit tagging, so if
* It never makes sense for CHOICE types to have implicit tagging, so if // tag != -1, then this looks like an error in the template.
* tag != -1, then this looks like an error in the template.
*/
if (tag != -1) { if (tag != -1) {
OPENSSL_PUT_ERROR(ASN1, ASN1_R_BAD_TEMPLATE); OPENSSL_PUT_ERROR(ASN1, ASN1_R_BAD_TEMPLATE);
goto err; goto err;
@ -271,7 +257,7 @@ static int asn1_item_ex_d2i(ASN1_VALUE **pval, const unsigned char **in,
} }
if (*pval) { if (*pval) {
/* Free up and zero CHOICE value if initialised */ // Free up and zero CHOICE value if initialised
i = asn1_get_choice_selector(pval, it); i = asn1_get_choice_selector(pval, it);
if ((i >= 0) && (i < it->tcount)) { if ((i >= 0) && (i < it->tcount)) {
tt = it->templates + i; tt = it->templates + i;
@ -283,33 +269,31 @@ static int asn1_item_ex_d2i(ASN1_VALUE **pval, const unsigned char **in,
OPENSSL_PUT_ERROR(ASN1, ASN1_R_NESTED_ASN1_ERROR); OPENSSL_PUT_ERROR(ASN1, ASN1_R_NESTED_ASN1_ERROR);
goto err; goto err;
} }
/* CHOICE type, try each possibility in turn */ // CHOICE type, try each possibility in turn
p = *in; p = *in;
for (i = 0, tt = it->templates; i < it->tcount; i++, tt++) { for (i = 0, tt = it->templates; i < it->tcount; i++, tt++) {
pchptr = asn1_get_field_ptr(pval, tt); pchptr = asn1_get_field_ptr(pval, tt);
/* // We mark field as OPTIONAL so its absence can be recognised.
* We mark field as OPTIONAL so its absence can be recognised.
*/
ret = asn1_template_ex_d2i(pchptr, &p, len, tt, 1, depth); ret = asn1_template_ex_d2i(pchptr, &p, len, tt, 1, depth);
/* If field not present, try the next one */ // If field not present, try the next one
if (ret == -1) { if (ret == -1) {
continue; continue;
} }
/* If positive return, read OK, break loop */ // If positive return, read OK, break loop
if (ret > 0) { if (ret > 0) {
break; break;
} }
/* Otherwise must be an ASN1 parsing error */ // Otherwise must be an ASN1 parsing error
errtt = tt; errtt = tt;
OPENSSL_PUT_ERROR(ASN1, ASN1_R_NESTED_ASN1_ERROR); OPENSSL_PUT_ERROR(ASN1, ASN1_R_NESTED_ASN1_ERROR);
goto err; goto err;
} }
/* Did we fall off the end without reading anything? */ // Did we fall off the end without reading anything?
if (i == it->tcount) { if (i == it->tcount) {
/* If OPTIONAL, this is OK */ // If OPTIONAL, this is OK
if (opt) { if (opt) {
/* Free and zero it */ // Free and zero it
ASN1_item_ex_free(pval, it); ASN1_item_ex_free(pval, it);
return -1; return -1;
} }
@ -328,12 +312,12 @@ static int asn1_item_ex_d2i(ASN1_VALUE **pval, const unsigned char **in,
case ASN1_ITYPE_SEQUENCE: { case ASN1_ITYPE_SEQUENCE: {
p = *in; p = *in;
/* If no IMPLICIT tagging set to SEQUENCE, UNIVERSAL */ // If no IMPLICIT tagging set to SEQUENCE, UNIVERSAL
if (tag == -1) { if (tag == -1) {
tag = V_ASN1_SEQUENCE; tag = V_ASN1_SEQUENCE;
aclass = V_ASN1_UNIVERSAL; aclass = V_ASN1_UNIVERSAL;
} }
/* Get SEQUENCE length and update len, p */ // Get SEQUENCE length and update len, p
ret = asn1_check_tlen(&len, NULL, NULL, &cst, &p, len, tag, aclass, opt); ret = asn1_check_tlen(&len, NULL, NULL, &cst, &p, len, tag, aclass, opt);
if (!ret) { if (!ret) {
OPENSSL_PUT_ERROR(ASN1, ASN1_R_NESTED_ASN1_ERROR); OPENSSL_PUT_ERROR(ASN1, ASN1_R_NESTED_ASN1_ERROR);
@ -357,7 +341,7 @@ static int asn1_item_ex_d2i(ASN1_VALUE **pval, const unsigned char **in,
goto auxerr; goto auxerr;
} }
/* Free up and zero any ADB found */ // Free up and zero any ADB found
for (i = 0, tt = it->templates; i < it->tcount; i++, tt++) { for (i = 0, tt = it->templates; i < it->tcount; i++, tt++) {
if (tt->flags & ASN1_TFLG_ADB_MASK) { if (tt->flags & ASN1_TFLG_ADB_MASK) {
const ASN1_TEMPLATE *seqtt; const ASN1_TEMPLATE *seqtt;
@ -371,7 +355,7 @@ static int asn1_item_ex_d2i(ASN1_VALUE **pval, const unsigned char **in,
} }
} }
/* Get each field entry */ // Get each field entry
for (i = 0, tt = it->templates; i < it->tcount; i++, tt++) { for (i = 0, tt = it->templates; i < it->tcount; i++, tt++) {
const ASN1_TEMPLATE *seqtt; const ASN1_TEMPLATE *seqtt;
ASN1_VALUE **pseqval; ASN1_VALUE **pseqval;
@ -380,52 +364,44 @@ static int asn1_item_ex_d2i(ASN1_VALUE **pval, const unsigned char **in,
goto err; goto err;
} }
pseqval = asn1_get_field_ptr(pval, seqtt); pseqval = asn1_get_field_ptr(pval, seqtt);
/* Have we ran out of data? */ // Have we ran out of data?
if (!len) { if (!len) {
break; break;
} }
q = p; q = p;
/* // This determines the OPTIONAL flag value. The field cannot be
* This determines the OPTIONAL flag value. The field cannot be // omitted if it is the last of a SEQUENCE and there is still
* omitted if it is the last of a SEQUENCE and there is still // data to be read. This isn't strictly necessary but it
* data to be read. This isn't strictly necessary but it // increases efficiency in some cases.
* increases efficiency in some cases.
*/
if (i == (it->tcount - 1)) { if (i == (it->tcount - 1)) {
isopt = 0; isopt = 0;
} else { } else {
isopt = (char)(seqtt->flags & ASN1_TFLG_OPTIONAL); isopt = (char)(seqtt->flags & ASN1_TFLG_OPTIONAL);
} }
/* // attempt to read in field, allowing each to be OPTIONAL
* attempt to read in field, allowing each to be OPTIONAL
*/
ret = asn1_template_ex_d2i(pseqval, &p, len, seqtt, isopt, depth); ret = asn1_template_ex_d2i(pseqval, &p, len, seqtt, isopt, depth);
if (!ret) { if (!ret) {
errtt = seqtt; errtt = seqtt;
goto err; goto err;
} else if (ret == -1) { } else if (ret == -1) {
/* // OPTIONAL component absent. Free and zero the field.
* OPTIONAL component absent. Free and zero the field.
*/
ASN1_template_free(pseqval, seqtt); ASN1_template_free(pseqval, seqtt);
continue; continue;
} }
/* Update length */ // Update length
len -= p - q; len -= p - q;
} }
/* Check all data read */ // Check all data read
if (len) { if (len) {
OPENSSL_PUT_ERROR(ASN1, ASN1_R_SEQUENCE_LENGTH_MISMATCH); OPENSSL_PUT_ERROR(ASN1, ASN1_R_SEQUENCE_LENGTH_MISMATCH);
goto err; goto err;
} }
/* // If we get here we've got no more data in the SEQUENCE, however we
* 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
* may not have read all fields so check all remaining are OPTIONAL // and clear any that are.
* and clear any that are.
*/
for (; i < it->tcount; tt++, i++) { for (; i < it->tcount; tt++, i++) {
const ASN1_TEMPLATE *seqtt; const ASN1_TEMPLATE *seqtt;
seqtt = asn1_do_adb(pval, tt, 1); seqtt = asn1_do_adb(pval, tt, 1);
@ -442,7 +418,7 @@ static int asn1_item_ex_d2i(ASN1_VALUE **pval, const unsigned char **in,
goto err; goto err;
} }
} }
/* Save encoding */ // Save encoding
if (!asn1_enc_save(pval, *in, p - *in, it)) { if (!asn1_enc_save(pval, *in, p - *in, it)) {
goto auxerr; goto auxerr;
} }
@ -476,10 +452,8 @@ int ASN1_item_ex_d2i(ASN1_VALUE **pval, const unsigned char **in, long len,
return asn1_item_ex_d2i(pval, in, len, it, tag, aclass, opt, 0); return asn1_item_ex_d2i(pval, in, len, it, tag, aclass, opt, 0);
} }
/* // Templates are handled with two separate functions. One handles any
* Templates are handled with two separate functions. One handles any // EXPLICIT tag and the other handles the rest.
* EXPLICIT tag and the other handles the rest.
*/
static int asn1_template_ex_d2i(ASN1_VALUE **val, const unsigned char **in, static int asn1_template_ex_d2i(ASN1_VALUE **val, const unsigned char **in,
long inlen, const ASN1_TEMPLATE *tt, char opt, long inlen, const ASN1_TEMPLATE *tt, char opt,
@ -496,13 +470,11 @@ static int asn1_template_ex_d2i(ASN1_VALUE **val, const unsigned char **in,
p = *in; p = *in;
/* Check if EXPLICIT tag expected */ // Check if EXPLICIT tag expected
if (flags & ASN1_TFLG_EXPTAG) { if (flags & ASN1_TFLG_EXPTAG) {
char cst; char cst;
/* // Need to work out amount of data available to the inner content and
* 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.
* 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, ret = asn1_check_tlen(&len, NULL, NULL, &cst, &p, inlen, tt->tag, aclass,
opt); opt);
q = p; q = p;
@ -516,15 +488,15 @@ static int asn1_template_ex_d2i(ASN1_VALUE **val, const unsigned char **in,
OPENSSL_PUT_ERROR(ASN1, ASN1_R_EXPLICIT_TAG_NOT_CONSTRUCTED); OPENSSL_PUT_ERROR(ASN1, ASN1_R_EXPLICIT_TAG_NOT_CONSTRUCTED);
return 0; return 0;
} }
/* We've found the field so it can't be OPTIONAL now */ // We've found the field so it can't be OPTIONAL now
ret = asn1_template_noexp_d2i(val, &p, len, tt, 0, depth); ret = asn1_template_noexp_d2i(val, &p, len, tt, 0, depth);
if (!ret) { if (!ret) {
OPENSSL_PUT_ERROR(ASN1, ASN1_R_NESTED_ASN1_ERROR); OPENSSL_PUT_ERROR(ASN1, ASN1_R_NESTED_ASN1_ERROR);
return 0; return 0;
} }
/* We read the field in OK so update length */ // We read the field in OK so update length
len -= p - q; len -= p - q;
/* Check for trailing data. */ // Check for trailing data.
if (len) { if (len) {
OPENSSL_PUT_ERROR(ASN1, ASN1_R_EXPLICIT_LENGTH_MISMATCH); OPENSSL_PUT_ERROR(ASN1, ASN1_R_EXPLICIT_LENGTH_MISMATCH);
goto err; goto err;
@ -556,9 +528,9 @@ static int asn1_template_noexp_d2i(ASN1_VALUE **val, const unsigned char **in,
p = *in; p = *in;
if (flags & ASN1_TFLG_SK_MASK) { if (flags & ASN1_TFLG_SK_MASK) {
/* SET OF, SEQUENCE OF */ // SET OF, SEQUENCE OF
int sktag, skaclass; int sktag, skaclass;
/* First work out expected inner tag value */ // First work out expected inner tag value
if (flags & ASN1_TFLG_IMPTAG) { if (flags & ASN1_TFLG_IMPTAG) {
sktag = tt->tag; sktag = tt->tag;
skaclass = aclass; skaclass = aclass;
@ -570,7 +542,7 @@ static int asn1_template_noexp_d2i(ASN1_VALUE **val, const unsigned char **in,
sktag = V_ASN1_SEQUENCE; sktag = V_ASN1_SEQUENCE;
} }
} }
/* Get the tag */ // Get the tag
ret = ret =
asn1_check_tlen(&len, NULL, NULL, NULL, &p, len, sktag, skaclass, opt); asn1_check_tlen(&len, NULL, NULL, NULL, &p, len, sktag, skaclass, opt);
if (!ret) { if (!ret) {
@ -582,9 +554,7 @@ static int asn1_template_noexp_d2i(ASN1_VALUE **val, const unsigned char **in,
if (!*val) { if (!*val) {
*val = (ASN1_VALUE *)sk_ASN1_VALUE_new_null(); *val = (ASN1_VALUE *)sk_ASN1_VALUE_new_null();
} else { } else {
/* // We've got a valid STACK: free up any items present
* We've got a valid STACK: free up any items present
*/
STACK_OF(ASN1_VALUE) *sktmp = (STACK_OF(ASN1_VALUE) *)*val; STACK_OF(ASN1_VALUE) *sktmp = (STACK_OF(ASN1_VALUE) *)*val;
ASN1_VALUE *vtmp; ASN1_VALUE *vtmp;
while (sk_ASN1_VALUE_num(sktmp) > 0) { while (sk_ASN1_VALUE_num(sktmp) > 0) {
@ -598,7 +568,7 @@ static int asn1_template_noexp_d2i(ASN1_VALUE **val, const unsigned char **in,
goto err; goto err;
} }
/* Read as many items as we can */ // Read as many items as we can
while (len > 0) { while (len > 0) {
ASN1_VALUE *skfield; ASN1_VALUE *skfield;
const unsigned char *q = p; const unsigned char *q = p;
@ -616,7 +586,7 @@ static int asn1_template_noexp_d2i(ASN1_VALUE **val, const unsigned char **in,
} }
} }
} else if (flags & ASN1_TFLG_IMPTAG) { } else if (flags & ASN1_TFLG_IMPTAG) {
/* IMPLICIT tagging */ // IMPLICIT tagging
ret = asn1_item_ex_d2i(val, &p, len, ASN1_ITEM_ptr(tt->item), tt->tag, ret = asn1_item_ex_d2i(val, &p, len, ASN1_ITEM_ptr(tt->item), tt->tag,
aclass, opt, depth); aclass, opt, depth);
if (!ret) { if (!ret) {
@ -626,7 +596,7 @@ static int asn1_template_noexp_d2i(ASN1_VALUE **val, const unsigned char **in,
return -1; return -1;
} }
} else { } else {
/* Nothing special */ // Nothing special
ret = asn1_item_ex_d2i(val, &p, len, ASN1_ITEM_ptr(tt->item), -1, ret = asn1_item_ex_d2i(val, &p, len, ASN1_ITEM_ptr(tt->item), -1,
tt->flags & ASN1_TFLG_COMBINE, opt, depth); tt->flags & ASN1_TFLG_COMBINE, opt, depth);
if (!ret) { if (!ret) {
@ -656,7 +626,7 @@ static int asn1_d2i_ex_primitive(ASN1_VALUE **pval, const unsigned char **in,
long len; long len;
if (!pval) { if (!pval) {
OPENSSL_PUT_ERROR(ASN1, ASN1_R_ILLEGAL_NULL); OPENSSL_PUT_ERROR(ASN1, ASN1_R_ILLEGAL_NULL);
return 0; /* Should never happen */ return 0; // Should never happen
} }
if (it->itype == ASN1_ITYPE_MSTRING) { if (it->itype == ASN1_ITYPE_MSTRING) {
@ -667,7 +637,7 @@ static int asn1_d2i_ex_primitive(ASN1_VALUE **pval, const unsigned char **in,
} }
if (utype == V_ASN1_ANY) { if (utype == V_ASN1_ANY) {
/* If type is ANY need to figure out type from tag */ // If type is ANY need to figure out type from tag
unsigned char oclass; unsigned char oclass;
if (tag >= 0) { if (tag >= 0) {
OPENSSL_PUT_ERROR(ASN1, ASN1_R_ILLEGAL_TAGGED_ANY); OPENSSL_PUT_ERROR(ASN1, ASN1_R_ILLEGAL_TAGGED_ANY);
@ -692,7 +662,7 @@ static int asn1_d2i_ex_primitive(ASN1_VALUE **pval, const unsigned char **in,
aclass = V_ASN1_UNIVERSAL; aclass = V_ASN1_UNIVERSAL;
} }
p = *in; p = *in;
/* Check header */ // Check header
ret = asn1_check_tlen(&plen, NULL, NULL, &cst, &p, inlen, tag, aclass, opt); ret = asn1_check_tlen(&plen, NULL, NULL, &cst, &p, inlen, tag, aclass, opt);
if (!ret) { if (!ret) {
OPENSSL_PUT_ERROR(ASN1, ASN1_R_NESTED_ASN1_ERROR); OPENSSL_PUT_ERROR(ASN1, ASN1_R_NESTED_ASN1_ERROR);
@ -701,10 +671,10 @@ static int asn1_d2i_ex_primitive(ASN1_VALUE **pval, const unsigned char **in,
return -1; return -1;
} }
ret = 0; ret = 0;
/* SEQUENCE, SET and "OTHER" are left in encoded form */ // SEQUENCE, SET and "OTHER" are left in encoded form
if ((utype == V_ASN1_SEQUENCE) || (utype == V_ASN1_SET) || if ((utype == V_ASN1_SEQUENCE) || (utype == V_ASN1_SET) ||
(utype == V_ASN1_OTHER)) { (utype == V_ASN1_OTHER)) {
/* SEQUENCE and SET must be constructed */ // SEQUENCE and SET must be constructed
if (utype != V_ASN1_OTHER && !cst) { if (utype != V_ASN1_OTHER && !cst) {
OPENSSL_PUT_ERROR(ASN1, ASN1_R_TYPE_NOT_CONSTRUCTED); OPENSSL_PUT_ERROR(ASN1, ASN1_R_TYPE_NOT_CONSTRUCTED);
return 0; return 0;
@ -714,9 +684,9 @@ static int asn1_d2i_ex_primitive(ASN1_VALUE **pval, const unsigned char **in,
len = p - cont + plen; len = p - cont + plen;
p += plen; p += plen;
} else if (cst) { } else if (cst) {
/* This parser historically supported BER constructed strings. We no // This parser historically supported BER constructed strings. We no
* longer do and will gradually tighten this parser into a DER // longer do and will gradually tighten this parser into a DER
* parser. BER types should use |CBS_asn1_ber_to_der|. */ // parser. BER types should use |CBS_asn1_ber_to_der|.
OPENSSL_PUT_ERROR(ASN1, ASN1_R_TYPE_NOT_PRIMITIVE); OPENSSL_PUT_ERROR(ASN1, ASN1_R_TYPE_NOT_PRIMITIVE);
return 0; return 0;
} else { } else {
@ -725,7 +695,7 @@ static int asn1_d2i_ex_primitive(ASN1_VALUE **pval, const unsigned char **in,
p += plen; p += plen;
} }
/* We now have content length and type: translate into a structure */ // We now have content length and type: translate into a structure
if (!asn1_ex_c2i(pval, cont, len, utype, it)) { if (!asn1_ex_c2i(pval, cont, len, utype, it)) {
goto err; goto err;
} }
@ -736,7 +706,7 @@ err:
return ret; return ret;
} }
/* Translate ASN1 content octets into a structure */ // Translate ASN1 content octets into a structure
static int asn1_ex_c2i(ASN1_VALUE **pval, const unsigned char *cont, int len, static int asn1_ex_c2i(ASN1_VALUE **pval, const unsigned char *cont, int len,
int utype, const ASN1_ITEM *it) { int utype, const ASN1_ITEM *it) {
@ -746,11 +716,11 @@ static int asn1_ex_c2i(ASN1_VALUE **pval, const unsigned char *cont, int len,
int ret = 0; int ret = 0;
ASN1_INTEGER **tint; ASN1_INTEGER **tint;
/* Historically, |it->funcs| for primitive types contained an // Historically, |it->funcs| for primitive types contained an
* |ASN1_PRIMITIVE_FUNCS| table of callbacks. */ // |ASN1_PRIMITIVE_FUNCS| table of callbacks.
assert(it->funcs == NULL); assert(it->funcs == NULL);
/* If ANY type clear type and set pointer to internal value */ // If ANY type clear type and set pointer to internal value
if (it->utype == V_ASN1_ANY) { if (it->utype == V_ASN1_ANY) {
if (!*pval) { if (!*pval) {
typ = ASN1_TYPE_new(); typ = ASN1_TYPE_new();
@ -806,7 +776,7 @@ static int asn1_ex_c2i(ASN1_VALUE **pval, const unsigned char *cont, int len,
if (!c2i_ASN1_INTEGER(tint, &cont, len)) { if (!c2i_ASN1_INTEGER(tint, &cont, len)) {
goto err; goto err;
} }
/* Fixup type to match the expected form */ // Fixup type to match the expected form
(*tint)->type = utype | ((*tint)->type & V_ASN1_NEG); (*tint)->type = utype | ((*tint)->type & V_ASN1_NEG);
break; break;
@ -853,7 +823,7 @@ static int asn1_ex_c2i(ASN1_VALUE **pval, const unsigned char *cont, int len,
goto err; goto err;
} }
} }
/* All based on ASN1_STRING and handled the same */ // All based on ASN1_STRING and handled the same
if (!*pval) { if (!*pval) {
stmp = ASN1_STRING_type_new(utype); stmp = ASN1_STRING_type_new(utype);
if (!stmp) { if (!stmp) {
@ -873,7 +843,7 @@ static int asn1_ex_c2i(ASN1_VALUE **pval, const unsigned char *cont, int len,
} }
break; break;
} }
/* If ASN1_ANY and NULL type fix up value */ // If ASN1_ANY and NULL type fix up value
if (typ && (utype == V_ASN1_NULL)) { if (typ && (utype == V_ASN1_NULL)) {
typ->value.ptr = NULL; typ->value.ptr = NULL;
} }
@ -889,10 +859,8 @@ err:
return ret; return ret;
} }
/* // Check an ASN1 tag and length: a bit like ASN1_get_object but it
* Check an ASN1 tag and length: a bit like ASN1_get_object but it // checks the expected tag.
* checks the expected tag.
*/
static int asn1_check_tlen(long *olen, int *otag, unsigned char *oclass, static int asn1_check_tlen(long *olen, int *otag, unsigned char *oclass,
char *cst, const unsigned char **in, long len, char *cst, const unsigned char **in, long len,
@ -910,9 +878,7 @@ static int asn1_check_tlen(long *olen, int *otag, unsigned char *oclass,
} }
if (exptag >= 0) { if (exptag >= 0) {
if ((exptag != ptag) || (expclass != pclass)) { if ((exptag != ptag) || (expclass != pclass)) {
/* // If type is OPTIONAL, not an error: indicate missing type.
* If type is OPTIONAL, not an error: indicate missing type.
*/
if (opt) { if (opt) {
return -1; return -1;
} }

@ -80,9 +80,7 @@ static int asn1_set_seq_out(STACK_OF(ASN1_VALUE) *sk, unsigned char **out,
static int asn1_template_ex_i2d(ASN1_VALUE **pval, unsigned char **out, static int asn1_template_ex_i2d(ASN1_VALUE **pval, unsigned char **out,
const ASN1_TEMPLATE *tt, int tag, int aclass); const ASN1_TEMPLATE *tt, int tag, int aclass);
/* // Top level i2d equivalents
* Top level i2d equivalents
*/
int ASN1_item_i2d(ASN1_VALUE *val, unsigned char **out, const ASN1_ITEM *it) { int ASN1_item_i2d(ASN1_VALUE *val, unsigned char **out, const ASN1_ITEM *it) {
if (out && !*out) { if (out && !*out) {
@ -109,10 +107,8 @@ int ASN1_item_i2d(ASN1_VALUE *val, unsigned char **out, const ASN1_ITEM *it) {
return ASN1_item_ex_i2d(&val, out, it, /*tag=*/-1, /*aclass=*/0); return ASN1_item_ex_i2d(&val, out, it, /*tag=*/-1, /*aclass=*/0);
} }
/* // Encode an item, taking care of IMPLICIT tagging (if any). This function
* Encode an item, taking care of IMPLICIT tagging (if any). This function // performs the normal item handling: it can be used in external types.
* performs the normal item handling: it can be used in external types.
*/
int ASN1_item_ex_i2d(ASN1_VALUE **pval, unsigned char **out, int ASN1_item_ex_i2d(ASN1_VALUE **pval, unsigned char **out,
const ASN1_ITEM *it, int tag, int aclass) { const ASN1_ITEM *it, int tag, int aclass) {
@ -121,22 +117,22 @@ int ASN1_item_ex_i2d(ASN1_VALUE **pval, unsigned char **out,
return ret; return ret;
} }
/* asn1_item_ex_i2d_opt behaves like |ASN1_item_ex_i2d| but, if |optional| is // 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. */ // 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, int asn1_item_ex_i2d_opt(ASN1_VALUE **pval, unsigned char **out,
const ASN1_ITEM *it, int tag, int aclass, const ASN1_ITEM *it, int tag, int aclass,
int optional) { int optional) {
const ASN1_TEMPLATE *tt = NULL; const ASN1_TEMPLATE *tt = NULL;
int i, seqcontlen, seqlen; int i, seqcontlen, seqlen;
/* Historically, |aclass| was repurposed to pass additional flags into the // Historically, |aclass| was repurposed to pass additional flags into the
* encoding process. */ // encoding process.
assert((aclass & ASN1_TFLG_TAG_CLASS) == aclass); assert((aclass & ASN1_TFLG_TAG_CLASS) == aclass);
/* If not overridding the tag, |aclass| is ignored and should be zero. */ // If not overridding the tag, |aclass| is ignored and should be zero.
assert(tag != -1 || aclass == 0); assert(tag != -1 || aclass == 0);
/* All fields are pointers, except for boolean |ASN1_ITYPE_PRIMITIVE|s. // All fields are pointers, except for boolean |ASN1_ITYPE_PRIMITIVE|s.
* Optional primitives are handled later. */ // Optional primitives are handled later.
if ((it->itype != ASN1_ITYPE_PRIMITIVE) && !*pval) { if ((it->itype != ASN1_ITYPE_PRIMITIVE) && !*pval) {
if (optional) { if (optional) {
return 0; return 0;
@ -157,10 +153,8 @@ int asn1_item_ex_i2d_opt(ASN1_VALUE **pval, unsigned char **out,
return asn1_i2d_ex_primitive(pval, out, it, tag, aclass, optional); return asn1_i2d_ex_primitive(pval, out, it, tag, aclass, optional);
case ASN1_ITYPE_MSTRING: case ASN1_ITYPE_MSTRING:
/* // It never makes sense for multi-strings to have implicit tagging, so
* 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, then this looks like an error in the template.
*/
if (tag != -1) { if (tag != -1) {
OPENSSL_PUT_ERROR(ASN1, ASN1_R_BAD_TEMPLATE); OPENSSL_PUT_ERROR(ASN1, ASN1_R_BAD_TEMPLATE);
return -1; return -1;
@ -168,10 +162,8 @@ int asn1_item_ex_i2d_opt(ASN1_VALUE **pval, unsigned char **out,
return asn1_i2d_ex_primitive(pval, out, it, -1, 0, optional); return asn1_i2d_ex_primitive(pval, out, it, -1, 0, optional);
case ASN1_ITYPE_CHOICE: { case ASN1_ITYPE_CHOICE: {
/* // It never makes sense for CHOICE types to have implicit tagging, so if
* It never makes sense for CHOICE types to have implicit tagging, so if // tag != -1, then this looks like an error in the template.
* tag != -1, then this looks like an error in the template.
*/
if (tag != -1) { if (tag != -1) {
OPENSSL_PUT_ERROR(ASN1, ASN1_R_BAD_TEMPLATE); OPENSSL_PUT_ERROR(ASN1, ASN1_R_BAD_TEMPLATE);
return -1; return -1;
@ -191,13 +183,13 @@ int asn1_item_ex_i2d_opt(ASN1_VALUE **pval, unsigned char **out,
} }
case ASN1_ITYPE_EXTERN: { case ASN1_ITYPE_EXTERN: {
/* If new style i2d it does all the work */ // If new style i2d it does all the work
const ASN1_EXTERN_FUNCS *ef = it->funcs; const ASN1_EXTERN_FUNCS *ef = it->funcs;
int ret = ef->asn1_ex_i2d(pval, out, it, tag, aclass); int ret = ef->asn1_ex_i2d(pval, out, it, tag, aclass);
if (ret == 0) { if (ret == 0) {
/* |asn1_ex_i2d| should never return zero. We have already checked // |asn1_ex_i2d| should never return zero. We have already checked
* for optional values generically, and |ASN1_ITYPE_EXTERN| fields // for optional values generically, and |ASN1_ITYPE_EXTERN| fields
* must be pointers. */ // must be pointers.
OPENSSL_PUT_ERROR(ASN1, ERR_R_INTERNAL_ERROR); OPENSSL_PUT_ERROR(ASN1, ERR_R_INTERNAL_ERROR);
return -1; return -1;
} }
@ -206,22 +198,22 @@ int asn1_item_ex_i2d_opt(ASN1_VALUE **pval, unsigned char **out,
case ASN1_ITYPE_SEQUENCE: { case ASN1_ITYPE_SEQUENCE: {
i = asn1_enc_restore(&seqcontlen, out, pval, it); i = asn1_enc_restore(&seqcontlen, out, pval, it);
/* An error occurred */ // An error occurred
if (i < 0) { if (i < 0) {
return -1; return -1;
} }
/* We have a valid cached encoding... */ // We have a valid cached encoding...
if (i > 0) { if (i > 0) {
return seqcontlen; return seqcontlen;
} }
/* Otherwise carry on */ // Otherwise carry on
seqcontlen = 0; seqcontlen = 0;
/* If no IMPLICIT tagging set to SEQUENCE, UNIVERSAL */ // If no IMPLICIT tagging set to SEQUENCE, UNIVERSAL
if (tag == -1) { if (tag == -1) {
tag = V_ASN1_SEQUENCE; tag = V_ASN1_SEQUENCE;
aclass = V_ASN1_UNIVERSAL; aclass = V_ASN1_UNIVERSAL;
} }
/* First work out sequence content length */ // First work out sequence content length
for (i = 0, tt = it->templates; i < it->tcount; tt++, i++) { for (i = 0, tt = it->templates; i < it->tcount; tt++, i++) {
const ASN1_TEMPLATE *seqtt; const ASN1_TEMPLATE *seqtt;
ASN1_VALUE **pseqval; ASN1_VALUE **pseqval;
@ -242,7 +234,7 @@ int asn1_item_ex_i2d_opt(ASN1_VALUE **pval, unsigned char **out,
if (!out || seqlen == -1) { if (!out || seqlen == -1) {
return seqlen; return seqlen;
} }
/* Output SEQUENCE header */ // Output SEQUENCE header
ASN1_put_object(out, /*constructed=*/1, seqcontlen, tag, aclass); ASN1_put_object(out, /*constructed=*/1, seqcontlen, tag, aclass);
for (i = 0, tt = it->templates; i < it->tcount; tt++, i++) { for (i = 0, tt = it->templates; i < it->tcount; tt++, i++) {
const ASN1_TEMPLATE *seqtt; const ASN1_TEMPLATE *seqtt;
@ -265,38 +257,36 @@ int asn1_item_ex_i2d_opt(ASN1_VALUE **pval, unsigned char **out,
} }
} }
/* asn1_template_ex_i2d behaves like |asn1_item_ex_i2d_opt| but uses an // asn1_template_ex_i2d behaves like |asn1_item_ex_i2d_opt| but uses an
* |ASN1_TEMPLATE| instead of an |ASN1_ITEM|. An |ASN1_TEMPLATE| wraps an // |ASN1_TEMPLATE| instead of an |ASN1_ITEM|. An |ASN1_TEMPLATE| wraps an
* |ASN1_ITEM| with modifiers such as tagging, SEQUENCE or SET, etc. Instead of // |ASN1_ITEM| with modifiers such as tagging, SEQUENCE or SET, etc. Instead of
* taking an |optional| parameter, it uses the |ASN1_TFLG_OPTIONAL| flag. */ // taking an |optional| parameter, it uses the |ASN1_TFLG_OPTIONAL| flag.
static int asn1_template_ex_i2d(ASN1_VALUE **pval, unsigned char **out, static int asn1_template_ex_i2d(ASN1_VALUE **pval, unsigned char **out,
const ASN1_TEMPLATE *tt, int tag, int iclass) { const ASN1_TEMPLATE *tt, int tag, int iclass) {
int i, ret, flags, ttag, tclass; int i, ret, flags, ttag, tclass;
size_t j; size_t j;
flags = tt->flags; flags = tt->flags;
/* Historically, |iclass| was repurposed to pass additional flags into the // Historically, |iclass| was repurposed to pass additional flags into the
* encoding process. */ // encoding process.
assert((iclass & ASN1_TFLG_TAG_CLASS) == iclass); assert((iclass & ASN1_TFLG_TAG_CLASS) == iclass);
/* If not overridding the tag, |iclass| is ignored and should be zero. */ // If not overridding the tag, |iclass| is ignored and should be zero.
assert(tag != -1 || iclass == 0); assert(tag != -1 || iclass == 0);
/* // Work out tag and class to use: tagging may come either from the
* Work out tag and class to use: tagging may come either from the // template or the arguments, not both because this would create
* template or the arguments, not both because this would create // ambiguity.
* ambiguity.
*/
if (flags & ASN1_TFLG_TAG_MASK) { if (flags & ASN1_TFLG_TAG_MASK) {
/* Error if argument and template tagging */ // Error if argument and template tagging
if (tag != -1) { if (tag != -1) {
OPENSSL_PUT_ERROR(ASN1, ASN1_R_BAD_TEMPLATE); OPENSSL_PUT_ERROR(ASN1, ASN1_R_BAD_TEMPLATE);
return -1; return -1;
} }
/* Get tagging from template */ // Get tagging from template
ttag = tt->tag; ttag = tt->tag;
tclass = flags & ASN1_TFLG_TAG_CLASS; tclass = flags & ASN1_TFLG_TAG_CLASS;
} else if (tag != -1) { } else if (tag != -1) {
/* No template tagging, get from arguments */ // No template tagging, get from arguments
ttag = tag; ttag = tag;
tclass = iclass & ASN1_TFLG_TAG_CLASS; tclass = iclass & ASN1_TFLG_TAG_CLASS;
} else { } else {
@ -306,13 +296,11 @@ static int asn1_template_ex_i2d(ASN1_VALUE **pval, unsigned char **out,
const int optional = (flags & ASN1_TFLG_OPTIONAL) != 0; const int optional = (flags & ASN1_TFLG_OPTIONAL) != 0;
/* // At this point 'ttag' contains the outer tag to use, and 'tclass' is the
* At this point 'ttag' contains the outer tag to use, and 'tclass' is the // class.
* class.
*/
if (flags & ASN1_TFLG_SK_MASK) { if (flags & ASN1_TFLG_SK_MASK) {
/* SET OF, SEQUENCE OF */ // SET OF, SEQUENCE OF
STACK_OF(ASN1_VALUE) *sk = (STACK_OF(ASN1_VALUE) *)*pval; STACK_OF(ASN1_VALUE) *sk = (STACK_OF(ASN1_VALUE) *)*pval;
int isset, sktag, skaclass; int isset, sktag, skaclass;
int skcontlen, sklen; int skcontlen, sklen;
@ -328,17 +316,15 @@ static int asn1_template_ex_i2d(ASN1_VALUE **pval, unsigned char **out,
if (flags & ASN1_TFLG_SET_OF) { if (flags & ASN1_TFLG_SET_OF) {
isset = 1; isset = 1;
/* Historically, types with both bits set were mutated when // Historically, types with both bits set were mutated when
* serialized to apply the sort. We no longer support this. */ // serialized to apply the sort. We no longer support this.
assert((flags & ASN1_TFLG_SEQUENCE_OF) == 0); assert((flags & ASN1_TFLG_SEQUENCE_OF) == 0);
} else { } else {
isset = 0; isset = 0;
} }
/* // Work out inner tag value: if EXPLICIT or no tagging use underlying
* Work out inner tag value: if EXPLICIT or no tagging use underlying // type.
* type.
*/
if ((ttag != -1) && !(flags & ASN1_TFLG_EXPTAG)) { if ((ttag != -1) && !(flags & ASN1_TFLG_EXPTAG)) {
sktag = ttag; sktag = ttag;
skaclass = tclass; skaclass = tclass;
@ -351,7 +337,7 @@ static int asn1_template_ex_i2d(ASN1_VALUE **pval, unsigned char **out,
} }
} }
/* Determine total length of items */ // Determine total length of items
skcontlen = 0; skcontlen = 0;
for (j = 0; j < sk_ASN1_VALUE_num(sk); j++) { for (j = 0; j < sk_ASN1_VALUE_num(sk); j++) {
int tmplen; int tmplen;
@ -366,7 +352,7 @@ static int asn1_template_ex_i2d(ASN1_VALUE **pval, unsigned char **out,
if (sklen == -1) { if (sklen == -1) {
return -1; return -1;
} }
/* If EXPLICIT need length of surrounding tag */ // If EXPLICIT need length of surrounding tag
if (flags & ASN1_TFLG_EXPTAG) { if (flags & ASN1_TFLG_EXPTAG) {
ret = ASN1_object_size(/*constructed=*/1, sklen, ttag); ret = ASN1_object_size(/*constructed=*/1, sklen, ttag);
} else { } else {
@ -377,14 +363,14 @@ static int asn1_template_ex_i2d(ASN1_VALUE **pval, unsigned char **out,
return ret; return ret;
} }
/* Now encode this lot... */ // Now encode this lot...
/* EXPLICIT tag */ // EXPLICIT tag
if (flags & ASN1_TFLG_EXPTAG) { if (flags & ASN1_TFLG_EXPTAG) {
ASN1_put_object(out, /*constructed=*/1, sklen, ttag, tclass); ASN1_put_object(out, /*constructed=*/1, sklen, ttag, tclass);
} }
/* SET or SEQUENCE and IMPLICIT tag */ // SET or SEQUENCE and IMPLICIT tag
ASN1_put_object(out, /*constructed=*/1, skcontlen, sktag, skaclass); ASN1_put_object(out, /*constructed=*/1, skcontlen, sktag, skaclass);
/* And the stuff itself */ // And the stuff itself
if (!asn1_set_seq_out(sk, out, skcontlen, ASN1_ITEM_ptr(tt->item), isset)) { if (!asn1_set_seq_out(sk, out, skcontlen, ASN1_ITEM_ptr(tt->item), isset)) {
return -1; return -1;
} }
@ -392,17 +378,17 @@ static int asn1_template_ex_i2d(ASN1_VALUE **pval, unsigned char **out,
} }
if (flags & ASN1_TFLG_EXPTAG) { if (flags & ASN1_TFLG_EXPTAG) {
/* EXPLICIT tagging */ // EXPLICIT tagging
/* Find length of tagged item */ // Find length of tagged item
i = asn1_item_ex_i2d_opt(pval, NULL, ASN1_ITEM_ptr(tt->item), -1, 0, i = asn1_item_ex_i2d_opt(pval, NULL, ASN1_ITEM_ptr(tt->item), -1, 0,
optional); optional);
if (i <= 0) { if (i <= 0) {
return i; return i;
} }
/* Find length of EXPLICIT tag */ // Find length of EXPLICIT tag
ret = ASN1_object_size(/*constructed=*/1, i, ttag); ret = ASN1_object_size(/*constructed=*/1, i, ttag);
if (out && ret != -1) { if (out && ret != -1) {
/* Output tag and item */ // Output tag and item
ASN1_put_object(out, /*constructed=*/1, i, ttag, tclass); ASN1_put_object(out, /*constructed=*/1, i, ttag, tclass);
if (ASN1_item_ex_i2d(pval, out, ASN1_ITEM_ptr(tt->item), -1, 0) < 0) { if (ASN1_item_ex_i2d(pval, out, ASN1_ITEM_ptr(tt->item), -1, 0) < 0) {
return -1; return -1;
@ -411,12 +397,12 @@ static int asn1_template_ex_i2d(ASN1_VALUE **pval, unsigned char **out,
return ret; return ret;
} }
/* Either normal or IMPLICIT tagging */ // Either normal or IMPLICIT tagging
return asn1_item_ex_i2d_opt(pval, out, ASN1_ITEM_ptr(tt->item), ttag, tclass, return asn1_item_ex_i2d_opt(pval, out, ASN1_ITEM_ptr(tt->item), ttag, tclass,
optional); optional);
} }
/* Temporary structure used to hold DER encoding of items for SET OF */ // Temporary structure used to hold DER encoding of items for SET OF
typedef struct { typedef struct {
unsigned char *data; unsigned char *data;
@ -434,14 +420,14 @@ static int der_cmp(const void *a, const void *b) {
return d1->length - d2->length; return d1->length - d2->length;
} }
/* asn1_set_seq_out writes |sk| to |out| under the i2d output convention, // asn1_set_seq_out writes |sk| to |out| under the i2d output convention,
* excluding the tag and length. It returns one on success and zero on error. // excluding the tag and length. It returns one on success and zero on error.
* |skcontlen| must be the total encoded size. If |do_sort| is non-zero, the // |skcontlen| must be the total encoded size. If |do_sort| is non-zero, the
* elements are sorted for a SET OF type. Each element of |sk| has type // elements are sorted for a SET OF type. Each element of |sk| has type
* |item|. */ // |item|.
static int asn1_set_seq_out(STACK_OF(ASN1_VALUE) *sk, unsigned char **out, static int asn1_set_seq_out(STACK_OF(ASN1_VALUE) *sk, unsigned char **out,
int skcontlen, const ASN1_ITEM *item, int do_sort) { int skcontlen, const ASN1_ITEM *item, int do_sort) {
/* No need to sort if there are fewer than two items. */ // No need to sort if there are fewer than two items.
if (!do_sort || sk_ASN1_VALUE_num(sk) < 2) { if (!do_sort || sk_ASN1_VALUE_num(sk) < 2) {
for (size_t i = 0; i < sk_ASN1_VALUE_num(sk); i++) { for (size_t i = 0; i < sk_ASN1_VALUE_num(sk); i++) {
ASN1_VALUE *skitem = sk_ASN1_VALUE_value(sk, i); ASN1_VALUE *skitem = sk_ASN1_VALUE_value(sk, i);
@ -465,7 +451,7 @@ static int asn1_set_seq_out(STACK_OF(ASN1_VALUE) *sk, unsigned char **out,
goto err; goto err;
} }
/* Encode all the elements into |buf| and populate |encoded|. */ // Encode all the elements into |buf| and populate |encoded|.
unsigned char *p = buf; unsigned char *p = buf;
for (size_t i = 0; i < sk_ASN1_VALUE_num(sk); i++) { for (size_t i = 0; i < sk_ASN1_VALUE_num(sk); i++) {
ASN1_VALUE *skitem = sk_ASN1_VALUE_value(sk, i); ASN1_VALUE *skitem = sk_ASN1_VALUE_value(sk, i);
@ -479,7 +465,7 @@ static int asn1_set_seq_out(STACK_OF(ASN1_VALUE) *sk, unsigned char **out,
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. */ // Output the elements in sorted order.
p = *out; p = *out;
for (size_t i = 0; i < sk_ASN1_VALUE_num(sk); i++) { for (size_t i = 0; i < sk_ASN1_VALUE_num(sk); i++) {
OPENSSL_memcpy(p, encoded[i].data, encoded[i].length); OPENSSL_memcpy(p, encoded[i].data, encoded[i].length);
@ -495,12 +481,12 @@ err:
return ret; return ret;
} }
/* asn1_i2d_ex_primitive behaves like |ASN1_item_ex_i2d| but |item| must be a // 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|. */ // a PRIMITIVE or MSTRING type that is not an |ASN1_ITEM_TEMPLATE|.
static int asn1_i2d_ex_primitive(ASN1_VALUE **pval, unsigned char **out, static int asn1_i2d_ex_primitive(ASN1_VALUE **pval, unsigned char **out,
const ASN1_ITEM *it, int tag, int aclass, const ASN1_ITEM *it, int tag, int aclass,
int optional) { int optional) {
/* Get length of content octets and maybe find out the underlying type. */ // Get length of content octets and maybe find out the underlying type.
int omit; int omit;
int utype = it->utype; int utype = it->utype;
int len = asn1_ex_i2c(pval, NULL, &omit, &utype, it); int len = asn1_ex_i2c(pval, NULL, &omit, &utype, it);
@ -515,20 +501,18 @@ static int asn1_i2d_ex_primitive(ASN1_VALUE **pval, unsigned char **out,
return -1; return -1;
} }
/* // If SEQUENCE, SET or OTHER then header is included in pseudo content
* 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
* octets so don't include tag+length. We need to check here because the // call to asn1_ex_i2c() could change utype.
* call to asn1_ex_i2c() could change utype.
*/
int usetag = int usetag =
utype != V_ASN1_SEQUENCE && utype != V_ASN1_SET && utype != V_ASN1_OTHER; utype != V_ASN1_SEQUENCE && utype != V_ASN1_SET && utype != V_ASN1_OTHER;
/* If not implicitly tagged get tag from underlying type */ // If not implicitly tagged get tag from underlying type
if (tag == -1) { if (tag == -1) {
tag = utype; tag = utype;
} }
/* Output tag+length followed by content octets */ // Output tag+length followed by content octets
if (out) { if (out) {
if (usetag) { if (usetag) {
ASN1_put_object(out, /*constructed=*/0, len, tag, aclass); ASN1_put_object(out, /*constructed=*/0, len, tag, aclass);
@ -548,22 +532,22 @@ static int asn1_i2d_ex_primitive(ASN1_VALUE **pval, unsigned char **out,
return len; return len;
} }
/* asn1_ex_i2c writes the |*pval| to |cout| under the i2d output convention, // asn1_ex_i2c writes the |*pval| to |cout| under the i2d output convention,
* excluding the tag and length. It returns the number of bytes written, // excluding the tag and length. It returns the number of bytes written,
* possibly zero, on success or -1 on error. If |*pval| should be omitted, it // possibly zero, on success or -1 on error. If |*pval| should be omitted, it
* returns zero and sets |*out_omit| to true. // returns zero and sets |*out_omit| to true.
* //
* If |it| is an MSTRING or ANY type, it gets the underlying type from |*pval|, // If |it| is an MSTRING or ANY type, it gets the underlying type from |*pval|,
* which must be an |ASN1_STRING| or |ASN1_TYPE|, respectively. It then updates // which must be an |ASN1_STRING| or |ASN1_TYPE|, respectively. It then updates
* |*putype| with the tag number of type used, or |V_ASN1_OTHER| if it was not a // |*putype| with the tag number of type used, or |V_ASN1_OTHER| if it was not a
* universal type. If |*putype| is set to |V_ASN1_SEQUENCE|, |V_ASN1_SET|, or // universal type. If |*putype| is set to |V_ASN1_SEQUENCE|, |V_ASN1_SET|, or
* |V_ASN1_OTHER|, it additionally outputs the tag and length, so the caller // |V_ASN1_OTHER|, it additionally outputs the tag and length, so the caller
* must not do so. // must not do so.
* //
* Otherwise, |*putype| must contain |it->utype|. // Otherwise, |*putype| must contain |it->utype|.
* //
* WARNING: Unlike most functions in this file, |asn1_ex_i2c| can return zero // WARNING: Unlike most functions in this file, |asn1_ex_i2c| can return zero
* without omitting the element. ASN.1 values may have empty contents. */ // 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, static int asn1_ex_i2c(ASN1_VALUE **pval, unsigned char *cout, int *out_omit,
int *putype, const ASN1_ITEM *it) { int *putype, const ASN1_ITEM *it) {
ASN1_BOOLEAN *tbool = NULL; ASN1_BOOLEAN *tbool = NULL;
@ -574,13 +558,13 @@ static int asn1_ex_i2c(ASN1_VALUE **pval, unsigned char *cout, int *out_omit,
unsigned char c; unsigned char c;
int len; int len;
/* Historically, |it->funcs| for primitive types contained an // Historically, |it->funcs| for primitive types contained an
* |ASN1_PRIMITIVE_FUNCS| table of callbacks. */ // |ASN1_PRIMITIVE_FUNCS| table of callbacks.
assert(it->funcs == NULL); assert(it->funcs == NULL);
*out_omit = 0; *out_omit = 0;
/* Should type be omitted? */ // Should type be omitted?
if ((it->itype != ASN1_ITYPE_PRIMITIVE) || (it->utype != V_ASN1_BOOLEAN)) { if ((it->itype != ASN1_ITYPE_PRIMITIVE) || (it->utype != V_ASN1_BOOLEAN)) {
if (!*pval) { if (!*pval) {
*out_omit = 1; *out_omit = 1;
@ -589,23 +573,23 @@ static int asn1_ex_i2c(ASN1_VALUE **pval, unsigned char *cout, int *out_omit,
} }
if (it->itype == ASN1_ITYPE_MSTRING) { if (it->itype == ASN1_ITYPE_MSTRING) {
/* If MSTRING type set the underlying type */ // If MSTRING type set the underlying type
strtmp = (ASN1_STRING *)*pval; strtmp = (ASN1_STRING *)*pval;
utype = strtmp->type; utype = strtmp->type;
if (utype < 0 && utype != V_ASN1_OTHER) { if (utype < 0 && utype != V_ASN1_OTHER) {
/* MSTRINGs can have type -1 when default-constructed. */ // MSTRINGs can have type -1 when default-constructed.
OPENSSL_PUT_ERROR(ASN1, ASN1_R_WRONG_TYPE); OPENSSL_PUT_ERROR(ASN1, ASN1_R_WRONG_TYPE);
return -1; return -1;
} }
/* Negative INTEGER and ENUMERATED values use |ASN1_STRING| type values // Negative INTEGER and ENUMERATED values use |ASN1_STRING| type values
* that do not match their corresponding utype values. INTEGERs cannot // that do not match their corresponding utype values. INTEGERs cannot
* participate in MSTRING types, but ENUMERATEDs can. // participate in MSTRING types, but ENUMERATEDs can.
* //
* TODO(davidben): Is this a bug? Although arguably one of the MSTRING // TODO(davidben): Is this a bug? Although arguably one of the MSTRING
* types should contain more values, rather than less. See // types should contain more values, rather than less. See
* https://crbug.com/boringssl/412. But it is not possible to fit all // 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 // possible ANY values into an |ASN1_STRING|, so matching the spec here
* is somewhat hopeless. */ // is somewhat hopeless.
if (utype == V_ASN1_NEG_INTEGER) { if (utype == V_ASN1_NEG_INTEGER) {
utype = V_ASN1_INTEGER; utype = V_ASN1_INTEGER;
} else if (utype == V_ASN1_NEG_ENUMERATED) { } else if (utype == V_ASN1_NEG_ENUMERATED) {
@ -613,12 +597,12 @@ static int asn1_ex_i2c(ASN1_VALUE **pval, unsigned char *cout, int *out_omit,
} }
*putype = utype; *putype = utype;
} else if (it->utype == V_ASN1_ANY) { } else if (it->utype == V_ASN1_ANY) {
/* If ANY set type and pointer to value */ // If ANY set type and pointer to value
ASN1_TYPE *typ; ASN1_TYPE *typ;
typ = (ASN1_TYPE *)*pval; typ = (ASN1_TYPE *)*pval;
utype = typ->type; utype = typ->type;
if (utype < 0 && utype != V_ASN1_OTHER) { if (utype < 0 && utype != V_ASN1_OTHER) {
/* |ASN1_TYPE|s can have type -1 when default-constructed. */ // |ASN1_TYPE|s can have type -1 when default-constructed.
OPENSSL_PUT_ERROR(ASN1, ASN1_R_WRONG_TYPE); OPENSSL_PUT_ERROR(ASN1, ASN1_R_WRONG_TYPE);
return -1; return -1;
} }
@ -634,7 +618,7 @@ static int asn1_ex_i2c(ASN1_VALUE **pval, unsigned char *cout, int *out_omit,
cont = otmp->data; cont = otmp->data;
len = otmp->length; len = otmp->length;
if (len == 0) { if (len == 0) {
/* Some |ASN1_OBJECT|s do not have OIDs and cannot be serialized. */ // Some |ASN1_OBJECT|s do not have OIDs and cannot be serialized.
OPENSSL_PUT_ERROR(ASN1, ASN1_R_ILLEGAL_OBJECT); OPENSSL_PUT_ERROR(ASN1, ASN1_R_ILLEGAL_OBJECT);
return -1; return -1;
} }
@ -652,9 +636,7 @@ static int asn1_ex_i2c(ASN1_VALUE **pval, unsigned char *cout, int *out_omit,
return 0; return 0;
} }
if (it->utype != V_ASN1_ANY) { if (it->utype != V_ASN1_ANY) {
/* // Default handling if value == size field then omit
* Default handling if value == size field then omit
*/
if ((*tbool && (it->size > 0)) || (!*tbool && !it->size)) { if ((*tbool && (it->size > 0)) || (!*tbool && !it->size)) {
*out_omit = 1; *out_omit = 1;
return 0; return 0;
@ -668,15 +650,15 @@ static int asn1_ex_i2c(ASN1_VALUE **pval, unsigned char *cout, int *out_omit,
case V_ASN1_BIT_STRING: { case V_ASN1_BIT_STRING: {
int ret = int ret =
i2c_ASN1_BIT_STRING((ASN1_BIT_STRING *)*pval, cout ? &cout : NULL); i2c_ASN1_BIT_STRING((ASN1_BIT_STRING *)*pval, cout ? &cout : NULL);
/* |i2c_ASN1_BIT_STRING| returns zero on error instead of -1. */ // |i2c_ASN1_BIT_STRING| returns zero on error instead of -1.
return ret <= 0 ? -1 : ret; return ret <= 0 ? -1 : ret;
} }
case V_ASN1_INTEGER: case V_ASN1_INTEGER:
case V_ASN1_ENUMERATED: { case V_ASN1_ENUMERATED: {
/* |i2c_ASN1_INTEGER| also handles ENUMERATED. */ // |i2c_ASN1_INTEGER| also handles ENUMERATED.
int ret = i2c_ASN1_INTEGER((ASN1_INTEGER *)*pval, cout ? &cout : NULL); int ret = i2c_ASN1_INTEGER((ASN1_INTEGER *)*pval, cout ? &cout : NULL);
/* |i2c_ASN1_INTEGER| returns zero on error instead of -1. */ // |i2c_ASN1_INTEGER| returns zero on error instead of -1.
return ret <= 0 ? -1 : ret; return ret <= 0 ? -1 : ret;
} }
@ -697,7 +679,7 @@ static int asn1_ex_i2c(ASN1_VALUE **pval, unsigned char *cout, int *out_omit,
case V_ASN1_SEQUENCE: case V_ASN1_SEQUENCE:
case V_ASN1_SET: case V_ASN1_SET:
default: default:
/* All based on ASN1_STRING and handled the same */ // All based on ASN1_STRING and handled the same
strtmp = (ASN1_STRING *)*pval; strtmp = (ASN1_STRING *)*pval;
cont = strtmp->data; cont = strtmp->data;
len = strtmp->length; len = strtmp->length;

@ -63,7 +63,7 @@
#include "internal.h" #include "internal.h"
/* Free up an ASN1 structure */ // Free up an ASN1 structure
void ASN1_item_free(ASN1_VALUE *val, const ASN1_ITEM *it) { void ASN1_item_free(ASN1_VALUE *val, const ASN1_ITEM *it) {
asn1_item_combine_free(&val, it, 0); asn1_item_combine_free(&val, it, 0);
@ -144,11 +144,9 @@ void asn1_item_combine_free(ASN1_VALUE **pval, const ASN1_ITEM *it,
} }
} }
asn1_enc_free(pval, it); asn1_enc_free(pval, it);
/* // If we free up as normal we will invalidate any ANY DEFINED BY
* 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
* field and we wont be able to determine the type of the field it // defines. So free up in reverse order.
* defines. So free up in reverse order.
*/
tt = it->templates + it->tcount - 1; tt = it->templates + it->tcount - 1;
for (i = 0; i < it->tcount; tt--, i++) { for (i = 0; i < it->tcount; tt--, i++) {
ASN1_VALUE **pseqval; ASN1_VALUE **pseqval;
@ -190,10 +188,10 @@ void ASN1_template_free(ASN1_VALUE **pval, const ASN1_TEMPLATE *tt) {
void ASN1_primitive_free(ASN1_VALUE **pval, const ASN1_ITEM *it) { void ASN1_primitive_free(ASN1_VALUE **pval, const ASN1_ITEM *it) {
int utype; int utype;
/* Historically, |it->funcs| for primitive types contained an // Historically, |it->funcs| for primitive types contained an
* |ASN1_PRIMITIVE_FUNCS| table of calbacks. */ // |ASN1_PRIMITIVE_FUNCS| table of calbacks.
assert(it == NULL || it->funcs == NULL); assert(it == NULL || it->funcs == NULL);
/* Special case: if 'it' is NULL free contents of ASN1_TYPE */ // Special case: if 'it' is NULL free contents of ASN1_TYPE
if (!it) { if (!it) {
ASN1_TYPE *typ = (ASN1_TYPE *)*pval; ASN1_TYPE *typ = (ASN1_TYPE *)*pval;
utype = typ->type; utype = typ->type;

@ -83,7 +83,7 @@ ASN1_VALUE *ASN1_item_new(const ASN1_ITEM *it) {
return NULL; return NULL;
} }
/* Allocate an ASN1 structure */ // Allocate an ASN1 structure
int ASN1_item_ex_new(ASN1_VALUE **pval, const ASN1_ITEM *it) { int ASN1_item_ex_new(ASN1_VALUE **pval, const ASN1_ITEM *it) {
return asn1_item_ex_combine_new(pval, it, 0); return asn1_item_ex_combine_new(pval, it, 0);
@ -235,13 +235,13 @@ static int ASN1_template_new(ASN1_VALUE **pval, const ASN1_TEMPLATE *tt) {
asn1_template_clear(pval, tt); asn1_template_clear(pval, tt);
return 1; return 1;
} }
/* If ANY DEFINED BY nothing to do */ // If ANY DEFINED BY nothing to do
if (tt->flags & ASN1_TFLG_ADB_MASK) { if (tt->flags & ASN1_TFLG_ADB_MASK) {
*pval = NULL; *pval = NULL;
return 1; return 1;
} }
/* If SET OF or SEQUENCE OF, its a STACK */ // If SET OF or SEQUENCE OF, its a STACK
if (tt->flags & ASN1_TFLG_SK_MASK) { if (tt->flags & ASN1_TFLG_SK_MASK) {
STACK_OF(ASN1_VALUE) *skval; STACK_OF(ASN1_VALUE) *skval;
skval = sk_ASN1_VALUE_new_null(); skval = sk_ASN1_VALUE_new_null();
@ -254,14 +254,14 @@ static int ASN1_template_new(ASN1_VALUE **pval, const ASN1_TEMPLATE *tt) {
ret = 1; ret = 1;
goto done; goto done;
} }
/* Otherwise pass it back to the item routine */ // Otherwise pass it back to the item routine
ret = asn1_item_ex_combine_new(pval, it, tt->flags & ASN1_TFLG_COMBINE); ret = asn1_item_ex_combine_new(pval, it, tt->flags & ASN1_TFLG_COMBINE);
done: done:
return ret; return ret;
} }
static void asn1_template_clear(ASN1_VALUE **pval, const ASN1_TEMPLATE *tt) { static void asn1_template_clear(ASN1_VALUE **pval, const ASN1_TEMPLATE *tt) {
/* If ADB or STACK just NULL the field */ // If ADB or STACK just NULL the field
if (tt->flags & (ASN1_TFLG_ADB_MASK | ASN1_TFLG_SK_MASK)) { if (tt->flags & (ASN1_TFLG_ADB_MASK | ASN1_TFLG_SK_MASK)) {
*pval = NULL; *pval = NULL;
} else { } else {
@ -269,10 +269,8 @@ static void asn1_template_clear(ASN1_VALUE **pval, const ASN1_TEMPLATE *tt) {
} }
} }
/* // NB: could probably combine most of the real XXX_new() behaviour and junk
* NB: could probably combine most of the real XXX_new() behaviour and junk // all the old functions.
* all the old functions.
*/
static int ASN1_primitive_new(ASN1_VALUE **pval, const ASN1_ITEM *it) { static int ASN1_primitive_new(ASN1_VALUE **pval, const ASN1_ITEM *it) {
ASN1_TYPE *typ; ASN1_TYPE *typ;
@ -282,8 +280,8 @@ static int ASN1_primitive_new(ASN1_VALUE **pval, const ASN1_ITEM *it) {
return 0; return 0;
} }
/* Historically, |it->funcs| for primitive types contained an // Historically, |it->funcs| for primitive types contained an
* |ASN1_PRIMITIVE_FUNCS| table of calbacks. */ // |ASN1_PRIMITIVE_FUNCS| table of calbacks.
assert(it->funcs == NULL); assert(it->funcs == NULL);
if (it->itype == ASN1_ITYPE_MSTRING) { if (it->itype == ASN1_ITYPE_MSTRING) {
@ -326,8 +324,8 @@ static int ASN1_primitive_new(ASN1_VALUE **pval, const ASN1_ITEM *it) {
static void asn1_primitive_clear(ASN1_VALUE **pval, const ASN1_ITEM *it) { static void asn1_primitive_clear(ASN1_VALUE **pval, const ASN1_ITEM *it) {
int utype; int utype;
/* Historically, |it->funcs| for primitive types contained an // Historically, |it->funcs| for primitive types contained an
* |ASN1_PRIMITIVE_FUNCS| table of calbacks. */ // |ASN1_PRIMITIVE_FUNCS| table of calbacks.
assert(it == NULL || it->funcs == NULL); assert(it == NULL || it->funcs == NULL);
if (!it || (it->itype == ASN1_ITYPE_MSTRING)) { if (!it || (it->itype == ASN1_ITYPE_MSTRING)) {
utype = -1; utype = -1;

@ -58,7 +58,7 @@
#include <openssl/asn1t.h> #include <openssl/asn1t.h>
/* Declarations for string types */ // Declarations for string types
#define IMPLEMENT_ASN1_STRING_FUNCTIONS(sname) \ #define IMPLEMENT_ASN1_STRING_FUNCTIONS(sname) \
IMPLEMENT_ASN1_TYPE(sname) \ IMPLEMENT_ASN1_TYPE(sname) \
@ -88,12 +88,12 @@ IMPLEMENT_ASN1_TYPE(ASN1_OBJECT)
IMPLEMENT_ASN1_TYPE(ASN1_ANY) IMPLEMENT_ASN1_TYPE(ASN1_ANY)
/* Just swallow an ASN1_SEQUENCE in an ASN1_STRING */ // Just swallow an ASN1_SEQUENCE in an ASN1_STRING
IMPLEMENT_ASN1_TYPE(ASN1_SEQUENCE) IMPLEMENT_ASN1_TYPE(ASN1_SEQUENCE)
IMPLEMENT_ASN1_FUNCTIONS_const_fname(ASN1_TYPE, ASN1_ANY, ASN1_TYPE) IMPLEMENT_ASN1_FUNCTIONS_const_fname(ASN1_TYPE, ASN1_ANY, ASN1_TYPE)
/* Multistring types */ // Multistring types
IMPLEMENT_ASN1_MSTRING(ASN1_PRINTABLE, B_ASN1_PRINTABLE) IMPLEMENT_ASN1_MSTRING(ASN1_PRINTABLE, B_ASN1_PRINTABLE)
IMPLEMENT_ASN1_FUNCTIONS_const_fname(ASN1_STRING, ASN1_PRINTABLE, IMPLEMENT_ASN1_FUNCTIONS_const_fname(ASN1_STRING, ASN1_PRINTABLE,
@ -106,12 +106,12 @@ IMPLEMENT_ASN1_MSTRING(DIRECTORYSTRING, B_ASN1_DIRECTORYSTRING)
IMPLEMENT_ASN1_FUNCTIONS_const_fname(ASN1_STRING, DIRECTORYSTRING, IMPLEMENT_ASN1_FUNCTIONS_const_fname(ASN1_STRING, DIRECTORYSTRING,
DIRECTORYSTRING) DIRECTORYSTRING)
/* Three separate BOOLEAN type: normal, DEFAULT TRUE and DEFAULT FALSE */ // Three separate BOOLEAN type: normal, DEFAULT TRUE and DEFAULT FALSE
IMPLEMENT_ASN1_TYPE_ex(ASN1_BOOLEAN, ASN1_BOOLEAN, -1) IMPLEMENT_ASN1_TYPE_ex(ASN1_BOOLEAN, ASN1_BOOLEAN, -1)
IMPLEMENT_ASN1_TYPE_ex(ASN1_TBOOLEAN, ASN1_BOOLEAN, 1) IMPLEMENT_ASN1_TYPE_ex(ASN1_TBOOLEAN, ASN1_BOOLEAN, 1)
IMPLEMENT_ASN1_TYPE_ex(ASN1_FBOOLEAN, ASN1_BOOLEAN, 0) IMPLEMENT_ASN1_TYPE_ex(ASN1_FBOOLEAN, ASN1_BOOLEAN, 0)
/* Special, OCTET STRING with indefinite length constructed support */ // Special, OCTET STRING with indefinite length constructed support
ASN1_ITEM_TEMPLATE(ASN1_SEQUENCE_ANY) = 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)

@ -69,18 +69,18 @@
#include "internal.h" #include "internal.h"
/* Utility functions for manipulating fields and offsets */ // Utility functions for manipulating fields and offsets
/* Add 'offset' to 'addr' */ // Add 'offset' to 'addr'
#define offset2ptr(addr, offset) (void *)(((char *)(addr)) + (offset)) #define offset2ptr(addr, offset) (void *)(((char *)(addr)) + (offset))
/* Given an ASN1_ITEM CHOICE type return the selector value */ // Given an ASN1_ITEM CHOICE type return the selector value
int asn1_get_choice_selector(ASN1_VALUE **pval, const ASN1_ITEM *it) { int asn1_get_choice_selector(ASN1_VALUE **pval, const ASN1_ITEM *it) {
int *sel = offset2ptr(*pval, it->utype); int *sel = offset2ptr(*pval, it->utype);
return *sel; return *sel;
} }
/* Given an ASN1_ITEM CHOICE type set the selector value, return old value. */ // Given an ASN1_ITEM CHOICE type set the selector value, return old value.
int asn1_set_choice_selector(ASN1_VALUE **pval, int value, int asn1_set_choice_selector(ASN1_VALUE **pval, int value,
const ASN1_ITEM *it) { const ASN1_ITEM *it) {
int *sel, ret; int *sel, ret;
@ -205,20 +205,20 @@ int asn1_enc_restore(int *len, unsigned char **out, ASN1_VALUE **pval,
return 1; return 1;
} }
/* Given an ASN1_TEMPLATE get a pointer to a field */ // Given an ASN1_TEMPLATE get a pointer to a field
ASN1_VALUE **asn1_get_field_ptr(ASN1_VALUE **pval, const ASN1_TEMPLATE *tt) { ASN1_VALUE **asn1_get_field_ptr(ASN1_VALUE **pval, const ASN1_TEMPLATE *tt) {
ASN1_VALUE **pvaltmp; ASN1_VALUE **pvaltmp;
if (tt->flags & ASN1_TFLG_COMBINE) { if (tt->flags & ASN1_TFLG_COMBINE) {
return pval; return pval;
} }
pvaltmp = offset2ptr(*pval, tt->offset); pvaltmp = offset2ptr(*pval, tt->offset);
/* NOTE for BOOLEAN types the field is just a plain int so we can't return // NOTE for BOOLEAN types the field is just a plain int so we can't return
* int **, so settle for (int *). */ // int **, so settle for (int *).
return pvaltmp; return pvaltmp;
} }
/* Handle ANY DEFINED BY template, find the selector, look up the relevant // Handle ANY DEFINED BY template, find the selector, look up the relevant
* ASN1_TEMPLATE in the table and return it. */ // ASN1_TEMPLATE in the table and return it.
const ASN1_TEMPLATE *asn1_do_adb(ASN1_VALUE **pval, const ASN1_TEMPLATE *tt, const ASN1_TEMPLATE *asn1_do_adb(ASN1_VALUE **pval, const ASN1_TEMPLATE *tt,
int nullerr) { int nullerr) {
const ASN1_ADB *adb; const ASN1_ADB *adb;
@ -229,13 +229,13 @@ const ASN1_TEMPLATE *asn1_do_adb(ASN1_VALUE **pval, const ASN1_TEMPLATE *tt,
return tt; return tt;
} }
/* Else ANY DEFINED BY ... get the table */ // Else ANY DEFINED BY ... get the table
adb = ASN1_ADB_ptr(tt->item); adb = ASN1_ADB_ptr(tt->item);
/* Get the selector field */ // Get the selector field
sfld = offset2ptr(*pval, adb->offset); sfld = offset2ptr(*pval, adb->offset);
/* Check if NULL */ // Check if NULL
if (*sfld == NULL) { if (*sfld == NULL) {
if (!adb->null_tt) { if (!adb->null_tt) {
goto err; goto err;
@ -243,16 +243,16 @@ const ASN1_TEMPLATE *asn1_do_adb(ASN1_VALUE **pval, const ASN1_TEMPLATE *tt,
return adb->null_tt; return adb->null_tt;
} }
/* Convert type to a NID: // Convert type to a NID:
* NB: don't check for NID_undef here because it // NB: don't check for NID_undef here because it
* might be a legitimate value in the table */ // might be a legitimate value in the table
assert(tt->flags & ASN1_TFLG_ADB_OID); assert(tt->flags & ASN1_TFLG_ADB_OID);
int selector = OBJ_obj2nid((ASN1_OBJECT *)*sfld); int selector = OBJ_obj2nid((ASN1_OBJECT *)*sfld);
/* Try to find matching entry in table Maybe should check application types // Try to find matching entry in table Maybe should check application types
* first to allow application override? Might also be useful to have a flag // first to allow application override? Might also be useful to have a flag
* which indicates table is sorted and we can do a binary search. For now // which indicates table is sorted and we can do a binary search. For now
* stick to a linear search. */ // stick to a linear search.
for (atbl = adb->tbl, i = 0; i < adb->tblcount; i++, atbl++) { for (atbl = adb->tbl, i = 0; i < adb->tblcount; i++, atbl++) {
if (atbl->value == selector) { if (atbl->value == selector) {
@ -260,16 +260,16 @@ const ASN1_TEMPLATE *asn1_do_adb(ASN1_VALUE **pval, const ASN1_TEMPLATE *tt,
} }
} }
/* FIXME: need to search application table too */ // FIXME: need to search application table too
/* No match, return default type */ // No match, return default type
if (!adb->default_tt) { if (!adb->default_tt) {
goto err; goto err;
} }
return adb->default_tt; return adb->default_tt;
err: err:
/* FIXME: should log the value or OID of unsupported type */ // FIXME: should log the value or OID of unsupported type
if (nullerr) { if (nullerr) {
OPENSSL_PUT_ERROR(ASN1, ASN1_R_UNSUPPORTED_ANY_DEFINED_BY_TYPE); OPENSSL_PUT_ERROR(ASN1, ASN1_R_UNSUPPORTED_ANY_DEFINED_BY_TYPE);
} }

@ -56,7 +56,7 @@
* Hudson (tjh@cryptsoft.com). */ * Hudson (tjh@cryptsoft.com). */
#if defined(__linux__) && !defined(_POSIX_C_SOURCE) #if defined(__linux__) && !defined(_POSIX_C_SOURCE)
#define _POSIX_C_SOURCE 201410L /* for gmtime_r */ #define _POSIX_C_SOURCE 201410L // for gmtime_r
#endif #endif
#include "internal.h" #include "internal.h"
@ -77,7 +77,7 @@ struct tm *OPENSSL_gmtime(const time_t *time, struct tm *result) {
#endif #endif
} }
/* Convert date to and from julian day Uses Fliegel & Van Flandern algorithm */ // Convert date to and from julian day Uses Fliegel & Van Flandern algorithm
static long date_to_julian(int y, int m, int d) { static long date_to_julian(int y, int m, int d) {
return (1461 * (y + 4800 + (m - 14) / 12)) / 4 + return (1461 * (y + 4800 + (m - 14) / 12)) / 4 +
(367 * (m - 2 - 12 * ((m - 14) / 12))) / 12 - (367 * (m - 2 - 12 * ((m - 14) / 12))) / 12 -
@ -99,20 +99,20 @@ static void julian_to_date(long jd, int *y, int *m, int *d) {
*y = 100 * (n - 49) + i + L; *y = 100 * (n - 49) + i + L;
} }
/* Convert tm structure and offset into julian day and seconds */ // Convert tm structure and offset into julian day and seconds
static int julian_adj(const struct tm *tm, int off_day, long offset_sec, static int julian_adj(const struct tm *tm, int off_day, long offset_sec,
long *pday, int *psec) { long *pday, int *psec) {
int offset_hms, offset_day; int offset_hms, offset_day;
long time_jd; long time_jd;
int time_year, time_month, time_day; int time_year, time_month, time_day;
/* split offset into days and day seconds */ // split offset into days and day seconds
offset_day = offset_sec / SECS_PER_DAY; offset_day = offset_sec / SECS_PER_DAY;
/* Avoid sign issues with % operator */ // Avoid sign issues with % operator
offset_hms = offset_sec - (offset_day * SECS_PER_DAY); offset_hms = offset_sec - (offset_day * SECS_PER_DAY);
offset_day += off_day; offset_day += off_day;
/* Add current time seconds to offset */ // Add current time seconds to offset
offset_hms += tm->tm_hour * 3600 + tm->tm_min * 60 + tm->tm_sec; offset_hms += tm->tm_hour * 3600 + tm->tm_min * 60 + tm->tm_sec;
/* Adjust day seconds if overflow */ // Adjust day seconds if overflow
if (offset_hms >= SECS_PER_DAY) { if (offset_hms >= SECS_PER_DAY) {
offset_day++; offset_day++;
offset_hms -= SECS_PER_DAY; offset_hms -= SECS_PER_DAY;
@ -121,7 +121,7 @@ static int julian_adj(const struct tm *tm, int off_day, long offset_sec,
offset_hms += SECS_PER_DAY; offset_hms += SECS_PER_DAY;
} }
/* Convert date of time structure into a Julian day number. */ // Convert date of time structure into a Julian day number.
time_year = tm->tm_year + 1900; time_year = tm->tm_year + 1900;
time_month = tm->tm_mon + 1; time_month = tm->tm_mon + 1;
@ -129,7 +129,7 @@ static int julian_adj(const struct tm *tm, int off_day, long offset_sec,
time_jd = date_to_julian(time_year, time_month, time_day); time_jd = date_to_julian(time_year, time_month, time_day);
/* Work out Julian day of new date */ // Work out Julian day of new date
time_jd += offset_day; time_jd += offset_day;
if (time_jd < 0) { if (time_jd < 0) {
@ -145,12 +145,12 @@ int OPENSSL_gmtime_adj(struct tm *tm, int off_day, long offset_sec) {
int time_sec, time_year, time_month, time_day; int time_sec, time_year, time_month, time_day;
long time_jd; long time_jd;
/* Convert time and offset into julian day and seconds */ // Convert time and offset into julian day and seconds
if (!julian_adj(tm, off_day, offset_sec, &time_jd, &time_sec)) { if (!julian_adj(tm, off_day, offset_sec, &time_jd, &time_sec)) {
return 0; return 0;
} }
/* Convert Julian day back to date */ // Convert Julian day back to date
julian_to_date(time_jd, &time_year, &time_month, &time_day); julian_to_date(time_jd, &time_year, &time_month, &time_day);
@ -158,7 +158,7 @@ int OPENSSL_gmtime_adj(struct tm *tm, int off_day, long offset_sec) {
return 0; return 0;
} }
/* Update tm structure */ // Update tm structure
tm->tm_year = time_year - 1900; tm->tm_year = time_year - 1900;
tm->tm_mon = time_month - 1; tm->tm_mon = time_month - 1;
@ -185,7 +185,7 @@ int OPENSSL_gmtime_diff(int *out_days, int *out_secs, const struct tm *from,
diff_day = to_jd - from_jd; diff_day = to_jd - from_jd;
diff_sec = to_sec - from_sec; diff_sec = to_sec - from_sec;
/* Adjust differences so both positive or both negative */ // Adjust differences so both positive or both negative
if (diff_day > 0 && diff_sec < 0) { if (diff_day > 0 && diff_sec < 0) {
diff_day--; diff_day--;
diff_sec += SECS_PER_DAY; diff_sec += SECS_PER_DAY;

@ -127,12 +127,10 @@ IMPLEMENT_PEM_write(X509_REQ_NEW, X509_REQ, PEM_STRING_X509_REQ_OLD, X509_REQ)
IMPLEMENT_PEM_rw(X509_CRL, X509_CRL, PEM_STRING_X509_CRL, X509_CRL) IMPLEMENT_PEM_rw(X509_CRL, X509_CRL, PEM_STRING_X509_CRL, X509_CRL)
IMPLEMENT_PEM_rw(PKCS7, PKCS7, PEM_STRING_PKCS7, PKCS7) IMPLEMENT_PEM_rw(PKCS7, PKCS7, PEM_STRING_PKCS7, PKCS7)
/* // We treat RSA or DSA private keys as a special case. For private keys we
* We treat RSA or DSA private keys as a special case. For private keys we // read in an EVP_PKEY structure with PEM_read_bio_PrivateKey() and extract
* read in an EVP_PKEY structure with PEM_read_bio_PrivateKey() and extract // the relevant private key: this means can handle "traditional" and PKCS#8
* the relevant private key: this means can handle "traditional" and PKCS#8 // formats transparently.
* formats transparently.
*/
static RSA *pkey_get_rsa(EVP_PKEY *key, RSA **rsa) { static RSA *pkey_get_rsa(EVP_PKEY *key, RSA **rsa) {
RSA *rtmp; RSA *rtmp;
if (!key) { if (!key) {
@ -190,7 +188,7 @@ DSA *PEM_read_bio_DSAPrivateKey(BIO *bp, DSA **dsa, pem_password_cb *cb,
void *u) { void *u) {
EVP_PKEY *pktmp; EVP_PKEY *pktmp;
pktmp = PEM_read_bio_PrivateKey(bp, NULL, cb, u); pktmp = PEM_read_bio_PrivateKey(bp, NULL, cb, u);
return pkey_get_dsa(pktmp, dsa); /* will free pktmp */ 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)
@ -199,7 +197,7 @@ 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) { DSA *PEM_read_DSAPrivateKey(FILE *fp, DSA **dsa, pem_password_cb *cb, void *u) {
EVP_PKEY *pktmp; EVP_PKEY *pktmp;
pktmp = PEM_read_PrivateKey(fp, NULL, cb, u); pktmp = PEM_read_PrivateKey(fp, NULL, cb, u);
return pkey_get_dsa(pktmp, dsa); /* will free pktmp */ return pkey_get_dsa(pktmp, dsa); // will free pktmp
} }
IMPLEMENT_PEM_rw_const(DSAparams, DSA, PEM_STRING_DSAPARAMS, DSAparams) IMPLEMENT_PEM_rw_const(DSAparams, DSA, PEM_STRING_DSAPARAMS, DSAparams)
@ -225,7 +223,7 @@ EC_KEY *PEM_read_bio_ECPrivateKey(BIO *bp, EC_KEY **key, pem_password_cb *cb,
void *u) { void *u) {
EVP_PKEY *pktmp; EVP_PKEY *pktmp;
pktmp = PEM_read_bio_PrivateKey(bp, NULL, cb, u); pktmp = PEM_read_bio_PrivateKey(bp, NULL, cb, u);
return pkey_get_eckey(pktmp, key); /* will free pktmp */ return pkey_get_eckey(pktmp, key); // will free pktmp
} }
IMPLEMENT_PEM_write_cb(ECPrivateKey, EC_KEY, PEM_STRING_ECPRIVATEKEY, IMPLEMENT_PEM_write_cb(ECPrivateKey, EC_KEY, PEM_STRING_ECPRIVATEKEY,
@ -236,7 +234,7 @@ EC_KEY *PEM_read_ECPrivateKey(FILE *fp, EC_KEY **eckey, pem_password_cb *cb,
void *u) { void *u) {
EVP_PKEY *pktmp; EVP_PKEY *pktmp;
pktmp = PEM_read_PrivateKey(fp, NULL, cb, u); pktmp = PEM_read_PrivateKey(fp, NULL, cb, u);
return pkey_get_eckey(pktmp, eckey); /* will free pktmp */ return pkey_get_eckey(pktmp, eckey); // will free pktmp
} }

@ -185,7 +185,7 @@ STACK_OF(X509_INFO) *PEM_X509_INFO_read_bio(BIO *bp, STACK_OF(X509_INFO) *sk,
key_type = EVP_PKEY_EC; key_type = EVP_PKEY_EC;
} }
/* If a private key has a header, assume it is encrypted. */ // If a private key has a header, assume it is encrypted.
if (key_type != EVP_PKEY_NONE && strlen(header) > 10) { if (key_type != EVP_PKEY_NONE && strlen(header) > 10) {
if (info->x_pkey != NULL) { if (info->x_pkey != NULL) {
if (!sk_X509_INFO_push(ret, info)) { if (!sk_X509_INFO_push(ret, info)) {
@ -196,7 +196,7 @@ STACK_OF(X509_INFO) *PEM_X509_INFO_read_bio(BIO *bp, STACK_OF(X509_INFO) *sk,
goto err; goto err;
} }
} }
/* Historically, raw entries pushed an empty key. */ // Historically, raw entries pushed an empty key.
info->x_pkey = X509_PKEY_new(); info->x_pkey = X509_PKEY_new();
if (info->x_pkey == NULL || if (info->x_pkey == NULL ||
!PEM_get_EVP_CIPHER_INFO(header, &info->enc_cipher)) { !PEM_get_EVP_CIPHER_INFO(header, &info->enc_cipher)) {
@ -235,7 +235,7 @@ STACK_OF(X509_INFO) *PEM_X509_INFO_read_bio(BIO *bp, STACK_OF(X509_INFO) *sk,
data = NULL; data = NULL;
} }
/* Push the last entry on the stack if not empty. */ // Push the last entry on the stack if not empty.
if (info->x509 != NULL || info->crl != NULL || info->x_pkey != NULL || if (info->x509 != NULL || info->crl != NULL || info->x_pkey != NULL ||
info->enc_data != NULL) { info->enc_data != NULL) {
if (!sk_X509_INFO_push(ret, info)) { if (!sk_X509_INFO_push(ret, info)) {
@ -264,7 +264,7 @@ err:
return ret; return ret;
} }
/* A TJH addition */ // A TJH addition
int PEM_X509_INFO_write_bio(BIO *bp, X509_INFO *xi, EVP_CIPHER *enc, int PEM_X509_INFO_write_bio(BIO *bp, X509_INFO *xi, EVP_CIPHER *enc,
unsigned char *kstr, int klen, pem_password_cb *cb, unsigned char *kstr, int klen, pem_password_cb *cb,
void *u) { void *u) {
@ -284,11 +284,9 @@ int PEM_X509_INFO_write_bio(BIO *bp, X509_INFO *xi, EVP_CIPHER *enc,
} }
} }
/* // now for the fun part ... if we have a private key then we have to be
* 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 ...
* 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 it is decrypted or it is non-encrypted then we use the base code
*/
if (xi->x_pkey != NULL) { if (xi->x_pkey != NULL) {
if ((xi->enc_data != NULL) && (xi->enc_len > 0)) { if ((xi->enc_data != NULL) && (xi->enc_len > 0)) {
if (enc == NULL) { if (enc == NULL) {
@ -296,36 +294,34 @@ int PEM_X509_INFO_write_bio(BIO *bp, X509_INFO *xi, EVP_CIPHER *enc,
goto err; goto err;
} }
/* copy from weirdo names into more normal things */ // copy from weirdo names into more normal things
iv = xi->enc_cipher.iv; iv = xi->enc_cipher.iv;
data = (unsigned char *)xi->enc_data; data = (unsigned char *)xi->enc_data;
i = xi->enc_len; i = xi->enc_len;
/* // we take the encryption data from the internal stuff rather
* we take the encryption data from the internal stuff rather // than what the user has passed us ... as we have to match
* than what the user has passed us ... as we have to match // exactly for some strange reason
* exactly for some strange reason
*/
objstr = OBJ_nid2sn(EVP_CIPHER_nid(xi->enc_cipher.cipher)); objstr = OBJ_nid2sn(EVP_CIPHER_nid(xi->enc_cipher.cipher));
if (objstr == NULL) { if (objstr == NULL) {
OPENSSL_PUT_ERROR(PEM, PEM_R_UNSUPPORTED_CIPHER); OPENSSL_PUT_ERROR(PEM, PEM_R_UNSUPPORTED_CIPHER);
goto err; goto err;
} }
/* create the right magic header stuff */ // create the right magic header stuff
assert(strlen(objstr) + 23 + 2 * iv_len + 13 <= sizeof buf); assert(strlen(objstr) + 23 + 2 * iv_len + 13 <= sizeof buf);
buf[0] = '\0'; buf[0] = '\0';
PEM_proc_type(buf, PEM_TYPE_ENCRYPTED); PEM_proc_type(buf, PEM_TYPE_ENCRYPTED);
PEM_dek_info(buf, objstr, iv_len, (char *)iv); PEM_dek_info(buf, objstr, iv_len, (char *)iv);
/* use the normal code to write things out */ // use the normal code to write things out
i = PEM_write_bio(bp, PEM_STRING_RSA, buf, data, i); i = PEM_write_bio(bp, PEM_STRING_RSA, buf, data, i);
if (i <= 0) { if (i <= 0) {
goto err; goto err;
} }
} else { } else {
/* Add DSA/DH */ // Add DSA/DH
/* normal optionally encrypted stuff */ // normal optionally encrypted stuff
if (PEM_write_bio_RSAPrivateKey(bp, xi->x_pkey->dec_pkey->pkey.rsa, enc, if (PEM_write_bio_RSAPrivateKey(bp, xi->x_pkey->dec_pkey->pkey.rsa, enc,
kstr, klen, cb, u) <= 0) { kstr, klen, cb, u) <= 0) {
goto err; goto err;
@ -333,16 +329,14 @@ int PEM_X509_INFO_write_bio(BIO *bp, X509_INFO *xi, EVP_CIPHER *enc,
} }
} }
/* if we have a certificate then write it out now */ // if we have a certificate then write it out now
if ((xi->x509 != NULL) && (PEM_write_bio_X509(bp, xi->x509) <= 0)) { if ((xi->x509 != NULL) && (PEM_write_bio_X509(bp, xi->x509) <= 0)) {
goto err; goto err;
} }
/* // we are ignoring anything else that is loaded into the X509_INFO
* 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
* 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
* here and Eric can do it when this makes it into the base library --tjh
*/
ret = 1; ret = 1;

@ -130,12 +130,12 @@ void *PEM_ASN1_read(d2i_of_void *d2i, const char *name, FILE *fp, void **x,
} }
static int check_pem(const char *nm, const char *name) { static int check_pem(const char *nm, const char *name) {
/* Normal matching nm and name */ // Normal matching nm and name
if (!strcmp(nm, name)) { if (!strcmp(nm, name)) {
return 1; 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)) { if (!strcmp(name, PEM_STRING_EVP_PKEY)) {
return !strcmp(nm, PEM_STRING_PKCS8) || !strcmp(nm, PEM_STRING_PKCS8INF) || return !strcmp(nm, PEM_STRING_PKCS8) || !strcmp(nm, PEM_STRING_PKCS8INF) ||
@ -143,7 +143,7 @@ static int check_pem(const char *nm, const char *name) {
!strcmp(nm, PEM_STRING_DSA); !strcmp(nm, PEM_STRING_DSA);
} }
/* Permit older strings */ // Permit older strings
if (!strcmp(nm, PEM_STRING_X509_OLD) && !strcmp(name, PEM_STRING_X509)) { if (!strcmp(nm, PEM_STRING_X509_OLD) && !strcmp(name, PEM_STRING_X509)) {
return 1; return 1;
@ -154,7 +154,7 @@ static int check_pem(const char *nm, const char *name) {
return 1; return 1;
} }
/* Allow normal certs to be read as trusted certs */ // Allow normal certs to be read as trusted certs
if (!strcmp(nm, PEM_STRING_X509) && !strcmp(name, PEM_STRING_X509_TRUSTED)) { if (!strcmp(nm, PEM_STRING_X509) && !strcmp(name, PEM_STRING_X509_TRUSTED)) {
return 1; return 1;
} }
@ -164,7 +164,7 @@ static int check_pem(const char *nm, const char *name) {
return 1; return 1;
} }
/* Some CAs use PKCS#7 with CERTIFICATE headers */ // Some CAs use PKCS#7 with CERTIFICATE headers
if (!strcmp(nm, PEM_STRING_X509) && !strcmp(name, PEM_STRING_PKCS7)) { if (!strcmp(nm, PEM_STRING_X509) && !strcmp(name, PEM_STRING_PKCS7)) {
return 1; return 1;
} }
@ -177,7 +177,7 @@ static int check_pem(const char *nm, const char *name) {
if (!strcmp(nm, PEM_STRING_X509) && !strcmp(name, PEM_STRING_CMS)) { if (!strcmp(nm, PEM_STRING_X509) && !strcmp(name, PEM_STRING_CMS)) {
return 1; return 1;
} }
/* Allow CMS to be read from PKCS#7 headers */ // Allow CMS to be read from PKCS#7 headers
if (!strcmp(nm, PEM_STRING_PKCS7) && !strcmp(name, PEM_STRING_CMS)) { if (!strcmp(nm, PEM_STRING_PKCS7) && !strcmp(name, PEM_STRING_CMS)) {
return 1; return 1;
} }
@ -187,9 +187,9 @@ static int check_pem(const char *nm, const char *name) {
} }
static const EVP_CIPHER *cipher_by_name(const char *name) { static const EVP_CIPHER *cipher_by_name(const char *name) {
/* This is similar to the (deprecated) function |EVP_get_cipherbyname|. Note // 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 // 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. */ // bytes of overhead and generally behave like CBC mode.
if (0 == strcmp(name, SN_des_cbc)) { if (0 == strcmp(name, SN_des_cbc)) {
return EVP_des_cbc(); return EVP_des_cbc();
} else if (0 == strcmp(name, SN_des_ede3_cbc)) { } else if (0 == strcmp(name, SN_des_ede3_cbc)) {
@ -295,8 +295,8 @@ int PEM_ASN1_write_bio(i2d_of_void *i2d, const char *name, BIO *bp, void *x,
dsize = 0; dsize = 0;
goto err; goto err;
} }
/* dzise + 8 bytes are needed */ // dzise + 8 bytes are needed
/* actually it needs the cipher block size extra... */ // actually it needs the cipher block size extra...
data = (unsigned char *)OPENSSL_malloc((unsigned int)dsize + 20); data = (unsigned char *)OPENSSL_malloc((unsigned int)dsize + 20);
if (data == NULL) { if (data == NULL) {
OPENSSL_PUT_ERROR(PEM, ERR_R_MALLOC_FAILURE); OPENSSL_PUT_ERROR(PEM, ERR_R_MALLOC_FAILURE);
@ -321,13 +321,11 @@ int PEM_ASN1_write_bio(i2d_of_void *i2d, const char *name, BIO *bp, void *x,
kstr = (unsigned char *)buf; kstr = (unsigned char *)buf;
} }
assert(iv_len <= (int)sizeof(iv)); assert(iv_len <= (int)sizeof(iv));
if (!RAND_bytes(iv, iv_len)) { /* Generate a salt */ if (!RAND_bytes(iv, iv_len)) { // Generate a salt
goto err; goto err;
} }
/* // The 'iv' is used as the iv and as a salt. It is NOT taken from
* The 'iv' is used as the iv and as a salt. It is NOT taken from // the BytesToKey function
* the BytesToKey function
*/
if (!EVP_BytesToKey(enc, EVP_md5(), iv, kstr, klen, 1, key, NULL)) { if (!EVP_BytesToKey(enc, EVP_md5(), iv, kstr, klen, 1, key, NULL)) {
goto err; goto err;
} }
@ -341,7 +339,7 @@ int PEM_ASN1_write_bio(i2d_of_void *i2d, const char *name, BIO *bp, void *x,
buf[0] = '\0'; buf[0] = '\0';
PEM_proc_type(buf, PEM_TYPE_ENCRYPTED); PEM_proc_type(buf, PEM_TYPE_ENCRYPTED);
PEM_dek_info(buf, objstr, iv_len, (char *)iv); PEM_dek_info(buf, objstr, iv_len, (char *)iv);
/* k=strlen(buf); */ // k=strlen(buf);
EVP_CIPHER_CTX_init(&ctx); EVP_CIPHER_CTX_init(&ctx);
ret = 1; ret = 1;

@ -66,7 +66,7 @@
#include <openssl/rand.h> #include <openssl/rand.h>
#include <openssl/x509.h> #include <openssl/x509.h>
/* Handle 'other' PEMs: not private keys */ // Handle 'other' PEMs: not private keys
void *PEM_ASN1_read_bio(d2i_of_void *d2i, const char *name, BIO *bp, void **x, void *PEM_ASN1_read_bio(d2i_of_void *d2i, const char *name, BIO *bp, void **x,
pem_password_cb *cb, void *u) { pem_password_cb *cb, void *u) {

@ -71,12 +71,10 @@ static int do_pk8pkey_fp(FILE *bp, EVP_PKEY *x, int isder, int nid,
const EVP_CIPHER *enc, char *kstr, int klen, const EVP_CIPHER *enc, char *kstr, int klen,
pem_password_cb *cb, void *u); pem_password_cb *cb, void *u);
/* // These functions write a private key in PKCS#8 format: it is a "drop in"
* These functions write a private key in PKCS#8 format: it is a "drop in" // replacement for PEM_write_bio_PrivateKey() and friends. As usual if 'enc'
* replacement for PEM_write_bio_PrivateKey() and friends. As usual if 'enc' // is NULL then it uses the unencrypted private key form. The 'nid' versions
* is NULL then it uses the unencrypted private key form. The 'nid' versions // uses PKCS#5 v1.5 PBE algorithms whereas the others use PKCS#5 v2.0.
* 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 PEM_write_bio_PKCS8PrivateKey_nid(BIO *bp, EVP_PKEY *x, int nid, char *kstr,
int klen, pem_password_cb *cb, void *u) { int klen, pem_password_cb *cb, void *u) {

@ -130,9 +130,9 @@ EVP_PKEY *PEM_read_bio_PrivateKey(BIO *bp, EVP_PKEY **x, pem_password_cb *cb,
} }
PKCS8_PRIV_KEY_INFO_free(p8inf); PKCS8_PRIV_KEY_INFO_free(p8inf);
} else if (strcmp(nm, PEM_STRING_RSA) == 0) { } else if (strcmp(nm, PEM_STRING_RSA) == 0) {
/* TODO(davidben): d2i_PrivateKey parses PKCS#8 along with the // TODO(davidben): d2i_PrivateKey parses PKCS#8 along with the
* standalone format. This and the cases below probably should not // standalone format. This and the cases below probably should not
* accept PKCS#8. */ // accept PKCS#8.
ret = d2i_PrivateKey(EVP_PKEY_RSA, x, &p, len); ret = d2i_PrivateKey(EVP_PKEY_RSA, x, &p, len);
} else if (strcmp(nm, PEM_STRING_EC) == 0) { } else if (strcmp(nm, PEM_STRING_EC) == 0) {
ret = d2i_PrivateKey(EVP_PKEY_EC, x, &p, len); ret = d2i_PrivateKey(EVP_PKEY_EC, x, &p, len);

@ -85,7 +85,7 @@ int ASN1_item_sign_ctx(const ASN1_ITEM *it, X509_ALGOR *algor1,
pkey = EVP_PKEY_CTX_get0_pkey(ctx->pctx); pkey = EVP_PKEY_CTX_get0_pkey(ctx->pctx);
/* Write out the requested copies of the AlgorithmIdentifier. */ // Write out the requested copies of the AlgorithmIdentifier.
if (algor1 && !x509_digest_sign_algorithm(ctx, algor1)) { if (algor1 && !x509_digest_sign_algorithm(ctx, algor1)) {
goto err; goto err;
} }
@ -113,10 +113,8 @@ int ASN1_item_sign_ctx(const ASN1_ITEM *it, X509_ALGOR *algor1,
signature->data = buf_out; signature->data = buf_out;
buf_out = NULL; buf_out = NULL;
signature->length = outl; signature->length = outl;
/* // In the interests of compatibility, I'll make sure that the bit string
* In the interests of compatibility, I'll make sure that the bit string // has a 'not-used bits' value of 0
* has a 'not-used bits' value of 0
*/
signature->flags &= ~(ASN1_STRING_FLAG_BITS_LEFT | 0x07); signature->flags &= ~(ASN1_STRING_FLAG_BITS_LEFT | 0x07);
signature->flags |= ASN1_STRING_FLAG_BITS_LEFT; signature->flags |= ASN1_STRING_FLAG_BITS_LEFT;
err: err:

@ -64,7 +64,7 @@
#include "internal.h" #include "internal.h"
/* Restrict the digests that are allowed in X509 certificates */ // Restrict the digests that are allowed in X509 certificates
static int x509_digest_nid_ok(const int digest_nid) { static int x509_digest_nid_ok(const int digest_nid) {
switch (digest_nid) { switch (digest_nid) {
case NID_md4: case NID_md4:
@ -86,7 +86,7 @@ int x509_digest_sign_algorithm(EVP_MD_CTX *ctx, X509_ALGOR *algor) {
if (!EVP_PKEY_CTX_get_rsa_padding(ctx->pctx, &pad_mode)) { if (!EVP_PKEY_CTX_get_rsa_padding(ctx->pctx, &pad_mode)) {
return 0; return 0;
} }
/* RSA-PSS has special signature algorithm logic. */ // RSA-PSS has special signature algorithm logic.
if (pad_mode == RSA_PKCS1_PSS_PADDING) { if (pad_mode == RSA_PKCS1_PSS_PADDING) {
return x509_rsa_ctx_to_pss(ctx, algor); return x509_rsa_ctx_to_pss(ctx, algor);
} }
@ -96,8 +96,8 @@ int x509_digest_sign_algorithm(EVP_MD_CTX *ctx, X509_ALGOR *algor) {
return X509_ALGOR_set0(algor, OBJ_nid2obj(NID_ED25519), V_ASN1_UNDEF, NULL); return X509_ALGOR_set0(algor, OBJ_nid2obj(NID_ED25519), V_ASN1_UNDEF, NULL);
} }
/* Default behavior: look up the OID for the algorithm/hash pair and encode // Default behavior: look up the OID for the algorithm/hash pair and encode
* that. */ // that.
const EVP_MD *digest = EVP_MD_CTX_md(ctx); const EVP_MD *digest = EVP_MD_CTX_md(ctx);
if (digest == NULL) { if (digest == NULL) {
OPENSSL_PUT_ERROR(ASN1, ASN1_R_CONTEXT_NOT_INITIALISED); OPENSSL_PUT_ERROR(ASN1, ASN1_R_CONTEXT_NOT_INITIALISED);
@ -112,8 +112,8 @@ int x509_digest_sign_algorithm(EVP_MD_CTX *ctx, X509_ALGOR *algor) {
return 0; return 0;
} }
/* RSA signature algorithms include an explicit NULL parameter. Others omit // RSA signature algorithms include an explicit NULL parameter. Others omit
* it. */ // it.
int paramtype = int paramtype =
(EVP_PKEY_id(pkey) == EVP_PKEY_RSA) ? V_ASN1_NULL : V_ASN1_UNDEF; (EVP_PKEY_id(pkey) == EVP_PKEY_RSA) ? V_ASN1_NULL : V_ASN1_UNDEF;
X509_ALGOR_set0(algor, OBJ_nid2obj(sign_nid), paramtype, NULL); X509_ALGOR_set0(algor, OBJ_nid2obj(sign_nid), paramtype, NULL);
@ -122,7 +122,7 @@ int x509_digest_sign_algorithm(EVP_MD_CTX *ctx, X509_ALGOR *algor) {
int x509_digest_verify_init(EVP_MD_CTX *ctx, const X509_ALGOR *sigalg, int x509_digest_verify_init(EVP_MD_CTX *ctx, const X509_ALGOR *sigalg,
EVP_PKEY *pkey) { EVP_PKEY *pkey) {
/* Convert the signature OID into digest and public key OIDs. */ // Convert the signature OID into digest and public key OIDs.
int sigalg_nid = OBJ_obj2nid(sigalg->algorithm); int sigalg_nid = OBJ_obj2nid(sigalg->algorithm);
int digest_nid, pkey_nid; int digest_nid, pkey_nid;
if (!OBJ_find_sigid_algs(sigalg_nid, &digest_nid, &pkey_nid)) { if (!OBJ_find_sigid_algs(sigalg_nid, &digest_nid, &pkey_nid)) {
@ -130,19 +130,19 @@ int x509_digest_verify_init(EVP_MD_CTX *ctx, const X509_ALGOR *sigalg,
return 0; return 0;
} }
/* Check the public key OID matches the public key type. */ // Check the public key OID matches the public key type.
if (pkey_nid != EVP_PKEY_id(pkey)) { if (pkey_nid != EVP_PKEY_id(pkey)) {
OPENSSL_PUT_ERROR(ASN1, ASN1_R_WRONG_PUBLIC_KEY_TYPE); OPENSSL_PUT_ERROR(ASN1, ASN1_R_WRONG_PUBLIC_KEY_TYPE);
return 0; return 0;
} }
/* Check for permitted digest algorithms */ // Check for permitted digest algorithms
if (!x509_digest_nid_ok(digest_nid)) { if (!x509_digest_nid_ok(digest_nid)) {
OPENSSL_PUT_ERROR(ASN1, ASN1_R_DIGEST_AND_KEY_TYPE_NOT_SUPPORTED); OPENSSL_PUT_ERROR(ASN1, ASN1_R_DIGEST_AND_KEY_TYPE_NOT_SUPPORTED);
return 0; return 0;
} }
/* NID_undef signals that there are custom parameters to set. */ // NID_undef signals that there are custom parameters to set.
if (digest_nid == NID_undef) { if (digest_nid == NID_undef) {
if (sigalg_nid == NID_rsassaPss) { if (sigalg_nid == NID_rsassaPss) {
return x509_rsa_pss_to_ctx(ctx, sigalg, pkey); return x509_rsa_pss_to_ctx(ctx, sigalg, pkey);
@ -158,17 +158,17 @@ int x509_digest_verify_init(EVP_MD_CTX *ctx, const X509_ALGOR *sigalg,
return 0; return 0;
} }
/* The parameter should be an explicit NULL for RSA and omitted for ECDSA. For // The parameter should be an explicit NULL for RSA and omitted for ECDSA. For
* compatibility, we allow either for both algorithms. See b/167375496. // compatibility, we allow either for both algorithms. See b/167375496.
* //
* TODO(davidben): Chromium's verifier allows both forms for RSA, but enforces // TODO(davidben): Chromium's verifier allows both forms for RSA, but enforces
* ECDSA more strictly. Align with Chromium and add a flag for b/167375496. */ // ECDSA more strictly. Align with Chromium and add a flag for b/167375496.
if (sigalg->parameter != NULL && sigalg->parameter->type != V_ASN1_NULL) { if (sigalg->parameter != NULL && sigalg->parameter->type != V_ASN1_NULL) {
OPENSSL_PUT_ERROR(X509, X509_R_INVALID_PARAMETER); OPENSSL_PUT_ERROR(X509, X509_R_INVALID_PARAMETER);
return 0; return 0;
} }
/* Otherwise, initialize with the digest from the OID. */ // Otherwise, initialize with the digest from the OID.
const EVP_MD *digest = EVP_get_digestbynid(digest_nid); const EVP_MD *digest = EVP_get_digestbynid(digest_nid);
if (digest == NULL) { if (digest == NULL) {
OPENSSL_PUT_ERROR(ASN1, ASN1_R_UNKNOWN_MESSAGE_DIGEST_ALGORITHM); OPENSSL_PUT_ERROR(ASN1, ASN1_R_UNKNOWN_MESSAGE_DIGEST_ALGORITHM);

@ -68,10 +68,8 @@
#include "../x509v3/internal.h" #include "../x509v3/internal.h"
#include "internal.h" #include "internal.h"
/* // Although this file is in crypto/x509 for layering purposes, it emits
* Although this file is in crypto/x509 for layering purposes, it emits // errors from the ASN.1 module for OpenSSL compatibility.
* errors from the ASN.1 module for OpenSSL compatibility.
*/
#define ASN1_GEN_FLAG 0x10000 #define ASN1_GEN_FLAG 0x10000
#define ASN1_GEN_FLAG_IMP (ASN1_GEN_FLAG | 1) #define ASN1_GEN_FLAG_IMP (ASN1_GEN_FLAG | 1)
@ -87,18 +85,18 @@
{ str, sizeof(str) - 1, val } { str, sizeof(str) - 1, val }
#define ASN1_FLAG_EXP_MAX 20 #define ASN1_FLAG_EXP_MAX 20
/* Maximum number of nested sequences */ // Maximum number of nested sequences
#define ASN1_GEN_SEQ_MAX_DEPTH 50 #define ASN1_GEN_SEQ_MAX_DEPTH 50
/* Input formats */ // Input formats
/* ASCII: default */ // ASCII: default
#define ASN1_GEN_FORMAT_ASCII 1 #define ASN1_GEN_FORMAT_ASCII 1
/* UTF8 */ // UTF8
#define ASN1_GEN_FORMAT_UTF8 2 #define ASN1_GEN_FORMAT_UTF8 2
/* Hex */ // Hex
#define ASN1_GEN_FORMAT_HEX 3 #define ASN1_GEN_FORMAT_HEX 3
/* List of bits */ // List of bits
#define ASN1_GEN_FORMAT_BITLIST 4 #define ASN1_GEN_FORMAT_BITLIST 4
struct tag_name_st { struct tag_name_st {
@ -190,65 +188,61 @@ static ASN1_TYPE *generate_v3(const char *str, X509V3_CTX *cnf, int depth,
return NULL; return NULL;
} }
/* If no tagging return base type */ // If no tagging return base type
if ((asn1_tags.imp_tag == -1) && (asn1_tags.exp_count == 0)) { if ((asn1_tags.imp_tag == -1) && (asn1_tags.exp_count == 0)) {
return ret; return ret;
} }
/* Generate the encoding */ // Generate the encoding
cpy_len = i2d_ASN1_TYPE(ret, &orig_der); cpy_len = i2d_ASN1_TYPE(ret, &orig_der);
ASN1_TYPE_free(ret); ASN1_TYPE_free(ret);
ret = NULL; ret = NULL;
/* Set point to start copying for modified encoding */ // Set point to start copying for modified encoding
cpy_start = orig_der; cpy_start = orig_der;
/* Do we need IMPLICIT tagging? */ // Do we need IMPLICIT tagging?
if (asn1_tags.imp_tag != -1) { if (asn1_tags.imp_tag != -1) {
/* If IMPLICIT we will replace the underlying tag */ // If IMPLICIT we will replace the underlying tag
/* Skip existing tag+len */ // Skip existing tag+len
r = ASN1_get_object(&cpy_start, &hdr_len, &hdr_tag, &hdr_class, cpy_len); r = ASN1_get_object(&cpy_start, &hdr_len, &hdr_tag, &hdr_class, cpy_len);
if (r & 0x80) { if (r & 0x80) {
goto err; goto err;
} }
/* Update copy length */ // Update copy length
cpy_len -= cpy_start - orig_der; cpy_len -= cpy_start - orig_der;
/* // For IMPLICIT tagging the length should match the original length
* For IMPLICIT tagging the length should match the original length // and constructed flag should be consistent.
* and constructed flag should be consistent.
*/
hdr_constructed = r & V_ASN1_CONSTRUCTED; hdr_constructed = r & V_ASN1_CONSTRUCTED;
/* // Work out new length with IMPLICIT tag: ignore constructed because
* Work out new length with IMPLICIT tag: ignore constructed because // it will mess up if indefinite length
* it will mess up if indefinite length
*/
len = ASN1_object_size(0, hdr_len, asn1_tags.imp_tag); len = ASN1_object_size(0, hdr_len, asn1_tags.imp_tag);
} else { } else {
len = cpy_len; len = cpy_len;
} }
/* Work out length in any EXPLICIT, starting from end */ // Work out length in any EXPLICIT, starting from end
for (i = 0, etmp = asn1_tags.exp_list + asn1_tags.exp_count - 1; for (i = 0, etmp = asn1_tags.exp_list + asn1_tags.exp_count - 1;
i < asn1_tags.exp_count; i++, etmp--) { i < asn1_tags.exp_count; i++, etmp--) {
/* Content length: number of content octets + any padding */ // Content length: number of content octets + any padding
len += etmp->exp_pad; len += etmp->exp_pad;
etmp->exp_len = len; etmp->exp_len = len;
/* Total object length: length including new header */ // Total object length: length including new header
len = ASN1_object_size(0, len, etmp->exp_tag); len = ASN1_object_size(0, len, etmp->exp_tag);
} }
/* Allocate buffer for new encoding */ // Allocate buffer for new encoding
new_der = OPENSSL_malloc(len); new_der = OPENSSL_malloc(len);
if (!new_der) { if (!new_der) {
goto err; goto err;
} }
/* Generate tagged encoding */ // Generate tagged encoding
p = new_der; p = new_der;
/* Output explicit tags first */ // Output explicit tags first
for (i = 0, etmp = asn1_tags.exp_list; i < asn1_tags.exp_count; i++, etmp++) { 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, ASN1_put_object(&p, etmp->exp_constructed, etmp->exp_len, etmp->exp_tag,
@ -258,7 +252,7 @@ static ASN1_TYPE *generate_v3(const char *str, X509V3_CTX *cnf, int depth,
} }
} }
/* If IMPLICIT, output tag */ // If IMPLICIT, output tag
if (asn1_tags.imp_tag != -1) { if (asn1_tags.imp_tag != -1) {
if (asn1_tags.imp_class == V_ASN1_UNIVERSAL && if (asn1_tags.imp_class == V_ASN1_UNIVERSAL &&
@ -270,12 +264,12 @@ static ASN1_TYPE *generate_v3(const char *str, X509V3_CTX *cnf, int depth,
asn1_tags.imp_class); asn1_tags.imp_class);
} }
/* Copy across original encoding */ // Copy across original encoding
OPENSSL_memcpy(p, cpy_start, cpy_len); OPENSSL_memcpy(p, cpy_start, cpy_len);
cp = new_der; cp = new_der;
/* Obtain new ASN1_TYPE structure */ // Obtain new ASN1_TYPE structure
ret = d2i_ASN1_TYPE(NULL, &cp, len); ret = d2i_ASN1_TYPE(NULL, &cp, len);
err: err:
@ -303,7 +297,7 @@ static int asn1_cb(const char *elem, int len, void *bitstr) {
} }
for (i = 0, p = elem; i < len; p++, i++) { for (i = 0, p = elem; i < len; p++, i++) {
/* Look for the ':' in name value pairs */ // Look for the ':' in name value pairs
if (*p == ':') { if (*p == ':') {
vstart = p + 1; vstart = p + 1;
vlen = len - (vstart - elem); vlen = len - (vstart - elem);
@ -320,11 +314,11 @@ static int asn1_cb(const char *elem, int len, void *bitstr) {
return -1; return -1;
} }
/* If this is not a modifier mark end of string and exit */ // If this is not a modifier mark end of string and exit
if (!(utype & ASN1_GEN_FLAG)) { if (!(utype & ASN1_GEN_FLAG)) {
arg->utype = utype; arg->utype = utype;
arg->str = vstart; arg->str = vstart;
/* If no value and not end of string, error */ // If no value and not end of string, error
if (!vstart && elem[len]) { if (!vstart && elem[len]) {
OPENSSL_PUT_ERROR(ASN1, ASN1_R_MISSING_VALUE); OPENSSL_PUT_ERROR(ASN1, ASN1_R_MISSING_VALUE);
return -1; return -1;
@ -334,7 +328,7 @@ static int asn1_cb(const char *elem, int len, void *bitstr) {
switch (utype) { switch (utype) {
case ASN1_GEN_FLAG_IMP: case ASN1_GEN_FLAG_IMP:
/* Check for illegal multiple IMPLICIT tagging */ // Check for illegal multiple IMPLICIT tagging
if (arg->imp_tag != -1) { if (arg->imp_tag != -1) {
OPENSSL_PUT_ERROR(ASN1, ASN1_R_ILLEGAL_NESTED_TAGGING); OPENSSL_PUT_ERROR(ASN1, ASN1_R_ILLEGAL_NESTED_TAGGING);
return -1; return -1;
@ -409,7 +403,7 @@ static int parse_tagging(const char *vstart, int vlen, int *ptag, int *pclass) {
return 0; return 0;
} }
tag_num = strtoul(vstart, &eptr, 10); tag_num = strtoul(vstart, &eptr, 10);
/* Check we haven't gone past max length: should be impossible */ // Check we haven't gone past max length: should be impossible
if (eptr && *eptr && (eptr > vstart + vlen)) { if (eptr && *eptr && (eptr > vstart + vlen)) {
return 0; return 0;
} }
@ -418,7 +412,7 @@ static int parse_tagging(const char *vstart, int vlen, int *ptag, int *pclass) {
return 0; return 0;
} }
*ptag = tag_num; *ptag = tag_num;
/* If we have non numeric characters, parse them */ // If we have non numeric characters, parse them
if (eptr) { if (eptr) {
vlen -= eptr - vstart; vlen -= eptr - vstart;
} else { } else {
@ -457,7 +451,7 @@ static int parse_tagging(const char *vstart, int vlen, int *ptag, int *pclass) {
return 1; return 1;
} }
/* Handle multiple types: SET and SEQUENCE */ // Handle multiple types: SET and SEQUENCE
static ASN1_TYPE *asn1_multi(int utype, const char *section, X509V3_CTX *cnf, static ASN1_TYPE *asn1_multi(int utype, const char *section, X509V3_CTX *cnf,
int depth, int *perr) { int depth, int *perr) {
@ -491,9 +485,7 @@ static ASN1_TYPE *asn1_multi(int utype, const char *section, X509V3_CTX *cnf,
} }
} }
/* // 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) { if (utype == V_ASN1_SET) {
derlen = i2d_ASN1_SET_ANY(sk, &der); derlen = i2d_ASN1_SET_ANY(sk, &der);
@ -539,7 +531,7 @@ bad:
static int append_exp(tag_exp_arg *arg, int exp_tag, int exp_class, static int append_exp(tag_exp_arg *arg, int exp_tag, int exp_class,
int exp_constructed, int exp_pad, int imp_ok) { int exp_constructed, int exp_pad, int imp_ok) {
tag_exp_type *exp_tmp; tag_exp_type *exp_tmp;
/* Can only have IMPLICIT if permitted */ // Can only have IMPLICIT if permitted
if ((arg->imp_tag != -1) && !imp_ok) { if ((arg->imp_tag != -1) && !imp_ok) {
OPENSSL_PUT_ERROR(ASN1, ASN1_R_ILLEGAL_IMPLICIT_TAG); OPENSSL_PUT_ERROR(ASN1, ASN1_R_ILLEGAL_IMPLICIT_TAG);
return 0; return 0;
@ -552,10 +544,8 @@ static int append_exp(tag_exp_arg *arg, int exp_tag, int exp_class,
exp_tmp = &arg->exp_list[arg->exp_count++]; exp_tmp = &arg->exp_list[arg->exp_count++];
/* // If IMPLICIT set tag to implicit value then reset implicit tag since it
* If IMPLICIT set tag to implicit value then reset implicit tag since it // has been used.
* has been used.
*/
if (arg->imp_tag != -1) { if (arg->imp_tag != -1) {
exp_tmp->exp_tag = arg->imp_tag; exp_tmp->exp_tag = arg->imp_tag;
exp_tmp->exp_class = arg->imp_class; exp_tmp->exp_class = arg->imp_class;
@ -612,24 +602,24 @@ static int asn1_str2tag(const char *tagstr, int len) {
ASN1_GEN_STR("NUMERIC", V_ASN1_NUMERICSTRING), ASN1_GEN_STR("NUMERIC", V_ASN1_NUMERICSTRING),
ASN1_GEN_STR("NUMERICSTRING", V_ASN1_NUMERICSTRING), ASN1_GEN_STR("NUMERICSTRING", V_ASN1_NUMERICSTRING),
/* Special cases */ // Special cases
ASN1_GEN_STR("SEQUENCE", V_ASN1_SEQUENCE), ASN1_GEN_STR("SEQUENCE", V_ASN1_SEQUENCE),
ASN1_GEN_STR("SEQ", V_ASN1_SEQUENCE), ASN1_GEN_STR("SEQ", V_ASN1_SEQUENCE),
ASN1_GEN_STR("SET", V_ASN1_SET), ASN1_GEN_STR("SET", V_ASN1_SET),
/* type modifiers */ // type modifiers
/* Explicit tag */ // Explicit tag
ASN1_GEN_STR("EXP", ASN1_GEN_FLAG_EXP), ASN1_GEN_STR("EXP", ASN1_GEN_FLAG_EXP),
ASN1_GEN_STR("EXPLICIT", ASN1_GEN_FLAG_EXP), ASN1_GEN_STR("EXPLICIT", ASN1_GEN_FLAG_EXP),
/* Implicit tag */ // Implicit tag
ASN1_GEN_STR("IMP", ASN1_GEN_FLAG_IMP), ASN1_GEN_STR("IMP", ASN1_GEN_FLAG_IMP),
ASN1_GEN_STR("IMPLICIT", ASN1_GEN_FLAG_IMP), ASN1_GEN_STR("IMPLICIT", ASN1_GEN_FLAG_IMP),
/* OCTET STRING wrapper */ // OCTET STRING wrapper
ASN1_GEN_STR("OCTWRAP", ASN1_GEN_FLAG_OCTWRAP), ASN1_GEN_STR("OCTWRAP", ASN1_GEN_FLAG_OCTWRAP),
/* SEQUENCE wrapper */ // SEQUENCE wrapper
ASN1_GEN_STR("SEQWRAP", ASN1_GEN_FLAG_SEQWRAP), ASN1_GEN_STR("SEQWRAP", ASN1_GEN_FLAG_SEQWRAP),
/* SET wrapper */ // SET wrapper
ASN1_GEN_STR("SETWRAP", ASN1_GEN_FLAG_SETWRAP), ASN1_GEN_STR("SETWRAP", ASN1_GEN_FLAG_SETWRAP),
/* BIT STRING wrapper */ // BIT STRING wrapper
ASN1_GEN_STR("BITWRAP", ASN1_GEN_FLAG_BITWRAP), ASN1_GEN_STR("BITWRAP", ASN1_GEN_FLAG_BITWRAP),
ASN1_GEN_STR("FORM", ASN1_GEN_FLAG_FORMAT), ASN1_GEN_STR("FORM", ASN1_GEN_FLAG_FORMAT),
ASN1_GEN_STR("FORMAT", ASN1_GEN_FLAG_FORMAT), ASN1_GEN_STR("FORMAT", ASN1_GEN_FLAG_FORMAT),

@ -98,15 +98,15 @@ static int get_cert_by_subject(X509_LOOKUP *xl, int type, X509_NAME *name,
X509_OBJECT *ret); X509_OBJECT *ret);
static X509_LOOKUP_METHOD x509_dir_lookup = { static X509_LOOKUP_METHOD x509_dir_lookup = {
"Load certs from files in a directory", "Load certs from files in a directory",
new_dir, /* new */ new_dir, // new
free_dir, /* free */ free_dir, // free
NULL, /* init */ NULL, // init
NULL, /* shutdown */ NULL, // shutdown
dir_ctrl, /* ctrl */ dir_ctrl, // ctrl
get_cert_by_subject, /* get_by_subject */ get_cert_by_subject, // get_by_subject
NULL, /* get_by_issuer_serial */ NULL, // get_by_issuer_serial
NULL, /* get_by_fingerprint */ NULL, // get_by_fingerprint
NULL, /* get_by_alias */ 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); }
@ -247,10 +247,8 @@ static int add_cert_dir(BY_DIR *ctx, const char *dir, int type) {
return 1; return 1;
} }
/* // g_ent_hashes_lock protects the |hashes| member of all |BY_DIR_ENTRY|
* g_ent_hashes_lock protects the |hashes| member of all |BY_DIR_ENTRY| // objects.
* 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, static int get_cert_by_subject(X509_LOOKUP *xl, int type, X509_NAME *name,
@ -337,23 +335,19 @@ static int get_cert_by_subject(X509_LOOKUP *xl, int type, X509_NAME *name,
#ifdef OPENSSL_SYS_VMS #ifdef OPENSSL_SYS_VMS
c = ent->dir[strlen(ent->dir) - 1]; c = ent->dir[strlen(ent->dir) - 1];
if (c != ':' && c != '>' && c != ']') { if (c != ':' && c != '>' && c != ']') {
/* // If no separator is present, we assume the directory
* If no separator is present, we assume the directory // specifier is a logical name, and add a colon. We
* specifier is a logical name, and add a colon. We // really should use better VMS routines for merging
* really should use better VMS routines for merging // things like this, but this will do for now... --
* things like this, but this will do for now... -- // Richard Levitte
* Richard Levitte
*/
c = ':'; c = ':';
} else { } else {
c = '\0'; c = '\0';
} }
#endif #endif
if (c == '\0') { if (c == '\0') {
/* // This is special. When c == '\0', no directory
* This is special. When c == '\0', no directory // separator should be added.
* separator should be added.
*/
BIO_snprintf(b->data, b->max, "%s%08lx.%s%d", ent->dir, h, postfix, BIO_snprintf(b->data, b->max, "%s%08lx.%s%d", ent->dir, h, postfix,
k); k);
} else { } else {
@ -371,7 +365,7 @@ static int get_cert_by_subject(X509_LOOKUP *xl, int type, X509_NAME *name,
} }
} }
#endif #endif
/* found one. */ // found one.
if (type == X509_LU_X509) { if (type == X509_LU_X509) {
if ((X509_load_cert_file(xl, b->data, ent->dir_type)) == 0) { if ((X509_load_cert_file(xl, b->data, ent->dir_type)) == 0) {
break; break;
@ -381,13 +375,11 @@ static int get_cert_by_subject(X509_LOOKUP *xl, int type, X509_NAME *name,
break; break;
} }
} }
/* else case will caught higher up */ // else case will caught higher up
k++; k++;
} }
/* // we have added it to the cache so now pull it out again
* we have added it to the cache so now pull it out again
*/
CRYPTO_MUTEX_lock_write(&xl->store_ctx->objs_lock); CRYPTO_MUTEX_lock_write(&xl->store_ctx->objs_lock);
tmp = NULL; tmp = NULL;
sk_X509_OBJECT_sort(xl->store_ctx->objs); sk_X509_OBJECT_sort(xl->store_ctx->objs);
@ -396,16 +388,12 @@ static int get_cert_by_subject(X509_LOOKUP *xl, int type, X509_NAME *name,
} }
CRYPTO_MUTEX_unlock_write(&xl->store_ctx->objs_lock); CRYPTO_MUTEX_unlock_write(&xl->store_ctx->objs_lock);
/* // If a CRL, update the last file suffix added for this
* If a CRL, update the last file suffix added for this
*/
if (type == X509_LU_CRL) { if (type == X509_LU_CRL) {
CRYPTO_STATIC_MUTEX_lock_write(&g_ent_hashes_lock); CRYPTO_STATIC_MUTEX_lock_write(&g_ent_hashes_lock);
/* // Look for entry again in case another thread added an entry
* Look for entry again in case another thread added an entry // first.
* first.
*/
if (!hent) { if (!hent) {
htmp.hash = h; htmp.hash = h;
sk_BY_DIR_HASH_sort(ent->hashes); sk_BY_DIR_HASH_sort(ent->hashes);
@ -441,20 +429,15 @@ static int get_cert_by_subject(X509_LOOKUP *xl, int type, X509_NAME *name,
ret->type = tmp->type; ret->type = tmp->type;
OPENSSL_memcpy(&ret->data, &tmp->data, sizeof(ret->data)); OPENSSL_memcpy(&ret->data, &tmp->data, sizeof(ret->data));
/* // Clear any errors that might have been raised processing empty
* Clear any errors that might have been raised processing empty // or malformed files.
* or malformed files.
*/
ERR_clear_error(); ERR_clear_error();
/* // If we were going to up the reference count, we would need
* If we were going to up the reference count, we would need // to do it on a perl 'type' basis
* to do it on a perl 'type' basis //
*/ // CRYPTO_add(&tmp->data.x509->references,1,
/* // CRYPTO_LOCK_X509);
* CRYPTO_add(&tmp->data.x509->references,1,
* CRYPTO_LOCK_X509);
*/
goto finish; goto finish;
} }
} }

@ -69,15 +69,15 @@ static int by_file_ctrl(X509_LOOKUP *ctx, int cmd, const char *argc, long argl,
char **ret); char **ret);
static X509_LOOKUP_METHOD x509_file_lookup = { static X509_LOOKUP_METHOD x509_file_lookup = {
"Load file into cache", "Load file into cache",
NULL, /* new */ NULL, // new
NULL, /* free */ NULL, // free
NULL, /* init */ NULL, // init
NULL, /* shutdown */ NULL, // shutdown
by_file_ctrl, /* ctrl */ by_file_ctrl, // ctrl
NULL, /* get_by_subject */ NULL, // get_by_subject
NULL, /* get_by_issuer_serial */ NULL, // get_by_issuer_serial
NULL, /* get_by_fingerprint */ NULL, // get_by_fingerprint
NULL, /* get_by_alias */ 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); }
@ -291,4 +291,4 @@ err:
return count; return count;
} }
#endif /* OPENSSL_NO_STDIO */ #endif // OPENSSL_NO_STDIO

@ -72,10 +72,8 @@ int i2d_PrivateKey(const EVP_PKEY *a, uint8_t **pp) {
case EVP_PKEY_DSA: case EVP_PKEY_DSA:
return i2d_DSAPrivateKey(a->pkey.dsa, pp); return i2d_DSAPrivateKey(a->pkey.dsa, pp);
default: default:
/* // Although this file is in crypto/x509 for layering reasons, it emits
* Although this file is in crypto/x509 for layering reasons, it emits // an error code from ASN1 for OpenSSL compatibility.
* an error code from ASN1 for OpenSSL compatibility.
*/
OPENSSL_PUT_ERROR(ASN1, ASN1_R_UNSUPPORTED_PUBLIC_KEY_TYPE); OPENSSL_PUT_ERROR(ASN1, ASN1_R_UNSUPPORTED_PUBLIC_KEY_TYPE);
return -1; return -1;
} }

@ -70,7 +70,7 @@ extern "C" {
#endif #endif
/* Internal structures. */ // Internal structures.
typedef struct X509_val_st { typedef struct X509_val_st {
ASN1_TIME *notBefore; ASN1_TIME *notBefore;
@ -372,44 +372,44 @@ ASN1_TYPE *ASN1_generate_v3(const char *str, X509V3_CTX *cnf);
int X509_CERT_AUX_print(BIO *bp, X509_CERT_AUX *x, int indent); int X509_CERT_AUX_print(BIO *bp, X509_CERT_AUX *x, int indent);
/* RSA-PSS functions. */ // RSA-PSS functions.
/* x509_rsa_pss_to_ctx configures |ctx| for an RSA-PSS operation based on // x509_rsa_pss_to_ctx configures |ctx| for an RSA-PSS operation based on
* signature algorithm parameters in |sigalg| (which must have type // signature algorithm parameters in |sigalg| (which must have type
* |NID_rsassaPss|) and key |pkey|. It returns one on success and zero on // |NID_rsassaPss|) and key |pkey|. It returns one on success and zero on
* error. */ // error.
int x509_rsa_pss_to_ctx(EVP_MD_CTX *ctx, const X509_ALGOR *sigalg, int x509_rsa_pss_to_ctx(EVP_MD_CTX *ctx, const X509_ALGOR *sigalg,
EVP_PKEY *pkey); EVP_PKEY *pkey);
/* x509_rsa_pss_to_ctx sets |algor| to the signature algorithm parameters for // x509_rsa_pss_to_ctx sets |algor| to the signature algorithm parameters for
* |ctx|, which must have been configured for an RSA-PSS signing operation. It // |ctx|, which must have been configured for an RSA-PSS signing operation. It
* returns one on success and zero on error. */ // returns one on success and zero on error.
int x509_rsa_ctx_to_pss(EVP_MD_CTX *ctx, X509_ALGOR *algor); int x509_rsa_ctx_to_pss(EVP_MD_CTX *ctx, X509_ALGOR *algor);
/* x509_print_rsa_pss_params prints a human-readable representation of RSA-PSS // x509_print_rsa_pss_params prints a human-readable representation of RSA-PSS
* parameters in |sigalg| to |bp|. It returns one on success and zero on // parameters in |sigalg| to |bp|. It returns one on success and zero on
* error. */ // error.
int x509_print_rsa_pss_params(BIO *bp, const X509_ALGOR *sigalg, int indent, int x509_print_rsa_pss_params(BIO *bp, const X509_ALGOR *sigalg, int indent,
ASN1_PCTX *pctx); ASN1_PCTX *pctx);
/* Signature algorithm functions. */ // Signature algorithm functions.
/* x509_digest_sign_algorithm encodes the signing parameters of |ctx| as an // x509_digest_sign_algorithm encodes the signing parameters of |ctx| as an
* AlgorithmIdentifer and saves the result in |algor|. It returns one on // AlgorithmIdentifer and saves the result in |algor|. It returns one on
* success, or zero on error. */ // success, or zero on error.
int x509_digest_sign_algorithm(EVP_MD_CTX *ctx, X509_ALGOR *algor); int x509_digest_sign_algorithm(EVP_MD_CTX *ctx, X509_ALGOR *algor);
/* x509_digest_verify_init sets up |ctx| for a signature verification operation // x509_digest_verify_init sets up |ctx| for a signature verification operation
* with public key |pkey| and parameters from |algor|. The |ctx| argument must // with public key |pkey| and parameters from |algor|. The |ctx| argument must
* have been initialised with |EVP_MD_CTX_init|. It returns one on success, or // have been initialised with |EVP_MD_CTX_init|. It returns one on success, or
* zero on error. */ // zero on error.
int x509_digest_verify_init(EVP_MD_CTX *ctx, const X509_ALGOR *sigalg, int x509_digest_verify_init(EVP_MD_CTX *ctx, const X509_ALGOR *sigalg,
EVP_PKEY *pkey); EVP_PKEY *pkey);
#if defined(__cplusplus) #if defined(__cplusplus)
} /* extern C */ } // extern C
#endif #endif
#endif /* OPENSSL_HEADER_X509_INTERNAL_H */ #endif // OPENSSL_HEADER_X509_INTERNAL_H

@ -65,11 +65,11 @@
static int maybe_write(BIO *out, const void *buf, int len) { static int maybe_write(BIO *out, const void *buf, int len) {
/* If |out| is NULL, ignore the output but report the length. */ // If |out| is NULL, ignore the output but report the length.
return out == NULL || BIO_write(out, buf, len) == len; return out == NULL || BIO_write(out, buf, len) == len;
} }
/* do_indent prints |indent| spaces to |out|. */ // do_indent prints |indent| spaces to |out|.
static int do_indent(BIO *out, int indent) { static int do_indent(BIO *out, int indent) {
for (int i = 0; i < indent; i++) { for (int i = 0; i < indent; i++) {
if (!maybe_write(out, " ", 1)) { if (!maybe_write(out, " ", 1)) {
@ -179,7 +179,7 @@ static int do_name_ex(BIO *out, const X509_NAME *n, int indent,
int objlen, fld_len; int objlen, fld_len;
if ((fn_opt == XN_FLAG_FN_OID) || (fn_nid == NID_undef)) { if ((fn_opt == XN_FLAG_FN_OID) || (fn_nid == NID_undef)) {
OBJ_obj2txt(objtmp, sizeof objtmp, fn, 1); OBJ_obj2txt(objtmp, sizeof objtmp, fn, 1);
fld_len = 0; /* XXX: what should this be? */ fld_len = 0; // XXX: what should this be?
objbuf = objtmp; objbuf = objtmp;
} else { } else {
if (fn_opt == XN_FLAG_FN_SN) { if (fn_opt == XN_FLAG_FN_SN) {
@ -189,7 +189,7 @@ static int do_name_ex(BIO *out, const X509_NAME *n, int indent,
fld_len = FN_WIDTH_LN; fld_len = FN_WIDTH_LN;
objbuf = OBJ_nid2ln(fn_nid); objbuf = OBJ_nid2ln(fn_nid);
} else { } else {
fld_len = 0; /* XXX: what should this be? */ fld_len = 0; // XXX: what should this be?
objbuf = ""; objbuf = "";
} }
} }
@ -208,11 +208,9 @@ static int do_name_ex(BIO *out, const X509_NAME *n, int indent,
} }
outlen += objlen + sep_eq_len; outlen += objlen + sep_eq_len;
} }
/* // If the field name is unknown then fix up the DER dump flag. We
* 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
* might want to limit this further so it will DER dump on anything // other than a few 'standard' fields.
* other than a few 'standard' fields.
*/
if ((fn_nid == NID_undef) && (flags & XN_FLAG_DUMP_UNKNOWN_FIELDS)) { if ((fn_nid == NID_undef) && (flags & XN_FLAG_DUMP_UNKNOWN_FIELDS)) {
orflags = ASN1_STRFLGS_DUMP_ALL; orflags = ASN1_STRFLGS_DUMP_ALL;
} else { } else {
@ -240,8 +238,8 @@ int X509_NAME_print_ex_fp(FILE *fp, const X509_NAME *nm, int indent,
unsigned long flags) { unsigned long flags) {
BIO *bio = NULL; BIO *bio = NULL;
if (fp != NULL) { if (fp != NULL) {
/* If |fp| is NULL, this function returns the number of bytes without // If |fp| is NULL, this function returns the number of bytes without
* writing. */ // writing.
bio = BIO_new_fp(fp, BIO_NOCLOSE); bio = BIO_new_fp(fp, BIO_NOCLOSE);
if (bio == NULL) { if (bio == NULL) {
return -1; return -1;

@ -86,7 +86,7 @@ ASN1_SEQUENCE_cb(RSA_PSS_PARAMS, rsa_pss_cb) = {
IMPLEMENT_ASN1_FUNCTIONS(RSA_PSS_PARAMS) IMPLEMENT_ASN1_FUNCTIONS(RSA_PSS_PARAMS)
/* Given an MGF1 Algorithm ID decode to an Algorithm Identifier */ // Given an MGF1 Algorithm ID decode to an Algorithm Identifier
static X509_ALGOR *rsa_mgf1_decode(X509_ALGOR *alg) { static X509_ALGOR *rsa_mgf1_decode(X509_ALGOR *alg) {
if (alg == NULL || alg->parameter == NULL || if (alg == NULL || alg->parameter == NULL ||
OBJ_obj2nid(alg->algorithm) != NID_mgf1 || OBJ_obj2nid(alg->algorithm) != NID_mgf1 ||
@ -118,7 +118,7 @@ static RSA_PSS_PARAMS *rsa_pss_decode(const X509_ALGOR *alg,
return pss; return pss;
} }
/* allocate and set algorithm ID from EVP_MD, default SHA1 */ // allocate and set algorithm ID from EVP_MD, default SHA1
static int rsa_md_to_algor(X509_ALGOR **palg, const EVP_MD *md) { static int rsa_md_to_algor(X509_ALGOR **palg, const EVP_MD *md) {
if (EVP_MD_type(md) == NID_sha1) { if (EVP_MD_type(md) == NID_sha1) {
return 1; return 1;
@ -131,7 +131,7 @@ static int rsa_md_to_algor(X509_ALGOR **palg, const EVP_MD *md) {
return 1; return 1;
} }
/* Allocate and set MGF1 algorithm ID from EVP_MD */ // Allocate and set MGF1 algorithm ID from EVP_MD
static int rsa_md_to_mgf1(X509_ALGOR **palg, const EVP_MD *mgf1md) { static int rsa_md_to_mgf1(X509_ALGOR **palg, const EVP_MD *mgf1md) {
X509_ALGOR *algtmp = NULL; X509_ALGOR *algtmp = NULL;
ASN1_STRING *stmp = NULL; ASN1_STRING *stmp = NULL;
@ -140,7 +140,7 @@ static int rsa_md_to_mgf1(X509_ALGOR **palg, const EVP_MD *mgf1md) {
if (EVP_MD_type(mgf1md) == NID_sha1) { if (EVP_MD_type(mgf1md) == NID_sha1) {
return 1; return 1;
} }
/* need to embed algorithm ID inside another */ // need to embed algorithm ID inside another
if (!rsa_md_to_algor(&algtmp, mgf1md) || if (!rsa_md_to_algor(&algtmp, mgf1md) ||
!ASN1_item_pack(algtmp, ASN1_ITEM_rptr(X509_ALGOR), &stmp)) { !ASN1_item_pack(algtmp, ASN1_ITEM_rptr(X509_ALGOR), &stmp)) {
goto err; goto err;
@ -162,7 +162,7 @@ err:
return 0; return 0;
} }
/* convert algorithm ID to EVP_MD, default SHA1 */ // convert algorithm ID to EVP_MD, default SHA1
static const EVP_MD *rsa_algor_to_md(X509_ALGOR *alg) { static const EVP_MD *rsa_algor_to_md(X509_ALGOR *alg) {
const EVP_MD *md; const EVP_MD *md;
if (!alg) { if (!alg) {
@ -175,14 +175,14 @@ static const EVP_MD *rsa_algor_to_md(X509_ALGOR *alg) {
return md; return md;
} }
/* convert MGF1 algorithm ID to EVP_MD, default SHA1 */ // convert MGF1 algorithm ID to EVP_MD, default SHA1
static const EVP_MD *rsa_mgf1_to_md(const X509_ALGOR *alg, static const EVP_MD *rsa_mgf1_to_md(const X509_ALGOR *alg,
X509_ALGOR *maskHash) { X509_ALGOR *maskHash) {
const EVP_MD *md; const EVP_MD *md;
if (!alg) { if (!alg) {
return EVP_sha1(); return EVP_sha1();
} }
/* Check mask and lookup mask hash algorithm */ // 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); OPENSSL_PUT_ERROR(X509, X509_R_INVALID_PSS_PARAMETERS);
return NULL; return NULL;
@ -239,7 +239,7 @@ int x509_rsa_ctx_to_pss(EVP_MD_CTX *ctx, X509_ALGOR *algor) {
goto err; goto err;
} }
/* Finally create string with pss parameter encoding. */ // Finally create string with pss parameter encoding.
if (!ASN1_item_pack(pss, ASN1_ITEM_rptr(RSA_PSS_PARAMS), &os)) { if (!ASN1_item_pack(pss, ASN1_ITEM_rptr(RSA_PSS_PARAMS), &os)) {
goto err; goto err;
} }
@ -258,7 +258,7 @@ int x509_rsa_pss_to_ctx(EVP_MD_CTX *ctx, const X509_ALGOR *sigalg,
EVP_PKEY *pkey) { EVP_PKEY *pkey) {
assert(OBJ_obj2nid(sigalg->algorithm) == NID_rsassaPss); assert(OBJ_obj2nid(sigalg->algorithm) == NID_rsassaPss);
/* Decode PSS parameters */ // Decode PSS parameters
int ret = 0; int ret = 0;
X509_ALGOR *maskHash; X509_ALGOR *maskHash;
RSA_PSS_PARAMS *pss = rsa_pss_decode(sigalg, &maskHash); RSA_PSS_PARAMS *pss = rsa_pss_decode(sigalg, &maskHash);
@ -277,16 +277,16 @@ int x509_rsa_pss_to_ctx(EVP_MD_CTX *ctx, const X509_ALGOR *sigalg,
if (pss->saltLength != NULL) { if (pss->saltLength != NULL) {
saltlen = ASN1_INTEGER_get(pss->saltLength); saltlen = ASN1_INTEGER_get(pss->saltLength);
/* Could perform more salt length sanity checks but the main // Could perform more salt length sanity checks but the main
* RSA routines will trap other invalid values anyway. */ // RSA routines will trap other invalid values anyway.
if (saltlen < 0) { if (saltlen < 0) {
OPENSSL_PUT_ERROR(X509, X509_R_INVALID_PSS_PARAMETERS); OPENSSL_PUT_ERROR(X509, X509_R_INVALID_PSS_PARAMETERS);
goto err; goto err;
} }
} }
/* low-level routines support only trailer field 0xbc (value 1) // low-level routines support only trailer field 0xbc (value 1)
* and PKCS#1 says we should reject any other value anyway. */ // and PKCS#1 says we should reject any other value anyway.
if (pss->trailerField != NULL && ASN1_INTEGER_get(pss->trailerField) != 1) { if (pss->trailerField != NULL && ASN1_INTEGER_get(pss->trailerField) != 1) {
OPENSSL_PUT_ERROR(X509, X509_R_INVALID_PSS_PARAMETERS); OPENSSL_PUT_ERROR(X509, X509_R_INVALID_PSS_PARAMETERS);
goto err; goto err;

@ -139,7 +139,7 @@ int X509_print_ex(BIO *bp, X509 *x, unsigned long nmflags,
goto err; goto err;
} }
} else { } else {
ERR_clear_error(); /* Clear |ASN1_INTEGER_get_uint64|'s error. */ ERR_clear_error(); // Clear |ASN1_INTEGER_get_uint64|'s error.
neg = (serial->type == V_ASN1_NEG_INTEGER) ? " (Negative)" : ""; neg = (serial->type == V_ASN1_NEG_INTEGER) ? " (Negative)" : "";
if (BIO_printf(bp, "\n%12s%s", "", neg) <= 0) { if (BIO_printf(bp, "\n%12s%s", "", neg) <= 0) {
goto err; goto err;
@ -276,9 +276,7 @@ int X509_ocspid_print(BIO *bp, X509 *x) {
int i; int i;
unsigned char SHA1md[SHA_DIGEST_LENGTH]; unsigned char SHA1md[SHA_DIGEST_LENGTH];
/* // display the hash of the subject as it would appear in OCSP requests
* display the hash of the subject as it would appear in OCSP requests
*/
if (BIO_printf(bp, " Subject OCSP hash: ") <= 0) { if (BIO_printf(bp, " Subject OCSP hash: ") <= 0) {
goto err; goto err;
} }
@ -299,9 +297,7 @@ int X509_ocspid_print(BIO *bp, X509 *x) {
OPENSSL_free(der); OPENSSL_free(der);
der = NULL; der = NULL;
/* // display the hash of the public key as it would appear in OCSP requests
* 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 (BIO_printf(bp, "\n Public key OCSP hash: ") <= 0) {
goto err; goto err;
} }
@ -335,7 +331,7 @@ int X509_signature_print(BIO *bp, const X509_ALGOR *sigalg,
return 0; return 0;
} }
/* RSA-PSS signatures have parameters to print. */ // RSA-PSS signatures have parameters to print.
int sig_nid = OBJ_obj2nid(sigalg->algorithm); int sig_nid = OBJ_obj2nid(sigalg->algorithm);
if (sig_nid == NID_rsassaPss && if (sig_nid == NID_rsassaPss &&
!x509_print_rsa_pss_params(bp, sigalg, 9, 0)) { !x509_print_rsa_pss_params(bp, sigalg, 9, 0)) {
@ -362,7 +358,7 @@ int X509_NAME_print(BIO *bp, const X509_NAME *name, int obase) {
OPENSSL_free(b); OPENSSL_free(b);
return 1; return 1;
} }
s = b + 1; /* skip the first slash */ s = b + 1; // skip the first slash
c = s; c = s;
for (;;) { for (;;) {
@ -374,7 +370,7 @@ int X509_NAME_print(BIO *bp, const X509_NAME *name, int obase) {
if (BIO_write(bp, c, i) != i) { if (BIO_write(bp, c, i) != i) {
goto err; goto err;
} }
c = s + 1; /* skip following slash */ c = s + 1; // skip following slash
if (*s != '\0') { if (*s != '\0') {
if (BIO_write(bp, ", ", 2) != 2) { if (BIO_write(bp, ", ", 2) != 2) {
goto err; goto err;

@ -63,7 +63,7 @@
#include "internal.h" #include "internal.h"
/* X509_CERT_AUX and string set routines */ // X509_CERT_AUX and string set routines
int X509_CERT_AUX_print(BIO *out, X509_CERT_AUX *aux, int indent) { int X509_CERT_AUX_print(BIO *out, X509_CERT_AUX *aux, int indent) {
char oidstr[80], first; char oidstr[80], first;

@ -61,8 +61,8 @@
#include <openssl/mem.h> #include <openssl/mem.h>
/* |X509_R_UNSUPPORTED_ALGORITHM| is no longer emitted, but continue to define // |X509_R_UNSUPPORTED_ALGORITHM| is no longer emitted, but continue to define
* it to avoid downstream churn. */ // it to avoid downstream churn.
OPENSSL_DECLARE_ERROR_REASON(X509, UNSUPPORTED_ALGORITHM) OPENSSL_DECLARE_ERROR_REASON(X509, UNSUPPORTED_ALGORITHM)
int X509_signature_dump(BIO *bp, const ASN1_STRING *sig, int indent) { int X509_signature_dump(BIO *bp, const ASN1_STRING *sig, int indent) {

@ -304,11 +304,9 @@ int X509_ATTRIBUTE_set1_data(X509_ATTRIBUTE *attr, int attrtype,
} }
atype = attrtype; atype = attrtype;
} }
/* // This is a bit naughty because the attribute should really have at
* 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
* least one value but some types use and zero length SET and require // this.
* this.
*/
if (attrtype == 0) { if (attrtype == 0) {
ASN1_STRING_free(stmp); ASN1_STRING_free(stmp);
return 1; return 1;

@ -132,23 +132,21 @@ unsigned long X509_subject_name_hash_old(X509 *x) {
return (X509_NAME_hash_old(x->cert_info->subject)); return (X509_NAME_hash_old(x->cert_info->subject));
} }
/* // Compare two certificates: they must be identical for this to work. NB:
* Compare two certificates: they must be identical for this to work. NB: // Although "cmp" operations are generally prototyped to take "const"
* Although "cmp" operations are generally prototyped to take "const" // arguments (eg. for use in STACKs), the way X509 handling is - these
* arguments (eg. for use in STACKs), the way X509 handling is - these // operations may involve ensuring the hashes are up-to-date and ensuring
* operations may involve ensuring the hashes are up-to-date and ensuring // certain cert information is cached. So this is the point where the
* certain cert information is cached. So this is the point where the // "depth-first" constification tree has to halt with an evil cast.
* "depth-first" constification tree has to halt with an evil cast.
*/
int X509_cmp(const X509 *a, const X509 *b) { int X509_cmp(const X509 *a, const X509 *b) {
/* Fill in the |cert_hash| fields. // Fill in the |cert_hash| fields.
* //
* TODO(davidben): This may fail, in which case the the hash will be all // TODO(davidben): This may fail, in which case the the hash will be all
* zeros. This produces a consistent comparison (failures are sticky), but // zeros. This produces a consistent comparison (failures are sticky), but
* not a good one. OpenSSL now returns -2, but this is not a consistent // 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 // comparison and may cause misbehaving sorts by transitivity. For now, we
* retain the old OpenSSL behavior, which was to ignore the error. See // retain the old OpenSSL behavior, which was to ignore the error. See
* https://crbug.com/boringssl/355. */ // https://crbug.com/boringssl/355.
x509v3_cache_extensions((X509 *)a); x509v3_cache_extensions((X509 *)a);
x509v3_cache_extensions((X509 *)b); x509v3_cache_extensions((X509 *)b);
@ -158,7 +156,7 @@ int X509_cmp(const X509 *a, const X509 *b) {
int X509_NAME_cmp(const X509_NAME *a, const X509_NAME *b) { int X509_NAME_cmp(const X509_NAME *a, const X509_NAME *b) {
int ret; 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) { if (!a->canon_enc || a->modified) {
ret = i2d_X509_NAME((X509_NAME *)a, NULL); ret = i2d_X509_NAME((X509_NAME *)a, NULL);
@ -187,7 +185,7 @@ unsigned long X509_NAME_hash(X509_NAME *x) {
unsigned long ret = 0; unsigned long ret = 0;
unsigned char md[SHA_DIGEST_LENGTH]; unsigned char md[SHA_DIGEST_LENGTH];
/* Make sure X509_NAME structure contains valid cached encoding */ // Make sure X509_NAME structure contains valid cached encoding
i2d_X509_NAME(x, NULL); i2d_X509_NAME(x, NULL);
if (!EVP_Digest(x->canon_enc, x->canon_enclen, md, NULL, EVP_sha1(), NULL)) { if (!EVP_Digest(x->canon_enc, x->canon_enclen, md, NULL, EVP_sha1(), NULL)) {
return 0; return 0;
@ -199,20 +197,18 @@ unsigned long X509_NAME_hash(X509_NAME *x) {
return (ret); return (ret);
} }
/* // I now DER encode the name and hash it. Since I cache the DER encoding,
* I now DER encode the name and hash it. Since I cache the DER encoding, // this is reasonably efficient.
* this is reasonably efficient.
*/
unsigned long X509_NAME_hash_old(X509_NAME *x) { unsigned long X509_NAME_hash_old(X509_NAME *x) {
EVP_MD_CTX md_ctx; EVP_MD_CTX md_ctx;
unsigned long ret = 0; unsigned long ret = 0;
unsigned char md[16]; unsigned char md[16];
/* Make sure X509_NAME structure contains valid cached encoding */ // Make sure X509_NAME structure contains valid cached encoding
i2d_X509_NAME(x, NULL); i2d_X509_NAME(x, NULL);
EVP_MD_CTX_init(&md_ctx); EVP_MD_CTX_init(&md_ctx);
/* EVP_MD_CTX_set_flags(&md_ctx, EVP_MD_CTX_FLAG_NON_FIPS_ALLOW); */ // EVP_MD_CTX_set_flags(&md_ctx, EVP_MD_CTX_FLAG_NON_FIPS_ALLOW);
if (EVP_DigestInit_ex(&md_ctx, EVP_md5(), NULL) && if (EVP_DigestInit_ex(&md_ctx, EVP_md5(), NULL) &&
EVP_DigestUpdate(&md_ctx, x->bytes->data, x->bytes->length) && EVP_DigestUpdate(&md_ctx, x->bytes->data, x->bytes->length) &&
EVP_DigestFinal_ex(&md_ctx, md, NULL)) { EVP_DigestFinal_ex(&md_ctx, md, NULL)) {
@ -225,7 +221,7 @@ unsigned long X509_NAME_hash_old(X509_NAME *x) {
return (ret); return (ret);
} }
/* Search a stack of X509 for a match */ // Search a stack of X509 for a match
X509 *X509_find_by_issuer_and_serial(STACK_OF(X509) *sk, X509_NAME *name, X509 *X509_find_by_issuer_and_serial(STACK_OF(X509) *sk, X509_NAME *name,
ASN1_INTEGER *serial) { ASN1_INTEGER *serial) {
size_t i; size_t i;
@ -309,11 +305,9 @@ int X509_check_private_key(X509 *x, const EVP_PKEY *k) {
return 0; return 0;
} }
/* // Check a suite B algorithm is permitted: pass in a public key and the NID
* Check a suite B algorithm is permitted: pass in a public key and the NID // of its signature (or 0 if no signature). The pflags is a pointer to a
* of its signature (or 0 if no signature). The pflags is a pointer to a // flags field which must contain the suite B verification flags.
* flags field which must contain the suite B verification flags.
*/
static int check_suite_b(EVP_PKEY *pkey, int sign_nid, unsigned long *pflags) { static int check_suite_b(EVP_PKEY *pkey, int sign_nid, unsigned long *pflags) {
const EC_GROUP *grp = NULL; const EC_GROUP *grp = NULL;
@ -325,20 +319,18 @@ static int check_suite_b(EVP_PKEY *pkey, int sign_nid, unsigned long *pflags) {
return X509_V_ERR_SUITE_B_INVALID_ALGORITHM; return X509_V_ERR_SUITE_B_INVALID_ALGORITHM;
} }
curve_nid = EC_GROUP_get_curve_name(grp); curve_nid = EC_GROUP_get_curve_name(grp);
/* Check curve is consistent with LOS */ // Check curve is consistent with LOS
if (curve_nid == NID_secp384r1) { /* P-384 */ if (curve_nid == NID_secp384r1) { // P-384
/* // Check signature algorithm is consistent with curve.
* Check signature algorithm is consistent with curve.
*/
if (sign_nid != -1 && sign_nid != NID_ecdsa_with_SHA384) { if (sign_nid != -1 && sign_nid != NID_ecdsa_with_SHA384) {
return X509_V_ERR_SUITE_B_INVALID_SIGNATURE_ALGORITHM; return X509_V_ERR_SUITE_B_INVALID_SIGNATURE_ALGORITHM;
} }
if (!(*pflags & X509_V_FLAG_SUITEB_192_LOS)) { if (!(*pflags & X509_V_FLAG_SUITEB_192_LOS)) {
return X509_V_ERR_SUITE_B_LOS_NOT_ALLOWED; return X509_V_ERR_SUITE_B_LOS_NOT_ALLOWED;
} }
/* If we encounter P-384 we cannot use P-256 later */ // If we encounter P-384 we cannot use P-256 later
*pflags &= ~X509_V_FLAG_SUITEB_128_LOS_ONLY; *pflags &= ~X509_V_FLAG_SUITEB_128_LOS_ONLY;
} else if (curve_nid == NID_X9_62_prime256v1) { /* P-256 */ } else if (curve_nid == NID_X9_62_prime256v1) { // P-256
if (sign_nid != -1 && sign_nid != NID_ecdsa_with_SHA256) { if (sign_nid != -1 && sign_nid != NID_ecdsa_with_SHA256) {
return X509_V_ERR_SUITE_B_INVALID_SIGNATURE_ALGORITHM; return X509_V_ERR_SUITE_B_INVALID_SIGNATURE_ALGORITHM;
} }
@ -362,7 +354,7 @@ int X509_chain_check_suiteb(int *perror_depth, X509 *x, STACK_OF(X509) *chain,
return X509_V_OK; return X509_V_OK;
} }
tflags = flags; tflags = flags;
/* If no EE certificate passed in must be first in chain */ // If no EE certificate passed in must be first in chain
if (x == NULL) { if (x == NULL) {
x = sk_X509_value(chain, 0); x = sk_X509_value(chain, 0);
i = 1; i = 1;
@ -372,16 +364,16 @@ int X509_chain_check_suiteb(int *perror_depth, X509 *x, STACK_OF(X509) *chain,
if (X509_get_version(x) != X509_VERSION_3) { if (X509_get_version(x) != X509_VERSION_3) {
rv = X509_V_ERR_SUITE_B_INVALID_VERSION; rv = X509_V_ERR_SUITE_B_INVALID_VERSION;
/* Correct error depth */ // Correct error depth
i = 0; i = 0;
goto end; goto end;
} }
pk = X509_get_pubkey(x); pk = X509_get_pubkey(x);
/* Check EE key only */ // Check EE key only
rv = check_suite_b(pk, -1, &tflags); rv = check_suite_b(pk, -1, &tflags);
if (rv != X509_V_OK) { if (rv != X509_V_OK) {
/* Correct error depth */ // Correct error depth
i = 0; i = 0;
goto end; goto end;
} }
@ -400,23 +392,21 @@ int X509_chain_check_suiteb(int *perror_depth, X509 *x, STACK_OF(X509) *chain,
} }
} }
/* Final check: root CA signature */ // Final check: root CA signature
rv = check_suite_b(pk, X509_get_signature_nid(x), &tflags); rv = check_suite_b(pk, X509_get_signature_nid(x), &tflags);
end: end:
if (pk) { if (pk) {
EVP_PKEY_free(pk); EVP_PKEY_free(pk);
} }
if (rv != X509_V_OK) { if (rv != X509_V_OK) {
/* Invalid signature or LOS errors are for previous cert */ // Invalid signature or LOS errors are for previous cert
if ((rv == X509_V_ERR_SUITE_B_INVALID_SIGNATURE_ALGORITHM || if ((rv == X509_V_ERR_SUITE_B_INVALID_SIGNATURE_ALGORITHM ||
rv == X509_V_ERR_SUITE_B_LOS_NOT_ALLOWED) && rv == X509_V_ERR_SUITE_B_LOS_NOT_ALLOWED) &&
i) { i) {
i--; i--;
} }
/* // If we have LOS error and flags changed then we are signing P-384
* If we have LOS error and flags changed then we are signing P-384 // with P-256. Use more meaninggul error.
* with P-256. Use more meaninggul error.
*/
if (rv == X509_V_ERR_SUITE_B_LOS_NOT_ALLOWED && flags != tflags) { 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; rv = X509_V_ERR_SUITE_B_CANNOT_SIGN_P_384_WITH_P_256;
} }
@ -436,11 +426,9 @@ int X509_CRL_check_suiteb(X509_CRL *crl, EVP_PKEY *pk, unsigned long flags) {
return check_suite_b(pk, sign_nid, &flags); return check_suite_b(pk, sign_nid, &flags);
} }
/* // Not strictly speaking an "up_ref" as a STACK doesn't have a reference
* Not strictly speaking an "up_ref" as a STACK doesn't have a reference // count but it has the same effect by duping the STACK and upping the ref of
* count but it has the same effect by duping the STACK and upping the ref of // each X509 structure.
* each X509 structure.
*/
STACK_OF(X509) *X509_chain_up_ref(STACK_OF(X509) *chain) { STACK_OF(X509) *X509_chain_up_ref(STACK_OF(X509) *chain) {
STACK_OF(X509) *ret; STACK_OF(X509) *ret;
size_t i; size_t i;

@ -74,7 +74,7 @@ int X509_STORE_set_default_paths(X509_STORE *ctx) {
} }
X509_LOOKUP_add_dir(lookup, NULL, X509_FILETYPE_DEFAULT); X509_LOOKUP_add_dir(lookup, NULL, X509_FILETYPE_DEFAULT);
/* clear any errors */ // clear any errors
ERR_clear_error(); ERR_clear_error();
return (1); return (1);

@ -57,7 +57,7 @@
#include <openssl/x509.h> #include <openssl/x509.h>
/* TODO(fork): cleanup */ // TODO(fork): cleanup
#if defined(OPENSSL_FUCHSIA) #if defined(OPENSSL_FUCHSIA)
#define OPENSSLDIR "/config/ssl" #define OPENSSLDIR "/config/ssl"

@ -180,7 +180,7 @@ static int x509_object_cmp(const X509_OBJECT **a, const X509_OBJECT **b) {
ret = X509_CRL_cmp((*a)->data.crl, (*b)->data.crl); ret = X509_CRL_cmp((*a)->data.crl, (*b)->data.crl);
break; break;
default: default:
/* abort(); */ // abort();
return 0; return 0;
} }
return ret; return ret;
@ -241,7 +241,7 @@ static void cleanup(X509_OBJECT *a) {
} else if (a->type == X509_LU_CRL) { } else if (a->type == X509_LU_CRL) {
X509_CRL_free(a->data.crl); X509_CRL_free(a->data.crl);
} else { } else {
/* abort(); */ // abort();
} }
OPENSSL_free(a); OPENSSL_free(a);
@ -289,7 +289,7 @@ X509_LOOKUP *X509_STORE_add_lookup(X509_STORE *v, X509_LOOKUP_METHOD *m) {
return lu; return lu;
} }
} }
/* a new one */ // a new one
lu = X509_LOOKUP_new(m); lu = X509_LOOKUP_new(m);
if (lu == NULL) { if (lu == NULL) {
return NULL; return NULL;
@ -328,9 +328,7 @@ int X509_STORE_get_by_subject(X509_STORE_CTX *vs, int type, X509_NAME *name,
} }
} }
/* // 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->type = tmp->type;
ret->data.ptr = tmp->data.ptr; ret->data.ptr = tmp->data.ptr;
@ -364,7 +362,7 @@ static int x509_store_add(X509_STORE *ctx, void *x, int is_crl) {
int ret = 1; int ret = 1;
int added = 0; int added = 0;
/* Duplicates are silently ignored */ // Duplicates are silently ignored
if (!X509_OBJECT_retrieve_match(ctx->objs, obj)) { if (!X509_OBJECT_retrieve_match(ctx->objs, obj)) {
ret = added = (sk_X509_OBJECT_push(ctx->objs, obj) != 0); ret = added = (sk_X509_OBJECT_push(ctx->objs, obj) != 0);
} }
@ -440,7 +438,7 @@ static int x509_object_idx_cnt(STACK_OF(X509_OBJECT) *h, int type,
crl_info_s.issuer = name; crl_info_s.issuer = name;
break; break;
default: default:
/* abort(); */ // abort();
return -1; return -1;
} }
@ -498,10 +496,8 @@ STACK_OF(X509) *X509_STORE_get1_certs(X509_STORE_CTX *ctx, X509_NAME *nm) {
CRYPTO_MUTEX_lock_write(&ctx->ctx->objs_lock); CRYPTO_MUTEX_lock_write(&ctx->ctx->objs_lock);
idx = x509_object_idx_cnt(ctx->ctx->objs, X509_LU_X509, nm, &cnt); idx = x509_object_idx_cnt(ctx->ctx->objs, X509_LU_X509, nm, &cnt);
if (idx < 0) { if (idx < 0) {
/* // Nothing found in cache: do lookup to possibly add new objects to
* Nothing found in cache: do lookup to possibly add new objects to // cache
* cache
*/
X509_OBJECT xobj; X509_OBJECT xobj;
CRYPTO_MUTEX_unlock_write(&ctx->ctx->objs_lock); CRYPTO_MUTEX_unlock_write(&ctx->ctx->objs_lock);
if (!X509_STORE_get_by_subject(ctx, X509_LU_X509, nm, &xobj)) { if (!X509_STORE_get_by_subject(ctx, X509_LU_X509, nm, &xobj)) {
@ -541,7 +537,7 @@ STACK_OF(X509_CRL) *X509_STORE_get1_crls(X509_STORE_CTX *ctx, X509_NAME *nm) {
return NULL; return NULL;
} }
/* Always do lookup to possibly add new CRLs to cache. */ // Always do lookup to possibly add new CRLs to cache.
if (!X509_STORE_get_by_subject(ctx, X509_LU_CRL, nm, &xobj)) { if (!X509_STORE_get_by_subject(ctx, X509_LU_CRL, nm, &xobj)) {
sk_X509_CRL_free(sk); sk_X509_CRL_free(sk);
return NULL; return NULL;
@ -602,13 +598,11 @@ X509_OBJECT *X509_OBJECT_retrieve_match(STACK_OF(X509_OBJECT) *h,
return NULL; return NULL;
} }
/* // Try to get issuer certificate from store. Due to limitations of the API
* Try to get issuer certificate from store. Due to limitations of the API // this can only retrieve a single certificate matching a given subject name.
* this can only retrieve a single certificate matching a given subject name. // However it will fill the cache with all matching certificates, so we can
* However it will fill the cache with all matching certificates, so we can // examine the cache for all matches. Return values are: 1 lookup
* examine the cache for all matches. Return values are: 1 lookup // successful. 0 certificate not found. -1 some other error.
* successful. 0 certificate not found. -1 some other error.
*/
int X509_STORE_CTX_get1_issuer(X509 **issuer, X509_STORE_CTX *ctx, X509 *x) { int X509_STORE_CTX_get1_issuer(X509 **issuer, X509_STORE_CTX *ctx, X509 *x) {
X509_NAME *xn; X509_NAME *xn;
X509_OBJECT obj, *pobj; X509_OBJECT obj, *pobj;
@ -618,23 +612,23 @@ int X509_STORE_CTX_get1_issuer(X509 **issuer, X509_STORE_CTX *ctx, X509 *x) {
if (!X509_STORE_get_by_subject(ctx, X509_LU_X509, xn, &obj)) { if (!X509_STORE_get_by_subject(ctx, X509_LU_X509, xn, &obj)) {
return 0; return 0;
} }
/* If certificate matches all OK */ // If certificate matches all OK
if (ctx->check_issued(ctx, x, obj.data.x509)) { if (ctx->check_issued(ctx, x, obj.data.x509)) {
*issuer = obj.data.x509; *issuer = obj.data.x509;
return 1; return 1;
} }
X509_OBJECT_free_contents(&obj); X509_OBJECT_free_contents(&obj);
/* Else find index of first cert accepted by 'check_issued' */ // Else find index of first cert accepted by 'check_issued'
ret = 0; ret = 0;
CRYPTO_MUTEX_lock_write(&ctx->ctx->objs_lock); CRYPTO_MUTEX_lock_write(&ctx->ctx->objs_lock);
idx = X509_OBJECT_idx_by_subject(ctx->ctx->objs, X509_LU_X509, xn); 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 if (idx != -1) { // should be true as we've had at least one
* match */ // match
/* Look through all matching certs for suitable issuer */ // Look through all matching certs for suitable issuer
for (i = idx; i < sk_X509_OBJECT_num(ctx->ctx->objs); i++) { for (i = idx; i < sk_X509_OBJECT_num(ctx->ctx->objs); i++) {
pobj = sk_X509_OBJECT_value(ctx->ctx->objs, i); pobj = sk_X509_OBJECT_value(ctx->ctx->objs, i);
/* See if we've run past the matches */ // See if we've run past the matches
if (pobj->type != X509_LU_X509) { if (pobj->type != X509_LU_X509) {
break; break;
} }

@ -67,10 +67,8 @@
#include "internal.h" #include "internal.h"
/* // Limit to ensure we don't overflow: much greater than
* Limit to ensure we don't overflow: much greater than // anything enountered in practice.
* anything enountered in practice.
*/
#define NAME_ONELINE_MAX (1024 * 1024) #define NAME_ONELINE_MAX (1024 * 1024)
@ -107,7 +105,7 @@ char *X509_NAME_oneline(const X509_NAME *a, char *buf, int len) {
return buf; return buf;
} }
len--; /* space for '\0' */ len--; // space for '\0'
l = 0; l = 0;
for (i = 0; i < sk_X509_NAME_ENTRY_num(a->entries); i++) { for (i = 0; i < sk_X509_NAME_ENTRY_num(a->entries); i++) {
ne = sk_X509_NAME_ENTRY_value(a->entries, i); ne = sk_X509_NAME_ENTRY_value(a->entries, i);

@ -104,7 +104,7 @@ int X509_REQ_check_private_key(X509_REQ *x, EVP_PKEY *k) {
break; break;
} }
if (k->type == EVP_PKEY_DH) { if (k->type == EVP_PKEY_DH) {
/* No idea */ // No idea
OPENSSL_PUT_ERROR(X509, X509_R_CANT_CHECK_DH_KEY); OPENSSL_PUT_ERROR(X509, X509_R_CANT_CHECK_DH_KEY);
break; break;
} }
@ -142,14 +142,12 @@ STACK_OF(X509_EXTENSION) *X509_REQ_get_extensions(X509_REQ *req) {
NULL, &p, ext->value.sequence->length, ASN1_ITEM_rptr(X509_EXTENSIONS)); NULL, &p, ext->value.sequence->length, ASN1_ITEM_rptr(X509_EXTENSIONS));
} }
/* // Add a STACK_OF extensions to a certificate request: allow alternative OIDs
* Add a STACK_OF extensions to a certificate request: allow alternative OIDs // in case we want to create a non standard one.
* in case we want to create a non standard one.
*/
int X509_REQ_add_extensions_nid(X509_REQ *req, int X509_REQ_add_extensions_nid(X509_REQ *req,
const STACK_OF(X509_EXTENSION) *exts, int nid) { const STACK_OF(X509_EXTENSION) *exts, int nid) {
/* Generate encoding of extensions */ // Generate encoding of extensions
unsigned char *ext = NULL; unsigned char *ext = NULL;
int ext_len = int ext_len =
ASN1_item_i2d((ASN1_VALUE *)exts, &ext, ASN1_ITEM_rptr(X509_EXTENSIONS)); ASN1_item_i2d((ASN1_VALUE *)exts, &ext, ASN1_ITEM_rptr(X509_EXTENSIONS));
@ -161,13 +159,13 @@ int X509_REQ_add_extensions_nid(X509_REQ *req,
return ret; return ret;
} }
/* This is the normal usage: use the "official" OID */ // This is the normal usage: use the "official" OID
int X509_REQ_add_extensions(X509_REQ *req, int X509_REQ_add_extensions(X509_REQ *req,
const STACK_OF(X509_EXTENSION) *exts) { const STACK_OF(X509_EXTENSION) *exts) {
return X509_REQ_add_extensions_nid(req, exts, NID_ext_req); return X509_REQ_add_extensions_nid(req, exts, NID_ext_req);
} }
/* Request attribute functions */ // Request attribute functions
int X509_REQ_get_attr_count(const X509_REQ *req) { int X509_REQ_get_attr_count(const X509_REQ *req) {
return X509at_get_attr_count(req->req_info->attributes); return X509at_get_attr_count(req->req_info->attributes);

@ -81,7 +81,7 @@ int X509_set_version(X509 *x, long version) {
return 0; return 0;
} }
/* v1(0) is default and is represented by omitting the version. */ // v1(0) is default and is represented by omitting the version.
if (version == X509_VERSION_1) { if (version == X509_VERSION_1) {
ASN1_INTEGER_free(x->cert_info->version); ASN1_INTEGER_free(x->cert_info->version);
x->cert_info->version = NULL; x->cert_info->version = NULL;

@ -72,11 +72,9 @@ static int trust_compat(X509_TRUST *trust, X509 *x, int flags);
static int obj_trust(int id, X509 *x, int flags); static int obj_trust(int id, X509 *x, int flags);
/* // WARNING: the following table should be kept in order of trust and without
* WARNING: the following table should be kept in order of trust and without // any gaps so we can just subtract the minimum trust value to get an index
* any gaps so we can just subtract the minimum trust value to get an index // into the table
* into the table
*/
static X509_TRUST trstandard[] = { static X509_TRUST trstandard[] = {
{X509_TRUST_COMPAT, 0, trust_compat, (char *)"compatible", 0, NULL}, {X509_TRUST_COMPAT, 0, trust_compat, (char *)"compatible", 0, NULL},
@ -109,7 +107,7 @@ int X509_check_trust(X509 *x, int id, int flags) {
if (id == -1) { if (id == -1) {
return 1; return 1;
} }
/* We get this as a default value */ // We get this as a default value
if (id == 0) { if (id == 0) {
int rv; int rv;
rv = obj_trust(NID_anyExtendedKeyUsage, x, 0); rv = obj_trust(NID_anyExtendedKeyUsage, x, 0);
@ -176,15 +174,13 @@ int X509_TRUST_add(int id, int flags, int (*ck)(X509_TRUST *, X509 *, int),
X509_TRUST *trtmp; X509_TRUST *trtmp;
char *name_dup; char *name_dup;
/* // This is set according to what we change: application can't set it
* This is set according to what we change: application can't set it
*/
flags &= ~X509_TRUST_DYNAMIC; flags &= ~X509_TRUST_DYNAMIC;
/* This will always be set for application modified trust entries */ // This will always be set for application modified trust entries
flags |= X509_TRUST_DYNAMIC_NAME; flags |= X509_TRUST_DYNAMIC_NAME;
/* Get existing entry if any */ // Get existing entry if any
idx = X509_TRUST_get_by_id(id); idx = X509_TRUST_get_by_id(id);
/* Need a new entry */ // Need a new entry
if (idx == -1) { if (idx == -1) {
if (!(trtmp = OPENSSL_malloc(sizeof(X509_TRUST)))) { if (!(trtmp = OPENSSL_malloc(sizeof(X509_TRUST)))) {
OPENSSL_PUT_ERROR(X509, ERR_R_MALLOC_FAILURE); OPENSSL_PUT_ERROR(X509, ERR_R_MALLOC_FAILURE);
@ -195,7 +191,7 @@ int X509_TRUST_add(int id, int flags, int (*ck)(X509_TRUST *, X509 *, int),
trtmp = X509_TRUST_get0(idx); trtmp = X509_TRUST_get0(idx);
} }
/* Duplicate the supplied name. */ // Duplicate the supplied name.
name_dup = OPENSSL_strdup(name); name_dup = OPENSSL_strdup(name);
if (name_dup == NULL) { if (name_dup == NULL) {
OPENSSL_PUT_ERROR(X509, ERR_R_MALLOC_FAILURE); OPENSSL_PUT_ERROR(X509, ERR_R_MALLOC_FAILURE);
@ -205,14 +201,14 @@ int X509_TRUST_add(int id, int flags, int (*ck)(X509_TRUST *, X509 *, int),
return 0; return 0;
} }
/* OPENSSL_free existing name if dynamic */ // OPENSSL_free existing name if dynamic
if (trtmp->flags & X509_TRUST_DYNAMIC_NAME) { if (trtmp->flags & X509_TRUST_DYNAMIC_NAME) {
OPENSSL_free(trtmp->name); OPENSSL_free(trtmp->name);
} }
trtmp->name = name_dup; trtmp->name = name_dup;
/* Keep the dynamic flag of existing entry */ // Keep the dynamic flag of existing entry
trtmp->flags &= X509_TRUST_DYNAMIC; trtmp->flags &= X509_TRUST_DYNAMIC;
/* Set all other flags */ // Set all other flags
trtmp->flags |= flags; trtmp->flags |= flags;
trtmp->trust = id; trtmp->trust = id;
@ -220,7 +216,7 @@ int X509_TRUST_add(int id, int flags, int (*ck)(X509_TRUST *, X509 *, int),
trtmp->arg1 = arg1; trtmp->arg1 = arg1;
trtmp->arg2 = arg2; trtmp->arg2 = arg2;
/* If its a new entry manage the dynamic table */ // If its a new entry manage the dynamic table
if (idx == -1) { if (idx == -1) {
if (!trtable && !(trtable = sk_X509_TRUST_new(tr_cmp))) { if (!trtable && !(trtable = sk_X509_TRUST_new(tr_cmp))) {
OPENSSL_PUT_ERROR(X509, ERR_R_MALLOC_FAILURE); OPENSSL_PUT_ERROR(X509, ERR_R_MALLOC_FAILURE);
@ -267,10 +263,8 @@ static int trust_1oidany(X509_TRUST *trust, X509 *x, int flags) {
if (x->aux && (x->aux->trust || x->aux->reject)) { if (x->aux && (x->aux->trust || x->aux->reject)) {
return obj_trust(trust->arg1, x, flags); return obj_trust(trust->arg1, x, flags);
} }
/* // we don't have any trust settings: for compatibility we return trusted
* we don't have any trust settings: for compatibility we return trusted // if it is self signed
* if it is self signed
*/
return trust_compat(trust, x, flags); return trust_compat(trust, x, flags);
} }

File diff suppressed because it is too large Load Diff

@ -67,7 +67,7 @@
#include "internal.h" #include "internal.h"
/* X509_VERIFY_PARAM functions */ // X509_VERIFY_PARAM functions
#define SET_HOST 0 #define SET_HOST 0
#define ADD_HOST 1 #define ADD_HOST 1
@ -87,10 +87,8 @@ static int int_x509_param_set_hosts(X509_VERIFY_PARAM *param, int mode,
return 0; return 0;
} }
/* // Refuse names with embedded NUL bytes.
* Refuse names with embedded NUL bytes. // XXX: Do we need to push an error onto the error stack?
* XXX: Do we need to push an error onto the error stack?
*/
if (name && OPENSSL_memchr(name, '\0', namelen)) { if (name && OPENSSL_memchr(name, '\0', namelen)) {
return 0; return 0;
} }
@ -130,9 +128,7 @@ static void x509_verify_param_zero(X509_VERIFY_PARAM *param) {
param->name = NULL; param->name = NULL;
param->purpose = 0; param->purpose = 0;
param->trust = 0; param->trust = 0;
/* // param->inh_flags = X509_VP_FLAG_DEFAULT;
* param->inh_flags = X509_VP_FLAG_DEFAULT;
*/
param->inh_flags = 0; param->inh_flags = 0;
param->flags = 0; param->flags = 0;
param->depth = -1; param->depth = -1;
@ -180,45 +176,44 @@ void X509_VERIFY_PARAM_free(X509_VERIFY_PARAM *param) {
OPENSSL_free(param); OPENSSL_free(param);
} }
/*- //-
* This function determines how parameters are "inherited" from one structure // This function determines how parameters are "inherited" from one structure
* to another. There are several different ways this can happen. // to another. There are several different ways this can happen.
* //
* 1. If a child structure needs to have its values initialized from a parent // 1. If a child structure needs to have its values initialized from a parent
* they are simply copied across. For example SSL_CTX copied to SSL. // they are simply copied across. For example SSL_CTX copied to SSL.
* 2. If the structure should take on values only if they are currently unset. // 2. If the structure should take on values only if they are currently unset.
* For example the values in an SSL structure will take appropriate value // For example the values in an SSL structure will take appropriate value
* for SSL servers or clients but only if the application has not set new // for SSL servers or clients but only if the application has not set new
* ones. // ones.
* //
* The "inh_flags" field determines how this function behaves. // The "inh_flags" field determines how this function behaves.
* //
* Normally any values which are set in the default are not copied from the // Normally any values which are set in the default are not copied from the
* destination and verify flags are ORed together. // destination and verify flags are ORed together.
* //
* If X509_VP_FLAG_DEFAULT is set then anything set in the source is copied // If X509_VP_FLAG_DEFAULT is set then anything set in the source is copied
* to the destination. Effectively the values in "to" become default values // to the destination. Effectively the values in "to" become default values
* which will be used only if nothing new is set in "from". // which will be used only if nothing new is set in "from".
* //
* If X509_VP_FLAG_OVERWRITE is set then all value are copied across whether // If X509_VP_FLAG_OVERWRITE is set then all value are copied across whether
* they are set or not. Flags is still Ored though. // they are set or not. Flags is still Ored though.
* //
* If X509_VP_FLAG_RESET_FLAGS is set then the flags value is copied instead // If X509_VP_FLAG_RESET_FLAGS is set then the flags value is copied instead
* of ORed. // of ORed.
* //
* If X509_VP_FLAG_LOCKED is set then no values are copied. // If X509_VP_FLAG_LOCKED is set then no values are copied.
* //
* If X509_VP_FLAG_ONCE is set then the current inh_flags setting is zeroed // If X509_VP_FLAG_ONCE is set then the current inh_flags setting is zeroed
* after the next call. // after the next call.
*/
// Macro to test if a field should be copied from src to dest
/* Macro to test if a field should be copied from src to dest */
#define test_x509_verify_param_copy(field, def) \ #define test_x509_verify_param_copy(field, def) \
(to_overwrite || \ (to_overwrite || \
((src->field != (def)) && (to_default || (dest->field == (def))))) ((src->field != (def)) && (to_default || (dest->field == (def)))))
/* Macro to test and copy a field if necessary */ // Macro to test and copy a field if necessary
#define x509_verify_param_copy(field, def) \ #define x509_verify_param_copy(field, def) \
if (test_x509_verify_param_copy(field, def)) \ if (test_x509_verify_param_copy(field, def)) \
@ -257,12 +252,12 @@ int X509_VERIFY_PARAM_inherit(X509_VERIFY_PARAM *dest,
x509_verify_param_copy(trust, 0); x509_verify_param_copy(trust, 0);
x509_verify_param_copy(depth, -1); x509_verify_param_copy(depth, -1);
/* If overwrite or check time not set, copy across */ // If overwrite or check time not set, copy across
if (to_overwrite || !(dest->flags & X509_V_FLAG_USE_CHECK_TIME)) { if (to_overwrite || !(dest->flags & X509_V_FLAG_USE_CHECK_TIME)) {
dest->check_time = src->check_time; dest->check_time = src->check_time;
dest->flags &= ~X509_V_FLAG_USE_CHECK_TIME; dest->flags &= ~X509_V_FLAG_USE_CHECK_TIME;
/* Don't need to copy flag: that is done below */ // Don't need to copy flag: that is done below
} }
if (inh_flags & X509_VP_FLAG_RESET_FLAGS) { if (inh_flags & X509_VP_FLAG_RESET_FLAGS) {
@ -277,7 +272,7 @@ int X509_VERIFY_PARAM_inherit(X509_VERIFY_PARAM *dest,
} }
} }
/* Copy the host flags if and only if we're copying the host list */ // Copy the host flags if and only if we're copying the host list
if (test_x509_verify_param_copy(hosts, NULL)) { if (test_x509_verify_param_copy(hosts, NULL)) {
if (dest->hosts) { if (dest->hosts) {
string_stack_free(dest->hosts); string_stack_free(dest->hosts);
@ -510,57 +505,55 @@ const char *X509_VERIFY_PARAM_get0_name(const X509_VERIFY_PARAM *param) {
#define vpm_empty_id NULL, 0U, NULL, NULL, 0, NULL, 0, 0 #define vpm_empty_id NULL, 0U, NULL, NULL, 0, NULL, 0, 0
/* // Default verify parameters: these are used for various applications and can
* Default verify parameters: these are used for various applications and can // be overridden by the user specified table. NB: the 'name' field *must* be
* be overridden by the user specified table. NB: the 'name' field *must* be // in alphabetical order because it will be searched using OBJ_search.
* in alphabetical order because it will be searched using OBJ_search.
*/
static const X509_VERIFY_PARAM default_table[] = { static const X509_VERIFY_PARAM default_table[] = {
{(char *)"default", /* X509 default parameters */ {(char *)"default", // X509 default parameters
0, /* Check time */ 0, // Check time
0, /* internal flags */ 0, // internal flags
X509_V_FLAG_TRUSTED_FIRST, /* flags */ X509_V_FLAG_TRUSTED_FIRST, // flags
0, /* purpose */ 0, // purpose
0, /* trust */ 0, // trust
100, /* depth */ 100, // depth
NULL, /* policies */ NULL, // policies
vpm_empty_id}, vpm_empty_id},
{(char *)"pkcs7", /* S/MIME sign parameters */ {(char *)"pkcs7", // S/MIME sign parameters
0, /* Check time */ 0, // Check time
0, /* internal flags */ 0, // internal flags
0, /* flags */ 0, // flags
X509_PURPOSE_SMIME_SIGN, /* purpose */ X509_PURPOSE_SMIME_SIGN, // purpose
X509_TRUST_EMAIL, /* trust */ X509_TRUST_EMAIL, // trust
-1, /* depth */ -1, // depth
NULL, /* policies */ NULL, // policies
vpm_empty_id}, vpm_empty_id},
{(char *)"smime_sign", /* S/MIME sign parameters */ {(char *)"smime_sign", // S/MIME sign parameters
0, /* Check time */ 0, // Check time
0, /* internal flags */ 0, // internal flags
0, /* flags */ 0, // flags
X509_PURPOSE_SMIME_SIGN, /* purpose */ X509_PURPOSE_SMIME_SIGN, // purpose
X509_TRUST_EMAIL, /* trust */ X509_TRUST_EMAIL, // trust
-1, /* depth */ -1, // depth
NULL, /* policies */ NULL, // policies
vpm_empty_id}, vpm_empty_id},
{(char *)"ssl_client", /* SSL/TLS client parameters */ {(char *)"ssl_client", // SSL/TLS client parameters
0, /* Check time */ 0, // Check time
0, /* internal flags */ 0, // internal flags
0, /* flags */ 0, // flags
X509_PURPOSE_SSL_CLIENT, /* purpose */ X509_PURPOSE_SSL_CLIENT, // purpose
X509_TRUST_SSL_CLIENT, /* trust */ X509_TRUST_SSL_CLIENT, // trust
-1, /* depth */ -1, // depth
NULL, /* policies */ NULL, // policies
vpm_empty_id}, vpm_empty_id},
{(char *)"ssl_server", /* SSL/TLS server parameters */ {(char *)"ssl_server", // SSL/TLS server parameters
0, /* Check time */ 0, // Check time
0, /* internal flags */ 0, // internal flags
0, /* flags */ 0, // flags
X509_PURPOSE_SSL_SERVER, /* purpose */ X509_PURPOSE_SSL_SERVER, // purpose
X509_TRUST_SSL_SERVER, /* trust */ X509_TRUST_SSL_SERVER, // trust
-1, /* depth */ -1, // depth
NULL, /* policies */ NULL, // policies
vpm_empty_id}}; vpm_empty_id}};
static STACK_OF(X509_VERIFY_PARAM) *param_table = NULL; static STACK_OF(X509_VERIFY_PARAM) *param_table = NULL;

@ -72,7 +72,7 @@ int X509_CRL_set_version(X509_CRL *x, long version) {
return 0; return 0;
} }
/* v1(0) is default and is represented by omitting the version. */ // v1(0) is default and is represented by omitting the version.
if (version == X509_CRL_VERSION_1) { if (version == X509_CRL_VERSION_1) {
ASN1_INTEGER_free(x->crl->version); ASN1_INTEGER_free(x->crl->version);
x->crl->version = NULL; x->crl->version = NULL;
@ -130,7 +130,7 @@ int X509_CRL_set1_nextUpdate(X509_CRL *x, const ASN1_TIME *tm) {
} }
int X509_CRL_sort(X509_CRL *c) { int X509_CRL_sort(X509_CRL *c) {
/* Sort the data so it will be written in serial number order. */ // Sort the data so it will be written in serial number order.
sk_X509_REVOKED_sort(c->crl->revoked); sk_X509_REVOKED_sort(c->crl->revoked);
c->crl->enc.modified = 1; c->crl->enc.modified = 1;
return 1; return 1;
@ -245,9 +245,9 @@ int i2d_X509_CRL_tbs(X509_CRL *crl, unsigned char **outp) {
} }
int X509_CRL_set1_signature_algo(X509_CRL *crl, const X509_ALGOR *algo) { int X509_CRL_set1_signature_algo(X509_CRL *crl, const X509_ALGOR *algo) {
/* TODO(https://crbug.com/boringssl/407): Generated ASN.1 dup functions // TODO(https://crbug.com/boringssl/407): Generated ASN.1 dup functions
* should be const. Alternatively, when we can embed required fields // should be const. Alternatively, when we can embed required fields
* directly in structs, import |X509_ALGOR_copy| from upstream. */ // directly in structs, import |X509_ALGOR_copy| from upstream.
X509_ALGOR *copy1 = X509_ALGOR_dup((X509_ALGOR *)algo); X509_ALGOR *copy1 = X509_ALGOR_dup((X509_ALGOR *)algo);
X509_ALGOR *copy2 = X509_ALGOR_dup((X509_ALGOR *)algo); X509_ALGOR *copy2 = X509_ALGOR_dup((X509_ALGOR *)algo);
if (copy1 == NULL || copy2 == NULL) { if (copy1 == NULL || copy2 == NULL) {

@ -114,7 +114,7 @@ int X509_NAME_get_index_by_NID(const X509_NAME *name, int nid, int lastpos) {
return (X509_NAME_get_index_by_OBJ(name, obj, lastpos)); return (X509_NAME_get_index_by_OBJ(name, obj, lastpos));
} }
/* NOTE: you should be passsing -1, not 0 as 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 X509_NAME_get_index_by_OBJ(const X509_NAME *name, const ASN1_OBJECT *obj,
int lastpos) { int lastpos) {
int n; int n;
@ -164,7 +164,7 @@ X509_NAME_ENTRY *X509_NAME_delete_entry(X509_NAME *name, int loc) {
return (ret); return (ret);
} }
/* else we need to fixup the set field */ // else we need to fixup the set field
if (loc != 0) { if (loc != 0) {
set_prev = (sk_X509_NAME_ENTRY_value(sk, loc - 1))->set; set_prev = (sk_X509_NAME_ENTRY_value(sk, loc - 1))->set;
} else { } else {
@ -172,11 +172,9 @@ X509_NAME_ENTRY *X509_NAME_delete_entry(X509_NAME *name, int loc) {
} }
set_next = sk_X509_NAME_ENTRY_value(sk, loc)->set; 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
* 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
* 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
* basically only if prev and next differ by 2, then re-number down by 1
*/
if (set_prev + 1 < set_next) { if (set_prev + 1 < set_next) {
for (i = loc; i < n; i++) { for (i = loc; i < n; i++) {
sk_X509_NAME_ENTRY_value(sk, i)->set--; sk_X509_NAME_ENTRY_value(sk, i)->set--;
@ -227,10 +225,8 @@ int X509_NAME_add_entry_by_txt(X509_NAME *name, const char *field, int type,
return ret; return ret;
} }
/* // if set is -1, append to previous set, 0 'a new one', and 1, prepend to the
* if set is -1, append to previous set, 0 'a new one', and 1, prepend to the // guy we are about to stomp on.
* guy we are about to stomp on.
*/
int X509_NAME_add_entry(X509_NAME *name, X509_NAME_ENTRY *ne, int loc, int X509_NAME_add_entry(X509_NAME *name, X509_NAME_ENTRY *ne, int loc,
int set) { int set) {
X509_NAME_ENTRY *new_name = NULL; X509_NAME_ENTRY *new_name = NULL;
@ -258,7 +254,7 @@ int X509_NAME_add_entry(X509_NAME *name, X509_NAME_ENTRY *ne, int loc,
} else { } else {
set = sk_X509_NAME_ENTRY_value(sk, loc - 1)->set; set = sk_X509_NAME_ENTRY_value(sk, loc - 1)->set;
} }
} else { /* if (set >= 0) */ } else { // if (set >= 0)
if (loc >= n) { if (loc >= n) {
if (loc != 0) { if (loc != 0) {

@ -88,9 +88,9 @@ int X509_REQ_set_pubkey(X509_REQ *x, EVP_PKEY *pkey) {
} }
int X509_REQ_set1_signature_algo(X509_REQ *req, const X509_ALGOR *algo) { int X509_REQ_set1_signature_algo(X509_REQ *req, const X509_ALGOR *algo) {
/* TODO(https://crbug.com/boringssl/407): Generated ASN.1 dup functions // TODO(https://crbug.com/boringssl/407): Generated ASN.1 dup functions
* should be const. Alternatively, when we can embed required fields // should be const. Alternatively, when we can embed required fields
* directly in structs, import |X509_ALGOR_copy| from upstream. */ // directly in structs, import |X509_ALGOR_copy| from upstream.
X509_ALGOR *copy = X509_ALGOR_dup((X509_ALGOR *)algo); X509_ALGOR *copy = X509_ALGOR_dup((X509_ALGOR *)algo);
if (copy == NULL) { if (copy == NULL) {
return 0; return 0;

@ -75,7 +75,7 @@ EVP_PKEY *NETSCAPE_SPKI_get_pubkey(NETSCAPE_SPKI *x) {
return (X509_PUBKEY_get(x->spkac->pubkey)); return (X509_PUBKEY_get(x->spkac->pubkey));
} }
/* Load a Netscape SPKI from a base64 encoded string */ // Load a Netscape SPKI from a base64 encoded string
NETSCAPE_SPKI *NETSCAPE_SPKI_b64_decode(const char *str, int len) { NETSCAPE_SPKI *NETSCAPE_SPKI_b64_decode(const char *str, int len) {
unsigned char *spki_der; unsigned char *spki_der;
@ -105,7 +105,7 @@ NETSCAPE_SPKI *NETSCAPE_SPKI_b64_decode(const char *str, int len) {
return spki; return spki;
} }
/* Generate a base64 encoded string from an SPKI */ // Generate a base64 encoded string from an SPKI
char *NETSCAPE_SPKI_b64_encode(NETSCAPE_SPKI *spki) { char *NETSCAPE_SPKI_b64_encode(NETSCAPE_SPKI *spki) {
unsigned char *der_spki, *p; unsigned char *der_spki, *p;

@ -127,7 +127,7 @@ void X509_ALGOR_get0(const ASN1_OBJECT **out_obj, int *out_param_type,
} }
} }
/* Set up an X509_ALGOR DigestAlgorithmIdentifier from an EVP_MD */ // Set up an X509_ALGOR DigestAlgorithmIdentifier from an EVP_MD
void X509_ALGOR_set_md(X509_ALGOR *alg, const EVP_MD *md) { void X509_ALGOR_set_md(X509_ALGOR *alg, const EVP_MD *md) {
int param_type; int param_type;
@ -141,9 +141,7 @@ void X509_ALGOR_set_md(X509_ALGOR *alg, const EVP_MD *md) {
X509_ALGOR_set0(alg, OBJ_nid2obj(EVP_MD_type(md)), param_type, 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.
* 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 X509_ALGOR_cmp(const X509_ALGOR *a, const X509_ALGOR *b) {
int rv; int rv;
rv = OBJ_cmp(a->algorithm, b->algorithm); rv = OBJ_cmp(a->algorithm, b->algorithm);

@ -80,11 +80,9 @@ ASN1_SEQUENCE(X509_REVOKED) = {
static int crl_lookup(X509_CRL *crl, X509_REVOKED **ret, ASN1_INTEGER *serial, static int crl_lookup(X509_CRL *crl, X509_REVOKED **ret, ASN1_INTEGER *serial,
X509_NAME *issuer); X509_NAME *issuer);
/* // The X509_CRL_INFO structure needs a bit of customisation. Since we cache
* The X509_CRL_INFO structure needs a bit of customisation. Since we cache // the original encoding the signature wont be affected by reordering of the
* the original encoding the signature wont be affected by reordering of the // revoked field.
* revoked field.
*/
static int crl_inf_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it, static int crl_inf_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it,
void *exarg) { void *exarg) {
X509_CRL_INFO *a = (X509_CRL_INFO *)*pval; X509_CRL_INFO *a = (X509_CRL_INFO *)*pval;
@ -93,10 +91,8 @@ static int crl_inf_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it,
return 1; return 1;
} }
switch (operation) { switch (operation) {
/* // Just set cmp function here. We don't sort because that would
* Just set cmp function here. We don't sort because that would // affect the output of X509_CRL_print().
* affect the output of X509_CRL_print().
*/
case ASN1_OP_D2I_POST: case ASN1_OP_D2I_POST:
(void)sk_X509_REVOKED_set_cmp_func(a->revoked, X509_REVOKED_cmp); (void)sk_X509_REVOKED_set_cmp_func(a->revoked, X509_REVOKED_cmp);
break; break;
@ -115,10 +111,8 @@ ASN1_SEQUENCE_enc(X509_CRL_INFO, enc, crl_inf_cb) = {
ASN1_EXP_SEQUENCE_OF_OPT(X509_CRL_INFO, extensions, X509_EXTENSION, 0), ASN1_EXP_SEQUENCE_OF_OPT(X509_CRL_INFO, extensions, X509_EXTENSION, 0),
} ASN1_SEQUENCE_END_enc(X509_CRL_INFO, X509_CRL_INFO) } ASN1_SEQUENCE_END_enc(X509_CRL_INFO, X509_CRL_INFO)
/* // Set CRL entry issuer according to CRL certificate issuer extension. Check
* Set CRL entry issuer according to CRL certificate issuer extension. Check // for unhandled critical CRL entry extensions.
* for unhandled critical CRL entry extensions.
*/
static int crl_set_issuers(X509_CRL *crl) { static int crl_set_issuers(X509_CRL *crl) {
size_t i, k; size_t i, k;
@ -167,7 +161,7 @@ static int crl_set_issuers(X509_CRL *crl) {
rev->reason = CRL_REASON_NONE; rev->reason = CRL_REASON_NONE;
} }
/* Check for critical CRL entry extensions */ // Check for critical CRL entry extensions
exts = rev->extensions; exts = rev->extensions;
@ -187,10 +181,8 @@ static int crl_set_issuers(X509_CRL *crl) {
return 1; return 1;
} }
/* // The X509_CRL structure needs a bit of customisation. Cache some extensions
* The X509_CRL structure needs a bit of customisation. Cache some extensions // and hash of the whole CRL.
* and hash of the whole CRL.
*/
static int crl_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it, static int crl_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it,
void *exarg) { void *exarg) {
X509_CRL *crl = (X509_CRL *)*pval; X509_CRL *crl = (X509_CRL *)*pval;
@ -212,20 +204,20 @@ static int crl_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it,
break; break;
case ASN1_OP_D2I_POST: { case ASN1_OP_D2I_POST: {
/* The version must be one of v1(0) or v2(1). */ // The version must be one of v1(0) or v2(1).
long version = X509_CRL_VERSION_1; long version = X509_CRL_VERSION_1;
if (crl->crl->version != NULL) { if (crl->crl->version != NULL) {
version = ASN1_INTEGER_get(crl->crl->version); version = ASN1_INTEGER_get(crl->crl->version);
/* TODO(https://crbug.com/boringssl/364): |X509_CRL_VERSION_1| // TODO(https://crbug.com/boringssl/364): |X509_CRL_VERSION_1|
* should also be rejected. This means an explicitly-encoded X.509v1 // should also be rejected. This means an explicitly-encoded X.509v1
* version. v1 is DEFAULT, so DER requires it be omitted. */ // version. v1 is DEFAULT, so DER requires it be omitted.
if (version < X509_CRL_VERSION_1 || version > X509_CRL_VERSION_2) { if (version < X509_CRL_VERSION_1 || version > X509_CRL_VERSION_2) {
OPENSSL_PUT_ERROR(X509, X509_R_INVALID_VERSION); OPENSSL_PUT_ERROR(X509, X509_R_INVALID_VERSION);
return 0; return 0;
} }
} }
/* Per RFC 5280, section 5.1.2.1, extensions require v2. */ // Per RFC 5280, section 5.1.2.1, extensions require v2.
if (version != X509_CRL_VERSION_2 && crl->crl->extensions != NULL) { if (version != X509_CRL_VERSION_2 && crl->crl->extensions != NULL) {
OPENSSL_PUT_ERROR(X509, X509_R_INVALID_FIELD_FOR_VERSION); OPENSSL_PUT_ERROR(X509, X509_R_INVALID_FIELD_FOR_VERSION);
return 0; return 0;
@ -260,18 +252,16 @@ static int crl_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it,
if (crl->base_crl_number == NULL && i != -1) { if (crl->base_crl_number == NULL && i != -1) {
return 0; return 0;
} }
/* Delta CRLs must have CRL number */ // Delta CRLs must have CRL number
if (crl->base_crl_number && !crl->crl_number) { if (crl->base_crl_number && !crl->crl_number) {
OPENSSL_PUT_ERROR(X509, X509_R_DELTA_CRL_WITHOUT_CRL_NUMBER); OPENSSL_PUT_ERROR(X509, X509_R_DELTA_CRL_WITHOUT_CRL_NUMBER);
return 0; return 0;
} }
/* // See if we have any unhandled critical CRL extensions and indicate
* See if we have any unhandled critical CRL extensions and indicate // this in a flag. We only currently handle IDP so anything else
* this in a flag. We only currently handle IDP so anything else // critical sets the flag. This code accesses the X509_CRL structure
* critical sets the flag. This code accesses the X509_CRL structure // directly: applications shouldn't do this.
* directly: applications shouldn't do this.
*/
exts = crl->crl->extensions; exts = crl->crl->extensions;
@ -283,7 +273,7 @@ static int crl_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it,
crl->flags |= EXFLAG_FRESHEST; crl->flags |= EXFLAG_FRESHEST;
} }
if (X509_EXTENSION_get_critical(ext)) { if (X509_EXTENSION_get_critical(ext)) {
/* We handle IDP and deltas */ // We handle IDP and deltas
if ((nid == NID_issuing_distribution_point) || if ((nid == NID_issuing_distribution_point) ||
(nid == NID_authority_key_identifier) || (nid == NID_delta_crl)) { (nid == NID_authority_key_identifier) || (nid == NID_delta_crl)) {
continue; continue;
@ -311,11 +301,11 @@ static int crl_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it,
return 1; return 1;
} }
/* Convert IDP into a more convenient form */ // Convert IDP into a more convenient form
static int setup_idp(X509_CRL *crl, ISSUING_DIST_POINT *idp) { static int setup_idp(X509_CRL *crl, ISSUING_DIST_POINT *idp) {
int idp_only = 0; int idp_only = 0;
/* Set various flags according to IDP */ // Set various flags according to IDP
crl->idp_flags |= IDP_PRESENT; crl->idp_flags |= IDP_PRESENT;
if (idp->onlyuser > 0) { if (idp->onlyuser > 0) {
idp_only++; idp_only++;
@ -441,10 +431,8 @@ static int crl_lookup(X509_CRL *crl, X509_REVOKED **ret, ASN1_INTEGER *serial,
X509_REVOKED rtmp, *rev; X509_REVOKED rtmp, *rev;
size_t idx; size_t idx;
rtmp.serialNumber = serial; rtmp.serialNumber = serial;
/* // Sort revoked into serial number order if not already sorted. Do this
* Sort revoked into serial number order if not already sorted. Do this // under a lock to avoid race condition.
* under a lock to avoid race condition.
*/
CRYPTO_STATIC_MUTEX_lock_read(&g_crl_sort_lock); CRYPTO_STATIC_MUTEX_lock_read(&g_crl_sort_lock);
const int is_sorted = sk_X509_REVOKED_is_sorted(crl->crl->revoked); const int is_sorted = sk_X509_REVOKED_is_sorted(crl->crl->revoked);
@ -461,7 +449,7 @@ static int crl_lookup(X509_CRL *crl, X509_REVOKED **ret, ASN1_INTEGER *serial,
if (!sk_X509_REVOKED_find(crl->crl->revoked, &idx, &rtmp)) { if (!sk_X509_REVOKED_find(crl->crl->revoked, &idx, &rtmp)) {
return 0; return 0;
} }
/* Need to look for matching name */ // Need to look for matching name
for (; idx < sk_X509_REVOKED_num(crl->crl->revoked); idx++) { for (; idx < sk_X509_REVOKED_num(crl->crl->revoked); idx++) {
rev = sk_X509_REVOKED_value(crl->crl->revoked, idx); rev = sk_X509_REVOKED_value(crl->crl->revoked, idx);
if (ASN1_INTEGER_cmp(rev->serialNumber, serial)) { if (ASN1_INTEGER_cmp(rev->serialNumber, serial)) {

@ -74,10 +74,8 @@
typedef STACK_OF(X509_NAME_ENTRY) STACK_OF_X509_NAME_ENTRY; typedef STACK_OF(X509_NAME_ENTRY) STACK_OF_X509_NAME_ENTRY;
DEFINE_STACK_OF(STACK_OF_X509_NAME_ENTRY) DEFINE_STACK_OF(STACK_OF_X509_NAME_ENTRY)
/* // Maximum length of X509_NAME: much larger than anything we should
* Maximum length of X509_NAME: much larger than anything we should // ever see in practice.
* ever see in practice.
*/
#define X509_NAME_MAX (1024 * 1024) #define X509_NAME_MAX (1024 * 1024)
@ -104,10 +102,8 @@ ASN1_SEQUENCE(X509_NAME_ENTRY) = {
IMPLEMENT_ASN1_FUNCTIONS(X509_NAME_ENTRY) IMPLEMENT_ASN1_FUNCTIONS(X509_NAME_ENTRY)
IMPLEMENT_ASN1_DUP_FUNCTION(X509_NAME_ENTRY) IMPLEMENT_ASN1_DUP_FUNCTION(X509_NAME_ENTRY)
/* // For the "Name" type we need a SEQUENCE OF { SET OF X509_NAME_ENTRY } so
* For the "Name" type we need a SEQUENCE OF { SET OF X509_NAME_ENTRY } so // declare two template wrappers for this
* declare two template wrappers for this
*/
ASN1_ITEM_TEMPLATE(X509_NAME_ENTRIES) = ASN1_EX_TEMPLATE_TYPE(ASN1_TFLG_SET_OF, ASN1_ITEM_TEMPLATE(X509_NAME_ENTRIES) = ASN1_EX_TEMPLATE_TYPE(ASN1_TFLG_SET_OF,
0, RDNS, 0, RDNS,
@ -118,18 +114,16 @@ 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) ASN1_ITEM_TEMPLATE_END(X509_NAME_INTERNAL)
/* // Normally that's where it would end: we'd have two nested STACK structures
* Normally that's where it would end: we'd have two nested STACK structures // representing the ASN1. Unfortunately X509_NAME uses a completely different
* representing the ASN1. Unfortunately X509_NAME uses a completely different // form and caches encodings so we have to process the internal form and
* form and caches encodings so we have to process the internal form and // convert to the external form.
* convert to the external form.
*/
static const ASN1_EXTERN_FUNCS x509_name_ff = { static const ASN1_EXTERN_FUNCS x509_name_ff = {
NULL, NULL,
x509_name_ex_new, x509_name_ex_new,
x509_name_ex_free, x509_name_ex_free,
0, /* Default clear behaviour is OK */ 0, // Default clear behaviour is OK
x509_name_ex_d2i, x509_name_ex_d2i,
x509_name_ex_i2d, x509_name_ex_i2d,
NULL, NULL,
@ -204,13 +198,13 @@ static int x509_name_ex_d2i(ASN1_VALUE **val, const unsigned char **in,
int ret; int ret;
STACK_OF(X509_NAME_ENTRY) *entries; STACK_OF(X509_NAME_ENTRY) *entries;
X509_NAME_ENTRY *entry; X509_NAME_ENTRY *entry;
/* Bound the size of an X509_NAME we are willing to parse. */ // Bound the size of an X509_NAME we are willing to parse.
if (len > X509_NAME_MAX) { if (len > X509_NAME_MAX) {
len = X509_NAME_MAX; len = X509_NAME_MAX;
} }
q = p; q = p;
/* Get internal representation of Name */ // Get internal representation of Name
ASN1_VALUE *intname_val = NULL; ASN1_VALUE *intname_val = NULL;
ret = ASN1_item_ex_d2i(&intname_val, &p, len, ret = ASN1_item_ex_d2i(&intname_val, &p, len,
ASN1_ITEM_rptr(X509_NAME_INTERNAL), tag, aclass, opt, ASN1_ITEM_rptr(X509_NAME_INTERNAL), tag, aclass, opt,
@ -228,13 +222,13 @@ static int x509_name_ex_d2i(ASN1_VALUE **val, const unsigned char **in,
goto err; goto err;
} }
nm = (X509_NAME *)nm_val; nm = (X509_NAME *)nm_val;
/* We've decoded it: now cache encoding */ // We've decoded it: now cache encoding
if (!BUF_MEM_grow(nm->bytes, p - q)) { if (!BUF_MEM_grow(nm->bytes, p - q)) {
goto err; goto err;
} }
OPENSSL_memcpy(nm->bytes->data, q, p - q); OPENSSL_memcpy(nm->bytes->data, q, p - q);
/* Convert internal representation to X509_NAME structure */ // Convert internal representation to X509_NAME structure
for (i = 0; i < sk_STACK_OF_X509_NAME_ENTRY_num(intname); i++) { for (i = 0; i < sk_STACK_OF_X509_NAME_ENTRY_num(intname); i++) {
entries = sk_STACK_OF_X509_NAME_ENTRY_value(intname, i); entries = sk_STACK_OF_X509_NAME_ENTRY_value(intname, i);
for (j = 0; j < sk_X509_NAME_ENTRY_num(entries); j++) { for (j = 0; j < sk_X509_NAME_ENTRY_num(entries); j++) {
@ -330,16 +324,14 @@ err:
return 0; return 0;
} }
/* // This function generates the canonical encoding of the Name structure. In
* This function generates the canonical encoding of the Name structure. In // it all strings are converted to UTF8, leading, trailing and multiple
* it all strings are converted to UTF8, leading, trailing and multiple // spaces collapsed, converted to lower case and the leading SEQUENCE header
* spaces collapsed, converted to lower case and the leading SEQUENCE header // removed. In future we could also normalize the UTF8 too. By doing this
* removed. In future we could also normalize the UTF8 too. By doing this // comparison of Name structures can be rapidly perfomed by just using
* comparison of Name structures can be rapidly perfomed by just using // OPENSSL_memcmp() of the canonical encoding. By omitting the leading SEQUENCE
* OPENSSL_memcmp() of the canonical encoding. By omitting the leading SEQUENCE // name constraints of type dirName can also be checked with a simple
* name constraints of type dirName can also be checked with a simple // OPENSSL_memcmp().
* OPENSSL_memcmp().
*/
static int x509_name_canon(X509_NAME *a) { static int x509_name_canon(X509_NAME *a) {
unsigned char *p; unsigned char *p;
@ -353,7 +345,7 @@ static int x509_name_canon(X509_NAME *a) {
OPENSSL_free(a->canon_enc); OPENSSL_free(a->canon_enc);
a->canon_enc = NULL; a->canon_enc = NULL;
} }
/* Special case: empty X509_NAME => null encoding */ // Special case: empty X509_NAME => null encoding
if (sk_X509_NAME_ENTRY_num(a->entries) == 0) { if (sk_X509_NAME_ENTRY_num(a->entries) == 0) {
a->canon_enclen = 0; a->canon_enclen = 0;
return 1; return 1;
@ -389,7 +381,7 @@ static int x509_name_canon(X509_NAME *a) {
tmpentry = NULL; tmpentry = NULL;
} }
/* Finally generate encoding */ // Finally generate encoding
len = i2d_name_canon(intname, NULL); len = i2d_name_canon(intname, NULL);
if (len < 0) { if (len < 0) {
@ -421,7 +413,7 @@ err:
return ret; return ret;
} }
/* Bitmap of all the types of string that will be canonicalized. */ // Bitmap of all the types of string that will be canonicalized.
#define ASN1_MASK_CANON \ #define ASN1_MASK_CANON \
(B_ASN1_UTF8STRING | B_ASN1_BMPSTRING | B_ASN1_UNIVERSALSTRING | \ (B_ASN1_UTF8STRING | B_ASN1_BMPSTRING | B_ASN1_UNIVERSALSTRING | \
@ -432,7 +424,7 @@ static int asn1_string_canon(ASN1_STRING *out, ASN1_STRING *in) {
unsigned char *to, *from; unsigned char *to, *from;
int len, i; int len, i;
/* If type not in bitmask just copy string across */ // If type not in bitmask just copy string across
if (!(ASN1_tag2bit(in->type) & ASN1_MASK_CANON)) { if (!(ASN1_tag2bit(in->type) & ASN1_MASK_CANON)) {
if (!ASN1_STRING_copy(out, in)) { if (!ASN1_STRING_copy(out, in)) {
return 0; return 0;
@ -451,13 +443,11 @@ static int asn1_string_canon(ASN1_STRING *out, ASN1_STRING *in) {
len = out->length; len = out->length;
/* // Convert string in place to canonical form. Ultimately we may need to
* Convert string in place to canonical form. Ultimately we may need to // handle a wider range of characters but for now ignore anything with
* handle a wider range of characters but for now ignore anything with // MSB set and rely on the isspace() and tolower() functions.
* MSB set and rely on the isspace() and tolower() functions.
*/
/* Ignore leading spaces */ // Ignore leading spaces
while ((len > 0) && !(*from & 0x80) && isspace(*from)) { while ((len > 0) && !(*from & 0x80) && isspace(*from)) {
from++; from++;
len--; len--;
@ -465,7 +455,7 @@ static int asn1_string_canon(ASN1_STRING *out, ASN1_STRING *in) {
to = from + len; to = from + len;
/* Ignore trailing spaces */ // Ignore trailing spaces
while ((len > 0) && !(to[-1] & 0x80) && isspace(to[-1])) { while ((len > 0) && !(to[-1] & 0x80) && isspace(to[-1])) {
to--; to--;
len--; len--;
@ -475,20 +465,18 @@ static int asn1_string_canon(ASN1_STRING *out, ASN1_STRING *in) {
i = 0; i = 0;
while (i < len) { while (i < len) {
/* If MSB set just copy across */ // If MSB set just copy across
if (*from & 0x80) { if (*from & 0x80) {
*to++ = *from++; *to++ = *from++;
i++; i++;
} }
/* Collapse multiple spaces */ // Collapse multiple spaces
else if (isspace(*from)) { else if (isspace(*from)) {
/* Copy one space across */ // Copy one space across
*to++ = ' '; *to++ = ' ';
/* // Ignore subsequent spaces. Note: don't need to check len here
* 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
* because we know the last character is a non-space so we can't // overflow.
* overflow.
*/
do { do {
from++; from++;
i++; i++;
@ -538,7 +526,7 @@ 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, int X509_NAME_get0_der(X509_NAME *nm, const unsigned char **pder,
size_t *pderlen) { size_t *pderlen) {
/* Make sure encoding is valid */ // Make sure encoding is valid
if (i2d_X509_NAME(nm, NULL) <= 0) { if (i2d_X509_NAME(nm, NULL) <= 0) {
return 0; return 0;
} }

@ -70,7 +70,7 @@
#include "../internal.h" #include "../internal.h"
#include "internal.h" #include "internal.h"
/* Minor tweak to operation: free up EVP_PKEY */ // Minor tweak to operation: free up EVP_PKEY
static int pubkey_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it, static int pubkey_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it,
void *exarg) { void *exarg) {
if (operation == ASN1_OP_FREE_POST) { if (operation == ASN1_OP_FREE_POST) {
@ -122,10 +122,10 @@ error:
return 0; return 0;
} }
/* g_pubkey_lock is used to protect the initialisation of the |pkey| member of // g_pubkey_lock is used to protect the initialisation of the |pkey| member of
* |X509_PUBKEY| objects. Really |X509_PUBKEY| should have a |CRYPTO_once_t| // |X509_PUBKEY| objects. Really |X509_PUBKEY| should have a |CRYPTO_once_t|
* inside it for this, but |CRYPTO_once_t| is private and |X509_PUBKEY| is // inside it for this, but |CRYPTO_once_t| is private and |X509_PUBKEY| is
* not. */ // not.
static struct CRYPTO_STATIC_MUTEX g_pubkey_lock = CRYPTO_STATIC_MUTEX_INIT; static struct CRYPTO_STATIC_MUTEX g_pubkey_lock = CRYPTO_STATIC_MUTEX_INIT;
EVP_PKEY *X509_PUBKEY_get(X509_PUBKEY *key) { EVP_PKEY *X509_PUBKEY_get(X509_PUBKEY *key) {
@ -144,7 +144,7 @@ EVP_PKEY *X509_PUBKEY_get(X509_PUBKEY *key) {
} }
CRYPTO_STATIC_MUTEX_unlock_read(&g_pubkey_lock); CRYPTO_STATIC_MUTEX_unlock_read(&g_pubkey_lock);
/* Re-encode the |X509_PUBKEY| to DER and parse it. */ // Re-encode the |X509_PUBKEY| to DER and parse it.
int spki_len = i2d_X509_PUBKEY(key, &spki); int spki_len = i2d_X509_PUBKEY(key, &spki);
if (spki_len < 0) { if (spki_len < 0) {
goto error; goto error;
@ -157,7 +157,7 @@ EVP_PKEY *X509_PUBKEY_get(X509_PUBKEY *key) {
goto error; goto error;
} }
/* Check to see if another thread set key->pkey first */ // Check to see if another thread set key->pkey first
CRYPTO_STATIC_MUTEX_lock_write(&g_pubkey_lock); CRYPTO_STATIC_MUTEX_lock_write(&g_pubkey_lock);
if (key->pkey) { if (key->pkey) {
CRYPTO_STATIC_MUTEX_unlock_write(&g_pubkey_lock); CRYPTO_STATIC_MUTEX_unlock_write(&g_pubkey_lock);
@ -185,7 +185,7 @@ int X509_PUBKEY_set0_param(X509_PUBKEY *pub, ASN1_OBJECT *obj, int param_type,
} }
ASN1_STRING_set0(pub->public_key, key, key_len); ASN1_STRING_set0(pub->public_key, key, key_len);
/* Set the number of unused bits to zero. */ // 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 | 0x07);
pub->public_key->flags |= ASN1_STRING_FLAG_BITS_LEFT; pub->public_key->flags |= ASN1_STRING_FLAG_BITS_LEFT;
return 1; return 1;

@ -63,14 +63,12 @@
#include "internal.h" #include "internal.h"
/* // X509_REQ_INFO is handled in an unusual way to get round invalid encodings.
* X509_REQ_INFO is handled in an unusual way to get round invalid encodings. // Some broken certificate requests don't encode the attributes field if it
* Some broken certificate requests don't encode the attributes field if it // is empty. This is in violation of PKCS#10 but we need to tolerate it. We
* is empty. This is in violation of PKCS#10 but we need to tolerate it. We // do this by making the attributes field OPTIONAL then using the callback to
* do this by making the attributes field OPTIONAL then using the callback to // initialise it to an empty STACK. This means that the field will be
* initialise it to an empty STACK. This means that the field will be // correctly encoded unless we NULL out the field.
* correctly encoded unless we NULL out the field.
*/
static int rinf_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it, static int rinf_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it,
void *exarg) { void *exarg) {
@ -97,7 +95,7 @@ ASN1_SEQUENCE_enc(X509_REQ_INFO, enc, rinf_cb) = {
ASN1_SIMPLE(X509_REQ_INFO, version, ASN1_INTEGER), ASN1_SIMPLE(X509_REQ_INFO, version, ASN1_INTEGER),
ASN1_SIMPLE(X509_REQ_INFO, subject, X509_NAME), ASN1_SIMPLE(X509_REQ_INFO, subject, X509_NAME),
ASN1_SIMPLE(X509_REQ_INFO, pubkey, X509_PUBKEY), ASN1_SIMPLE(X509_REQ_INFO, pubkey, X509_PUBKEY),
/* This isn't really OPTIONAL but it gets around invalid encodings. */ // This isn't really OPTIONAL but it gets around invalid encodings.
ASN1_IMP_SET_OF_OPT(X509_REQ_INFO, attributes, X509_ATTRIBUTE, 0), ASN1_IMP_SET_OF_OPT(X509_REQ_INFO, attributes, X509_ATTRIBUTE, 0),
} ASN1_SEQUENCE_END_enc(X509_REQ_INFO, X509_REQ_INFO) } ASN1_SEQUENCE_END_enc(X509_REQ_INFO, X509_REQ_INFO)

@ -55,10 +55,8 @@
* copied and put under another distribution licence * copied and put under another distribution licence
* [including the GNU Public Licence.] */ * [including the GNU Public Licence.] */
/* // This module was send to me my Pat Richards <patr@x509.com> who wrote it.
* This module was send to me my Pat Richards <patr@x509.com> who wrote it. // It is under my Copyright with his permission.
* It is under my Copyright with his permission.
*/
#include <openssl/asn1t.h> #include <openssl/asn1t.h>
#include <openssl/x509.h> #include <openssl/x509.h>

@ -87,7 +87,7 @@ ASN1_SEQUENCE_enc(X509_CINF, enc, 0) = {
} ASN1_SEQUENCE_END_enc(X509_CINF, X509_CINF) } ASN1_SEQUENCE_END_enc(X509_CINF, X509_CINF)
IMPLEMENT_ASN1_FUNCTIONS(X509_CINF) IMPLEMENT_ASN1_FUNCTIONS(X509_CINF)
/* X509 top level structure needs a bit of customisation */ // X509 top level structure needs a bit of customisation
extern void policy_cache_free(X509_POLICY_CACHE *cache); extern void policy_cache_free(X509_POLICY_CACHE *cache);
@ -114,27 +114,27 @@ static int x509_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it,
break; break;
case ASN1_OP_D2I_POST: { case ASN1_OP_D2I_POST: {
/* The version must be one of v1(0), v2(1), or v3(2). */ // The version must be one of v1(0), v2(1), or v3(2).
long version = X509_VERSION_1; long version = X509_VERSION_1;
if (ret->cert_info->version != NULL) { if (ret->cert_info->version != NULL) {
version = ASN1_INTEGER_get(ret->cert_info->version); version = ASN1_INTEGER_get(ret->cert_info->version);
/* TODO(https://crbug.com/boringssl/364): |X509_VERSION_1| should // TODO(https://crbug.com/boringssl/364): |X509_VERSION_1| should
* also be rejected here. This means an explicitly-encoded X.509v1 // also be rejected here. This means an explicitly-encoded X.509v1
* version. v1 is DEFAULT, so DER requires it be omitted. */ // version. v1 is DEFAULT, so DER requires it be omitted.
if (version < X509_VERSION_1 || version > X509_VERSION_3) { if (version < X509_VERSION_1 || version > X509_VERSION_3) {
OPENSSL_PUT_ERROR(X509, X509_R_INVALID_VERSION); OPENSSL_PUT_ERROR(X509, X509_R_INVALID_VERSION);
return 0; return 0;
} }
} }
/* Per RFC 5280, section 4.1.2.8, these fields require v2 or v3. */ // Per RFC 5280, section 4.1.2.8, these fields require v2 or v3.
if (version == X509_VERSION_1 && (ret->cert_info->issuerUID != NULL || if (version == X509_VERSION_1 && (ret->cert_info->issuerUID != NULL ||
ret->cert_info->subjectUID != NULL)) { ret->cert_info->subjectUID != NULL)) {
OPENSSL_PUT_ERROR(X509, X509_R_INVALID_FIELD_FOR_VERSION); OPENSSL_PUT_ERROR(X509, X509_R_INVALID_FIELD_FOR_VERSION);
return 0; return 0;
} }
/* Per RFC 5280, section 4.1.2.9, extensions require v3. */ // Per RFC 5280, section 4.1.2.9, extensions require v3.
if (version != X509_VERSION_3 && ret->cert_info->extensions != NULL) { if (version != X509_VERSION_3 && ret->cert_info->extensions != NULL) {
OPENSSL_PUT_ERROR(X509, X509_R_INVALID_FIELD_FOR_VERSION); OPENSSL_PUT_ERROR(X509, X509_R_INVALID_FIELD_FOR_VERSION);
return 0; return 0;
@ -224,12 +224,10 @@ void *X509_get_ex_data(X509 *r, int idx) {
return (CRYPTO_get_ex_data(&r->ex_data, idx)); return (CRYPTO_get_ex_data(&r->ex_data, idx));
} }
/* // X509_AUX ASN1 routines. X509_AUX is the name given to a certificate with
* X509_AUX ASN1 routines. X509_AUX is the name given to a certificate with // extra info tagged on the end. Since these functions set how a certificate
* extra info tagged on the end. Since these functions set how a certificate // is trusted they should only be used when the certificate comes from a
* is trusted they should only be used when the certificate comes from a // reliable source such as local storage.
* reliable source such as local storage.
*/
X509 *d2i_X509_AUX(X509 **a, const unsigned char **pp, long length) { X509 *d2i_X509_AUX(X509 **a, const unsigned char **pp, long length) {
const unsigned char *q = *pp; const unsigned char *q = *pp;
@ -240,13 +238,13 @@ X509 *d2i_X509_AUX(X509 **a, const unsigned char **pp, long length) {
freeret = 1; freeret = 1;
} }
ret = d2i_X509(a, &q, length); ret = d2i_X509(a, &q, length);
/* If certificate unreadable then forget it */ // If certificate unreadable then forget it
if (!ret) { if (!ret) {
return NULL; return NULL;
} }
/* update length */ // update length
length -= q - *pp; length -= q - *pp;
/* Parse auxiliary information if there is any. */ // Parse auxiliary information if there is any.
if (length > 0 && !d2i_X509_CERT_AUX(&ret->aux, &q, length)) { if (length > 0 && !d2i_X509_CERT_AUX(&ret->aux, &q, length)) {
goto err; goto err;
} }
@ -262,23 +260,19 @@ err:
return NULL; return NULL;
} }
/* // Serialize trusted certificate to *pp or just return the required buffer
* Serialize trusted certificate to *pp or just return the required buffer // length if pp == NULL. We ultimately want to avoid modifying *pp in the
* length if pp == NULL. We ultimately want to avoid modifying *pp in the // error path, but that depends on similar hygiene in lower-level functions.
* error path, but that depends on similar hygiene in lower-level functions. // Here we avoid compounding the problem.
* Here we avoid compounding the problem.
*/
static int i2d_x509_aux_internal(X509 *a, unsigned char **pp) { static int i2d_x509_aux_internal(X509 *a, unsigned char **pp) {
int length, tmplen; int length, tmplen;
unsigned char *start = pp != NULL ? *pp : NULL; unsigned char *start = pp != NULL ? *pp : NULL;
assert(pp == NULL || *pp != NULL); assert(pp == NULL || *pp != NULL);
/* // This might perturb *pp on error, but fixing that belongs in i2d_X509()
* 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
* not here. It should be that if a == NULL length is zero, but we check // both just in case.
* both just in case.
*/
length = i2d_X509(a, pp); length = i2d_X509(a, pp);
if (length <= 0 || a == NULL) { if (length <= 0 || a == NULL) {
return length; return length;
@ -298,36 +292,34 @@ static int i2d_x509_aux_internal(X509 *a, unsigned char **pp) {
return length; return length;
} }
/* // Serialize trusted certificate to *pp, or just return the required buffer
* Serialize trusted certificate to *pp, or just return the required buffer // length if pp == NULL.
* length if pp == NULL. //
* // When pp is not NULL, but *pp == NULL, we allocate the buffer, but since
* When pp is not NULL, but *pp == NULL, we allocate the buffer, but since // we're writing two ASN.1 objects back to back, we can't have i2d_X509() do
* we're writing two ASN.1 objects back to back, we can't have i2d_X509() do // the allocation, nor can we allow i2d_X509_CERT_AUX() to increment the
* the allocation, nor can we allow i2d_X509_CERT_AUX() to increment the // allocated buffer.
* allocated buffer.
*/
int i2d_X509_AUX(X509 *a, unsigned char **pp) { int i2d_X509_AUX(X509 *a, unsigned char **pp) {
int length; int length;
unsigned char *tmp; unsigned char *tmp;
/* Buffer provided by caller */ // Buffer provided by caller
if (pp == NULL || *pp != NULL) { if (pp == NULL || *pp != NULL) {
return i2d_x509_aux_internal(a, pp); return i2d_x509_aux_internal(a, pp);
} }
/* Obtain the combined length */ // Obtain the combined length
if ((length = i2d_x509_aux_internal(a, NULL)) <= 0) { if ((length = i2d_x509_aux_internal(a, NULL)) <= 0) {
return length; return length;
} }
/* Allocate requisite combined storage */ // Allocate requisite combined storage
*pp = tmp = OPENSSL_malloc(length); *pp = tmp = OPENSSL_malloc(length);
if (tmp == NULL) { if (tmp == NULL) {
return -1; /* Push error onto error stack? */ return -1; // Push error onto error stack?
} }
/* Encode, but keep *pp at the originally malloced pointer */ // Encode, but keep *pp at the originally malloced pointer
length = i2d_x509_aux_internal(a, &tmp); length = i2d_x509_aux_internal(a, &tmp);
if (length <= 0) { if (length <= 0) {
OPENSSL_free(*pp); OPENSSL_free(*pp);
@ -346,9 +338,9 @@ int i2d_X509_tbs(X509 *x509, unsigned char **outp) {
} }
int X509_set1_signature_algo(X509 *x509, const X509_ALGOR *algo) { int X509_set1_signature_algo(X509 *x509, const X509_ALGOR *algo) {
/* TODO(https://crbug.com/boringssl/407): Generated ASN.1 dup functions // TODO(https://crbug.com/boringssl/407): Generated ASN.1 dup functions
* should be const. Alternatively, when we can embed required fields // should be const. Alternatively, when we can embed required fields
* directly in structs, import |X509_ALGOR_copy| from upstream. */ // directly in structs, import |X509_ALGOR_copy| from upstream.
X509_ALGOR *copy1 = X509_ALGOR_dup((X509_ALGOR *)algo); X509_ALGOR *copy1 = X509_ALGOR_dup((X509_ALGOR *)algo);
X509_ALGOR *copy2 = X509_ALGOR_dup((X509_ALGOR *)algo); X509_ALGOR *copy2 = X509_ALGOR_dup((X509_ALGOR *)algo);
if (copy1 == NULL || copy2 == NULL) { if (copy1 == NULL || copy2 == NULL) {

@ -64,12 +64,10 @@
#include "internal.h" #include "internal.h"
/* // X509_CERT_AUX routines. These are used to encode additional user
* X509_CERT_AUX routines. These are used to encode additional user // modifiable data about a certificate. This data is appended to the X509
* modifiable data about a certificate. This data is appended to the X509 // encoding when the *_X509_AUX routines are used. This means that the
* encoding when the *_X509_AUX routines are used. This means that the // "traditional" X509 routines will simply ignore the extra data.
* "traditional" X509 routines will simply ignore the extra data.
*/
static X509_CERT_AUX *aux_get(X509 *x); static X509_CERT_AUX *aux_get(X509 *x);
@ -94,9 +92,9 @@ static X509_CERT_AUX *aux_get(X509 *x) {
int X509_alias_set1(X509 *x, const unsigned char *name, int len) { int X509_alias_set1(X509 *x, const unsigned char *name, int len) {
X509_CERT_AUX *aux; X509_CERT_AUX *aux;
/* TODO(davidben): Empty aliases are not meaningful in PKCS#12, and the // TODO(davidben): Empty aliases are not meaningful in PKCS#12, and the
* getters cannot quite represent them. Also erase the object if |len| is // getters cannot quite represent them. Also erase the object if |len| is
* zero. */ // zero.
if (!name) { if (!name) {
if (!x || !x->aux || !x->aux->alias) { if (!x || !x->aux || !x->aux->alias) {
return 1; return 1;
@ -116,9 +114,9 @@ int X509_alias_set1(X509 *x, const unsigned char *name, int len) {
int X509_keyid_set1(X509 *x, const unsigned char *id, int len) { int X509_keyid_set1(X509 *x, const unsigned char *id, int len) {
X509_CERT_AUX *aux; X509_CERT_AUX *aux;
/* TODO(davidben): Empty key IDs are not meaningful in PKCS#12, and the // 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 // getters cannot quite represent them. Also erase the object if |len| is
* zero. */ // zero.
if (!id) { if (!id) {
if (!x || !x->aux || !x->aux->keyid) { if (!x || !x->aux || !x->aux->keyid) {
return 1; return 1;

@ -54,7 +54,7 @@
* (eay@cryptsoft.com). This product includes software written by Tim * (eay@cryptsoft.com). This product includes software written by Tim
* Hudson (tjh@cryptsoft.com). */ * Hudson (tjh@cryptsoft.com). */
/* This file contains a table of "standard" extensions */ // This file contains a table of "standard" extensions
#if defined(__cplusplus) #if defined(__cplusplus)
extern "C" { extern "C" {
@ -74,12 +74,10 @@ extern const X509V3_EXT_METHOD v3_policy_mappings, v3_policy_constraints;
extern const X509V3_EXT_METHOD v3_name_constraints, v3_inhibit_anyp, v3_idp; extern const X509V3_EXT_METHOD v3_name_constraints, v3_inhibit_anyp, v3_idp;
extern const X509V3_EXT_METHOD v3_addr, v3_asid; extern const X509V3_EXT_METHOD v3_addr, v3_asid;
/* // This table will be searched using OBJ_bsearch so it *must* kept in order
* This table will be searched using OBJ_bsearch so it *must* kept in order // of the ext_nid values.
* of the ext_nid values.
*/
/* TODO(fork): OCSP support */ // TODO(fork): OCSP support
#define OPENSSL_NO_OCSP #define OPENSSL_NO_OCSP
static const X509V3_EXT_METHOD *const standard_exts[] = { static const X509V3_EXT_METHOD *const standard_exts[] = {
@ -127,11 +125,11 @@ static const X509V3_EXT_METHOD *const standard_exts[] = {
&v3_freshest_crl, &v3_freshest_crl,
}; };
/* Number of standard extensions */ // Number of standard extensions
#define STANDARD_EXTENSION_COUNT \ #define STANDARD_EXTENSION_COUNT \
(sizeof(standard_exts) / sizeof(X509V3_EXT_METHOD *)) (sizeof(standard_exts) / sizeof(X509V3_EXT_METHOD *))
#if defined(__cplusplus) #if defined(__cplusplus)
} /* extern C */ } // extern C
#endif #endif

@ -126,129 +126,114 @@ typedef struct X509_POLICY_DATA_st X509_POLICY_DATA;
DEFINE_STACK_OF(X509_POLICY_DATA) DEFINE_STACK_OF(X509_POLICY_DATA)
/* Internal structures */ // Internal structures
/* // This structure and the field names correspond to the Policy 'node' of
* This structure and the field names correspond to the Policy 'node' of // RFC 3280. NB this structure contains no pointers to parent or child data:
* RFC 3280. NB this structure contains no pointers to parent or child data: // X509_POLICY_NODE contains that. This means that the main policy data can
* X509_POLICY_NODE contains that. This means that the main policy data can // be kept static and cached with the certificate.
* be kept static and cached with the certificate.
*/
struct X509_POLICY_DATA_st { struct X509_POLICY_DATA_st {
unsigned int flags; unsigned int flags;
/* Policy OID and qualifiers for this data */ // Policy OID and qualifiers for this data
ASN1_OBJECT *valid_policy; ASN1_OBJECT *valid_policy;
STACK_OF(POLICYQUALINFO) *qualifier_set; STACK_OF(POLICYQUALINFO) *qualifier_set;
STACK_OF(ASN1_OBJECT) *expected_policy_set; STACK_OF(ASN1_OBJECT) *expected_policy_set;
}; };
/* X509_POLICY_DATA flags values */ // X509_POLICY_DATA flags values
/* // This flag indicates the structure has been mapped using a policy mapping
* This flag indicates the structure has been mapped using a policy mapping // extension. If policy mapping is not active its references get deleted.
* 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
* This flag indicates the data doesn't correspond to a policy in Certificate // Policies: it has been mapped to any policy.
* 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 */ // 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 */ // 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 */ // 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 */ // Corresponding CertificatePolicies is critical
#define POLICY_DATA_FLAG_CRITICAL 0x10 #define POLICY_DATA_FLAG_CRITICAL 0x10
/* This structure is cached with a certificate */ // This structure is cached with a certificate
struct X509_POLICY_CACHE_st { struct X509_POLICY_CACHE_st {
/* anyPolicy data or NULL if no anyPolicy */ // anyPolicy data or NULL if no anyPolicy
X509_POLICY_DATA *anyPolicy; X509_POLICY_DATA *anyPolicy;
/* other policy data */ // other policy data
STACK_OF(X509_POLICY_DATA) *data; STACK_OF(X509_POLICY_DATA) *data;
/* If InhibitAnyPolicy present this is its value or -1 if absent. */ // If InhibitAnyPolicy present this is its value or -1 if absent.
long any_skip; long any_skip;
/* // If policyConstraints and requireExplicitPolicy present this is its
* If policyConstraints and requireExplicitPolicy present this is its // value or -1 if absent.
* value or -1 if absent.
*/
long explicit_skip; long explicit_skip;
/* // If policyConstraints and policyMapping present this is its value or -1
* If policyConstraints and policyMapping present this is its value or -1 // if absent.
* if absent.
*/
long map_skip; long map_skip;
}; };
/* // #define POLICY_CACHE_FLAG_CRITICAL POLICY_DATA_FLAG_CRITICAL
* #define POLICY_CACHE_FLAG_CRITICAL POLICY_DATA_FLAG_CRITICAL
*/
/* This structure represents the relationship between nodes */ // This structure represents the relationship between nodes
struct X509_POLICY_NODE_st { struct X509_POLICY_NODE_st {
/* node data this refers to */ // node data this refers to
const X509_POLICY_DATA *data; const X509_POLICY_DATA *data;
/* Parent node */ // Parent node
X509_POLICY_NODE *parent; X509_POLICY_NODE *parent;
/* Number of child nodes */ // Number of child nodes
int nchild; int nchild;
}; };
struct X509_POLICY_LEVEL_st { struct X509_POLICY_LEVEL_st {
/* Cert for this level */ // Cert for this level
X509 *cert; X509 *cert;
/* nodes at this level */ // nodes at this level
STACK_OF(X509_POLICY_NODE) *nodes; STACK_OF(X509_POLICY_NODE) *nodes;
/* anyPolicy node */ // anyPolicy node
X509_POLICY_NODE *anyPolicy; X509_POLICY_NODE *anyPolicy;
/* Extra data */ // Extra data
/* //
* STACK_OF(X509_POLICY_DATA) *extra_data; // STACK_OF(X509_POLICY_DATA) *extra_data;
*/
unsigned int flags; unsigned int flags;
}; };
struct X509_POLICY_TREE_st { struct X509_POLICY_TREE_st {
/* This is the tree 'level' data */ // This is the tree 'level' data
X509_POLICY_LEVEL *levels; X509_POLICY_LEVEL *levels;
int nlevel; int nlevel;
/* // Extra policy data when additional nodes (not from the certificate) are
* Extra policy data when additional nodes (not from the certificate) are // required.
* required.
*/
STACK_OF(X509_POLICY_DATA) *extra_data; STACK_OF(X509_POLICY_DATA) *extra_data;
/* This is the authority constained policy set */ // This is the authority constained policy set
STACK_OF(X509_POLICY_NODE) *auth_policies; STACK_OF(X509_POLICY_NODE) *auth_policies;
STACK_OF(X509_POLICY_NODE) *user_policies; STACK_OF(X509_POLICY_NODE) *user_policies;
unsigned int flags; unsigned int flags;
}; };
/* Set if anyPolicy present in user policies */ // Set if anyPolicy present in user policies
#define POLICY_FLAG_ANY_POLICY 0x2 #define POLICY_FLAG_ANY_POLICY 0x2
/* Useful macros */ // Useful macros
#define node_data_critical(data) ((data)->flags & POLICY_DATA_FLAG_CRITICAL) #define node_data_critical(data) ((data)->flags & POLICY_DATA_FLAG_CRITICAL)
#define node_critical(node) node_data_critical((node)->data) #define node_critical(node) node_data_critical((node)->data)
/* Internal functions */ // Internal functions
X509_POLICY_DATA *policy_data_new(POLICYINFO *policy, const ASN1_OBJECT *id, X509_POLICY_DATA *policy_data_new(POLICYINFO *policy, const ASN1_OBJECT *id,
int crit); int crit);
@ -283,7 +268,7 @@ const X509_POLICY_CACHE *policy_cache_set(X509 *x);
#if defined(__cplusplus) #if defined(__cplusplus)
} /* extern C */ } // extern C
#endif #endif
#endif /* OPENSSL_HEADER_X509V3_INTERNAL_H */ #endif // OPENSSL_HEADER_X509V3_INTERNAL_H

@ -68,10 +68,8 @@ static int policy_data_cmp(const X509_POLICY_DATA **a,
const X509_POLICY_DATA **b); const X509_POLICY_DATA **b);
static int policy_cache_set_int(long *out, ASN1_INTEGER *value); static int policy_cache_set_int(long *out, ASN1_INTEGER *value);
/* // Set cache entry according to CertificatePolicies extension. Note: this
* Set cache entry according to CertificatePolicies extension. Note: this // destroys the passed CERTIFICATEPOLICIES structure.
* destroys the passed CERTIFICATEPOLICIES structure.
*/
static int policy_cache_create(X509 *x, CERTIFICATEPOLICIES *policies, static int policy_cache_create(X509 *x, CERTIFICATEPOLICIES *policies,
int crit) { int crit) {
@ -93,9 +91,7 @@ static int policy_cache_create(X509 *x, CERTIFICATEPOLICIES *policies,
if (!data) { if (!data) {
goto bad_policy; goto bad_policy;
} }
/* // Duplicate policy OIDs are illegal: reject if matches found.
* Duplicate policy OIDs are illegal: reject if matches found.
*/
sk_X509_POLICY_DATA_sort(cache->data); sk_X509_POLICY_DATA_sort(cache->data);
if (OBJ_obj2nid(data->valid_policy) == NID_any_policy) { if (OBJ_obj2nid(data->valid_policy) == NID_any_policy) {
if (cache->anyPolicy) { if (cache->anyPolicy) {
@ -146,10 +142,8 @@ static int policy_cache_new(X509 *x) {
x->policy_cache = cache; x->policy_cache = cache;
/* // Handle requireExplicitPolicy *first*. Need to process this even if we
* Handle requireExplicitPolicy *first*. Need to process this even if we // don't have any policies.
* don't have any policies.
*/
ext_pcons = X509_get_ext_d2i(x, NID_policy_constraints, &i, NULL); ext_pcons = X509_get_ext_d2i(x, NID_policy_constraints, &i, NULL);
if (!ext_pcons) { if (!ext_pcons) {
@ -170,15 +164,13 @@ static int policy_cache_new(X509 *x) {
} }
} }
/* Process CertificatePolicies */ // Process CertificatePolicies
ext_cpols = X509_get_ext_d2i(x, NID_certificate_policies, &i, NULL); ext_cpols = X509_get_ext_d2i(x, NID_certificate_policies, &i, NULL);
/* // If no CertificatePolicies extension or problem decoding then there is
* If no CertificatePolicies extension or problem decoding then there is // no point continuing because the valid policies will be NULL.
* no point continuing because the valid policies will be NULL.
*/
if (!ext_cpols) { if (!ext_cpols) {
/* If not absent some problem with extension */ // If not absent some problem with extension
if (i != -1) { if (i != -1) {
goto bad_cache; goto bad_cache;
} }
@ -187,7 +179,7 @@ static int policy_cache_new(X509 *x) {
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) { if (i <= 0) {
return i; return i;
@ -196,7 +188,7 @@ static int policy_cache_new(X509 *x) {
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 (!ext_pmaps) {
/* If not absent some problem with extension */ // If not absent some problem with extension
if (i != -1) { if (i != -1) {
goto bad_cache; goto bad_cache;
} }
@ -246,11 +238,9 @@ void policy_cache_free(X509_POLICY_CACHE *cache) {
OPENSSL_free(cache); OPENSSL_free(cache);
} }
/* // g_x509_policy_cache_lock is used to protect against concurrent calls to
* g_x509_policy_cache_lock is used to protect against concurrent calls to // |policy_cache_new|. Ideally this would be done with a |CRYPTO_once_t| in
* |policy_cache_new|. Ideally this would be done with a |CRYPTO_once_t| in // the |X509| structure, but |CRYPTO_once_t| isn't public.
* the |X509| structure, but |CRYPTO_once_t| isn't public.
*/
static struct CRYPTO_STATIC_MUTEX g_x509_policy_cache_lock = static struct CRYPTO_STATIC_MUTEX g_x509_policy_cache_lock =
CRYPTO_STATIC_MUTEX_INIT; CRYPTO_STATIC_MUTEX_INIT;

@ -64,11 +64,11 @@
#include "internal.h" #include "internal.h"
/* Policy Node routines */ // Policy Node routines
void policy_data_free(X509_POLICY_DATA *data) { void policy_data_free(X509_POLICY_DATA *data) {
ASN1_OBJECT_free(data->valid_policy); ASN1_OBJECT_free(data->valid_policy);
/* Don't free qualifiers if shared */ // Don't free qualifiers if shared
if (!(data->flags & POLICY_DATA_FLAG_SHARED_QUALIFIERS)) { if (!(data->flags & POLICY_DATA_FLAG_SHARED_QUALIFIERS)) {
sk_POLICYQUALINFO_pop_free(data->qualifier_set, POLICYQUALINFO_free); sk_POLICYQUALINFO_pop_free(data->qualifier_set, POLICYQUALINFO_free);
} }
@ -76,13 +76,11 @@ void policy_data_free(X509_POLICY_DATA *data) {
OPENSSL_free(data); OPENSSL_free(data);
} }
/* // Create a data based on an existing policy. If 'id' is NULL use the oid in
* Create a data based on an existing policy. If 'id' is NULL use the oid in // the policy, otherwise use 'id'. This behaviour covers the two types of
* the policy, otherwise use 'id'. This behaviour covers the two types of // data in RFC 3280: data with from a CertificatePolcies extension and
* data in RFC 3280: data with from a CertificatePolcies extension and // additional data with just the qualifiers of anyPolicy and ID from another
* additional data with just the qualifiers of anyPolicy and ID from another // source.
* source.
*/
X509_POLICY_DATA *policy_data_new(POLICYINFO *policy, const ASN1_OBJECT *cid, X509_POLICY_DATA *policy_data_new(POLICYINFO *policy, const ASN1_OBJECT *cid,
int crit) { int crit) {

@ -60,9 +60,9 @@
#include "internal.h" #include "internal.h"
/* accessor functions */ // accessor functions
/* X509_POLICY_TREE stuff */ // X509_POLICY_TREE stuff
int X509_policy_tree_level_count(const X509_POLICY_TREE *tree) { int X509_policy_tree_level_count(const X509_POLICY_TREE *tree) {
if (!tree) { if (!tree) {
@ -99,7 +99,7 @@ STACK_OF(X509_POLICY_NODE) *X509_policy_tree_get0_user_policies(
} }
} }
/* X509_POLICY_LEVEL stuff */ // X509_POLICY_LEVEL stuff
int X509_policy_level_node_count(X509_POLICY_LEVEL *level) { int X509_policy_level_node_count(X509_POLICY_LEVEL *level) {
int n; int n;
@ -130,7 +130,7 @@ X509_POLICY_NODE *X509_policy_level_get0_node(X509_POLICY_LEVEL *level, int i) {
return sk_X509_POLICY_NODE_value(level->nodes, i); return sk_X509_POLICY_NODE_value(level->nodes, i);
} }
/* X509_POLICY_NODE stuff */ // X509_POLICY_NODE stuff
const ASN1_OBJECT *X509_policy_node_get0_policy(const X509_POLICY_NODE *node) { const ASN1_OBJECT *X509_policy_node_get0_policy(const X509_POLICY_NODE *node) {
if (!node) { if (!node) {

@ -64,10 +64,8 @@
#include "../x509/internal.h" #include "../x509/internal.h"
#include "internal.h" #include "internal.h"
/* // Set policy mapping entries in cache. Note: this modifies the passed
* Set policy mapping entries in cache. Note: this modifies the passed // POLICY_MAPPINGS structure
* POLICY_MAPPINGS structure
*/
int policy_cache_set_mapping(X509 *x, POLICY_MAPPINGS *maps) { int policy_cache_set_mapping(X509 *x, POLICY_MAPPINGS *maps) {
POLICY_MAPPING *map; POLICY_MAPPING *map;
@ -81,21 +79,21 @@ int policy_cache_set_mapping(X509 *x, POLICY_MAPPINGS *maps) {
} }
for (i = 0; i < sk_POLICY_MAPPING_num(maps); i++) { for (i = 0; i < sk_POLICY_MAPPING_num(maps); i++) {
map = sk_POLICY_MAPPING_value(maps, i); map = sk_POLICY_MAPPING_value(maps, i);
/* Reject if map to or from anyPolicy */ // Reject if map to or from anyPolicy
if ((OBJ_obj2nid(map->subjectDomainPolicy) == NID_any_policy) || if ((OBJ_obj2nid(map->subjectDomainPolicy) == NID_any_policy) ||
(OBJ_obj2nid(map->issuerDomainPolicy) == NID_any_policy)) { (OBJ_obj2nid(map->issuerDomainPolicy) == NID_any_policy)) {
ret = -1; ret = -1;
goto bad_mapping; goto bad_mapping;
} }
/* Attempt to find matching policy data */ // Attempt to find matching policy data
data = policy_cache_find_data(cache, map->issuerDomainPolicy); data = policy_cache_find_data(cache, map->issuerDomainPolicy);
/* If we don't have anyPolicy can't map */ // If we don't have anyPolicy can't map
if (!data && !cache->anyPolicy) { if (!data && !cache->anyPolicy) {
continue; continue;
} }
/* Create a NODE from anyPolicy */ // Create a NODE from anyPolicy
if (!data) { if (!data) {
data = data =
policy_data_new(NULL, map->issuerDomainPolicy, policy_data_new(NULL, map->issuerDomainPolicy,
@ -104,9 +102,7 @@ int policy_cache_set_mapping(X509 *x, POLICY_MAPPINGS *maps) {
goto bad_mapping; goto bad_mapping;
} }
data->qualifier_set = cache->anyPolicy->qualifier_set; data->qualifier_set = cache->anyPolicy->qualifier_set;
/* // map->issuerDomainPolicy = NULL;
* map->issuerDomainPolicy = NULL;
*/
data->flags |= POLICY_DATA_FLAG_MAPPED_ANY; data->flags |= POLICY_DATA_FLAG_MAPPED_ANY;
data->flags |= POLICY_DATA_FLAG_SHARED_QUALIFIERS; data->flags |= POLICY_DATA_FLAG_SHARED_QUALIFIERS;
if (!sk_X509_POLICY_DATA_push(cache->data, data)) { if (!sk_X509_POLICY_DATA_push(cache->data, data)) {

@ -160,10 +160,8 @@ node_error:
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
* See if a policy node matches a policy OID. If mapping enabled look through // expected policy set otherwise just valid policy.
* expected policy set otherwise just valid policy.
*/
int policy_node_match(const X509_POLICY_LEVEL *lvl, int policy_node_match(const X509_POLICY_LEVEL *lvl,
const X509_POLICY_NODE *node, const ASN1_OBJECT *oid) { const X509_POLICY_NODE *node, const ASN1_OBJECT *oid) {

@ -69,14 +69,10 @@
#include "../x509/internal.h" #include "../x509/internal.h"
#include "internal.h" #include "internal.h"
/* // Enable this to print out the complete policy tree at various point during
* Enable this to print out the complete policy tree at various point during // evaluation.
* evaluation.
*/
/* // #define OPENSSL_POLICY_DEBUG
* #define OPENSSL_POLICY_DEBUG
*/
#ifdef OPENSSL_POLICY_DEBUG #ifdef OPENSSL_POLICY_DEBUG
@ -133,19 +129,18 @@ static void tree_print(char *str, X509_POLICY_TREE *tree,
} }
#else #else
#define tree_print(a, b, c) /* */ #define tree_print(a, b, c) //
#endif #endif
/*- //-
* Initialize policy tree. Return values: // Initialize policy tree. Return values:
* 0 Some internal error occurred. // 0 Some internal error occurred.
* -1 Inconsistent or invalid extensions in certificates. // -1 Inconsistent or invalid extensions in certificates.
* 1 Tree initialized OK. // 1 Tree initialized OK.
* 2 Policy tree is empty. // 2 Policy tree is empty.
* 5 Tree OK and requireExplicitPolicy true. // 5 Tree OK and requireExplicitPolicy true.
* 6 Tree empty and requireExplicitPolicy true. // 6 Tree empty and requireExplicitPolicy true.
*/
static int tree_init(X509_POLICY_TREE **ptree, STACK_OF(X509) *certs, static int tree_init(X509_POLICY_TREE **ptree, STACK_OF(X509) *certs,
unsigned int flags) { unsigned int flags) {
@ -163,7 +158,7 @@ static int tree_init(X509_POLICY_TREE **ptree, STACK_OF(X509) *certs,
n = sk_X509_num(certs); n = sk_X509_num(certs);
#if 0 #if 0
/* Disable policy mapping for now... */ // Disable policy mapping for now...
flags |= X509_V_FLAG_INHIBIT_MAP; flags |= X509_V_FLAG_INHIBIT_MAP;
#endif #endif
@ -185,33 +180,27 @@ static int tree_init(X509_POLICY_TREE **ptree, STACK_OF(X509) *certs,
map_skip = n + 1; map_skip = n + 1;
} }
/* Can't do anything with just a trust anchor */ // Can't do anything with just a trust anchor
if (n == 1) { if (n == 1) {
return 1; return 1;
} }
/* // First setup policy cache in all certificates apart from the trust
* First setup policy cache in all certificates apart from the trust // anchor. Note any bad cache results on the way. Also can calculate
* anchor. Note any bad cache results on the way. Also can calculate // explicit_policy value at this point.
* explicit_policy value at this point.
*/
for (i = n - 2; i >= 0; i--) { for (i = n - 2; i >= 0; i--) {
x = sk_X509_value(certs, i); x = sk_X509_value(certs, i);
X509_check_purpose(x, -1, -1); X509_check_purpose(x, -1, -1);
cache = policy_cache_set(x); cache = policy_cache_set(x);
/* If cache NULL something bad happened: return immediately */ // If cache NULL something bad happened: return immediately
if (cache == NULL) { if (cache == NULL) {
return 0; return 0;
} }
/* // If inconsistent extensions keep a note of it but continue
* If inconsistent extensions keep a note of it but continue
*/
if (x->ex_flags & EXFLAG_INVALID_POLICY) { if (x->ex_flags & EXFLAG_INVALID_POLICY) {
ret = -1; ret = -1;
} }
/* // Otherwise if we have no data (hence no CertificatePolicies) and
* Otherwise if we have no data (hence no CertificatePolicies) and // haven't already set an inconsistent code note it.
* haven't already set an inconsistent code note it.
*/
else if ((ret == 1) && !cache->data) { else if ((ret == 1) && !cache->data) {
ret = 2; ret = 2;
} }
@ -233,7 +222,7 @@ static int tree_init(X509_POLICY_TREE **ptree, STACK_OF(X509) *certs,
return ret; return ret;
} }
/* If we get this far initialize the tree */ // If we get this far initialize the tree
tree = OPENSSL_malloc(sizeof(X509_POLICY_TREE)); tree = OPENSSL_malloc(sizeof(X509_POLICY_TREE));
@ -259,7 +248,7 @@ static int tree_init(X509_POLICY_TREE **ptree, STACK_OF(X509) *certs,
level = tree->levels; level = tree->levels;
/* Root data: initialize to anyPolicy */ // Root data: initialize to anyPolicy
data = policy_data_new(NULL, OBJ_nid2obj(NID_any_policy), 0); data = policy_data_new(NULL, OBJ_nid2obj(NID_any_policy), 0);
@ -278,12 +267,10 @@ static int tree_init(X509_POLICY_TREE **ptree, STACK_OF(X509) *certs,
level->flags |= X509_V_FLAG_INHIBIT_ANY; level->flags |= X509_V_FLAG_INHIBIT_ANY;
} }
/* Determine inhibit any and inhibit map flags */ // Determine inhibit any and inhibit map flags
if (any_skip == 0) { if (any_skip == 0) {
/* // Any matching allowed if certificate is self issued and not the
* Any matching allowed if certificate is self issued and not the // last in the chain.
* last in the chain.
*/
if (!(x->ex_flags & EXFLAG_SI) || (i == 0)) { if (!(x->ex_flags & EXFLAG_SI) || (i == 0)) {
level->flags |= X509_V_FLAG_INHIBIT_ANY; level->flags |= X509_V_FLAG_INHIBIT_ANY;
} }
@ -329,7 +316,7 @@ static int tree_link_matching_nodes(X509_POLICY_LEVEL *curr,
X509_POLICY_NODE *node; X509_POLICY_NODE *node;
int matched = 0; int matched = 0;
size_t i; size_t i;
/* Iterate through all in nodes linking matches */ // Iterate through all in nodes linking matches
for (i = 0; i < sk_X509_POLICY_NODE_num(last->nodes); i++) { for (i = 0; i < sk_X509_POLICY_NODE_num(last->nodes); i++) {
node = sk_X509_POLICY_NODE_value(last->nodes, i); node = sk_X509_POLICY_NODE_value(last->nodes, i);
if (policy_node_match(last, node, data->valid_policy)) { if (policy_node_match(last, node, data->valid_policy)) {
@ -347,10 +334,8 @@ static int tree_link_matching_nodes(X509_POLICY_LEVEL *curr,
return 1; return 1;
} }
/* // This corresponds to RFC 3280 6.1.3(d)(1): link any data from
* This corresponds to RFC 3280 6.1.3(d)(1): link any data from // CertificatePolicies onto matching parent or anyPolicy if no match.
* CertificatePolicies onto matching parent or anyPolicy if no match.
*/
static int tree_link_nodes(X509_POLICY_LEVEL *curr, static int tree_link_nodes(X509_POLICY_LEVEL *curr,
const X509_POLICY_CACHE *cache) { const X509_POLICY_CACHE *cache) {
@ -359,20 +344,18 @@ static int tree_link_nodes(X509_POLICY_LEVEL *curr,
for (i = 0; i < sk_X509_POLICY_DATA_num(cache->data); i++) { for (i = 0; i < sk_X509_POLICY_DATA_num(cache->data); i++) {
data = sk_X509_POLICY_DATA_value(cache->data, i); data = sk_X509_POLICY_DATA_value(cache->data, i);
/* // If a node is mapped any it doesn't have a corresponding
* If a node is mapped any it doesn't have a corresponding // CertificatePolicies entry. However such an identical node would
* CertificatePolicies entry. However such an identical node would // be created if anyPolicy matching is enabled because there would be
* be created if anyPolicy matching is enabled because there would be // no match with the parent valid_policy_set. So we create link
* 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
* because then it will have the mapping flags right and we can prune // it later.
* it later.
*/
#if 0 #if 0
if ((data->flags & POLICY_DATA_FLAG_MAPPED_ANY) if ((data->flags & POLICY_DATA_FLAG_MAPPED_ANY)
&& !(curr->flags & X509_V_FLAG_INHIBIT_ANY)) && !(curr->flags & X509_V_FLAG_INHIBIT_ANY))
continue; continue;
#endif #endif
/* Look for matching nodes in previous level */ // Look for matching nodes in previous level
if (!tree_link_matching_nodes(curr, data)) { if (!tree_link_matching_nodes(curr, data)) {
return 0; return 0;
} }
@ -380,10 +363,8 @@ static int tree_link_nodes(X509_POLICY_LEVEL *curr,
return 1; return 1;
} }
/* // This corresponds to RFC 3280 6.1.3(d)(2): Create new data for any unmatched
* This corresponds to RFC 3280 6.1.3(d)(2): Create new data for any unmatched // policies in the parent and link to anyPolicy.
* policies in the parent and link to anyPolicy.
*/
static int tree_add_unmatched(X509_POLICY_LEVEL *curr, static int tree_add_unmatched(X509_POLICY_LEVEL *curr,
const X509_POLICY_CACHE *cache, const X509_POLICY_CACHE *cache,
@ -393,16 +374,14 @@ static int tree_add_unmatched(X509_POLICY_LEVEL *curr,
if (id == NULL) { if (id == NULL) {
id = node->data->valid_policy; id = node->data->valid_policy;
} }
/* // Create a new node with qualifiers from anyPolicy and id from unmatched
* Create a new node with qualifiers from anyPolicy and id from unmatched // node.
* node.
*/
data = policy_data_new(NULL, id, node_critical(node)); data = policy_data_new(NULL, id, node_critical(node));
if (data == NULL) { if (data == NULL) {
return 0; return 0;
} }
/* Curr may not have anyPolicy */ // Curr may not have anyPolicy
data->qualifier_set = cache->anyPolicy->qualifier_set; data->qualifier_set = cache->anyPolicy->qualifier_set;
data->flags |= POLICY_DATA_FLAG_SHARED_QUALIFIERS; data->flags |= POLICY_DATA_FLAG_SHARED_QUALIFIERS;
if (!level_add_node(curr, data, node, tree)) { if (!level_add_node(curr, data, node, tree)) {
@ -421,21 +400,21 @@ static int tree_link_unmatched(X509_POLICY_LEVEL *curr,
if ((last->flags & X509_V_FLAG_INHIBIT_MAP) || if ((last->flags & X509_V_FLAG_INHIBIT_MAP) ||
!(node->data->flags & POLICY_DATA_FLAG_MAPPED)) { !(node->data->flags & POLICY_DATA_FLAG_MAPPED)) {
/* If no policy mapping: matched if one child present */ // If no policy mapping: matched if one child present
if (node->nchild) { if (node->nchild) {
return 1; return 1;
} }
if (!tree_add_unmatched(curr, cache, NULL, node, tree)) { if (!tree_add_unmatched(curr, cache, NULL, node, tree)) {
return 0; return 0;
} }
/* Add it */ // Add it
} else { } else {
/* If mapping: matched if one child per expected policy set */ // If mapping: matched if one child per expected policy set
STACK_OF(ASN1_OBJECT) *expset = node->data->expected_policy_set; STACK_OF(ASN1_OBJECT) *expset = node->data->expected_policy_set;
if ((size_t)node->nchild == sk_ASN1_OBJECT_num(expset)) { if ((size_t)node->nchild == sk_ASN1_OBJECT_num(expset)) {
return 1; return 1;
} }
/* Locate unmatched nodes */ // Locate unmatched nodes
for (i = 0; i < sk_ASN1_OBJECT_num(expset); i++) { for (i = 0; i < sk_ASN1_OBJECT_num(expset); i++) {
ASN1_OBJECT *oid = sk_ASN1_OBJECT_value(expset, i); ASN1_OBJECT *oid = sk_ASN1_OBJECT_value(expset, i);
if (level_find_node(curr, node, oid)) { if (level_find_node(curr, node, oid)) {
@ -454,9 +433,7 @@ static int tree_link_any(X509_POLICY_LEVEL *curr,
const X509_POLICY_CACHE *cache, const X509_POLICY_CACHE *cache,
X509_POLICY_TREE *tree) { X509_POLICY_TREE *tree) {
size_t i; size_t i;
/* // X509_POLICY_DATA *data;
* X509_POLICY_DATA *data;
*/
X509_POLICY_NODE *node; X509_POLICY_NODE *node;
X509_POLICY_LEVEL *last = curr - 1; X509_POLICY_LEVEL *last = curr - 1;
@ -469,24 +446,20 @@ static int tree_link_any(X509_POLICY_LEVEL *curr,
#if 0 #if 0
/* // Skip any node with any children: we only want unmathced nodes.
* Skip any node with any children: we only want unmathced nodes. // Note: need something better for policy mapping because each node
* Note: need something better for policy mapping because each node // may have multiple children
* may have multiple children
*/
if (node->nchild) if (node->nchild)
continue; continue;
/* // Create a new node with qualifiers from anyPolicy and id from
* Create a new node with qualifiers from anyPolicy and id from // unmatched node.
* unmatched node.
*/
data = policy_data_new(NULL, node->data->valid_policy, data = policy_data_new(NULL, node->data->valid_policy,
node_critical(node)); node_critical(node));
if (data == NULL) if (data == NULL)
return 0; return 0;
/* Curr may not have anyPolicy */ // Curr may not have anyPolicy
data->qualifier_set = cache->anyPolicy->qualifier_set; data->qualifier_set = cache->anyPolicy->qualifier_set;
data->flags |= POLICY_DATA_FLAG_SHARED_QUALIFIERS; data->flags |= POLICY_DATA_FLAG_SHARED_QUALIFIERS;
if (!level_add_node(curr, data, node, tree)) { if (!level_add_node(curr, data, node, tree)) {
@ -495,7 +468,7 @@ static int tree_link_any(X509_POLICY_LEVEL *curr,
} }
#endif #endif
} }
/* Finally add link to anyPolicy */ // Finally add link to anyPolicy
if (last->anyPolicy) { if (last->anyPolicy) {
if (!level_add_node(curr, cache->anyPolicy, last->anyPolicy, NULL)) { if (!level_add_node(curr, cache->anyPolicy, last->anyPolicy, NULL)) {
return 0; return 0;
@ -504,11 +477,9 @@ static int tree_link_any(X509_POLICY_LEVEL *curr,
return 1; return 1;
} }
/* // Prune the tree: delete any child mapped child data on the current level
* Prune the tree: delete any child mapped child data on the current level // then proceed up the tree deleting any data with no children. If we ever
* then proceed up the tree deleting any data with no children. If we ever // have no data on a level we can halt because the tree will be empty.
* 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) { static int tree_prune(X509_POLICY_TREE *tree, X509_POLICY_LEVEL *curr) {
STACK_OF(X509_POLICY_NODE) *nodes; STACK_OF(X509_POLICY_NODE) *nodes;
@ -518,7 +489,7 @@ static int tree_prune(X509_POLICY_TREE *tree, X509_POLICY_LEVEL *curr) {
if (curr->flags & X509_V_FLAG_INHIBIT_MAP) { if (curr->flags & X509_V_FLAG_INHIBIT_MAP) {
for (i = sk_X509_POLICY_NODE_num(nodes) - 1; i >= 0; i--) { for (i = sk_X509_POLICY_NODE_num(nodes) - 1; i >= 0; i--) {
node = sk_X509_POLICY_NODE_value(nodes, i); node = sk_X509_POLICY_NODE_value(nodes, i);
/* Delete any mapped data: see RFC 3280 XXXX */ // Delete any mapped data: see RFC 3280 XXXX
if (node->data->flags & POLICY_DATA_FLAG_MAP_MASK) { if (node->data->flags & POLICY_DATA_FLAG_MAP_MASK) {
node->parent->nchild--; node->parent->nchild--;
OPENSSL_free(node); OPENSSL_free(node);
@ -546,7 +517,7 @@ static int tree_prune(X509_POLICY_TREE *tree, X509_POLICY_LEVEL *curr) {
curr->anyPolicy = NULL; curr->anyPolicy = NULL;
} }
if (curr == tree->levels) { if (curr == tree->levels) {
/* If we zapped anyPolicy at top then tree is empty */ // If we zapped anyPolicy at top then tree is empty
if (!curr->anyPolicy) { if (!curr->anyPolicy) {
return 2; return 2;
} }
@ -575,14 +546,12 @@ static int tree_add_auth_node(STACK_OF(X509_POLICY_NODE) **pnodes,
return 1; return 1;
} }
/* // Calculate the authority set based on policy tree. The 'pnodes' parameter
* Calculate the authority set based on policy tree. The 'pnodes' parameter // is used as a store for the set of policy nodes used to calculate the user
* is used as a store for the set of policy nodes used to calculate the user // set. If the authority set is not anyPolicy then pnodes will just point to
* set. If the authority set is not anyPolicy then pnodes will just point to // the authority set. If however the authority set is anyPolicy then the set
* the authority set. If however the authority set is anyPolicy then the set // of valid policies (other than anyPolicy) is store in pnodes. The return
* of valid policies (other than anyPolicy) is store in pnodes. The return // value of '2' is used in this case to indicate that pnodes should be freed.
* value of '2' is used in this case to indicate that pnodes should be freed.
*/
static int tree_calculate_authority_set(X509_POLICY_TREE *tree, static int tree_calculate_authority_set(X509_POLICY_TREE *tree,
STACK_OF(X509_POLICY_NODE) **pnodes) { STACK_OF(X509_POLICY_NODE) **pnodes) {
@ -593,23 +562,21 @@ static int tree_calculate_authority_set(X509_POLICY_TREE *tree,
size_t j; size_t j;
curr = tree->levels + tree->nlevel - 1; curr = tree->levels + tree->nlevel - 1;
/* If last level contains anyPolicy set is anyPolicy */ // If last level contains anyPolicy set is anyPolicy
if (curr->anyPolicy) { if (curr->anyPolicy) {
if (!tree_add_auth_node(&tree->auth_policies, curr->anyPolicy)) { if (!tree_add_auth_node(&tree->auth_policies, curr->anyPolicy)) {
return 0; return 0;
} }
addnodes = pnodes; addnodes = pnodes;
} else { } else {
/* Add policies to authority set */ // Add policies to authority set
addnodes = &tree->auth_policies; addnodes = &tree->auth_policies;
} }
curr = tree->levels; curr = tree->levels;
for (i = 1; i < tree->nlevel; i++) { for (i = 1; i < tree->nlevel; i++) {
/* // If no anyPolicy node on this this level it can't appear on lower
* If no anyPolicy node on this this level it can't appear on lower // levels so end search.
* levels so end search.
*/
if (!(anyptr = curr->anyPolicy)) { if (!(anyptr = curr->anyPolicy)) {
break; break;
} }
@ -641,10 +608,8 @@ static int tree_calculate_user_set(X509_POLICY_TREE *tree,
X509_POLICY_NODE *anyPolicy; X509_POLICY_NODE *anyPolicy;
X509_POLICY_DATA *extra; X509_POLICY_DATA *extra;
/* // Check if anyPolicy present in authority constrained policy set: this
* Check if anyPolicy present in authority constrained policy set: this // will happen if it is a leaf node.
* will happen if it is a leaf node.
*/
if (sk_ASN1_OBJECT_num(policy_oids) <= 0) { if (sk_ASN1_OBJECT_num(policy_oids) <= 0) {
return 1; return 1;
@ -667,10 +632,8 @@ static int tree_calculate_user_set(X509_POLICY_TREE *tree,
if (!anyPolicy) { if (!anyPolicy) {
continue; continue;
} }
/* // Create a new node with policy ID from user set and qualifiers
* Create a new node with policy ID from user set and qualifiers // from anyPolicy.
* from anyPolicy.
*/
extra = policy_data_new(NULL, oid, node_critical(anyPolicy)); extra = policy_data_new(NULL, oid, node_critical(anyPolicy));
if (!extra) { if (!extra) {
return 0; return 0;
@ -755,14 +718,13 @@ void X509_policy_tree_free(X509_POLICY_TREE *tree) {
OPENSSL_free(tree); OPENSSL_free(tree);
} }
/*- //-
* Application policy checking function. // Application policy checking function.
* Return codes: // Return codes:
* 0 Internal Error. // 0 Internal Error.
* 1 Successful. // 1 Successful.
* -1 One or more certificates contain invalid or inconsistent extensions // -1 One or more certificates contain invalid or inconsistent extensions
* -2 User constrained policy set empty and requireExplicit true. // -2 User constrained policy set empty and requireExplicit true.
*/
int X509_policy_check(X509_POLICY_TREE **ptree, int *pexplicit_policy, int X509_policy_check(X509_POLICY_TREE **ptree, int *pexplicit_policy,
STACK_OF(X509) *certs, STACK_OF(ASN1_OBJECT) *policy_oids, STACK_OF(X509) *certs, STACK_OF(ASN1_OBJECT) *policy_oids,
@ -777,41 +739,39 @@ int X509_policy_check(X509_POLICY_TREE **ptree, int *pexplicit_policy,
ret = tree_init(&tree, certs, flags); ret = tree_init(&tree, certs, flags);
switch (ret) { switch (ret) {
/* Tree empty requireExplicit False: OK */ // Tree empty requireExplicit False: OK
case 2: case 2:
return 1; return 1;
/* Some internal error */ // Some internal error
case -1: case -1:
return -1; return -1;
/* Some internal error */ // Some internal error
case 0: case 0:
return 0; return 0;
/* Tree empty requireExplicit True: Error */ // Tree empty requireExplicit True: Error
case 6: case 6:
*pexplicit_policy = 1; *pexplicit_policy = 1;
return -2; return -2;
/* Tree OK requireExplicit True: OK and continue */ // Tree OK requireExplicit True: OK and continue
case 5: case 5:
*pexplicit_policy = 1; *pexplicit_policy = 1;
break; break;
/* Tree OK: continue */ // Tree OK: continue
case 1: case 1:
if (!tree) { if (!tree) {
/* // tree_init() returns success and a null tree
* tree_init() returns success and a null tree // if it's just looking at a trust anchor.
* if it's just looking at a trust anchor. // I'm not sure that returning success here is
* I'm not sure that returning success here is // correct, but I'm sure that reporting this
* correct, but I'm sure that reporting this // as an internal error which our caller
* as an internal error which our caller // interprets as a malloc failure is wrong.
* interprets as a malloc failure is wrong.
*/
return 1; return 1;
} }
break; break;
@ -828,7 +788,7 @@ int X509_policy_check(X509_POLICY_TREE **ptree, int *pexplicit_policy,
goto error; goto error;
} }
/* Return value 2 means tree empty */ // Return value 2 means tree empty
if (ret == 2) { if (ret == 2) {
X509_policy_tree_free(tree); X509_policy_tree_free(tree);
if (*pexplicit_policy) { if (*pexplicit_policy) {
@ -838,7 +798,7 @@ int X509_policy_check(X509_POLICY_TREE **ptree, int *pexplicit_policy,
} }
} }
/* 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);

@ -125,13 +125,11 @@ err:
return NULL; return NULL;
} }
/* // Currently two options: keyid: use the issuers subject keyid, the value
* Currently two options: keyid: use the issuers subject keyid, the value // 'always' means its is an error if the issuer certificate doesn't have a
* 'always' means its is an error if the issuer certificate doesn't have a // key id. issuer: use the issuers cert issuer and serial number. The default
* key id. issuer: use the issuers cert issuer and serial number. The default // is to only use this if keyid is not present. With the option 'always' this
* is to only use this if keyid is not present. With the option 'always' this // is always included.
* is always included.
*/
static void *v2i_AUTHORITY_KEYID(const X509V3_EXT_METHOD *method, static void *v2i_AUTHORITY_KEYID(const X509V3_EXT_METHOD *method,
X509V3_CTX *ctx, X509V3_CTX *ctx,

@ -117,9 +117,9 @@ STACK_OF(CONF_VALUE) *i2v_GENERAL_NAMES(const X509V3_EXT_METHOD *method,
STACK_OF(CONF_VALUE) *i2v_GENERAL_NAME(const X509V3_EXT_METHOD *method, STACK_OF(CONF_VALUE) *i2v_GENERAL_NAME(const X509V3_EXT_METHOD *method,
GENERAL_NAME *gen, GENERAL_NAME *gen,
STACK_OF(CONF_VALUE) *ret) { STACK_OF(CONF_VALUE) *ret) {
/* Note the error-handling for this function relies on there being at most // 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 // one |X509V3_add_value| call. If there were two and the second failed, we
* would need to sometimes free the first call's result. */ // would need to sometimes free the first call's result.
unsigned char *p; unsigned char *p;
char oline[256], htmp[5]; char oline[256], htmp[5];
int i; int i;
@ -217,7 +217,7 @@ int GENERAL_NAME_print(BIO *out, GENERAL_NAME *gen) {
break; break;
case GEN_EDIPARTY: case GEN_EDIPARTY:
/* Maybe fix this: it is supported now */ // Maybe fix this: it is supported now
BIO_printf(out, "EdiPartyName:<unsupported>"); BIO_printf(out, "EdiPartyName:<unsupported>");
break; break;
@ -297,7 +297,7 @@ err:
return NULL; return NULL;
} }
/* Append subject altname of issuer to issuer alt name of subject */ // Append subject altname of issuer to issuer alt name of subject
static int copy_issuer(X509V3_CTX *ctx, GENERAL_NAMES *gens) { static int copy_issuer(X509V3_CTX *ctx, GENERAL_NAMES *gens) {
if (ctx && (ctx->flags == CTX_TEST)) { if (ctx && (ctx->flags == CTX_TEST)) {
@ -327,7 +327,7 @@ static int copy_issuer(X509V3_CTX *ctx, GENERAL_NAMES *gens) {
OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE); OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE);
goto err; goto err;
} }
/* Ownership of |gen| has moved from |ialt| to |gens|. */ // Ownership of |gen| has moved from |ialt| to |gens|.
sk_GENERAL_NAME_set(ialt, j, NULL); sk_GENERAL_NAME_set(ialt, j, NULL);
} }
@ -373,9 +373,7 @@ err:
return NULL; return NULL;
} }
/* // Copy any email addresses in a certificate or request to GENERAL_NAMES
* 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) { static int copy_email(X509V3_CTX *ctx, GENERAL_NAMES *gens, int move_p) {
X509_NAME *nm; X509_NAME *nm;
@ -390,14 +388,14 @@ static int copy_email(X509V3_CTX *ctx, GENERAL_NAMES *gens, int move_p) {
OPENSSL_PUT_ERROR(X509V3, X509V3_R_NO_SUBJECT_DETAILS); OPENSSL_PUT_ERROR(X509V3, X509V3_R_NO_SUBJECT_DETAILS);
goto err; goto err;
} }
/* Find the subject name */ // Find the subject name
if (ctx->subject_cert) { if (ctx->subject_cert) {
nm = X509_get_subject_name(ctx->subject_cert); nm = X509_get_subject_name(ctx->subject_cert);
} else { } else {
nm = X509_REQ_get_subject_name(ctx->subject_req); nm = X509_REQ_get_subject_name(ctx->subject_req);
} }
/* Now add any email address(es) to STACK */ // Now add any email address(es) to STACK
i = -1; i = -1;
while ((i = X509_NAME_get_index_by_NID(nm, NID_pkcs9_emailAddress, i)) >= 0) { while ((i = X509_NAME_get_index_by_NID(nm, NID_pkcs9_emailAddress, i)) >= 0) {
ne = X509_NAME_get_entry(nm, i); ne = X509_NAME_get_entry(nm, i);
@ -593,10 +591,8 @@ static int do_othername(GENERAL_NAME *gen, const char *value, X509V3_CTX *ctx) {
if (!(gen->d.otherName = OTHERNAME_new())) { if (!(gen->d.otherName = OTHERNAME_new())) {
return 0; return 0;
} }
/* // Free this up because we will overwrite it. no need to free type_id
* Free this up because we will overwrite it. no need to free type_id // because it is static
* because it is static
*/
ASN1_TYPE_free(gen->d.otherName->value); ASN1_TYPE_free(gen->d.otherName->value);
if (!(gen->d.otherName->value = ASN1_generate_v3(p + 1, ctx))) { if (!(gen->d.otherName->value = ASN1_generate_v3(p + 1, ctx))) {
return 0; return 0;
@ -628,7 +624,7 @@ static int do_dirname(GENERAL_NAME *gen, const char *value, X509V3_CTX *ctx) {
ERR_add_error_data(2, "section=", value); ERR_add_error_data(2, "section=", value);
goto err; goto err;
} }
/* FIXME: should allow other character types... */ // FIXME: should allow other character types...
if (!X509V3_NAME_from_section(nm, sk, MBSTRING_ASC)) { if (!X509V3_NAME_from_section(nm, sk, MBSTRING_ASC)) {
goto err; goto err;
} }

@ -55,7 +55,7 @@
* (eay@cryptsoft.com). This product includes software written by Tim * (eay@cryptsoft.com). This product includes software written by Tim
* Hudson (tjh@cryptsoft.com). */ * Hudson (tjh@cryptsoft.com). */
/* extension creation utilities */ // extension creation utilities
#include <ctype.h> #include <ctype.h>
#include <stdio.h> #include <stdio.h>
@ -83,9 +83,9 @@ static X509_EXTENSION *do_ext_i2d(const X509V3_EXT_METHOD *method, int ext_nid,
int crit, void *ext_struc); int crit, void *ext_struc);
static unsigned char *generic_asn1(const char *value, X509V3_CTX *ctx, static unsigned char *generic_asn1(const char *value, X509V3_CTX *ctx,
long *ext_len); long *ext_len);
/* CONF *conf: Config file */ // CONF *conf: Config file
/* char *name: Name */ // char *name: Name
/* char *value: Value */ // char *value: Value
X509_EXTENSION *X509V3_EXT_nconf(CONF *conf, X509V3_CTX *ctx, const char *name, X509_EXTENSION *X509V3_EXT_nconf(CONF *conf, X509V3_CTX *ctx, const char *name,
const char *value) { const char *value) {
int crit; int crit;
@ -103,8 +103,8 @@ X509_EXTENSION *X509V3_EXT_nconf(CONF *conf, X509V3_CTX *ctx, const char *name,
return ret; return ret;
} }
/* CONF *conf: Config file */ // CONF *conf: Config file
/* char *value: Value */ // char *value: Value
X509_EXTENSION *X509V3_EXT_nconf_nid(CONF *conf, X509V3_CTX *ctx, int ext_nid, X509_EXTENSION *X509V3_EXT_nconf_nid(CONF *conf, X509V3_CTX *ctx, int ext_nid,
const char *value) { const char *value) {
int crit; int crit;
@ -117,8 +117,8 @@ X509_EXTENSION *X509V3_EXT_nconf_nid(CONF *conf, X509V3_CTX *ctx, int ext_nid,
return do_ext_nconf(conf, ctx, ext_nid, crit, value); return do_ext_nconf(conf, ctx, ext_nid, crit, value);
} }
/* CONF *conf: Config file */ // CONF *conf: Config file
/* char *value: Value */ // char *value: Value
static X509_EXTENSION *do_ext_nconf(CONF *conf, X509V3_CTX *ctx, int ext_nid, static X509_EXTENSION *do_ext_nconf(CONF *conf, X509V3_CTX *ctx, int ext_nid,
int crit, const char *value) { int crit, const char *value) {
const X509V3_EXT_METHOD *method; const X509V3_EXT_METHOD *method;
@ -133,7 +133,7 @@ static X509_EXTENSION *do_ext_nconf(CONF *conf, X509V3_CTX *ctx, int ext_nid,
OPENSSL_PUT_ERROR(X509V3, X509V3_R_UNKNOWN_EXTENSION); OPENSSL_PUT_ERROR(X509V3, X509V3_R_UNKNOWN_EXTENSION);
return NULL; return NULL;
} }
/* Now get internal extension representation based on type */ // Now get internal extension representation based on type
if (method->v2i) { if (method->v2i) {
if (*value == '@') { if (*value == '@') {
nval = NCONF_get_section(conf, value + 1); nval = NCONF_get_section(conf, value + 1);
@ -188,7 +188,7 @@ static X509_EXTENSION *do_ext_i2d(const X509V3_EXT_METHOD *method, int ext_nid,
int ext_len; int ext_len;
ASN1_OCTET_STRING *ext_oct; ASN1_OCTET_STRING *ext_oct;
X509_EXTENSION *ext; X509_EXTENSION *ext;
/* Convert internal representation to DER */ // Convert internal representation to DER
if (method->it) { if (method->it) {
ext_der = NULL; ext_der = NULL;
ext_len = ASN1_item_i2d(ext_struc, &ext_der, ASN1_ITEM_ptr(method->it)); ext_len = ASN1_item_i2d(ext_struc, &ext_der, ASN1_ITEM_ptr(method->it));
@ -223,7 +223,7 @@ merr:
return NULL; return NULL;
} }
/* Given an internal structure, nid and critical flag create an extension */ // Given an internal structure, nid and critical flag create an extension
X509_EXTENSION *X509V3_EXT_i2d(int ext_nid, int crit, void *ext_struc) { X509_EXTENSION *X509V3_EXT_i2d(int ext_nid, int crit, void *ext_struc) {
const X509V3_EXT_METHOD *method; const X509V3_EXT_METHOD *method;
@ -234,7 +234,7 @@ X509_EXTENSION *X509V3_EXT_i2d(int ext_nid, int crit, void *ext_struc) {
return do_ext_i2d(method, ext_nid, crit, ext_struc); return do_ext_i2d(method, ext_nid, crit, ext_struc);
} }
/* Check the extension string for critical flag */ // Check the extension string for critical flag
static int v3_check_critical(const char **value) { static int v3_check_critical(const char **value) {
const char *p = *value; const char *p = *value;
if ((strlen(p) < 9) || strncmp(p, "critical,", 9)) { if ((strlen(p) < 9) || strncmp(p, "critical,", 9)) {
@ -248,7 +248,7 @@ static int v3_check_critical(const char **value) {
return 1; return 1;
} }
/* Check extension string for generic extension and return the type */ // Check extension string for generic extension and return the type
static int v3_check_generic(const char **value) { static int v3_check_generic(const char **value) {
int gen_type = 0; int gen_type = 0;
const char *p = *value; const char *p = *value;
@ -269,7 +269,7 @@ static int v3_check_generic(const char **value) {
return gen_type; return gen_type;
} }
/* Create a generic extension: for now just handle DER type */ // Create a generic extension: for now just handle DER type
static X509_EXTENSION *v3_generic_extension(const char *ext, const char *value, static X509_EXTENSION *v3_generic_extension(const char *ext, const char *value,
int crit, int gen_type, int crit, int gen_type,
X509V3_CTX *ctx) { X509V3_CTX *ctx) {
@ -329,10 +329,8 @@ static unsigned char *generic_asn1(const char *value, X509V3_CTX *ctx,
return ext_der; return ext_der;
} }
/* // This is the main function: add a bunch of extensions based on a config
* This is the main function: add a bunch of extensions based on a config // file section to an extension STACK.
* file section to an extension STACK.
*/
int X509V3_EXT_add_nconf_sk(CONF *conf, X509V3_CTX *ctx, const char *section, int X509V3_EXT_add_nconf_sk(CONF *conf, X509V3_CTX *ctx, const char *section,
STACK_OF(X509_EXTENSION) **sk) { STACK_OF(X509_EXTENSION) **sk) {
@ -356,9 +354,7 @@ int X509V3_EXT_add_nconf_sk(CONF *conf, X509V3_CTX *ctx, const char *section,
return 1; return 1;
} }
/* // Convenience functions to add extensions to a certificate, CRL and request
* Convenience functions to add extensions to a certificate, CRL and request
*/
int X509V3_EXT_add_nconf(CONF *conf, X509V3_CTX *ctx, const char *section, int X509V3_EXT_add_nconf(CONF *conf, X509V3_CTX *ctx, const char *section,
X509 *cert) { X509 *cert) {
@ -369,7 +365,7 @@ int X509V3_EXT_add_nconf(CONF *conf, X509V3_CTX *ctx, const char *section,
return X509V3_EXT_add_nconf_sk(conf, ctx, section, sk); return X509V3_EXT_add_nconf_sk(conf, ctx, section, sk);
} }
/* Same as above but for a CRL */ // Same as above but for a CRL
int X509V3_EXT_CRL_add_nconf(CONF *conf, X509V3_CTX *ctx, const char *section, int X509V3_EXT_CRL_add_nconf(CONF *conf, X509V3_CTX *ctx, const char *section,
X509_CRL *crl) { X509_CRL *crl) {
@ -380,7 +376,7 @@ int X509V3_EXT_CRL_add_nconf(CONF *conf, X509V3_CTX *ctx, const char *section,
return X509V3_EXT_add_nconf_sk(conf, ctx, section, sk); return X509V3_EXT_add_nconf_sk(conf, ctx, section, sk);
} }
/* Add extensions to certificate request */ // Add extensions to certificate request
int X509V3_EXT_REQ_add_nconf(CONF *conf, X509V3_CTX *ctx, const char *section, int X509V3_EXT_REQ_add_nconf(CONF *conf, X509V3_CTX *ctx, const char *section,
X509_REQ *req) { X509_REQ *req) {
@ -398,7 +394,7 @@ int X509V3_EXT_REQ_add_nconf(CONF *conf, X509V3_CTX *ctx, const char *section,
return i; return i;
} }
/* Config database functions */ // Config database functions
char *X509V3_get_string(X509V3_CTX *ctx, const char *name, char *X509V3_get_string(X509V3_CTX *ctx, const char *name,
const char *section) { const char *section) {
@ -443,11 +439,11 @@ void X509V3_section_free(X509V3_CTX *ctx, STACK_OF(CONF_VALUE) *section) {
static char *nconf_get_string(void *db, const char *section, static char *nconf_get_string(void *db, const char *section,
const char *value) { const char *value) {
/* TODO(fork): This returns a non-const pointer because |X509V3_CONF_METHOD| // TODO(fork): This returns a non-const pointer because |X509V3_CONF_METHOD|
* allows |get_string| to return caller-owned pointers, provided they're // allows |get_string| to return caller-owned pointers, provided they're
* freed by |free_string|. |nconf_method| leaves |free_string| NULL, and // freed by |free_string|. |nconf_method| leaves |free_string| NULL, and
* there are no other implementations of |X509V3_CONF_METHOD|, so this can // there are no other implementations of |X509V3_CONF_METHOD|, so this can
* be simplified if we make it private. */ // be simplified if we make it private.
return (char *)NCONF_get_string(db, section, value); return (char *)NCONF_get_string(db, section, value);
} }

@ -71,7 +71,7 @@
#include "internal.h" #include "internal.h"
/* Certificate policies extension support: this one is a bit complex... */ // Certificate policies extension support: this one is a bit complex...
static int i2r_certpol(const X509V3_EXT_METHOD *method, void *ext, BIO *out, static int i2r_certpol(const X509V3_EXT_METHOD *method, void *ext, BIO *out,
int indent); int indent);
@ -432,7 +432,7 @@ err:
static int i2r_certpol(const X509V3_EXT_METHOD *method, void *ext, BIO *out, static int i2r_certpol(const X509V3_EXT_METHOD *method, void *ext, BIO *out,
int indent) { int indent) {
const STACK_OF(POLICYINFO) *pol = ext; const STACK_OF(POLICYINFO) *pol = ext;
/* First print out the policy OIDs */ // First print out the policy OIDs
for (size_t i = 0; i < sk_POLICYINFO_num(pol); i++) { for (size_t i = 0; i < sk_POLICYINFO_num(pol); i++) {
const POLICYINFO *pinfo = sk_POLICYINFO_value(pol, i); const POLICYINFO *pinfo = sk_POLICYINFO_value(pol, i);
BIO_printf(out, "%*sPolicy: ", indent, ""); BIO_printf(out, "%*sPolicy: ", indent, "");

@ -161,9 +161,7 @@ static int set_dist_point_name(DIST_POINT_NAME **pdp, X509V3_CTX *ctx,
if (!ret || sk_X509_NAME_ENTRY_num(rnm) <= 0) { if (!ret || sk_X509_NAME_ENTRY_num(rnm) <= 0) {
goto err; goto err;
} }
/* // Since its a name fragment can't have more than one RDNSequence
* 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) { if (sk_X509_NAME_ENTRY_value(rnm, sk_X509_NAME_ENTRY_num(rnm) - 1)->set) {
OPENSSL_PUT_ERROR(X509V3, X509V3_R_INVALID_MULTIPLE_RDNS); OPENSSL_PUT_ERROR(X509V3, X509V3_R_INVALID_MULTIPLE_RDNS);
goto err; goto err;
@ -609,7 +607,7 @@ int DIST_POINT_set_dpname(DIST_POINT_NAME *dpn, X509_NAME *iname) {
return 0; return 0;
} }
} }
/* generate cached encoding of name */ // generate cached encoding of name
if (i2d_X509_NAME(dpn->dpname, NULL) < 0) { if (i2d_X509_NAME(dpn->dpname, NULL) < 0) {
X509_NAME_free(dpn->dpname); X509_NAME_free(dpn->dpname);
dpn->dpname = NULL; dpn->dpname = NULL;

@ -86,7 +86,7 @@ const X509V3_EXT_METHOD v3_ext_ku = {
NULL, NULL,
}; };
/* NB OCSP acceptable responses also is a SEQUENCE OF OBJECT */ // NB OCSP acceptable responses also is a SEQUENCE OF OBJECT
const X509V3_EXT_METHOD v3_ocsp_accresp = { const X509V3_EXT_METHOD v3_ocsp_accresp = {
NID_id_pkix_OCSP_acceptableResponses, NID_id_pkix_OCSP_acceptableResponses,
0, 0,

@ -65,14 +65,14 @@
ASN1_SEQUENCE(OTHERNAME) = { ASN1_SEQUENCE(OTHERNAME) = {
ASN1_SIMPLE(OTHERNAME, type_id, ASN1_OBJECT), ASN1_SIMPLE(OTHERNAME, type_id, ASN1_OBJECT),
/* Maybe have a true ANY DEFINED BY later */ // Maybe have a true ANY DEFINED BY later
ASN1_EXP(OTHERNAME, value, ASN1_ANY, 0), ASN1_EXP(OTHERNAME, value, ASN1_ANY, 0),
} ASN1_SEQUENCE_END(OTHERNAME) } ASN1_SEQUENCE_END(OTHERNAME)
IMPLEMENT_ASN1_FUNCTIONS(OTHERNAME) IMPLEMENT_ASN1_FUNCTIONS(OTHERNAME)
ASN1_SEQUENCE(EDIPARTYNAME) = { ASN1_SEQUENCE(EDIPARTYNAME) = {
/* DirectoryString is a CHOICE type, so use explicit tagging. */ // DirectoryString is a CHOICE type, so use explicit tagging.
ASN1_EXP_OPT(EDIPARTYNAME, nameAssigner, DIRECTORYSTRING, 0), ASN1_EXP_OPT(EDIPARTYNAME, nameAssigner, DIRECTORYSTRING, 0),
ASN1_EXP(EDIPARTYNAME, partyName, DIRECTORYSTRING, 1), ASN1_EXP(EDIPARTYNAME, partyName, DIRECTORYSTRING, 1),
} ASN1_SEQUENCE_END(EDIPARTYNAME) } ASN1_SEQUENCE_END(EDIPARTYNAME)
@ -83,9 +83,9 @@ ASN1_CHOICE(GENERAL_NAME) = {
ASN1_IMP(GENERAL_NAME, d.otherName, OTHERNAME, GEN_OTHERNAME), ASN1_IMP(GENERAL_NAME, d.otherName, OTHERNAME, GEN_OTHERNAME),
ASN1_IMP(GENERAL_NAME, d.rfc822Name, ASN1_IA5STRING, GEN_EMAIL), ASN1_IMP(GENERAL_NAME, d.rfc822Name, ASN1_IA5STRING, GEN_EMAIL),
ASN1_IMP(GENERAL_NAME, d.dNSName, ASN1_IA5STRING, GEN_DNS), ASN1_IMP(GENERAL_NAME, d.dNSName, ASN1_IA5STRING, GEN_DNS),
/* Don't decode this */ // Don't decode this
ASN1_IMP(GENERAL_NAME, d.x400Address, ASN1_SEQUENCE, GEN_X400), ASN1_IMP(GENERAL_NAME, d.x400Address, ASN1_SEQUENCE, GEN_X400),
/* X509_NAME is a CHOICE type so use EXPLICIT */ // X509_NAME is a CHOICE type so use EXPLICIT
ASN1_EXP(GENERAL_NAME, d.directoryName, X509_NAME, GEN_DIRNAME), ASN1_EXP(GENERAL_NAME, d.directoryName, X509_NAME, GEN_DIRNAME),
ASN1_IMP(GENERAL_NAME, d.ediPartyName, EDIPARTYNAME, GEN_EDIPARTY), ASN1_IMP(GENERAL_NAME, d.ediPartyName, EDIPARTYNAME, GEN_EDIPARTY),
ASN1_IMP(GENERAL_NAME, d.uniformResourceIdentifier, ASN1_IA5STRING, ASN1_IMP(GENERAL_NAME, d.uniformResourceIdentifier, ASN1_IA5STRING,
@ -106,7 +106,7 @@ IMPLEMENT_ASN1_FUNCTIONS(GENERAL_NAMES)
IMPLEMENT_ASN1_DUP_FUNCTION(GENERAL_NAME) IMPLEMENT_ASN1_DUP_FUNCTION(GENERAL_NAME)
static int edipartyname_cmp(const EDIPARTYNAME *a, const EDIPARTYNAME *b) { static int edipartyname_cmp(const EDIPARTYNAME *a, const EDIPARTYNAME *b) {
/* nameAssigner is optional and may be NULL. */ // nameAssigner is optional and may be NULL.
if (a->nameAssigner == NULL) { if (a->nameAssigner == NULL) {
if (b->nameAssigner != NULL) { if (b->nameAssigner != NULL) {
return -1; return -1;
@ -118,11 +118,11 @@ static int edipartyname_cmp(const EDIPARTYNAME *a, const EDIPARTYNAME *b) {
} }
} }
/* partyName may not be NULL. */ // partyName may not be NULL.
return ASN1_STRING_cmp(a->partyName, b->partyName); return ASN1_STRING_cmp(a->partyName, b->partyName);
} }
/* Returns 0 if they are equal, != 0 otherwise. */ // Returns 0 if they are equal, != 0 otherwise.
int GENERAL_NAME_cmp(const GENERAL_NAME *a, const GENERAL_NAME *b) { int GENERAL_NAME_cmp(const GENERAL_NAME *a, const GENERAL_NAME *b) {
if (!a || !b || a->type != b->type) { if (!a || !b || a->type != b->type) {
return -1; return -1;
@ -156,18 +156,18 @@ int GENERAL_NAME_cmp(const GENERAL_NAME *a, const GENERAL_NAME *b) {
return -1; return -1;
} }
/* Returns 0 if they are equal, != 0 otherwise. */ // Returns 0 if they are equal, != 0 otherwise.
int OTHERNAME_cmp(OTHERNAME *a, OTHERNAME *b) { int OTHERNAME_cmp(OTHERNAME *a, OTHERNAME *b) {
int result = -1; int result = -1;
if (!a || !b) { if (!a || !b) {
return -1; return -1;
} }
/* Check their type first. */ // Check their type first.
if ((result = OBJ_cmp(a->type_id, b->type_id)) != 0) { if ((result = OBJ_cmp(a->type_id, b->type_id)) != 0) {
return result; return result;
} }
/* Check the value. */ // Check the value.
result = ASN1_TYPE_cmp(a->value, b->value); result = ASN1_TYPE_cmp(a->value, b->value);
return result; return result;
} }

@ -189,14 +189,12 @@ static void ext_list_free(X509V3_EXT_METHOD *ext) {
} }
} }
/* // Legacy function: we don't need to add standard extensions any more because
* Legacy function: we don't need to add standard extensions any more because // they are now kept in ext_dat.h.
* 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 */ // Return an extension internal structure
void *X509V3_EXT_d2i(const X509_EXTENSION *ext) { void *X509V3_EXT_d2i(const X509_EXTENSION *ext) {
const X509V3_EXT_METHOD *method; const X509V3_EXT_METHOD *method;
@ -216,7 +214,7 @@ void *X509V3_EXT_d2i(const X509_EXTENSION *ext) {
if (ret == NULL) { if (ret == NULL) {
return NULL; return NULL;
} }
/* Check for trailing data. */ // Check for trailing data.
if (p != ext->value->data + ext->value->length) { if (p != ext->value->data + ext->value->length) {
if (method->it) { if (method->it) {
ASN1_item_free(ret, ASN1_ITEM_ptr(method->it)); ASN1_item_free(ret, ASN1_ITEM_ptr(method->it));
@ -255,13 +253,13 @@ void *X509V3_get_d2i(const STACK_OF(X509_EXTENSION) *extensions, int nid,
ex = sk_X509_EXTENSION_value(extensions, i); ex = sk_X509_EXTENSION_value(extensions, i);
if (OBJ_obj2nid(ex->object) == nid) { if (OBJ_obj2nid(ex->object) == nid) {
if (out_idx) { if (out_idx) {
/* TODO(https://crbug.com/boringssl/379): Consistently reject // TODO(https://crbug.com/boringssl/379): Consistently reject
* duplicate extensions. */ // duplicate extensions.
*out_idx = i; *out_idx = i;
found_ex = ex; found_ex = ex;
break; break;
} else if (found_ex) { } else if (found_ex) {
/* Found more than one */ // Found more than one
if (out_critical) { if (out_critical) {
*out_critical = -2; *out_critical = -2;
} }
@ -271,14 +269,14 @@ void *X509V3_get_d2i(const STACK_OF(X509_EXTENSION) *extensions, int nid,
} }
} }
if (found_ex) { if (found_ex) {
/* Found it */ // Found it
if (out_critical) { if (out_critical) {
*out_critical = X509_EXTENSION_get_critical(found_ex); *out_critical = X509_EXTENSION_get_critical(found_ex);
} }
return X509V3_EXT_d2i(found_ex); return X509V3_EXT_d2i(found_ex);
} }
/* Extension not found */ // Extension not found
if (out_idx) { if (out_idx) {
*out_idx = -1; *out_idx = -1;
} }
@ -288,11 +286,9 @@ void *X509V3_get_d2i(const STACK_OF(X509_EXTENSION) *extensions, int nid,
return NULL; return NULL;
} }
/* // This function is a general extension append, replace and delete utility.
* This function is a general extension append, replace and delete utility. // The precise operation is governed by the 'flags' value. The 'crit' and
* The precise operation is governed by the 'flags' value. The 'crit' and // 'value' arguments (if relevant) are the extensions internal structure.
* 'value' arguments (if relevant) are the extensions internal structure.
*/
int X509V3_add1_i2d(STACK_OF(X509_EXTENSION) **x, int nid, void *value, int X509V3_add1_i2d(STACK_OF(X509_EXTENSION) **x, int nid, void *value,
int crit, unsigned long flags) { int crit, unsigned long flags) {
@ -301,26 +297,24 @@ int X509V3_add1_i2d(STACK_OF(X509_EXTENSION) **x, int nid, void *value,
STACK_OF(X509_EXTENSION) *ret = NULL; STACK_OF(X509_EXTENSION) *ret = NULL;
unsigned long ext_op = flags & X509V3_ADD_OP_MASK; unsigned long ext_op = flags & X509V3_ADD_OP_MASK;
/* // If appending we don't care if it exists, otherwise look for existing
* If appending we don't care if it exists, otherwise look for existing // extension.
* extension.
*/
if (ext_op != X509V3_ADD_APPEND) { if (ext_op != X509V3_ADD_APPEND) {
extidx = X509v3_get_ext_by_NID(*x, nid, -1); extidx = X509v3_get_ext_by_NID(*x, nid, -1);
} }
/* See if extension exists */ // See if extension exists
if (extidx >= 0) { if (extidx >= 0) {
/* If keep existing, nothing to do */ // If keep existing, nothing to do
if (ext_op == X509V3_ADD_KEEP_EXISTING) { if (ext_op == X509V3_ADD_KEEP_EXISTING) {
return 1; return 1;
} }
/* If default then its an error */ // If default then its an error
if (ext_op == X509V3_ADD_DEFAULT) { if (ext_op == X509V3_ADD_DEFAULT) {
errcode = X509V3_R_EXTENSION_EXISTS; errcode = X509V3_R_EXTENSION_EXISTS;
goto err; goto err;
} }
/* If delete, just delete it */ // If delete, just delete it
if (ext_op == X509V3_ADD_DELETE) { if (ext_op == X509V3_ADD_DELETE) {
if (!sk_X509_EXTENSION_delete(*x, extidx)) { if (!sk_X509_EXTENSION_delete(*x, extidx)) {
return -1; return -1;
@ -328,9 +322,7 @@ int X509V3_add1_i2d(STACK_OF(X509_EXTENSION) **x, int nid, void *value,
return 1; return 1;
} }
} else { } else {
/* // If replace existing or delete, error since extension must exist
* If replace existing or delete, error since extension must exist
*/
if ((ext_op == X509V3_ADD_REPLACE_EXISTING) || if ((ext_op == X509V3_ADD_REPLACE_EXISTING) ||
(ext_op == X509V3_ADD_DELETE)) { (ext_op == X509V3_ADD_DELETE)) {
errcode = X509V3_R_EXTENSION_NOT_FOUND; errcode = X509V3_R_EXTENSION_NOT_FOUND;
@ -338,10 +330,8 @@ int X509V3_add1_i2d(STACK_OF(X509_EXTENSION) **x, int nid, void *value,
} }
} }
/* // If we get this far then we have to create an extension: could have
* If we get this far then we have to create an extension: could have // some flags for alternative encoding schemes...
* some flags for alternative encoding schemes...
*/
ext = X509V3_EXT_i2d(nid, crit, value); ext = X509V3_EXT_i2d(nid, crit, value);
@ -350,7 +340,7 @@ int X509V3_add1_i2d(STACK_OF(X509_EXTENSION) **x, int nid, void *value,
return 0; return 0;
} }
/* If extension exists replace it.. */ // If extension exists replace it..
if (extidx >= 0) { if (extidx >= 0) {
extmp = sk_X509_EXTENSION_value(*x, extidx); extmp = sk_X509_EXTENSION_value(*x, extidx);
X509_EXTENSION_free(extmp); X509_EXTENSION_free(extmp);

@ -227,19 +227,18 @@ static int print_nc_ipadd(BIO *bp, ASN1_OCTET_STRING *ip) {
return 1; return 1;
} }
/*- //-
* Check a certificate conforms to a specified set of constraints. // Check a certificate conforms to a specified set of constraints.
* Return values: // Return values:
* X509_V_OK: All constraints obeyed. // X509_V_OK: All constraints obeyed.
* X509_V_ERR_PERMITTED_VIOLATION: Permitted subtree violation. // X509_V_ERR_PERMITTED_VIOLATION: Permitted subtree violation.
* X509_V_ERR_EXCLUDED_VIOLATION: Excluded subtree violation. // X509_V_ERR_EXCLUDED_VIOLATION: Excluded subtree violation.
* X509_V_ERR_SUBTREE_MINMAX: Min or max values present and matching type. // X509_V_ERR_SUBTREE_MINMAX: Min or max values present and matching type.
* X509_V_ERR_UNSPECIFIED: Unspecified error. // X509_V_ERR_UNSPECIFIED: Unspecified error.
* X509_V_ERR_UNSUPPORTED_CONSTRAINT_TYPE: Unsupported constraint type. // X509_V_ERR_UNSUPPORTED_CONSTRAINT_TYPE: Unsupported constraint type.
* X509_V_ERR_UNSUPPORTED_CONSTRAINT_SYNTAX: Bad or unsupported constraint // X509_V_ERR_UNSUPPORTED_CONSTRAINT_SYNTAX: Bad or unsupported constraint
* syntax. // syntax.
* X509_V_ERR_UNSUPPORTED_NAME_SYNTAX: Bad or unsupported syntax of name. // X509_V_ERR_UNSUPPORTED_NAME_SYNTAX: Bad or unsupported syntax of name.
*/
int NAME_CONSTRAINTS_check(X509 *x, NAME_CONSTRAINTS *nc) { int NAME_CONSTRAINTS_check(X509 *x, NAME_CONSTRAINTS *nc) {
int r, i; int r, i;
@ -248,9 +247,9 @@ int NAME_CONSTRAINTS_check(X509 *x, NAME_CONSTRAINTS *nc) {
nm = X509_get_subject_name(x); nm = X509_get_subject_name(x);
/* Guard against certificates with an excessive number of names or // Guard against certificates with an excessive number of names or
* constraints causing a computationally expensive name constraints // constraints causing a computationally expensive name constraints
* check. */ // check.
size_t name_count = size_t name_count =
X509_NAME_entry_count(nm) + sk_GENERAL_NAME_num(x->altname); X509_NAME_entry_count(nm) + sk_GENERAL_NAME_num(x->altname);
size_t constraint_count = sk_GENERAL_SUBTREE_num(nc->permittedSubtrees) + size_t constraint_count = sk_GENERAL_SUBTREE_num(nc->permittedSubtrees) +
@ -276,7 +275,7 @@ int NAME_CONSTRAINTS_check(X509 *x, NAME_CONSTRAINTS *nc) {
gntmp.type = GEN_EMAIL; gntmp.type = GEN_EMAIL;
/* Process any email address attributes in subject name */ // Process any email address attributes in subject name
for (i = -1;;) { for (i = -1;;) {
X509_NAME_ENTRY *ne; X509_NAME_ENTRY *ne;
@ -314,10 +313,8 @@ static int nc_match(GENERAL_NAME *gen, NAME_CONSTRAINTS *nc) {
int r, match = 0; int r, match = 0;
size_t i; size_t i;
/* // Permitted subtrees: if any subtrees exist of matching the type at
* Permitted subtrees: if any subtrees exist of matching the type at // least one subtree must match.
* least one subtree must match.
*/
for (i = 0; i < sk_GENERAL_SUBTREE_num(nc->permittedSubtrees); i++) { for (i = 0; i < sk_GENERAL_SUBTREE_num(nc->permittedSubtrees); i++) {
sub = sk_GENERAL_SUBTREE_value(nc->permittedSubtrees, i); sub = sk_GENERAL_SUBTREE_value(nc->permittedSubtrees, i);
@ -327,7 +324,7 @@ static int nc_match(GENERAL_NAME *gen, NAME_CONSTRAINTS *nc) {
if (sub->minimum || sub->maximum) { if (sub->minimum || sub->maximum) {
return X509_V_ERR_SUBTREE_MINMAX; return X509_V_ERR_SUBTREE_MINMAX;
} }
/* If we already have a match don't bother trying any more */ // If we already have a match don't bother trying any more
if (match == 2) { if (match == 2) {
continue; continue;
} }
@ -346,7 +343,7 @@ static int nc_match(GENERAL_NAME *gen, NAME_CONSTRAINTS *nc) {
return X509_V_ERR_PERMITTED_VIOLATION; return X509_V_ERR_PERMITTED_VIOLATION;
} }
/* Excluded subtrees: must not match any of these */ // Excluded subtrees: must not match any of these
for (i = 0; i < sk_GENERAL_SUBTREE_num(nc->excludedSubtrees); i++) { for (i = 0; i < sk_GENERAL_SUBTREE_num(nc->excludedSubtrees); i++) {
sub = sk_GENERAL_SUBTREE_value(nc->excludedSubtrees, i); sub = sk_GENERAL_SUBTREE_value(nc->excludedSubtrees, i);
@ -388,14 +385,12 @@ static int nc_match_single(GENERAL_NAME *gen, GENERAL_NAME *base) {
} }
} }
/* // directoryName name constraint matching. The canonical encoding of
* directoryName name constraint matching. The canonical encoding of // X509_NAME makes this comparison easy. It is matched if the subtree is a
* X509_NAME makes this comparison easy. It is matched if the subtree is a // subset of the name.
* subset of the name.
*/
static int nc_dn(X509_NAME *nm, X509_NAME *base) { static int nc_dn(X509_NAME *nm, X509_NAME *base) {
/* Ensure canonical encodings are up to date. */ // Ensure canonical encodings are up to date.
if (nm->modified && i2d_X509_NAME(nm, NULL) < 0) { if (nm->modified && i2d_X509_NAME(nm, NULL) < 0) {
return X509_V_ERR_OUT_OF_MEM; return X509_V_ERR_OUT_OF_MEM;
} }
@ -419,8 +414,8 @@ static int equal_case(const CBS *a, const CBS *b) {
if (CBS_len(a) != CBS_len(b)) { if (CBS_len(a) != CBS_len(b)) {
return 0; return 0;
} }
/* Note we cannot use |OPENSSL_strncasecmp| because that would stop // Note we cannot use |OPENSSL_strncasecmp| because that would stop
* iterating at NUL. */ // iterating at NUL.
const uint8_t *a_data = CBS_data(a), *b_data = CBS_data(b); const uint8_t *a_data = CBS_data(a), *b_data = CBS_data(b);
for (size_t i = 0; i < CBS_len(a); i++) { for (size_t i = 0; i < CBS_len(a); i++) {
if (OPENSSL_tolower(a_data[i]) != OPENSSL_tolower(b_data[i])) { if (OPENSSL_tolower(a_data[i]) != OPENSSL_tolower(b_data[i])) {
@ -444,13 +439,13 @@ static int nc_dns(ASN1_IA5STRING *dns, ASN1_IA5STRING *base) {
CBS_init(&dns_cbs, dns->data, dns->length); CBS_init(&dns_cbs, dns->data, dns->length);
CBS_init(&base_cbs, base->data, base->length); CBS_init(&base_cbs, base->data, base->length);
/* Empty matches everything */ // Empty matches everything
if (CBS_len(&base_cbs) == 0) { if (CBS_len(&base_cbs) == 0) {
return X509_V_OK; return X509_V_OK;
} }
/* If |base_cbs| begins with a '.', do a simple suffix comparison. This is // 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. */ // not part of RFC5280, but is part of OpenSSL's original behavior.
if (starts_with(&base_cbs, '.')) { if (starts_with(&base_cbs, '.')) {
if (has_suffix_case(&dns_cbs, &base_cbs)) { if (has_suffix_case(&dns_cbs, &base_cbs)) {
return X509_V_OK; return X509_V_OK;
@ -458,10 +453,8 @@ static int nc_dns(ASN1_IA5STRING *dns, ASN1_IA5STRING *base) {
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
* Otherwise can add zero or more components on the left so compare RHS // and if dns is longer and expect '.' as preceding character.
* and if dns is longer and expect '.' as preceding character.
*/
if (CBS_len(&dns_cbs) > CBS_len(&base_cbs)) { if (CBS_len(&dns_cbs) > CBS_len(&base_cbs)) {
uint8_t dot; uint8_t dot;
if (!CBS_skip(&dns_cbs, CBS_len(&dns_cbs) - CBS_len(&base_cbs) - 1) || if (!CBS_skip(&dns_cbs, CBS_len(&dns_cbs) - CBS_len(&base_cbs) - 1) ||
@ -482,16 +475,16 @@ static int nc_email(ASN1_IA5STRING *eml, ASN1_IA5STRING *base) {
CBS_init(&eml_cbs, eml->data, eml->length); CBS_init(&eml_cbs, eml->data, eml->length);
CBS_init(&base_cbs, base->data, base->length); CBS_init(&base_cbs, base->data, base->length);
/* TODO(davidben): In OpenSSL 1.1.1, this switched from the first '@' to the // 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 // last one. Match them here, or perhaps do an actual parse. Looks like
* multiple '@'s may be allowed in quoted strings. */ // multiple '@'s may be allowed in quoted strings.
CBS eml_local, base_local; CBS eml_local, base_local;
if (!CBS_get_until_first(&eml_cbs, &eml_local, '@')) { if (!CBS_get_until_first(&eml_cbs, &eml_local, '@')) {
return X509_V_ERR_UNSUPPORTED_NAME_SYNTAX; return X509_V_ERR_UNSUPPORTED_NAME_SYNTAX;
} }
int base_has_at = CBS_get_until_first(&base_cbs, &base_local, '@'); int base_has_at = CBS_get_until_first(&base_cbs, &base_local, '@');
/* Special case: inital '.' is RHS match */ // Special case: inital '.' is RHS match
if (!base_has_at && starts_with(&base_cbs, '.')) { if (!base_has_at && starts_with(&base_cbs, '.')) {
if (has_suffix_case(&eml_cbs, &base_cbs)) { if (has_suffix_case(&eml_cbs, &base_cbs)) {
return X509_V_OK; return X509_V_OK;
@ -499,23 +492,23 @@ static int nc_email(ASN1_IA5STRING *eml, ASN1_IA5STRING *base) {
return X509_V_ERR_PERMITTED_VIOLATION; return X509_V_ERR_PERMITTED_VIOLATION;
} }
/* If we have anything before '@' match local part */ // If we have anything before '@' match local part
if (base_has_at) { if (base_has_at) {
/* TODO(davidben): This interprets a constraint of "@example.com" as // TODO(davidben): This interprets a constraint of "@example.com" as
* "example.com", which is not part of RFC5280. */ // "example.com", which is not part of RFC5280.
if (CBS_len(&base_local) > 0) { if (CBS_len(&base_local) > 0) {
/* Case sensitive match of local part */ // Case sensitive match of local part
if (!CBS_mem_equal(&base_local, CBS_data(&eml_local), if (!CBS_mem_equal(&base_local, CBS_data(&eml_local),
CBS_len(&eml_local))) { CBS_len(&eml_local))) {
return X509_V_ERR_PERMITTED_VIOLATION; return X509_V_ERR_PERMITTED_VIOLATION;
} }
} }
/* Position base after '@' */ // Position base after '@'
assert(starts_with(&base_cbs, '@')); assert(starts_with(&base_cbs, '@'));
CBS_skip(&base_cbs, 1); CBS_skip(&base_cbs, 1);
} }
/* Just have hostname left to match: case insensitive */ // Just have hostname left to match: case insensitive
assert(starts_with(&eml_cbs, '@')); assert(starts_with(&eml_cbs, '@'));
CBS_skip(&eml_cbs, 1); CBS_skip(&eml_cbs, 1);
if (!equal_case(&base_cbs, &eml_cbs)) { if (!equal_case(&base_cbs, &eml_cbs)) {
@ -530,7 +523,7 @@ static int nc_uri(ASN1_IA5STRING *uri, ASN1_IA5STRING *base) {
CBS_init(&uri_cbs, uri->data, uri->length); CBS_init(&uri_cbs, uri->data, uri->length);
CBS_init(&base_cbs, base->data, base->length); CBS_init(&base_cbs, base->data, base->length);
/* Check for foo:// and skip past it */ // Check for foo:// and skip past it
CBS scheme; CBS scheme;
uint8_t byte; uint8_t byte;
if (!CBS_get_until_first(&uri_cbs, &scheme, ':') || if (!CBS_get_until_first(&uri_cbs, &scheme, ':') ||
@ -540,10 +533,10 @@ static int nc_uri(ASN1_IA5STRING *uri, ASN1_IA5STRING *base) {
return X509_V_ERR_UNSUPPORTED_NAME_SYNTAX; return X509_V_ERR_UNSUPPORTED_NAME_SYNTAX;
} }
/* Look for a port indicator as end of hostname first. Otherwise look for // Look for a port indicator as end of hostname first. Otherwise look for
* trailing slash, or the end of the string. // trailing slash, or the end of the string.
* TODO(davidben): This is not a correct URI parser and mishandles IPv6 // TODO(davidben): This is not a correct URI parser and mishandles IPv6
* literals. */ // literals.
CBS host; CBS host;
if (!CBS_get_until_first(&uri_cbs, &host, ':') && if (!CBS_get_until_first(&uri_cbs, &host, ':') &&
!CBS_get_until_first(&uri_cbs, &host, '/')) { !CBS_get_until_first(&uri_cbs, &host, '/')) {
@ -554,7 +547,7 @@ static int nc_uri(ASN1_IA5STRING *uri, ASN1_IA5STRING *base) {
return X509_V_ERR_UNSUPPORTED_NAME_SYNTAX; return X509_V_ERR_UNSUPPORTED_NAME_SYNTAX;
} }
/* Special case: inital '.' is RHS match */ // Special case: inital '.' is RHS match
if (starts_with(&base_cbs, '.')) { if (starts_with(&base_cbs, '.')) {
if (has_suffix_case(&host, &base_cbs)) { if (has_suffix_case(&host, &base_cbs)) {
return X509_V_OK; return X509_V_OK;

@ -13,9 +13,7 @@
#include <openssl/bio.h> #include <openssl/bio.h>
#include <openssl/nid.h> #include <openssl/nid.h>
/* // OCSP extensions and a couple of CRL entry extensions
* OCSP extensions and a couple of CRL entry extensions
*/
static int i2r_ocsp_acutoff(const X509V3_EXT_METHOD *method, void *nonce, static int i2r_ocsp_acutoff(const X509V3_EXT_METHOD *method, void *nonce,
BIO *out, int indent); BIO *out, int indent);
@ -70,7 +68,7 @@ static int i2r_ocsp_acutoff(const X509V3_EXT_METHOD *method, void *cutoff,
return 1; return 1;
} }
/* Nocheck is just a single NULL. Don't print anything and always set it */ // 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, static int i2r_ocsp_nocheck(const X509V3_EXT_METHOD *method, void *nocheck,
BIO *out, int indent) { BIO *out, int indent) {

@ -147,10 +147,8 @@ static int process_pci_value(CONF_VALUE *val, ASN1_OBJECT **language,
(*policy)->data[(*policy)->length] = '\0'; (*policy)->data[(*policy)->length] = '\0';
} else { } else {
OPENSSL_free(tmp_data2); OPENSSL_free(tmp_data2);
/* // realloc failure implies the original data space is b0rked
* realloc failure implies the original data space is b0rked // too!
* too!
*/
(*policy)->data = NULL; (*policy)->data = NULL;
(*policy)->length = 0; (*policy)->length = 0;
OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE); OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE);
@ -169,10 +167,8 @@ static int process_pci_value(CONF_VALUE *val, ASN1_OBJECT **language,
(*policy)->length += val_len; (*policy)->length += val_len;
(*policy)->data[(*policy)->length] = '\0'; (*policy)->data[(*policy)->length] = '\0';
} else { } else {
/* // realloc failure implies the original data space is b0rked
* realloc failure implies the original data space is b0rked // too!
* too!
*/
(*policy)->data = NULL; (*policy)->data = NULL;
(*policy)->length = 0; (*policy)->length = 0;
OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE); OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE);
@ -243,7 +239,7 @@ static void *r2i_pci(const X509V3_EXT_METHOD *method, X509V3_CTX *ctx,
} }
} }
/* Language is mandatory */ // Language is mandatory
if (!language) { if (!language) {
OPENSSL_PUT_ERROR(X509V3, X509V3_R_NO_PROXY_CERT_POLICY_LANGUAGE_DEFINED); OPENSSL_PUT_ERROR(X509V3, X509V3_R_NO_PROXY_CERT_POLICY_LANGUAGE_DEFINED);
goto err; goto err;

@ -55,7 +55,7 @@
* (eay@cryptsoft.com). This product includes software written by Tim * (eay@cryptsoft.com). This product includes software written by Tim
* Hudson (tjh@cryptsoft.com). */ * Hudson (tjh@cryptsoft.com). */
/* X509 v3 extension utilities */ // X509 v3 extension utilities
#include <stdio.h> #include <stdio.h>
@ -64,12 +64,12 @@
#include <openssl/mem.h> #include <openssl/mem.h>
#include <openssl/x509v3.h> #include <openssl/x509v3.h>
/* Extension printing routines */ // Extension printing routines
static int unknown_ext_print(BIO *out, X509_EXTENSION *ext, unsigned long flag, static int unknown_ext_print(BIO *out, X509_EXTENSION *ext, unsigned long flag,
int indent, int supported); int indent, int supported);
/* Print out a name+value stack */ // Print out a name+value stack
void X509V3_EXT_val_prn(BIO *out, STACK_OF(CONF_VALUE) *val, int indent, void X509V3_EXT_val_prn(BIO *out, STACK_OF(CONF_VALUE) *val, int indent,
int ml) { int ml) {
@ -104,7 +104,7 @@ void X509V3_EXT_val_prn(BIO *out, STACK_OF(CONF_VALUE) *val, int indent,
} }
} }
/* Main routine: print out a general extension */ // Main routine: print out a general extension
int X509V3_EXT_print(BIO *out, X509_EXTENSION *ext, unsigned long flag, int X509V3_EXT_print(BIO *out, X509_EXTENSION *ext, unsigned long flag,
int indent) { int indent) {

@ -131,11 +131,9 @@ static int xp_cmp(const X509_PURPOSE **a, const X509_PURPOSE **b) {
return (*a)->purpose - (*b)->purpose; return (*a)->purpose - (*b)->purpose;
} }
/* // As much as I'd like to make X509_check_purpose use a "const" X509* I
* As much as I'd like to make X509_check_purpose use a "const" X509* I // really can't because it does recalculate hashes and do other non-const
* really can't because it does recalculate hashes and do other non-const // things.
* things.
*/
int X509_check_purpose(X509 *x, int id, int ca) { int X509_check_purpose(X509 *x, int id, int ca) {
int idx; int idx;
const X509_PURPOSE *pt; const X509_PURPOSE *pt;
@ -218,15 +216,13 @@ int X509_PURPOSE_add(int id, int trust, int flags,
X509_PURPOSE *ptmp; X509_PURPOSE *ptmp;
char *name_dup, *sname_dup; char *name_dup, *sname_dup;
/* // This is set according to what we change: application can't set it
* This is set according to what we change: application can't set it
*/
flags &= ~X509_PURPOSE_DYNAMIC; flags &= ~X509_PURPOSE_DYNAMIC;
/* This will always be set for application modified trust entries */ // This will always be set for application modified trust entries
flags |= X509_PURPOSE_DYNAMIC_NAME; flags |= X509_PURPOSE_DYNAMIC_NAME;
/* Get existing entry if any */ // Get existing entry if any
idx = X509_PURPOSE_get_by_id(id); idx = X509_PURPOSE_get_by_id(id);
/* Need a new entry */ // Need a new entry
if (idx == -1) { if (idx == -1) {
if (!(ptmp = OPENSSL_malloc(sizeof(X509_PURPOSE)))) { if (!(ptmp = OPENSSL_malloc(sizeof(X509_PURPOSE)))) {
OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE); OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE);
@ -237,7 +233,7 @@ int X509_PURPOSE_add(int id, int trust, int flags,
ptmp = X509_PURPOSE_get0(idx); ptmp = X509_PURPOSE_get0(idx);
} }
/* Duplicate the supplied names. */ // Duplicate the supplied names.
name_dup = OPENSSL_strdup(name); name_dup = OPENSSL_strdup(name);
sname_dup = OPENSSL_strdup(sname); sname_dup = OPENSSL_strdup(sname);
if (name_dup == NULL || sname_dup == NULL) { if (name_dup == NULL || sname_dup == NULL) {
@ -254,17 +250,17 @@ int X509_PURPOSE_add(int id, int trust, int flags,
return 0; return 0;
} }
/* OPENSSL_free existing name if dynamic */ // OPENSSL_free existing name if dynamic
if (ptmp->flags & X509_PURPOSE_DYNAMIC_NAME) { if (ptmp->flags & X509_PURPOSE_DYNAMIC_NAME) {
OPENSSL_free(ptmp->name); OPENSSL_free(ptmp->name);
OPENSSL_free(ptmp->sname); OPENSSL_free(ptmp->sname);
} }
/* dup supplied name */ // dup supplied name
ptmp->name = name_dup; ptmp->name = name_dup;
ptmp->sname = sname_dup; ptmp->sname = sname_dup;
/* Keep the dynamic flag of existing entry */ // Keep the dynamic flag of existing entry
ptmp->flags &= X509_PURPOSE_DYNAMIC; ptmp->flags &= X509_PURPOSE_DYNAMIC;
/* Set all other flags */ // Set all other flags
ptmp->flags |= flags; ptmp->flags |= flags;
ptmp->purpose = id; ptmp->purpose = id;
@ -272,7 +268,7 @@ int X509_PURPOSE_add(int id, int trust, int flags,
ptmp->check_purpose = ck; ptmp->check_purpose = ck;
ptmp->usr_data = arg; ptmp->usr_data = arg;
/* If its a new entry manage the dynamic table */ // If its a new entry manage the dynamic table
if (idx == -1) { if (idx == -1) {
if (!xptable && !(xptable = sk_X509_PURPOSE_new(xp_cmp))) { if (!xptable && !(xptable = sk_X509_PURPOSE_new(xp_cmp))) {
OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE); OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE);
@ -325,26 +321,24 @@ static int nid_cmp(const void *void_a, const void *void_b) {
} }
int X509_supported_extension(X509_EXTENSION *ex) { int X509_supported_extension(X509_EXTENSION *ex) {
/* // This table is a list of the NIDs of supported extensions: that is
* 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
* 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
* critical and doesn't appear in this list then the verify process will // normally reject the certificate. The list must be kept in numerical
* normally reject the certificate. The list must be kept in numerical // order because it will be searched using bsearch.
* order because it will be searched using bsearch.
*/
static const int supported_nids[] = { static const int supported_nids[] = {
NID_netscape_cert_type, /* 71 */ NID_netscape_cert_type, // 71
NID_key_usage, /* 83 */ NID_key_usage, // 83
NID_subject_alt_name, /* 85 */ NID_subject_alt_name, // 85
NID_basic_constraints, /* 87 */ NID_basic_constraints, // 87
NID_certificate_policies, /* 89 */ NID_certificate_policies, // 89
NID_ext_key_usage, /* 126 */ NID_ext_key_usage, // 126
NID_policy_constraints, /* 401 */ NID_policy_constraints, // 401
NID_proxyCertInfo, /* 663 */ NID_proxyCertInfo, // 663
NID_name_constraints, /* 666 */ NID_name_constraints, // 666
NID_policy_mappings, /* 747 */ NID_policy_mappings, // 747
NID_inhibit_any_policy /* 748 */ NID_inhibit_any_policy // 748
}; };
int ex_nid = OBJ_obj2nid(X509_EXTENSION_get_object(ex)); int ex_nid = OBJ_obj2nid(X509_EXTENSION_get_object(ex));
@ -432,11 +426,11 @@ int x509v3_cache_extensions(X509 *x) {
if (!X509_digest(x, EVP_sha256(), x->cert_hash, NULL)) { if (!X509_digest(x, EVP_sha256(), x->cert_hash, NULL)) {
x->ex_flags |= EXFLAG_INVALID; x->ex_flags |= EXFLAG_INVALID;
} }
/* V1 should mean no extensions ... */ // V1 should mean no extensions ...
if (X509_get_version(x) == X509_VERSION_1) { if (X509_get_version(x) == X509_VERSION_1) {
x->ex_flags |= EXFLAG_V1; x->ex_flags |= EXFLAG_V1;
} }
/* Handle basic constraints */ // Handle basic constraints
if ((bs = X509_get_ext_d2i(x, NID_basic_constraints, &j, NULL))) { if ((bs = X509_get_ext_d2i(x, NID_basic_constraints, &j, NULL))) {
if (bs->ca) { if (bs->ca) {
x->ex_flags |= EXFLAG_CA; x->ex_flags |= EXFLAG_CA;
@ -446,11 +440,11 @@ int x509v3_cache_extensions(X509 *x) {
x->ex_flags |= EXFLAG_INVALID; x->ex_flags |= EXFLAG_INVALID;
x->ex_pathlen = 0; x->ex_pathlen = 0;
} else { } else {
/* TODO(davidben): |ASN1_INTEGER_get| returns -1 on overflow, // TODO(davidben): |ASN1_INTEGER_get| returns -1 on overflow,
* which currently acts as if the constraint isn't present. This // which currently acts as if the constraint isn't present. This
* works (an overflowing path length constraint may as well be // works (an overflowing path length constraint may as well be
* infinity), but Chromium's verifier simply treats values above // infinity), but Chromium's verifier simply treats values above
* 255 as an error. */ // 255 as an error.
x->ex_pathlen = ASN1_INTEGER_get(bs->pathlen); x->ex_pathlen = ASN1_INTEGER_get(bs->pathlen);
} }
} else { } else {
@ -461,7 +455,7 @@ int x509v3_cache_extensions(X509 *x) {
} else if (j != -1) { } else if (j != -1) {
x->ex_flags |= EXFLAG_INVALID; x->ex_flags |= EXFLAG_INVALID;
} }
/* Handle proxy certificates */ // Handle proxy certificates
if ((pci = X509_get_ext_d2i(x, NID_proxyCertInfo, &j, NULL))) { if ((pci = X509_get_ext_d2i(x, NID_proxyCertInfo, &j, NULL))) {
if (x->ex_flags & EXFLAG_CA || 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_subject_alt_name, -1) >= 0 ||
@ -478,7 +472,7 @@ int x509v3_cache_extensions(X509 *x) {
} else if (j != -1) { } else if (j != -1) {
x->ex_flags |= EXFLAG_INVALID; x->ex_flags |= EXFLAG_INVALID;
} }
/* Handle key usage */ // Handle key usage
if ((usage = X509_get_ext_d2i(x, NID_key_usage, &j, NULL))) { if ((usage = X509_get_ext_d2i(x, NID_key_usage, &j, NULL))) {
if (usage->length > 0) { if (usage->length > 0) {
x->ex_kusage = usage->data[0]; x->ex_kusage = usage->data[0];
@ -560,10 +554,10 @@ int x509v3_cache_extensions(X509 *x) {
if (x->akid == NULL && j != -1) { if (x->akid == NULL && j != -1) {
x->ex_flags |= EXFLAG_INVALID; x->ex_flags |= EXFLAG_INVALID;
} }
/* Does subject name match issuer ? */ // Does subject name match issuer ?
if (!X509_NAME_cmp(X509_get_subject_name(x), X509_get_issuer_name(x))) { if (!X509_NAME_cmp(X509_get_subject_name(x), X509_get_issuer_name(x))) {
x->ex_flags |= EXFLAG_SI; x->ex_flags |= EXFLAG_SI;
/* If SKID matches AKID also indicate self signed */ // If SKID matches AKID also indicate self signed
if (X509_check_akid(x, x->akid) == X509_V_OK && if (X509_check_akid(x, x->akid) == X509_V_OK &&
!ku_reject(x, KU_KEY_CERT_SIGN)) { !ku_reject(x, KU_KEY_CERT_SIGN)) {
x->ex_flags |= EXFLAG_SS; x->ex_flags |= EXFLAG_SS;
@ -600,18 +594,18 @@ int x509v3_cache_extensions(X509 *x) {
return (x->ex_flags & EXFLAG_INVALID) == 0; return (x->ex_flags & EXFLAG_INVALID) == 0;
} }
/* check_ca returns one if |x| should be considered a CA certificate and zero // check_ca returns one if |x| should be considered a CA certificate and zero
* otherwise. */ // otherwise.
static int check_ca(const X509 *x) { static int check_ca(const X509 *x) {
/* keyUsage if present should allow cert signing */ // keyUsage if present should allow cert signing
if (ku_reject(x, KU_KEY_CERT_SIGN)) { if (ku_reject(x, KU_KEY_CERT_SIGN)) {
return 0; return 0;
} }
/* Version 1 certificates are considered CAs and don't have extensions. */ // Version 1 certificates are considered CAs and don't have extensions.
if ((x->ex_flags & V1_ROOT) == V1_ROOT) { if ((x->ex_flags & V1_ROOT) == V1_ROOT) {
return 1; return 1;
} }
/* Otherwise, it's only a CA if basicConstraints says so. */ // Otherwise, it's only a CA if basicConstraints says so.
return ((x->ex_flags & EXFLAG_BCONS) && (x->ex_flags & EXFLAG_CA)); return ((x->ex_flags & EXFLAG_BCONS) && (x->ex_flags & EXFLAG_CA));
} }
@ -630,22 +624,20 @@ static int check_purpose_ssl_client(const X509_PURPOSE *xp, const X509 *x,
if (ca) { if (ca) {
return check_ca(x); return check_ca(x);
} }
/* We need to do digital signatures or key agreement */ // We need to do digital signatures or key agreement
if (ku_reject(x, KU_DIGITAL_SIGNATURE | KU_KEY_AGREEMENT)) { if (ku_reject(x, KU_DIGITAL_SIGNATURE | KU_KEY_AGREEMENT)) {
return 0; return 0;
} }
/* nsCertType if present should allow SSL client use */ // nsCertType if present should allow SSL client use
if (ns_reject(x, NS_SSL_CLIENT)) { if (ns_reject(x, NS_SSL_CLIENT)) {
return 0; return 0;
} }
return 1; return 1;
} }
/* // Key usage needed for TLS/SSL server: digital signature, encipherment or
* Key usage needed for TLS/SSL server: digital signature, encipherment or // key agreement. The ssl code can check this more thoroughly for individual
* key agreement. The ssl code can check this more thoroughly for individual // key types.
* 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, static int check_purpose_ssl_server(const X509_PURPOSE *xp, const X509 *x,
@ -674,21 +666,21 @@ static int check_purpose_ns_ssl_server(const X509_PURPOSE *xp, const X509 *x,
if (!ret || ca) { if (!ret || ca) {
return ret; return ret;
} }
/* We need to encipher or Netscape complains */ // We need to encipher or Netscape complains
if (ku_reject(x, KU_KEY_ENCIPHERMENT)) { if (ku_reject(x, KU_KEY_ENCIPHERMENT)) {
return 0; return 0;
} }
return ret; return ret;
} }
/* purpose_smime returns one if |x| is a valid S/MIME leaf (|ca| is zero) or CA // purpose_smime returns one if |x| is a valid S/MIME leaf (|ca| is zero) or CA
* (|ca| is one) certificate, and zero otherwise. */ // (|ca| is one) certificate, and zero otherwise.
static int purpose_smime(const X509 *x, int ca) { static int purpose_smime(const X509 *x, int ca) {
if (xku_reject(x, XKU_SMIME)) { if (xku_reject(x, XKU_SMIME)) {
return 0; return 0;
} }
if (ca) { if (ca) {
/* check nsCertType if present */ // check nsCertType if present
if ((x->ex_flags & EXFLAG_NSCERT) && (x->ex_nscert & NS_SMIME_CA) == 0) { if ((x->ex_flags & EXFLAG_NSCERT) && (x->ex_nscert & NS_SMIME_CA) == 0) {
return 0; return 0;
} }
@ -738,16 +730,14 @@ static int check_purpose_crl_sign(const X509_PURPOSE *xp, const X509 *x,
return 1; return 1;
} }
/* // OCSP helper: this is *not* a full OCSP check. It just checks that each CA
* OCSP helper: this is *not* a full OCSP check. It just checks that each CA // is valid. Additional checks must be made on the chain.
* is valid. Additional checks must be made on the chain.
*/
static int ocsp_helper(const X509_PURPOSE *xp, const X509 *x, int ca) { static int ocsp_helper(const X509_PURPOSE *xp, const X509 *x, int ca) {
if (ca) { if (ca) {
return check_ca(x); return check_ca(x);
} }
/* leaf certificate is checked in OCSP_verify() */ // leaf certificate is checked in OCSP_verify()
return 1; return 1;
} }
@ -755,29 +745,27 @@ static int check_purpose_timestamp_sign(const X509_PURPOSE *xp, const X509 *x,
int ca) { int ca) {
int i_ext; int i_ext;
/* If ca is true we must return if this is a valid CA certificate. */ // If ca is true we must return if this is a valid CA certificate.
if (ca) { if (ca) {
return check_ca(x); return check_ca(x);
} }
/* // Check the optional key usage field:
* Check the optional key usage field: // if Key Usage is present, it must be one of digitalSignature
* if Key Usage is present, it must be one of digitalSignature // and/or nonRepudiation (other values are not consistent and shall
* and/or nonRepudiation (other values are not consistent and shall // be rejected).
* be rejected).
*/
if ((x->ex_flags & EXFLAG_KUSAGE) && if ((x->ex_flags & EXFLAG_KUSAGE) &&
((x->ex_kusage & ~(KU_NON_REPUDIATION | KU_DIGITAL_SIGNATURE)) || ((x->ex_kusage & ~(KU_NON_REPUDIATION | KU_DIGITAL_SIGNATURE)) ||
!(x->ex_kusage & (KU_NON_REPUDIATION | KU_DIGITAL_SIGNATURE)))) { !(x->ex_kusage & (KU_NON_REPUDIATION | KU_DIGITAL_SIGNATURE)))) {
return 0; return 0;
} }
/* Only time stamp key usage is permitted and it's required. */ // Only time stamp key usage is permitted and it's required.
if (!(x->ex_flags & EXFLAG_XKUSAGE) || x->ex_xkusage != XKU_TIMESTAMP) { if (!(x->ex_flags & EXFLAG_XKUSAGE) || x->ex_xkusage != XKU_TIMESTAMP) {
return 0; return 0;
} }
/* Extended Key Usage MUST be critical */ // Extended Key Usage MUST be critical
i_ext = X509_get_ext_by_NID((X509 *)x, NID_ext_key_usage, -1); i_ext = X509_get_ext_by_NID((X509 *)x, NID_ext_key_usage, -1);
if (i_ext >= 0) { if (i_ext >= 0) {
X509_EXTENSION *ext = X509_get_ext((X509 *)x, i_ext); X509_EXTENSION *ext = X509_get_ext((X509 *)x, i_ext);
@ -791,15 +779,13 @@ static int check_purpose_timestamp_sign(const X509_PURPOSE *xp, const X509 *x,
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
* Various checks to see if one certificate issued the second. This can be // used to prune a set of possible issuer certificates which have been looked
* used to prune a set of possible issuer certificates which have been looked // up using some simple method such as by subject name. These are: 1. Check
* up using some simple method such as by subject name. These are: 1. Check // issuer_name(subject) == subject_name(issuer) 2. If akid(subject) exists
* issuer_name(subject) == subject_name(issuer) 2. If akid(subject) exists // check it matches issuer 3. If key_usage(issuer) exists check it supports
* check it matches issuer 3. If key_usage(issuer) exists check it supports // certificate signing returns 0 for OK, positive for reason for mismatch,
* certificate signing returns 0 for OK, positive for reason for mismatch, // reasons match codes for X509_verify_cert()
* reasons match codes for X509_verify_cert()
*/
int X509_check_issued(X509 *issuer, X509 *subject) { int X509_check_issued(X509 *issuer, X509 *subject) {
if (X509_NAME_cmp(X509_get_subject_name(issuer), if (X509_NAME_cmp(X509_get_subject_name(issuer),
@ -832,23 +818,21 @@ int X509_check_akid(X509 *issuer, AUTHORITY_KEYID *akid) {
return X509_V_OK; return X509_V_OK;
} }
/* Check key ids (if present) */ // Check key ids (if present)
if (akid->keyid && issuer->skid && if (akid->keyid && issuer->skid &&
ASN1_OCTET_STRING_cmp(akid->keyid, issuer->skid)) { ASN1_OCTET_STRING_cmp(akid->keyid, issuer->skid)) {
return X509_V_ERR_AKID_SKID_MISMATCH; return X509_V_ERR_AKID_SKID_MISMATCH;
} }
/* Check serial number */ // Check serial number
if (akid->serial && if (akid->serial &&
ASN1_INTEGER_cmp(X509_get_serialNumber(issuer), akid->serial)) { ASN1_INTEGER_cmp(X509_get_serialNumber(issuer), akid->serial)) {
return X509_V_ERR_AKID_ISSUER_SERIAL_MISMATCH; return X509_V_ERR_AKID_ISSUER_SERIAL_MISMATCH;
} }
/* Check issuer name */ // Check issuer name
if (akid->issuer) { if (akid->issuer) {
/* // Ugh, for some peculiar reason AKID includes SEQUENCE OF
* Ugh, for some peculiar reason AKID includes SEQUENCE OF // GeneralName. So look for a DirName. There may be more than one but
* GeneralName. So look for a DirName. There may be more than one but // we only take any notice of the first.
* we only take any notice of the first.
*/
GENERAL_NAMES *gens; GENERAL_NAMES *gens;
GENERAL_NAME *gen; GENERAL_NAME *gen;
X509_NAME *nm = NULL; X509_NAME *nm = NULL;
@ -869,8 +853,8 @@ int X509_check_akid(X509 *issuer, AUTHORITY_KEYID *akid) {
} }
uint32_t X509_get_extension_flags(X509 *x) { uint32_t X509_get_extension_flags(X509 *x) {
/* Ignore the return value. On failure, |x->ex_flags| will include // Ignore the return value. On failure, |x->ex_flags| will include
* |EXFLAG_INVALID|. */ // |EXFLAG_INVALID|.
x509v3_cache_extensions(x); x509v3_cache_extensions(x);
return x->ex_flags; return x->ex_flags;
} }

@ -87,7 +87,7 @@ static int ipv6_from_asc(unsigned char v6[16], const char *in);
static int ipv6_cb(const char *elem, int len, void *usr); static int ipv6_cb(const char *elem, int len, void *usr);
static int ipv6_hex(unsigned char *out, const char *in, int inlen); static int ipv6_hex(unsigned char *out, const char *in, int inlen);
/* Add a CONF_VALUE name value pair to stack */ // Add a CONF_VALUE name value pair to stack
static int x509V3_add_len_value(const char *name, const char *value, static int x509V3_add_len_value(const char *name, const char *value,
size_t value_len, int omit_value, size_t value_len, int omit_value,
@ -99,7 +99,7 @@ static int x509V3_add_len_value(const char *name, const char *value,
goto malloc_err; goto malloc_err;
} }
if (!omit_value) { if (!omit_value) {
/* |CONF_VALUE| cannot represent strings with NULs. */ // |CONF_VALUE| cannot represent strings with NULs.
if (OPENSSL_memchr(value, 0, value_len)) { if (OPENSSL_memchr(value, 0, value_len)) {
OPENSSL_PUT_ERROR(X509V3, X509V3_R_INVALID_VALUE); OPENSSL_PUT_ERROR(X509V3, X509V3_R_INVALID_VALUE);
goto err; goto err;
@ -152,7 +152,7 @@ int x509V3_add_value_asn1_string(const char *name, const ASN1_STRING *value,
/*omit_value=*/0, extlist); /*omit_value=*/0, extlist);
} }
/* Free function for STACK_OF(CONF_VALUE) */ // Free function for STACK_OF(CONF_VALUE)
void X509V3_conf_free(CONF_VALUE *conf) { void X509V3_conf_free(CONF_VALUE *conf) {
if (!conf) { if (!conf) {
@ -190,11 +190,9 @@ static char *bignum_to_string(const BIGNUM *bn) {
char *tmp, *ret; char *tmp, *ret;
size_t len; size_t len;
/* // Display large numbers in hex and small numbers in decimal. Converting to
* 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
* decimal takes quadratic time and is no more useful than hex for large // numbers.
* numbers.
*/
if (BN_num_bits(bn) < 32) { if (BN_num_bits(bn) < 32) {
return BN_bn2dec(bn); return BN_bn2dec(bn);
} }
@ -212,7 +210,7 @@ static char *bignum_to_string(const BIGNUM *bn) {
return NULL; return NULL;
} }
/* Prepend "0x", but place it after the "-" if negative. */ // Prepend "0x", but place it after the "-" if negative.
if (tmp[0] == '-') { if (tmp[0] == '-') {
OPENSSL_strlcpy(ret, "-0x", len); OPENSSL_strlcpy(ret, "-0x", len);
OPENSSL_strlcat(ret, tmp + 1, len); OPENSSL_strlcat(ret, tmp + 1, len);
@ -355,9 +353,7 @@ int X509V3_get_value_int(const CONF_VALUE *value, ASN1_INTEGER **aint) {
#define HDR_NAME 1 #define HDR_NAME 1
#define HDR_VALUE 2 #define HDR_VALUE 2
/* // #define DEBUG
* #define DEBUG
*/
STACK_OF(CONF_VALUE) *X509V3_parse_list(const char *line) { STACK_OF(CONF_VALUE) *X509V3_parse_list(const char *line) {
char *p, *q, c; char *p, *q, c;
@ -365,7 +361,7 @@ STACK_OF(CONF_VALUE) *X509V3_parse_list(const char *line) {
STACK_OF(CONF_VALUE) *values = NULL; STACK_OF(CONF_VALUE) *values = NULL;
char *linebuf; char *linebuf;
int state; int state;
/* We are going to modify the line so copy it first */ // We are going to modify the line so copy it first
linebuf = OPENSSL_strdup(line); linebuf = OPENSSL_strdup(line);
if (linebuf == NULL) { if (linebuf == NULL) {
OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE); OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE);
@ -373,7 +369,7 @@ STACK_OF(CONF_VALUE) *X509V3_parse_list(const char *line) {
} }
state = HDR_NAME; state = HDR_NAME;
ntmp = NULL; ntmp = NULL;
/* Go through all characters */ // Go through all characters
for (p = linebuf, q = linebuf; (c = *p) && (c != '\r') && (c != '\n'); p++) { for (p = linebuf, q = linebuf; (c = *p) && (c != '\r') && (c != '\n'); p++) {
switch (state) { switch (state) {
case HDR_NAME: case HDR_NAME:
@ -450,10 +446,10 @@ err:
return NULL; return NULL;
} }
/* Delete leading and trailing spaces from a string */ // Delete leading and trailing spaces from a string
static char *strip_spaces(char *name) { static char *strip_spaces(char *name) {
char *p, *q; char *p, *q;
/* Skip over leading spaces */ // Skip over leading spaces
p = name; p = name;
while (*p && isspace((unsigned char)*p)) { while (*p && isspace((unsigned char)*p)) {
p++; p++;
@ -474,7 +470,7 @@ static char *strip_spaces(char *name) {
return p; return p;
} }
/* hex string utilities */ // hex string utilities
char *x509v3_bytes_to_hex(const uint8_t *in, size_t len) { char *x509v3_bytes_to_hex(const uint8_t *in, size_t len) {
CBB cbb; CBB cbb;
@ -637,9 +633,9 @@ static STACK_OF(OPENSSL_STRING) *get_email(X509_NAME *name,
GENERAL_NAME *gen; GENERAL_NAME *gen;
int i; int i;
size_t j; size_t j;
/* Now add any email address(es) to STACK */ // Now add any email address(es) to STACK
i = -1; i = -1;
/* First supplied X509_NAME */ // First supplied X509_NAME
while ((i = X509_NAME_get_index_by_NID(name, NID_pkcs9_emailAddress, i)) >= while ((i = X509_NAME_get_index_by_NID(name, NID_pkcs9_emailAddress, i)) >=
0) { 0) {
ne = X509_NAME_get_entry(name, i); ne = X509_NAME_get_entry(name, i);
@ -663,15 +659,15 @@ static STACK_OF(OPENSSL_STRING) *get_email(X509_NAME *name,
static void str_free(OPENSSL_STRING str) { OPENSSL_free(str); } static void str_free(OPENSSL_STRING str) { OPENSSL_free(str); }
static int append_ia5(STACK_OF(OPENSSL_STRING) **sk, ASN1_IA5STRING *email) { static int append_ia5(STACK_OF(OPENSSL_STRING) **sk, ASN1_IA5STRING *email) {
/* First some sanity checks */ // First some sanity checks
if (email->type != V_ASN1_IA5STRING) { if (email->type != V_ASN1_IA5STRING) {
return 1; return 1;
} }
if (email->data == NULL || email->length == 0) { if (email->data == NULL || email->length == 0) {
return 1; return 1;
} }
/* |OPENSSL_STRING| cannot represent strings with embedded NULs. Do not // |OPENSSL_STRING| cannot represent strings with embedded NULs. Do not
* report them as outputs. */ // report them as outputs.
if (OPENSSL_memchr(email->data, 0, email->length) != NULL) { if (OPENSSL_memchr(email->data, 0, email->length) != NULL) {
return 1; return 1;
} }
@ -689,7 +685,7 @@ static int append_ia5(STACK_OF(OPENSSL_STRING) **sk, ASN1_IA5STRING *email) {
goto err; goto err;
} }
/* Don't add duplicates */ // Don't add duplicates
sk_OPENSSL_STRING_sort(*sk); sk_OPENSSL_STRING_sort(*sk);
if (sk_OPENSSL_STRING_find(*sk, NULL, emtmp)) { if (sk_OPENSSL_STRING_find(*sk, NULL, emtmp)) {
OPENSSL_free(emtmp); OPENSSL_free(emtmp);
@ -701,8 +697,8 @@ static int append_ia5(STACK_OF(OPENSSL_STRING) **sk, ASN1_IA5STRING *email) {
return 1; return 1;
err: err:
/* TODO(davidben): Fix the error-handling in this file. It currently relies // TODO(davidben): Fix the error-handling in this file. It currently relies
* on |append_ia5| leaving |*sk| at NULL on error. */ // on |append_ia5| leaving |*sk| at NULL on error.
OPENSSL_free(emtmp); OPENSSL_free(emtmp);
X509_email_free(*sk); X509_email_free(*sk);
*sk = NULL; *sk = NULL;
@ -717,7 +713,7 @@ typedef int (*equal_fn)(const unsigned char *pattern, size_t pattern_len,
const unsigned char *subject, size_t subject_len, const unsigned char *subject, size_t subject_len,
unsigned int flags); unsigned int flags);
/* Compare while ASCII ignoring case. */ // Compare while ASCII ignoring case.
static int equal_nocase(const unsigned char *pattern, size_t pattern_len, static int equal_nocase(const unsigned char *pattern, size_t pattern_len,
const unsigned char *subject, size_t subject_len, const unsigned char *subject, size_t subject_len,
unsigned int flags) { unsigned int flags) {
@ -727,7 +723,7 @@ static int equal_nocase(const unsigned char *pattern, size_t pattern_len,
while (pattern_len) { while (pattern_len) {
unsigned char l = *pattern; unsigned char l = *pattern;
unsigned char r = *subject; unsigned char r = *subject;
/* The pattern must not contain NUL characters. */ // The pattern must not contain NUL characters.
if (l == 0) { if (l == 0) {
return 0; return 0;
} }
@ -749,7 +745,7 @@ static int equal_nocase(const unsigned char *pattern, size_t pattern_len,
return 1; return 1;
} }
/* Compare using OPENSSL_memcmp. */ // Compare using OPENSSL_memcmp.
static int equal_case(const unsigned char *pattern, size_t pattern_len, static int equal_case(const unsigned char *pattern, size_t pattern_len,
const unsigned char *subject, size_t subject_len, const unsigned char *subject, size_t subject_len,
unsigned int flags) { unsigned int flags) {
@ -759,10 +755,8 @@ static int equal_case(const unsigned char *pattern, size_t pattern_len,
return !OPENSSL_memcmp(pattern, subject, pattern_len); return !OPENSSL_memcmp(pattern, subject, pattern_len);
} }
/* // RFC 5280, section 7.5, requires that only the domain is compared in a
* RFC 5280, section 7.5, requires that only the domain is compared in a // case-insensitive manner.
* case-insensitive manner.
*/
static int equal_email(const unsigned char *a, size_t a_len, static int equal_email(const unsigned char *a, size_t a_len,
const unsigned char *b, size_t b_len, const unsigned char *b, size_t b_len,
unsigned int unused_flags) { unsigned int unused_flags) {
@ -770,11 +764,9 @@ static int equal_email(const unsigned char *a, size_t a_len,
if (a_len != b_len) { if (a_len != b_len) {
return 0; return 0;
} }
/* // We search backwards for the '@' character, so that we do not have to
* 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
* deal with quoted local-parts. The domain part is compared in a // case-insensitive manner.
* case-insensitive manner.
*/
while (i > 0) { while (i > 0) {
--i; --i;
if (a[i] == '@' || b[i] == '@') { if (a[i] == '@' || b[i] == '@') {
@ -790,10 +782,8 @@ static int equal_email(const unsigned char *a, size_t a_len,
return equal_case(a, i, b, i, 0); return equal_case(a, i, b, i, 0);
} }
/* // Compare the prefix and suffix with the subject, and check that the
* Compare the prefix and suffix with the subject, and check that the // characters in-between are valid.
* characters in-between are valid.
*/
static int wildcard_match(const unsigned char *prefix, size_t prefix_len, static int wildcard_match(const unsigned char *prefix, size_t prefix_len,
const unsigned char *suffix, size_t suffix_len, const unsigned char *suffix, size_t suffix_len,
const unsigned char *subject, size_t subject_len, const unsigned char *subject, size_t subject_len,
@ -814,29 +804,25 @@ static int wildcard_match(const unsigned char *prefix, size_t prefix_len,
if (!equal_nocase(wildcard_end, suffix_len, suffix, suffix_len, flags)) { if (!equal_nocase(wildcard_end, suffix_len, suffix, suffix_len, flags)) {
return 0; return 0;
} }
/* // If the wildcard makes up the entire first label, it must match at
* If the wildcard makes up the entire first label, it must match at // least one character.
* least one character.
*/
if (prefix_len == 0 && *suffix == '.') { if (prefix_len == 0 && *suffix == '.') {
if (wildcard_start == wildcard_end) { if (wildcard_start == wildcard_end) {
return 0; return 0;
} }
allow_idna = 1; allow_idna = 1;
} }
/* IDNA labels cannot match partial wildcards */ // IDNA labels cannot match partial wildcards
if (!allow_idna && subject_len >= 4 && if (!allow_idna && subject_len >= 4 &&
OPENSSL_strncasecmp((char *)subject, "xn--", 4) == 0) { OPENSSL_strncasecmp((char *)subject, "xn--", 4) == 0) {
return 0; return 0;
} }
/* The wildcard may match a literal '*' */ // The wildcard may match a literal '*'
if (wildcard_end == wildcard_start + 1 && *wildcard_start == '*') { if (wildcard_end == wildcard_start + 1 && *wildcard_start == '*') {
return 1; return 1;
} }
/* // Check that the part matched by the wildcard contains only
* Check that the part matched by the wildcard contains only // permitted characters and only matches a single label.
* permitted characters and only matches a single label.
*/
for (p = wildcard_start; p != wildcard_end; ++p) { for (p = wildcard_start; p != wildcard_end; ++p) {
if (!(('0' <= *p && *p <= '9') || ('A' <= *p && *p <= 'Z') || if (!(('0' <= *p && *p <= '9') || ('A' <= *p && *p <= 'Z') ||
('a' <= *p && *p <= 'z') || *p == '-')) { ('a' <= *p && *p <= 'z') || *p == '-')) {
@ -858,22 +844,18 @@ static const unsigned char *valid_star(const unsigned char *p, size_t len,
int state = LABEL_START; int state = LABEL_START;
int dots = 0; int dots = 0;
for (i = 0; i < len; ++i) { for (i = 0; i < len; ++i) {
/* // Locate first and only legal wildcard, either at the start
* Locate first and only legal wildcard, either at the start // or end of a non-IDNA first and not final label.
* or end of a non-IDNA first and not final label.
*/
if (p[i] == '*') { if (p[i] == '*') {
int atstart = (state & LABEL_START); int atstart = (state & LABEL_START);
int atend = (i == len - 1 || p[i + 1] == '.'); int atend = (i == len - 1 || p[i + 1] == '.');
/* // At most one wildcard per pattern.
* At most one wildcard per pattern. // No wildcards in IDNA labels.
* No wildcards in IDNA labels. // No wildcards after the first label.
* No wildcards after the first label.
*/
if (star != NULL || (state & LABEL_IDNA) != 0 || dots) { if (star != NULL || (state & LABEL_IDNA) != 0 || dots) {
return NULL; return NULL;
} }
/* Only full-label '*.example.com' wildcards. */ // Only full-label '*.example.com' wildcards.
if (!atstart || !atend) { if (!atstart || !atend) {
return NULL; return NULL;
} }
@ -893,7 +875,7 @@ static const unsigned char *valid_star(const unsigned char *p, size_t len,
state = LABEL_START; state = LABEL_START;
++dots; ++dots;
} else if (p[i] == '-') { } else if (p[i] == '-') {
/* no domain/subdomain starts with '-' */ // no domain/subdomain starts with '-'
if ((state & LABEL_START) != 0) { if ((state & LABEL_START) != 0) {
return NULL; return NULL;
} }
@ -903,26 +885,22 @@ static const unsigned char *valid_star(const unsigned char *p, size_t len,
} }
} }
/* // The final label must not end in a hyphen or ".", and
* The final label must not end in a hyphen or ".", and // there must be at least two dots after the star.
* there must be at least two dots after the star.
*/
if ((state & (LABEL_START | LABEL_HYPHEN)) != 0 || dots < 2) { if ((state & (LABEL_START | LABEL_HYPHEN)) != 0 || dots < 2) {
return NULL; return NULL;
} }
return star; return star;
} }
/* Compare using wildcards. */ // Compare using wildcards.
static int equal_wildcard(const unsigned char *pattern, size_t pattern_len, static int equal_wildcard(const unsigned char *pattern, size_t pattern_len,
const unsigned char *subject, size_t subject_len, const unsigned char *subject, size_t subject_len,
unsigned int flags) { unsigned int flags) {
const unsigned char *star = NULL; const unsigned char *star = NULL;
/* // Subject names starting with '.' can only match a wildcard pattern
* Subject names starting with '.' can only match a wildcard pattern // via a subject sub-domain pattern suffix match.
* via a subject sub-domain pattern suffix match.
*/
if (!(subject_len > 1 && subject[0] == '.')) { if (!(subject_len > 1 && subject[0] == '.')) {
star = valid_star(pattern, pattern_len, flags); star = valid_star(pattern, pattern_len, flags);
} }
@ -935,17 +913,17 @@ static int equal_wildcard(const unsigned char *pattern, size_t pattern_len,
} }
int x509v3_looks_like_dns_name(const unsigned char *in, size_t len) { 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 // 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 // hostname to be matched, or merely a decorative name to describe the
* subject. This heuristic must be applied to both name constraints and 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 name fallback, so it must be loose enough to accept hostname
* common names, and tight enough to reject decorative common names. */ // common names, and tight enough to reject decorative common names.
if (len > 0 && in[len - 1] == '.') { if (len > 0 && in[len - 1] == '.') {
len--; len--;
} }
/* Wildcards are allowed in front. */ // Wildcards are allowed in front.
if (len >= 2 && in[0] == '*' && in[1] == '.') { if (len >= 2 && in[0] == '*' && in[1] == '.') {
in += 2; in += 2;
len -= 2; len -= 2;
@ -960,13 +938,13 @@ int x509v3_looks_like_dns_name(const unsigned char *in, size_t len) {
unsigned char c = in[i]; unsigned char c = in[i];
if ((c >= 'a' && c <= 'z') || (c >= '0' && c <= '9') || if ((c >= 'a' && c <= 'z') || (c >= '0' && c <= '9') ||
(c >= 'A' && c <= 'Z') || (c == '-' && i > label_start) || (c >= 'A' && c <= 'Z') || (c == '-' && i > label_start) ||
/* These are not valid characters in hostnames, but commonly found // These are not valid characters in hostnames, but commonly found
* in deployments outside the Web PKI. */ // in deployments outside the Web PKI.
c == '_' || c == ':') { c == '_' || c == ':') {
continue; continue;
} }
/* Labels must not be empty. */ // Labels must not be empty.
if (c == '.' && i > label_start && i < len - 1) { if (c == '.' && i > label_start && i < len - 1) {
label_start = i + 1; label_start = i + 1;
continue; continue;
@ -978,11 +956,9 @@ int x509v3_looks_like_dns_name(const unsigned char *in, size_t len) {
return 1; return 1;
} }
/* // Compare an ASN1_STRING to a supplied string. If they match return 1. If
* Compare an ASN1_STRING to a supplied string. If they match return 1. If // cmp_type > 0 only compare if string matches the type, otherwise convert it
* cmp_type > 0 only compare if string matches the type, otherwise convert it // to UTF8.
* to UTF8.
*/
static int do_check_string(ASN1_STRING *a, int cmp_type, equal_fn equal, static int do_check_string(ASN1_STRING *a, int cmp_type, equal_fn equal,
unsigned int flags, int check_type, const char *b, unsigned int flags, int check_type, const char *b,
@ -1011,11 +987,9 @@ static int do_check_string(ASN1_STRING *a, int cmp_type, equal_fn equal,
if (astrlen < 0) { if (astrlen < 0) {
return -1; return -1;
} }
/* // We check the common name against DNS name constraints if it passes
* We check the common name against DNS name constraints if it passes // |x509v3_looks_like_dns_name|. Thus we must not consider common names
* |x509v3_looks_like_dns_name|. Thus we must not consider common names // for DNS fallbacks if they fail this check.
* for DNS fallbacks if they fail this check.
*/
if (check_type == GEN_DNS && !x509v3_looks_like_dns_name(astr, astrlen)) { if (check_type == GEN_DNS && !x509v3_looks_like_dns_name(astr, astrlen)) {
rv = 0; rv = 0;
} else { } else {
@ -1073,7 +1047,7 @@ static int do_x509_check(X509 *x, const char *chk, size_t chklen,
} else { } else {
cstr = gen->d.iPAddress; cstr = gen->d.iPAddress;
} }
/* Positive on success, negative on error! */ // Positive on success, negative on error!
if ((rv = do_check_string(cstr, alt_type, equal, flags, check_type, chk, if ((rv = do_check_string(cstr, alt_type, equal, flags, check_type, chk,
chklen, peername)) != 0) { chklen, peername)) != 0) {
break; break;
@ -1083,7 +1057,7 @@ static int do_x509_check(X509 *x, const char *chk, size_t chklen,
return rv; return rv;
} }
/* We're done if CN-ID is not pertinent */ // We're done if CN-ID is not pertinent
if (cnid == NID_undef || (flags & X509_CHECK_FLAG_NEVER_CHECK_SUBJECT)) { if (cnid == NID_undef || (flags & X509_CHECK_FLAG_NEVER_CHECK_SUBJECT)) {
return 0; return 0;
} }
@ -1095,7 +1069,7 @@ static int do_x509_check(X509 *x, const char *chk, size_t chklen,
ASN1_STRING *str; ASN1_STRING *str;
ne = X509_NAME_get_entry(name, j); ne = X509_NAME_get_entry(name, j);
str = X509_NAME_ENTRY_get_data(ne); str = X509_NAME_ENTRY_get_data(ne);
/* Positive on success, negative on error! */ // Positive on success, negative on error!
if ((rv = do_check_string(str, -1, equal, flags, check_type, chk, chklen, if ((rv = do_check_string(str, -1, equal, flags, check_type, chk, chklen,
peername)) != 0) { peername)) != 0) {
return rv; return rv;
@ -1148,10 +1122,8 @@ int X509_check_ip_asc(X509 *x, const char *ipasc, unsigned int flags) {
return do_x509_check(x, (char *)ipout, iplen, flags, GEN_IPADD, NULL); return do_x509_check(x, (char *)ipout, iplen, flags, GEN_IPADD, NULL);
} }
/* // Convert IP addresses both IPv4 and IPv6 into an OCTET STRING compatible
* Convert IP addresses both IPv4 and IPv6 into an OCTET STRING compatible // with RFC 3280.
* with RFC 3280.
*/
ASN1_OCTET_STRING *a2i_IPADDRESS(const char *ipasc) { ASN1_OCTET_STRING *a2i_IPADDRESS(const char *ipasc) {
unsigned char ipout[16]; unsigned char ipout[16];
@ -1226,7 +1198,7 @@ err:
} }
int x509v3_a2i_ipadd(unsigned char ipout[16], const char *ipasc) { int x509v3_a2i_ipadd(unsigned char ipout[16], const char *ipasc) {
/* If string contains a ':' assume IPv6 */ // If string contains a ':' assume IPv6
if (strchr(ipasc, ':')) { if (strchr(ipasc, ':')) {
if (!ipv6_from_asc(ipout, ipasc)) { if (!ipv6_from_asc(ipout, ipasc)) {
@ -1258,13 +1230,13 @@ static int ipv4_from_asc(unsigned char v4[4], const char *in) {
} }
typedef struct { typedef struct {
/* Temporary store for IPV6 output */ // Temporary store for IPV6 output
unsigned char tmp[16]; unsigned char tmp[16];
/* Total number of bytes in tmp */ // Total number of bytes in tmp
int total; int total;
/* The position of a zero (corresponding to '::') */ // The position of a zero (corresponding to '::')
int zero_pos; int zero_pos;
/* Number of zeroes */ // Number of zeroes
int zero_cnt; int zero_cnt;
} IPV6_STAT; } IPV6_STAT;
@ -1273,44 +1245,42 @@ static int ipv6_from_asc(unsigned char v6[16], const char *in) {
v6stat.total = 0; v6stat.total = 0;
v6stat.zero_pos = -1; v6stat.zero_pos = -1;
v6stat.zero_cnt = 0; v6stat.zero_cnt = 0;
/* // Treat the IPv6 representation as a list of values separated by ':'.
* Treat the IPv6 representation as a list of values separated by ':'. // The presence of a '::' will parse as one, two or three zero length
* The presence of a '::' will parse as one, two or three zero length // elements.
* elements.
*/
if (!CONF_parse_list(in, ':', 0, ipv6_cb, &v6stat)) { if (!CONF_parse_list(in, ':', 0, ipv6_cb, &v6stat)) {
return 0; return 0;
} }
/* Now for some sanity checks */ // Now for some sanity checks
if (v6stat.zero_pos == -1) { if (v6stat.zero_pos == -1) {
/* If no '::' must have exactly 16 bytes */ // If no '::' must have exactly 16 bytes
if (v6stat.total != 16) { if (v6stat.total != 16) {
return 0; return 0;
} }
} else { } else {
/* If '::' must have less than 16 bytes */ // If '::' must have less than 16 bytes
if (v6stat.total == 16) { if (v6stat.total == 16) {
return 0; return 0;
} }
/* More than three zeroes is an error */ // More than three zeroes is an error
if (v6stat.zero_cnt > 3) { if (v6stat.zero_cnt > 3) {
return 0; return 0;
} }
/* Can only have three zeroes if nothing else present */ // Can only have three zeroes if nothing else present
else if (v6stat.zero_cnt == 3) { else if (v6stat.zero_cnt == 3) {
if (v6stat.total > 0) { if (v6stat.total > 0) {
return 0; return 0;
} }
} }
/* Can only have two zeroes if at start or end */ // Can only have two zeroes if at start or end
else if (v6stat.zero_cnt == 2) { else if (v6stat.zero_cnt == 2) {
if ((v6stat.zero_pos != 0) && (v6stat.zero_pos != v6stat.total)) { if ((v6stat.zero_pos != 0) && (v6stat.zero_pos != v6stat.total)) {
return 0; return 0;
} }
} else } else
/* Can only have one zero if *not* start or end */ // Can only have one zero if *not* start or end
{ {
if ((v6stat.zero_pos == 0) || (v6stat.zero_pos == v6stat.total)) { if ((v6stat.zero_pos == 0) || (v6stat.zero_pos == v6stat.total)) {
return 0; return 0;
@ -1318,14 +1288,14 @@ static int ipv6_from_asc(unsigned char v6[16], const char *in) {
} }
} }
/* Format result */ // Format result
if (v6stat.zero_pos >= 0) { if (v6stat.zero_pos >= 0) {
/* Copy initial part */ // Copy initial part
OPENSSL_memcpy(v6, v6stat.tmp, v6stat.zero_pos); OPENSSL_memcpy(v6, v6stat.tmp, v6stat.zero_pos);
/* Zero middle */ // Zero middle
OPENSSL_memset(v6 + v6stat.zero_pos, 0, 16 - v6stat.total); OPENSSL_memset(v6 + v6stat.zero_pos, 0, 16 - v6stat.total);
/* Copy final part */ // Copy final part
if (v6stat.total != v6stat.zero_pos) { if (v6stat.total != v6stat.zero_pos) {
OPENSSL_memcpy(v6 + v6stat.zero_pos + 16 - v6stat.total, OPENSSL_memcpy(v6 + v6stat.zero_pos + 16 - v6stat.total,
v6stat.tmp + v6stat.zero_pos, v6stat.tmp + v6stat.zero_pos,
@ -1340,28 +1310,28 @@ static int ipv6_from_asc(unsigned char v6[16], const char *in) {
static int ipv6_cb(const char *elem, int len, void *usr) { static int ipv6_cb(const char *elem, int len, void *usr) {
IPV6_STAT *s = usr; IPV6_STAT *s = usr;
/* Error if 16 bytes written */ // Error if 16 bytes written
if (s->total == 16) { if (s->total == 16) {
return 0; return 0;
} }
if (len == 0) { if (len == 0) {
/* Zero length element, corresponds to '::' */ // Zero length element, corresponds to '::'
if (s->zero_pos == -1) { if (s->zero_pos == -1) {
s->zero_pos = s->total; s->zero_pos = s->total;
} }
/* If we've already got a :: its an error */ // If we've already got a :: its an error
else if (s->zero_pos != s->total) { else if (s->zero_pos != s->total) {
return 0; return 0;
} }
s->zero_cnt++; s->zero_cnt++;
} else { } else {
/* If more than 4 characters could be final a.b.c.d form */ // If more than 4 characters could be final a.b.c.d form
if (len > 4) { if (len > 4) {
/* Need at least 4 bytes left */ // Need at least 4 bytes left
if (s->total > 12) { if (s->total > 12) {
return 0; return 0;
} }
/* Must be end of string */ // Must be end of string
if (elem[len]) { if (elem[len]) {
return 0; return 0;
} }
@ -1379,9 +1349,7 @@ static int ipv6_cb(const char *elem, int len, void *usr) {
return 1; return 1;
} }
/* // Convert a string of up to 4 hex digits into the corresponding IPv6 form.
* 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) { static int ipv6_hex(unsigned char *out, const char *in, int inlen) {
unsigned char c; unsigned char c;
@ -1420,9 +1388,7 @@ int X509V3_NAME_from_section(X509_NAME *nm, STACK_OF(CONF_VALUE) *dn_sk,
for (i = 0; i < sk_CONF_VALUE_num(dn_sk); i++) { for (i = 0; i < sk_CONF_VALUE_num(dn_sk); i++) {
v = sk_CONF_VALUE_value(dn_sk, i); v = sk_CONF_VALUE_value(dn_sk, i);
type = v->name; type = v->name;
/* // Skip past any leading X. X: X, etc to allow for multiple instances
* Skip past any leading X. X: X, etc to allow for multiple instances
*/
for (p = type; *p; p++) { for (p = type; *p; p++) {
if ((*p == ':') || (*p == ',') || (*p == '.')) { if ((*p == ':') || (*p == ',') || (*p == '.')) {
p++; p++;

Loading…
Cancel
Save