diff options
author | Jung-uk Kim <jkim@FreeBSD.org> | 2016-09-22 13:05:59 +0000 |
---|---|---|
committer | Jung-uk Kim <jkim@FreeBSD.org> | 2016-09-22 13:05:59 +0000 |
commit | 2c14c598c3061ac2533f997352aa06a2266f44d9 (patch) | |
tree | 470894a14935f308eeac93c6cbf6cf25632e1cb1 /crypto/asn1 | |
parent | 47b11f985b9e0ff561a67e19674de6fbcf79281d (diff) |
Notes
Diffstat (limited to 'crypto/asn1')
-rw-r--r-- | crypto/asn1/a_bytes.c | 58 | ||||
-rw-r--r-- | crypto/asn1/a_object.c | 10 | ||||
-rw-r--r-- | crypto/asn1/a_set.c | 9 | ||||
-rw-r--r-- | crypto/asn1/asn1_lib.c | 32 | ||||
-rw-r--r-- | crypto/asn1/asn_mime.c | 2 | ||||
-rw-r--r-- | crypto/asn1/d2i_pr.c | 8 | ||||
-rw-r--r-- | crypto/asn1/f_enum.c | 4 | ||||
-rw-r--r-- | crypto/asn1/f_int.c | 4 | ||||
-rw-r--r-- | crypto/asn1/f_string.c | 4 | ||||
-rw-r--r-- | crypto/asn1/p5_pbe.c | 2 | ||||
-rw-r--r-- | crypto/asn1/p5_pbev2.c | 4 | ||||
-rw-r--r-- | crypto/asn1/tasn_enc.c | 26 | ||||
-rw-r--r-- | crypto/asn1/tasn_prn.c | 2 | ||||
-rw-r--r-- | crypto/asn1/x_name.c | 6 |
14 files changed, 111 insertions, 60 deletions
diff --git a/crypto/asn1/a_bytes.c b/crypto/asn1/a_bytes.c index 385b53986a29..65e5394664a4 100644 --- a/crypto/asn1/a_bytes.c +++ b/crypto/asn1/a_bytes.c @@ -60,7 +60,12 @@ #include "cryptlib.h" #include <openssl/asn1.h> -static int asn1_collate_primitive(ASN1_STRING *a, ASN1_const_CTX *c); +static int asn1_collate_primitive(ASN1_STRING *a, ASN1_const_CTX *c, + int depth); +static ASN1_STRING *int_d2i_ASN1_bytes(ASN1_STRING **a, + const unsigned char **pp, long length, + int Ptag, int Pclass, int depth, + int *perr); /* * type is a 'bitmap' of acceptable string types. */ @@ -99,7 +104,7 @@ ASN1_STRING *d2i_ASN1_type_bytes(ASN1_STRING **a, const unsigned char **pp, ret = (*a); if (len != 0) { - s = (unsigned char *)OPENSSL_malloc((int)len + 1); + s = OPENSSL_malloc((int)len + 1); if (s == NULL) { i = ERR_R_MALLOC_FAILURE; goto err; @@ -154,15 +159,38 @@ int i2d_ASN1_bytes(ASN1_STRING *a, unsigned char **pp, int tag, int xclass) return (r); } +/* + * Maximum recursion depth of d2i_ASN1_bytes(): much more than should be + * encountered in pratice. + */ + +#define ASN1_BYTES_MAXDEPTH 20 + ASN1_STRING *d2i_ASN1_bytes(ASN1_STRING **a, const unsigned char **pp, long length, int Ptag, int Pclass) { + int err = 0; + ASN1_STRING *s = int_d2i_ASN1_bytes(a, pp, length, Ptag, Pclass, 0, &err); + if (err != 0) + ASN1err(ASN1_F_D2I_ASN1_BYTES, err); + return s; +} + +static ASN1_STRING *int_d2i_ASN1_bytes(ASN1_STRING **a, + const unsigned char **pp, long length, + int Ptag, int Pclass, + int depth, int *perr) +{ ASN1_STRING *ret = NULL; const unsigned char *p; unsigned char *s; long len; int inf, tag, xclass; - int i = 0; + + if (depth > ASN1_BYTES_MAXDEPTH) { + *perr = ASN1_R_NESTED_ASN1_STRING; + return NULL; + } if ((a == NULL) || ((*a) == NULL)) { if ((ret = ASN1_STRING_new()) == NULL) @@ -173,18 +201,19 @@ ASN1_STRING *d2i_ASN1_bytes(ASN1_STRING **a, const unsigned char **pp, p = *pp; inf = ASN1_get_object(&p, &len, &tag, &xclass, length); if (inf & 0x80) { - i = ASN1_R_BAD_OBJECT_HEADER; + *perr = ASN1_R_BAD_OBJECT_HEADER; goto err; } if (tag != Ptag) { - i = ASN1_R_WRONG_TAG; + *perr = ASN1_R_WRONG_TAG; goto err; } if (inf & V_ASN1_CONSTRUCTED) { ASN1_const_CTX c; + c.error = 0; c.pp = pp; c.p = p; c.inf = inf; @@ -192,17 +221,18 @@ ASN1_STRING *d2i_ASN1_bytes(ASN1_STRING **a, const unsigned char **pp, c.tag = Ptag; c.xclass = Pclass; c.max = (length == 0) ? 0 : (p + length); - if (!asn1_collate_primitive(ret, &c)) + if (!asn1_collate_primitive(ret, &c, depth)) { + *perr = c.error; goto err; - else { + } else { p = c.p; } } else { if (len != 0) { if ((ret->length < len) || (ret->data == NULL)) { - s = (unsigned char *)OPENSSL_malloc((int)len + 1); + s = OPENSSL_malloc((int)len + 1); if (s == NULL) { - i = ERR_R_MALLOC_FAILURE; + *perr = ERR_R_MALLOC_FAILURE; goto err; } if (ret->data != NULL) @@ -230,7 +260,6 @@ ASN1_STRING *d2i_ASN1_bytes(ASN1_STRING **a, const unsigned char **pp, err: if ((ret != NULL) && ((a == NULL) || (*a != ret))) ASN1_STRING_free(ret); - ASN1err(ASN1_F_D2I_ASN1_BYTES, i); return (NULL); } @@ -242,7 +271,8 @@ ASN1_STRING *d2i_ASN1_bytes(ASN1_STRING **a, const unsigned char **pp, * There have been a few bug fixes for this function from Paul Keogh * <paul.keogh@sse.ie>, many thanks to him */ -static int asn1_collate_primitive(ASN1_STRING *a, ASN1_const_CTX *c) +static int asn1_collate_primitive(ASN1_STRING *a, ASN1_const_CTX *c, + int depth) { ASN1_STRING *os = NULL; BUF_MEM b; @@ -270,9 +300,8 @@ static int asn1_collate_primitive(ASN1_STRING *a, ASN1_const_CTX *c) } c->q = c->p; - if (d2i_ASN1_bytes(&os, &c->p, c->max - c->p, c->tag, c->xclass) - == NULL) { - c->error = ERR_R_ASN1_LIB; + if (int_d2i_ASN1_bytes(&os, &c->p, c->max - c->p, c->tag, c->xclass, + depth + 1, &c->error) == NULL) { goto err; } @@ -297,7 +326,6 @@ static int asn1_collate_primitive(ASN1_STRING *a, ASN1_const_CTX *c) ASN1_STRING_free(os); return (1); err: - ASN1err(ASN1_F_ASN1_COLLATE_PRIMITIVE, c->error); if (os != NULL) ASN1_STRING_free(os); if (b.data != NULL) diff --git a/crypto/asn1/a_object.c b/crypto/asn1/a_object.c index 27f9c1691462..229a40ffa344 100644 --- a/crypto/asn1/a_object.c +++ b/crypto/asn1/a_object.c @@ -73,7 +73,7 @@ int i2d_ASN1_OBJECT(ASN1_OBJECT *a, unsigned char **pp) return (0); objsize = ASN1_object_size(0, a->length, V_ASN1_OBJECT); - if (pp == NULL) + if (pp == NULL || objsize == -1) return objsize; p = *pp; @@ -174,8 +174,12 @@ int a2d_ASN1_OBJECT(unsigned char *out, int olen, const char *buf, int num) if (!tmp) goto err; } - while (blsize--) - tmp[i++] = (unsigned char)BN_div_word(bl, 0x80L); + while (blsize--) { + BN_ULONG t = BN_div_word(bl, 0x80L); + if (t == (BN_ULONG)-1) + goto err; + tmp[i++] = (unsigned char)t; + } } else { for (;;) { diff --git a/crypto/asn1/a_set.c b/crypto/asn1/a_set.c index bf3f97188926..5fb58655757d 100644 --- a/crypto/asn1/a_set.c +++ b/crypto/asn1/a_set.c @@ -57,6 +57,7 @@ */ #include <stdio.h> +#include <limits.h> #include "cryptlib.h" #include <openssl/asn1_mac.h> @@ -98,10 +99,14 @@ int i2d_ASN1_SET(STACK_OF(OPENSSL_BLOCK) *a, unsigned char **pp, if (a == NULL) return (0); - for (i = sk_OPENSSL_BLOCK_num(a) - 1; i >= 0; i--) + for (i = sk_OPENSSL_BLOCK_num(a) - 1; i >= 0; i--) { + int tmplen = i2d(sk_OPENSSL_BLOCK_value(a, i), NULL); + if (tmplen > INT_MAX - ret) + return -1; ret += i2d(sk_OPENSSL_BLOCK_value(a, i), NULL); + } r = ASN1_object_size(1, ret, ex_tag); - if (pp == NULL) + if (pp == NULL || r == -1) return (r); p = *pp; diff --git a/crypto/asn1/asn1_lib.c b/crypto/asn1/asn1_lib.c index 874b1af8b09a..e63e82a8b476 100644 --- a/crypto/asn1/asn1_lib.c +++ b/crypto/asn1/asn1_lib.c @@ -256,26 +256,30 @@ static void asn1_put_length(unsigned char **pp, int length) int ASN1_object_size(int constructed, int length, int tag) { - int ret; - - ret = length; - ret++; + int ret = 1; + if (length < 0) + return -1; if (tag >= 31) { while (tag > 0) { tag >>= 7; ret++; } } - if (constructed == 2) - return ret + 3; - ret++; - if (length > 127) { - while (length > 0) { - length >>= 8; - ret++; + if (constructed == 2) { + ret += 3; + } else { + ret++; + if (length > 127) { + int tmplen = length; + while (tmplen > 0) { + tmplen >>= 8; + ret++; + } } } - return (ret); + if (ret >= INT_MAX - length) + return -1; + return ret + length; } static int _asn1_Finish(ASN1_const_CTX *c) @@ -324,7 +328,7 @@ int asn1_GetSequence(ASN1_const_CTX *c, long *length) return (0); } if (c->inf == (1 | V_ASN1_CONSTRUCTED)) - c->slen = *length + *(c->pp) - c->p; + c->slen = *length; c->eos = 0; return (1); } @@ -366,7 +370,7 @@ int ASN1_STRING_set(ASN1_STRING *str, const void *_data, int len) else len = strlen(data); } - if ((str->length < len) || (str->data == NULL)) { + if ((str->length <= len) || (str->data == NULL)) { c = str->data; if (c == NULL) str->data = OPENSSL_malloc(len + 1); diff --git a/crypto/asn1/asn_mime.c b/crypto/asn1/asn_mime.c index 96110c540f3d..9fd5bef0fc97 100644 --- a/crypto/asn1/asn_mime.c +++ b/crypto/asn1/asn_mime.c @@ -289,7 +289,7 @@ int SMIME_write_ASN1(BIO *bio, ASN1_VALUE *val, BIO *data, int flags, if ((flags & SMIME_DETACHED) && data) { /* We want multipart/signed */ /* Generate a random boundary */ - if (RAND_pseudo_bytes((unsigned char *)bound, 32) < 0) + if (RAND_bytes((unsigned char *)bound, 32) <= 0) return 0; for (i = 0; i < 32; i++) { c = bound[i] & 0xf; diff --git a/crypto/asn1/d2i_pr.c b/crypto/asn1/d2i_pr.c index d21829af192f..86dcf5fba9d7 100644 --- a/crypto/asn1/d2i_pr.c +++ b/crypto/asn1/d2i_pr.c @@ -97,15 +97,17 @@ EVP_PKEY *d2i_PrivateKey(int type, EVP_PKEY **a, const unsigned char **pp, if (!ret->ameth->old_priv_decode || !ret->ameth->old_priv_decode(ret, &p, length)) { if (ret->ameth->priv_decode) { + EVP_PKEY *tmp; PKCS8_PRIV_KEY_INFO *p8 = NULL; p8 = d2i_PKCS8_PRIV_KEY_INFO(NULL, &p, length); if (!p8) goto err; - EVP_PKEY_free(ret); - ret = EVP_PKCS82PKEY(p8); + tmp = EVP_PKCS82PKEY(p8); PKCS8_PRIV_KEY_INFO_free(p8); - if (ret == NULL) + if (tmp == NULL) goto err; + EVP_PKEY_free(ret); + ret = tmp; } else { ASN1err(ASN1_F_D2I_PRIVATEKEY, ERR_R_ASN1_LIB); goto err; diff --git a/crypto/asn1/f_enum.c b/crypto/asn1/f_enum.c index 591c3b578127..94cd54dbeedd 100644 --- a/crypto/asn1/f_enum.c +++ b/crypto/asn1/f_enum.c @@ -160,8 +160,6 @@ int a2i_ASN1_ENUMERATED(BIO *bp, ASN1_ENUMERATED *bs, char *buf, int size) i * 2); if (sp == NULL) { ASN1err(ASN1_F_A2I_ASN1_ENUMERATED, ERR_R_MALLOC_FAILURE); - if (s != NULL) - OPENSSL_free(s); goto err; } s = sp; @@ -199,5 +197,7 @@ int a2i_ASN1_ENUMERATED(BIO *bp, ASN1_ENUMERATED *bs, char *buf, int size) err_sl: ASN1err(ASN1_F_A2I_ASN1_ENUMERATED, ASN1_R_SHORT_LINE); } + if (ret != 1) + OPENSSL_free(s); return (ret); } diff --git a/crypto/asn1/f_int.c b/crypto/asn1/f_int.c index 4a81f81c8832..2bdc78d74491 100644 --- a/crypto/asn1/f_int.c +++ b/crypto/asn1/f_int.c @@ -172,8 +172,6 @@ int a2i_ASN1_INTEGER(BIO *bp, ASN1_INTEGER *bs, char *buf, int size) sp = OPENSSL_realloc_clean(s, slen, num + i * 2); if (sp == NULL) { ASN1err(ASN1_F_A2I_ASN1_INTEGER, ERR_R_MALLOC_FAILURE); - if (s != NULL) - OPENSSL_free(s); goto err; } s = sp; @@ -211,5 +209,7 @@ int a2i_ASN1_INTEGER(BIO *bp, ASN1_INTEGER *bs, char *buf, int size) err_sl: ASN1err(ASN1_F_A2I_ASN1_INTEGER, ASN1_R_SHORT_LINE); } + if (ret != 1) + OPENSSL_free(s); return (ret); } diff --git a/crypto/asn1/f_string.c b/crypto/asn1/f_string.c index 6a6cf3471408..0f7b9cfb119b 100644 --- a/crypto/asn1/f_string.c +++ b/crypto/asn1/f_string.c @@ -166,8 +166,6 @@ int a2i_ASN1_STRING(BIO *bp, ASN1_STRING *bs, char *buf, int size) i * 2); if (sp == NULL) { ASN1err(ASN1_F_A2I_ASN1_STRING, ERR_R_MALLOC_FAILURE); - if (s != NULL) - OPENSSL_free(s); goto err; } s = sp; @@ -205,5 +203,7 @@ int a2i_ASN1_STRING(BIO *bp, ASN1_STRING *bs, char *buf, int size) err_sl: ASN1err(ASN1_F_A2I_ASN1_STRING, ASN1_R_SHORT_LINE); } + if (ret != 1) + OPENSSL_free(s); return (ret); } diff --git a/crypto/asn1/p5_pbe.c b/crypto/asn1/p5_pbe.c index bdbfdcd67c07..e2a1def53f1d 100644 --- a/crypto/asn1/p5_pbe.c +++ b/crypto/asn1/p5_pbe.c @@ -101,7 +101,7 @@ int PKCS5_pbe_set0_algor(X509_ALGOR *algor, int alg, int iter, sstr = ASN1_STRING_data(pbe->salt); if (salt) memcpy(sstr, salt, saltlen); - else if (RAND_pseudo_bytes(sstr, saltlen) < 0) + else if (RAND_bytes(sstr, saltlen) <= 0) goto err; if (!ASN1_item_pack(pbe, ASN1_ITEM_rptr(PBEPARAM), &pbe_str)) { diff --git a/crypto/asn1/p5_pbev2.c b/crypto/asn1/p5_pbev2.c index 73ba4a3d67aa..388053e0a1bf 100644 --- a/crypto/asn1/p5_pbev2.c +++ b/crypto/asn1/p5_pbev2.c @@ -120,7 +120,7 @@ X509_ALGOR *PKCS5_pbe2_set_iv(const EVP_CIPHER *cipher, int iter, if (EVP_CIPHER_iv_length(cipher)) { if (aiv) memcpy(iv, aiv, EVP_CIPHER_iv_length(cipher)); - else if (RAND_pseudo_bytes(iv, EVP_CIPHER_iv_length(cipher)) < 0) + else if (RAND_bytes(iv, EVP_CIPHER_iv_length(cipher)) <= 0) goto err; } @@ -225,7 +225,7 @@ X509_ALGOR *PKCS5_pbkdf2_set(int iter, unsigned char *salt, int saltlen, if (salt) memcpy(osalt->data, salt, saltlen); - else if (RAND_pseudo_bytes(osalt->data, saltlen) < 0) + else if (RAND_bytes(osalt->data, saltlen) <= 0) goto merr; if (iter <= 0) diff --git a/crypto/asn1/tasn_enc.c b/crypto/asn1/tasn_enc.c index f7f83e56a981..081a9d534f8a 100644 --- a/crypto/asn1/tasn_enc.c +++ b/crypto/asn1/tasn_enc.c @@ -59,6 +59,7 @@ #include <stddef.h> #include <string.h> +#include <limits.h> #include "cryptlib.h" #include <openssl/asn1.h> #include <openssl/asn1t.h> @@ -216,17 +217,19 @@ int ASN1_item_ex_i2d(ASN1_VALUE **pval, unsigned char **out, for (i = 0, tt = it->templates; i < it->tcount; tt++, i++) { const ASN1_TEMPLATE *seqtt; ASN1_VALUE **pseqval; + int tmplen; seqtt = asn1_do_adb(pval, tt, 1); if (!seqtt) return 0; pseqval = asn1_get_field_ptr(pval, seqtt); - /* FIXME: check for errors in enhanced version */ - seqcontlen += asn1_template_ex_i2d(pseqval, NULL, seqtt, - -1, aclass); + tmplen = asn1_template_ex_i2d(pseqval, NULL, seqtt, -1, aclass); + if (tmplen == -1 || (tmplen > INT_MAX - seqcontlen)) + return -1; + seqcontlen += tmplen; } seqlen = ASN1_object_size(ndef, seqcontlen, tag); - if (!out) + if (!out || seqlen == -1) return seqlen; /* Output SEQUENCE header */ ASN1_put_object(out, ndef, seqcontlen, tag, aclass); @@ -339,19 +342,24 @@ static int asn1_template_ex_i2d(ASN1_VALUE **pval, unsigned char **out, /* Determine total length of items */ skcontlen = 0; for (i = 0; i < sk_ASN1_VALUE_num(sk); i++) { + int tmplen; skitem = sk_ASN1_VALUE_value(sk, i); - skcontlen += ASN1_item_ex_i2d(&skitem, NULL, - ASN1_ITEM_ptr(tt->item), - -1, iclass); + tmplen = ASN1_item_ex_i2d(&skitem, NULL, ASN1_ITEM_ptr(tt->item), + -1, iclass); + if (tmplen == -1 || (skcontlen > INT_MAX - tmplen)) + return -1; + skcontlen += tmplen; } sklen = ASN1_object_size(ndef, skcontlen, sktag); + if (sklen == -1) + return -1; /* If EXPLICIT need length of surrounding tag */ if (flags & ASN1_TFLG_EXPTAG) ret = ASN1_object_size(ndef, sklen, ttag); else ret = sklen; - if (!out) + if (!out || ret == -1) return ret; /* Now encode this lot... */ @@ -380,7 +388,7 @@ static int asn1_template_ex_i2d(ASN1_VALUE **pval, unsigned char **out, return 0; /* Find length of EXPLICIT tag */ ret = ASN1_object_size(ndef, i, ttag); - if (out) { + if (out && ret != -1) { /* Output tag and item */ ASN1_put_object(out, ndef, i, ttag, tclass); ASN1_item_ex_i2d(pval, out, ASN1_ITEM_ptr(tt->item), -1, iclass); diff --git a/crypto/asn1/tasn_prn.c b/crypto/asn1/tasn_prn.c index 5e7d53e9854a..d163acb81400 100644 --- a/crypto/asn1/tasn_prn.c +++ b/crypto/asn1/tasn_prn.c @@ -446,6 +446,8 @@ static int asn1_print_integer_ctx(BIO *out, ASN1_INTEGER *str, char *s; int ret = 1; s = i2s_ASN1_INTEGER(NULL, str); + if (s == NULL) + return 0; if (BIO_puts(out, s) <= 0) ret = 0; OPENSSL_free(s); diff --git a/crypto/asn1/x_name.c b/crypto/asn1/x_name.c index a858c2993b90..26378fdb2a02 100644 --- a/crypto/asn1/x_name.c +++ b/crypto/asn1/x_name.c @@ -199,10 +199,8 @@ static int x509_name_ex_d2i(ASN1_VALUE **val, int i, j, ret; STACK_OF(X509_NAME_ENTRY) *entries; X509_NAME_ENTRY *entry; - if (len > X509_NAME_MAX) { - ASN1err(ASN1_F_X509_NAME_EX_D2I, ASN1_R_TOO_LONG); - return 0; - } + if (len > X509_NAME_MAX) + len = X509_NAME_MAX; q = p; /* Get internal representation of Name */ |