From 1554498e64df093a519f9074c3412047f398aa17 Mon Sep 17 00:00:00 2001 From: jkim Date: Wed, 27 Jun 2012 16:44:58 +0000 Subject: Import OpenSSL 0.9.8x. --- crypto/asn1/a_d2i_fp.c | 54 +++++++++++++++------ crypto/asn1/a_object.c | 4 +- crypto/asn1/a_strex.c | 17 +++++-- crypto/asn1/a_strnid.c | 2 +- crypto/asn1/asn1.h | 2 +- crypto/asn1/asn_mime.c | 7 ++- crypto/asn1/x_name.c | 4 +- crypto/asn1/x_pubkey.c | 11 ++++- crypto/bio/bf_buff.c | 15 +++--- crypto/bio/bio.h | 10 ++++ crypto/bio/bss_dgram.c | 21 +++++--- crypto/bn/asm/mo-586.pl | 4 +- crypto/bn/asm/ppc.pl | 2 +- crypto/bn/bn_blind.c | 37 +++++++++------ crypto/bn/bn_gf2m.c | 1 + crypto/buffer/buffer.c | 27 +++++++++++ crypto/cms/cms.h | 1 + crypto/cms/cms_enc.c | 60 +++++++++++++++++------ crypto/cms/cms_env.c | 12 ++++- crypto/cms/cms_io.c | 2 +- crypto/cms/cms_lcl.h | 2 + crypto/cms/cms_smime.c | 37 +++++++++++++-- crypto/comp/c_rle.c | 3 +- crypto/conf/conf_api.c | 1 + crypto/cryptlib.c | 1 - crypto/crypto.h | 6 +-- crypto/ec/ec2_smpl.c | 5 +- crypto/ec/ec_key.c | 8 +++- crypto/ec/ecp_smpl.c | 3 ++ crypto/ecdsa/ecdsatest.c | 91 +++++++++++++++++++++++++++++++---- crypto/ecdsa/ecs_ossl.c | 8 ++++ crypto/evp/evp_test.c | 1 + crypto/mem.c | 4 ++ crypto/ocsp/ocsp_lib.c | 8 ++-- crypto/opensslv.h | 6 +-- crypto/perlasm/cbc.pl | 2 - crypto/pkcs7/pk7_doit.c | 73 ++++++++++++++++++++-------- crypto/pkcs7/pk7_smime.c | 25 ++++++++-- crypto/rc4/asm/rc4-x86_64.pl | 2 +- crypto/rc4/rc4_skey.c | 4 +- crypto/rsa/rsa_eay.c | 80 ++++++++++++++++++++----------- crypto/x509/x509_vfy.c | 2 +- crypto/x509v3/pcy_map.c | 10 ++-- crypto/x509v3/pcy_tree.c | 5 +- crypto/x509v3/v3_addr.c | 111 +++++++++++++++++++++++++++++++------------ crypto/x509v3/v3_asid.c | 90 ++++++++++++++++++++++++++--------- 46 files changed, 665 insertions(+), 216 deletions(-) (limited to 'crypto') diff --git a/crypto/asn1/a_d2i_fp.c b/crypto/asn1/a_d2i_fp.c index ece40bc..52b2ebd 100644 --- a/crypto/asn1/a_d2i_fp.c +++ b/crypto/asn1/a_d2i_fp.c @@ -57,6 +57,7 @@ */ #include +#include #include "cryptlib.h" #include #include @@ -143,17 +144,11 @@ static int asn1_d2i_read_bio(BIO *in, BUF_MEM **pb) BUF_MEM *b; unsigned char *p; int i; - int ret=-1; ASN1_const_CTX c; - int want=HEADER_SIZE; + size_t want=HEADER_SIZE; int eos=0; -#if defined(__GNUC__) && defined(__ia64) - /* pathetic compiler bug in all known versions as of Nov. 2002 */ - long off=0; -#else - int off=0; -#endif - int len=0; + size_t off=0; + size_t len=0; b=BUF_MEM_new(); if (b == NULL) @@ -169,7 +164,7 @@ static int asn1_d2i_read_bio(BIO *in, BUF_MEM **pb) { want-=(len-off); - if (!BUF_MEM_grow_clean(b,len+want)) + if (len + want < len || !BUF_MEM_grow_clean(b,len+want)) { ASN1err(ASN1_F_ASN1_D2I_READ_BIO,ERR_R_MALLOC_FAILURE); goto err; @@ -181,7 +176,14 @@ static int asn1_d2i_read_bio(BIO *in, BUF_MEM **pb) goto err; } if (i > 0) + { + if (len+i < len) + { + ASN1err(ASN1_F_ASN1_D2I_READ_BIO,ASN1_R_TOO_LONG); + goto err; + } len+=i; + } } /* else data already loaded */ @@ -206,6 +208,11 @@ static int asn1_d2i_read_bio(BIO *in, BUF_MEM **pb) { /* no data body so go round again */ eos++; + if (eos < 0) + { + ASN1err(ASN1_F_ASN1_D2I_READ_BIO,ASN1_R_HEADER_TOO_LONG); + goto err; + } want=HEADER_SIZE; } else if (eos && (c.slen == 0) && (c.tag == V_ASN1_EOC)) @@ -220,10 +227,16 @@ static int asn1_d2i_read_bio(BIO *in, BUF_MEM **pb) else { /* suck in c.slen bytes of data */ - want=(int)c.slen; + want=c.slen; if (want > (len-off)) { want-=(len-off); + if (want > INT_MAX /* BIO_read takes an int length */ || + len+want < len) + { + ASN1err(ASN1_F_ASN1_D2I_READ_BIO,ASN1_R_TOO_LONG); + goto err; + } if (!BUF_MEM_grow_clean(b,len+want)) { ASN1err(ASN1_F_ASN1_D2I_READ_BIO,ERR_R_MALLOC_FAILURE); @@ -238,11 +251,18 @@ static int asn1_d2i_read_bio(BIO *in, BUF_MEM **pb) ASN1_R_NOT_ENOUGH_DATA); goto err; } + /* This can't overflow because + * |len+want| didn't overflow. */ len+=i; - want -= i; + want-=i; } } - off+=(int)c.slen; + if (off + c.slen < off) + { + ASN1err(ASN1_F_ASN1_D2I_READ_BIO,ASN1_R_TOO_LONG); + goto err; + } + off+=c.slen; if (eos <= 0) { break; @@ -252,9 +272,15 @@ static int asn1_d2i_read_bio(BIO *in, BUF_MEM **pb) } } + if (off > INT_MAX) + { + ASN1err(ASN1_F_ASN1_D2I_READ_BIO,ASN1_R_TOO_LONG); + goto err; + } + *pb = b; return off; err: if (b != NULL) BUF_MEM_free(b); - return(ret); + return -1; } diff --git a/crypto/asn1/a_object.c b/crypto/asn1/a_object.c index 365e467..3ac2bc2 100644 --- a/crypto/asn1/a_object.c +++ b/crypto/asn1/a_object.c @@ -139,7 +139,7 @@ int a2d_ASN1_OBJECT(unsigned char *out, int olen, const char *buf, int num) ASN1err(ASN1_F_A2D_ASN1_OBJECT,ASN1_R_INVALID_DIGIT); goto err; } - if (!use_bn && l > (ULONG_MAX / 10L)) + if (!use_bn && l >= ((ULONG_MAX - 80) / 10L)) { use_bn = 1; if (!bl) @@ -294,7 +294,7 @@ ASN1_OBJECT *c2i_ASN1_OBJECT(ASN1_OBJECT **a, const unsigned char **pp, /* Sanity check OID encoding: can't have leading 0x80 in * subidentifiers, see: X.690 8.19.2 */ - for (i = 0, p = *pp + 1; i < len - 1; i++, p++) + for (i = 0, p = *pp; i < len; i++, p++) { if (*p == 0x80 && (!i || !(p[-1] & 0x80))) { diff --git a/crypto/asn1/a_strex.c b/crypto/asn1/a_strex.c index 7fc14d3..264ebf2 100644 --- a/crypto/asn1/a_strex.c +++ b/crypto/asn1/a_strex.c @@ -74,6 +74,11 @@ #define CHARTYPE_BS_ESC (ASN1_STRFLGS_ESC_2253 | CHARTYPE_FIRST_ESC_2253 | CHARTYPE_LAST_ESC_2253) +#define ESC_FLAGS (ASN1_STRFLGS_ESC_2253 | \ + ASN1_STRFLGS_ESC_QUOTE | \ + ASN1_STRFLGS_ESC_CTRL | \ + ASN1_STRFLGS_ESC_MSB) + /* Three IO functions for sending data to memory, a BIO and * and a FILE pointer. @@ -148,6 +153,13 @@ static int do_esc_char(unsigned long c, unsigned char flags, char *do_quotes, ch if(!io_ch(arg, tmphex, 3)) return -1; return 3; } + /* If we get this far and do any escaping at all must escape + * the escape character itself: backslash. + */ + if (chtmp == '\\' && flags & ESC_FLAGS) { + if(!io_ch(arg, "\\\\", 2)) return -1; + return 2; + } if(!io_ch(arg, &chtmp, 1)) return -1; return 1; } @@ -292,11 +304,6 @@ static const signed char tag2nbyte[] = { 4, -1, 2 /* 28-30 */ }; -#define ESC_FLAGS (ASN1_STRFLGS_ESC_2253 | \ - ASN1_STRFLGS_ESC_QUOTE | \ - ASN1_STRFLGS_ESC_CTRL | \ - ASN1_STRFLGS_ESC_MSB) - /* This is the main function, print out an * ASN1_STRING taking note of various escape * and display options. Returns number of diff --git a/crypto/asn1/a_strnid.c b/crypto/asn1/a_strnid.c index fe515b5..b68ae43 100644 --- a/crypto/asn1/a_strnid.c +++ b/crypto/asn1/a_strnid.c @@ -96,7 +96,7 @@ unsigned long ASN1_STRING_get_default_mask(void) * default: the default value, Printable, T61, BMP. */ -int ASN1_STRING_set_default_mask_asc(char *p) +int ASN1_STRING_set_default_mask_asc(const char *p) { unsigned long mask; char *end; diff --git a/crypto/asn1/asn1.h b/crypto/asn1/asn1.h index 1958298..d9d5443 100644 --- a/crypto/asn1/asn1.h +++ b/crypto/asn1/asn1.h @@ -1051,7 +1051,7 @@ ASN1_STRING *ASN1_pack_string(void *obj, i2d_of_void *i2d, ASN1_STRING *ASN1_item_pack(void *obj, const ASN1_ITEM *it, ASN1_OCTET_STRING **oct); void ASN1_STRING_set_default_mask(unsigned long mask); -int ASN1_STRING_set_default_mask_asc(char *p); +int ASN1_STRING_set_default_mask_asc(const char *p); unsigned long ASN1_STRING_get_default_mask(void); int ASN1_mbstring_copy(ASN1_STRING **out, const unsigned char *in, int len, int inform, unsigned long mask); diff --git a/crypto/asn1/asn_mime.c b/crypto/asn1/asn_mime.c index d8d9e76..ad8fbed 100644 --- a/crypto/asn1/asn_mime.c +++ b/crypto/asn1/asn_mime.c @@ -418,9 +418,9 @@ ASN1_VALUE *SMIME_read_ASN1(BIO *bio, BIO **bcont, const ASN1_ITEM *it) if(strcmp(hdr->value, "application/x-pkcs7-signature") && strcmp(hdr->value, "application/pkcs7-signature")) { - sk_MIME_HEADER_pop_free(headers, mime_hdr_free); ASN1err(ASN1_F_SMIME_READ_ASN1,ASN1_R_SIG_INVALID_MIME_TYPE); ERR_add_error_data(2, "type: ", hdr->value); + sk_MIME_HEADER_pop_free(headers, mime_hdr_free); sk_BIO_pop_free(parts, BIO_vfree); return NULL; } @@ -790,12 +790,17 @@ static int mime_hdr_addparam(MIME_HEADER *mhdr, char *name, char *value) static int mime_hdr_cmp(const MIME_HEADER * const *a, const MIME_HEADER * const *b) { + if (!(*a)->name || !(*b)->name) + return !!(*a)->name - !!(*b)->name; + return(strcmp((*a)->name, (*b)->name)); } static int mime_param_cmp(const MIME_PARAM * const *a, const MIME_PARAM * const *b) { + if (!(*a)->param_name || !(*b)->param_name) + return !!(*a)->param_name - !!(*b)->param_name; return(strcmp((*a)->param_name, (*b)->param_name)); } diff --git a/crypto/asn1/x_name.c b/crypto/asn1/x_name.c index 04380ab..9a1a9f4 100644 --- a/crypto/asn1/x_name.c +++ b/crypto/asn1/x_name.c @@ -196,7 +196,9 @@ static int x509_name_ex_d2i(ASN1_VALUE **val, const unsigned char **in, long len *val = nm.a; *in = p; return ret; - err: +err: + if (nm.x != NULL) + X509_NAME_free(nm.x); ASN1err(ASN1_F_X509_NAME_EX_D2I, ERR_R_NESTED_ASN1_ERROR); return 0; } diff --git a/crypto/asn1/x_pubkey.c b/crypto/asn1/x_pubkey.c index 91c2756..94d9f7e 100644 --- a/crypto/asn1/x_pubkey.c +++ b/crypto/asn1/x_pubkey.c @@ -367,7 +367,16 @@ EVP_PKEY *X509_PUBKEY_get(X509_PUBKEY *key) goto err; } - key->pkey = ret; + /* Check to see if another thread set key->pkey first */ + CRYPTO_w_lock(CRYPTO_LOCK_EVP_PKEY); + if (key->pkey) + { + EVP_PKEY_free(ret); + ret = key->pkey; + } + else + key->pkey = ret; + CRYPTO_w_unlock(CRYPTO_LOCK_EVP_PKEY); CRYPTO_add(&ret->references, 1, CRYPTO_LOCK_EVP_PKEY); return(ret); err: diff --git a/crypto/bio/bf_buff.c b/crypto/bio/bf_buff.c index c1fd75a..4b5a132 100644 --- a/crypto/bio/bf_buff.c +++ b/crypto/bio/bf_buff.c @@ -209,7 +209,7 @@ start: /* add to buffer and return */ if (i >= inl) { - memcpy(&(ctx->obuf[ctx->obuf_len]),in,inl); + memcpy(&(ctx->obuf[ctx->obuf_off+ctx->obuf_len]),in,inl); ctx->obuf_len+=inl; return(num+inl); } @@ -219,7 +219,7 @@ start: { if (i > 0) /* lets fill it up if we can */ { - memcpy(&(ctx->obuf[ctx->obuf_len]),in,i); + memcpy(&(ctx->obuf[ctx->obuf_off+ctx->obuf_len]),in,i); in+=i; inl-=i; num+=i; @@ -294,9 +294,9 @@ static long buffer_ctrl(BIO *b, int cmd, long num, void *ptr) case BIO_C_GET_BUFF_NUM_LINES: ret=0; p1=ctx->ibuf; - for (i=ctx->ibuf_off; iibuf_len; i++) + for (i=0; iibuf_len; i++) { - if (p1[i] == '\n') ret++; + if (p1[ctx->ibuf_off + i] == '\n') ret++; } break; case BIO_CTRL_WPENDING: @@ -399,17 +399,18 @@ static long buffer_ctrl(BIO *b, int cmd, long num, void *ptr) for (;;) { BIO_clear_retry_flags(b); - if (ctx->obuf_len > ctx->obuf_off) + if (ctx->obuf_len > 0) { r=BIO_write(b->next_bio, &(ctx->obuf[ctx->obuf_off]), - ctx->obuf_len-ctx->obuf_off); + ctx->obuf_len); #if 0 -fprintf(stderr,"FLUSH [%3d] %3d -> %3d\n",ctx->obuf_off,ctx->obuf_len-ctx->obuf_off,r); +fprintf(stderr,"FLUSH [%3d] %3d -> %3d\n",ctx->obuf_off,ctx->obuf_len,r); #endif BIO_copy_next_retry(b); if (r <= 0) return((long)r); ctx->obuf_off+=r; + ctx->obuf_len-=r; } else { diff --git a/crypto/bio/bio.h b/crypto/bio/bio.h index ebb4278..03bd3b2 100644 --- a/crypto/bio/bio.h +++ b/crypto/bio/bio.h @@ -145,6 +145,7 @@ extern "C" { /* #endif */ #define BIO_CTRL_DGRAM_QUERY_MTU 40 /* as kernel for current MTU */ +#define BIO_CTRL_DGRAM_GET_FALLBACK_MTU 47 #define BIO_CTRL_DGRAM_GET_MTU 41 /* get cached value for MTU */ #define BIO_CTRL_DGRAM_SET_MTU 42 /* set cached value for * MTU. want to use this @@ -321,6 +322,15 @@ DECLARE_STACK_OF(BIO) typedef struct bio_f_buffer_ctx_struct { + /* Buffers are setup like this: + * + * <---------------------- size -----------------------> + * +---------------------------------------------------+ + * | consumed | remaining | free space | + * +---------------------------------------------------+ + * <-- off --><------- len -------> + */ + /* BIO *bio; */ /* this is now in the BIO struct */ int ibuf_size; /* how big is the input buffer */ int obuf_size; /* how big is the output buffer */ diff --git a/crypto/bio/bss_dgram.c b/crypto/bio/bss_dgram.c index 14ca854..e0327bd 100644 --- a/crypto/bio/bss_dgram.c +++ b/crypto/bio/bss_dgram.c @@ -57,7 +57,6 @@ * */ -#ifndef OPENSSL_NO_DGRAM #include #include @@ -65,6 +64,7 @@ #include "cryptlib.h" #include +#ifndef OPENSSL_NO_DGRAM #if defined(OPENSSL_SYS_WIN32) || defined(OPENSSL_SYS_VMS) #include @@ -288,7 +288,6 @@ static int dgram_read(BIO *b, char *out, int outl) */ dgram_adjust_rcv_timeout(b); ret=recvfrom(b->num,out,outl,0,&peer,(void *)&peerlen); - dgram_reset_rcv_timeout(b); if ( ! data->connected && ret >= 0) BIO_ctrl(b, BIO_CTRL_DGRAM_SET_PEER, 0, &peer); @@ -302,6 +301,8 @@ static int dgram_read(BIO *b, char *out, int outl) data->_errno = get_last_socket_error(); } } + + dgram_reset_rcv_timeout(b); } return(ret); } @@ -493,6 +494,9 @@ static long dgram_ctrl(BIO *b, int cmd, long num, void *ptr) ret = 0; #endif break; + case BIO_CTRL_DGRAM_GET_FALLBACK_MTU: + ret = 576 - 20 - 8; + break; case BIO_CTRL_DGRAM_GET_MTU: return data->mtu; break; @@ -654,9 +658,13 @@ static int BIO_dgram_should_retry(int i) { err=get_last_socket_error(); -#if defined(OPENSSL_SYS_WINDOWS) && 0 /* more microsoft stupidity? perhaps not? Ben 4/1/99 */ - if ((i == -1) && (err == 0)) - return(1); +#if defined(OPENSSL_SYS_WINDOWS) + /* If the socket return value (i) is -1 + * and err is unexpectedly 0 at this point, + * the error code was overwritten by + * another system call before this error + * handling is called. + */ #endif return(BIO_dgram_non_fatal_error(err)); @@ -719,7 +727,6 @@ int BIO_dgram_non_fatal_error(int err) } return(0); } -#endif static void get_current_time(struct timeval *t) { @@ -737,3 +744,5 @@ static void get_current_time(struct timeval *t) gettimeofday(t, NULL); #endif } + +#endif diff --git a/crypto/bn/asm/mo-586.pl b/crypto/bn/asm/mo-586.pl index 0982293..061127e 100755 --- a/crypto/bn/asm/mo-586.pl +++ b/crypto/bn/asm/mo-586.pl @@ -539,8 +539,10 @@ $sbit=$num; &jle (&label("sqradd")); &mov ($carry,"edx"); - &lea ("edx",&DWP(0,$sbit,"edx",2)); + &add ("edx","edx"); &shr ($carry,31); + &add ("edx",$sbit); + &adc ($carry,0); &set_label("sqrlast"); &mov ($word,$_n0); &mov ($inp,$_np); diff --git a/crypto/bn/asm/ppc.pl b/crypto/bn/asm/ppc.pl index 806e53a..8444883 100644 --- a/crypto/bn/asm/ppc.pl +++ b/crypto/bn/asm/ppc.pl @@ -1039,7 +1039,7 @@ sub data { addze r11,r0 #mul_add_c(a[3],b[2],c3,c1,c2); $LD r6,`3*$BNSZ`(r4) - $LD r7,`2*$BNSZ`(r4) + $LD r7,`2*$BNSZ`(r5) $UMULL r8,r6,r7 $UMULH r9,r6,r7 addc r12,r8,r12 diff --git a/crypto/bn/bn_blind.c b/crypto/bn/bn_blind.c index c11fb4cc..ca7f996 100644 --- a/crypto/bn/bn_blind.c +++ b/crypto/bn/bn_blind.c @@ -123,7 +123,7 @@ struct bn_blinding_st BIGNUM *mod; /* just a reference */ unsigned long thread_id; /* added in OpenSSL 0.9.6j and 0.9.7b; * used only by crypto/rsa/rsa_eay.c, rsa_lib.c */ - unsigned int counter; + int counter; unsigned long flags; BN_MONT_CTX *m_ctx; int (*bn_mod_exp)(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, @@ -157,7 +157,10 @@ BN_BLINDING *BN_BLINDING_new(const BIGNUM *A, const BIGNUM *Ai, /* const */ BIGN if (BN_get_flags(mod, BN_FLG_CONSTTIME) != 0) BN_set_flags(ret->mod, BN_FLG_CONSTTIME); - ret->counter = BN_BLINDING_COUNTER; + /* Set the counter to the special value -1 + * to indicate that this is never-used fresh blinding + * that does not need updating before first use. */ + ret->counter = -1; return(ret); err: if (ret != NULL) BN_BLINDING_free(ret); @@ -186,7 +189,10 @@ int BN_BLINDING_update(BN_BLINDING *b, BN_CTX *ctx) goto err; } - if (--(b->counter) == 0 && b->e != NULL && + if (b->counter == -1) + b->counter = 0; + + if (++b->counter == BN_BLINDING_COUNTER && b->e != NULL && !(b->flags & BN_BLINDING_NO_RECREATE)) { /* re-create blinding parameters */ @@ -201,8 +207,8 @@ int BN_BLINDING_update(BN_BLINDING *b, BN_CTX *ctx) ret=1; err: - if (b->counter == 0) - b->counter = BN_BLINDING_COUNTER; + if (b->counter == BN_BLINDING_COUNTER) + b->counter = 0; return(ret); } @@ -223,6 +229,12 @@ int BN_BLINDING_convert_ex(BIGNUM *n, BIGNUM *r, BN_BLINDING *b, BN_CTX *ctx) return(0); } + if (b->counter == -1) + /* Fresh blinding, doesn't need updating. */ + b->counter = 0; + else if (!BN_BLINDING_update(b,ctx)) + return(0); + if (r != NULL) { if (!BN_copy(r, b->Ai)) ret=0; @@ -243,22 +255,19 @@ int BN_BLINDING_invert_ex(BIGNUM *n, const BIGNUM *r, BN_BLINDING *b, BN_CTX *ct int ret; bn_check_top(n); - if ((b->A == NULL) || (b->Ai == NULL)) - { - BNerr(BN_F_BN_BLINDING_INVERT_EX,BN_R_NOT_INITIALIZED); - return(0); - } if (r != NULL) ret = BN_mod_mul(n, n, r, b->mod, ctx); else - ret = BN_mod_mul(n, n, b->Ai, b->mod, ctx); - - if (ret >= 0) { - if (!BN_BLINDING_update(b,ctx)) + if (b->Ai == NULL) + { + BNerr(BN_F_BN_BLINDING_INVERT_EX,BN_R_NOT_INITIALIZED); return(0); + } + ret = BN_mod_mul(n, n, b->Ai, b->mod, ctx); } + bn_check_top(n); return(ret); } diff --git a/crypto/bn/bn_gf2m.c b/crypto/bn/bn_gf2m.c index ae642cc..5d90f1e 100644 --- a/crypto/bn/bn_gf2m.c +++ b/crypto/bn/bn_gf2m.c @@ -607,6 +607,7 @@ int BN_GF2m_mod_inv(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, BN_CTX *ctx) { while (!BN_is_odd(u)) { + if (BN_is_zero(u)) goto err; if (!BN_rshift1(u, u)) goto err; if (BN_is_odd(b)) { diff --git a/crypto/buffer/buffer.c b/crypto/buffer/buffer.c index b3e9477..3b4c79f 100644 --- a/crypto/buffer/buffer.c +++ b/crypto/buffer/buffer.c @@ -60,6 +60,11 @@ #include "cryptlib.h" #include +/* LIMIT_BEFORE_EXPANSION is the maximum n such that (n+3)/3*4 < 2**31. That + * function is applied in several functions in this file and this limit ensures + * that the result fits in an int. */ +#define LIMIT_BEFORE_EXPANSION 0x5ffffffc + BUF_MEM *BUF_MEM_new(void) { BUF_MEM *ret; @@ -94,6 +99,11 @@ int BUF_MEM_grow(BUF_MEM *str, int len) char *ret; unsigned int n; + if (len < 0) + { + BUFerr(BUF_F_BUF_MEM_GROW,ERR_R_MALLOC_FAILURE); + return 0; + } if (str->length >= len) { str->length=len; @@ -105,6 +115,12 @@ int BUF_MEM_grow(BUF_MEM *str, int len) str->length=len; return(len); } + /* This limit is sufficient to ensure (len+3)/3*4 < 2**31 */ + if (len > LIMIT_BEFORE_EXPANSION) + { + BUFerr(BUF_F_BUF_MEM_GROW,ERR_R_MALLOC_FAILURE); + return 0; + } n=(len+3)/3*4; if (str->data == NULL) ret=OPENSSL_malloc(n); @@ -130,6 +146,11 @@ int BUF_MEM_grow_clean(BUF_MEM *str, int len) char *ret; unsigned int n; + if (len < 0) + { + BUFerr(BUF_F_BUF_MEM_GROW_CLEAN,ERR_R_MALLOC_FAILURE); + return 0; + } if (str->length >= len) { memset(&str->data[len],0,str->length-len); @@ -142,6 +163,12 @@ int BUF_MEM_grow_clean(BUF_MEM *str, int len) str->length=len; return(len); } + /* This limit is sufficient to ensure (len+3)/3*4 < 2**31 */ + if (len > LIMIT_BEFORE_EXPANSION) + { + BUFerr(BUF_F_BUF_MEM_GROW_CLEAN,ERR_R_MALLOC_FAILURE); + return 0; + } n=(len+3)/3*4; if (str->data == NULL) ret=OPENSSL_malloc(n); diff --git a/crypto/cms/cms.h b/crypto/cms/cms.h index 25f88745..75e3be0e 100644 --- a/crypto/cms/cms.h +++ b/crypto/cms/cms.h @@ -110,6 +110,7 @@ DECLARE_ASN1_FUNCTIONS_const(CMS_ReceiptRequest) #define CMS_PARTIAL 0x4000 #define CMS_REUSE_DIGEST 0x8000 #define CMS_USE_KEYID 0x10000 +#define CMS_DEBUG_DECRYPT 0x20000 const ASN1_OBJECT *CMS_get0_type(CMS_ContentInfo *cms); diff --git a/crypto/cms/cms_enc.c b/crypto/cms/cms_enc.c index bab2623..f873ce3 100644 --- a/crypto/cms/cms_enc.c +++ b/crypto/cms/cms_enc.c @@ -73,6 +73,8 @@ BIO *cms_EncryptedContent_init_bio(CMS_EncryptedContentInfo *ec) const EVP_CIPHER *ciph; X509_ALGOR *calg = ec->contentEncryptionAlgorithm; unsigned char iv[EVP_MAX_IV_LENGTH], *piv = NULL; + unsigned char *tkey = NULL; + size_t tkeylen; int ok = 0; @@ -137,32 +139,57 @@ BIO *cms_EncryptedContent_init_bio(CMS_EncryptedContentInfo *ec) CMS_R_CIPHER_PARAMETER_INITIALISATION_ERROR); goto err; } - - - if (enc && !ec->key) + tkeylen = EVP_CIPHER_CTX_key_length(ctx); + /* Generate random session key */ + if (!enc || !ec->key) { - /* Generate random key */ - if (!ec->keylen) - ec->keylen = EVP_CIPHER_CTX_key_length(ctx); - ec->key = OPENSSL_malloc(ec->keylen); - if (!ec->key) + tkey = OPENSSL_malloc(tkeylen); + if (!tkey) { CMSerr(CMS_F_CMS_ENCRYPTEDCONTENT_INIT_BIO, ERR_R_MALLOC_FAILURE); goto err; } - if (EVP_CIPHER_CTX_rand_key(ctx, ec->key) <= 0) + if (EVP_CIPHER_CTX_rand_key(ctx, tkey) <= 0) goto err; - keep_key = 1; } - else if (ec->keylen != (unsigned int)EVP_CIPHER_CTX_key_length(ctx)) + + if (!ec->key) + { + ec->key = tkey; + ec->keylen = tkeylen; + tkey = NULL; + if (enc) + keep_key = 1; + else + ERR_clear_error(); + + } + + if (ec->keylen != tkeylen) { /* If necessary set key length */ if (EVP_CIPHER_CTX_set_key_length(ctx, ec->keylen) <= 0) { - CMSerr(CMS_F_CMS_ENCRYPTEDCONTENT_INIT_BIO, - CMS_R_INVALID_KEY_LENGTH); - goto err; + /* Only reveal failure if debugging so we don't + * leak information which may be useful in MMA. + */ + if (enc || ec->debug) + { + CMSerr(CMS_F_CMS_ENCRYPTEDCONTENT_INIT_BIO, + CMS_R_INVALID_KEY_LENGTH); + goto err; + } + else + { + /* Use random key */ + OPENSSL_cleanse(ec->key, ec->keylen); + OPENSSL_free(ec->key); + ec->key = tkey; + ec->keylen = tkeylen; + tkey = NULL; + ERR_clear_error(); + } } } @@ -198,6 +225,11 @@ BIO *cms_EncryptedContent_init_bio(CMS_EncryptedContentInfo *ec) OPENSSL_free(ec->key); ec->key = NULL; } + if (tkey) + { + OPENSSL_cleanse(tkey, tkeylen); + OPENSSL_free(tkey); + } if (ok) return b; BIO_free(b); diff --git a/crypto/cms/cms_env.c b/crypto/cms/cms_env.c index d499ae85b..b8685fa 100644 --- a/crypto/cms/cms_env.c +++ b/crypto/cms/cms_env.c @@ -352,6 +352,8 @@ static int cms_RecipientInfo_ktri_decrypt(CMS_ContentInfo *cms, unsigned char *ek = NULL; int eklen; int ret = 0; + CMS_EncryptedContentInfo *ec; + ec = cms->d.envelopedData->encryptedContentInfo; if (ktri->pkey == NULL) { @@ -382,8 +384,14 @@ static int cms_RecipientInfo_ktri_decrypt(CMS_ContentInfo *cms, ret = 1; - cms->d.envelopedData->encryptedContentInfo->key = ek; - cms->d.envelopedData->encryptedContentInfo->keylen = eklen; + if (ec->key) + { + OPENSSL_cleanse(ec->key, ec->keylen); + OPENSSL_free(ec->key); + } + + ec->key = ek; + ec->keylen = eklen; err: if (!ret && ek) diff --git a/crypto/cms/cms_io.c b/crypto/cms/cms_io.c index 30f5ddf..6d3edba 100644 --- a/crypto/cms/cms_io.c +++ b/crypto/cms/cms_io.c @@ -112,7 +112,7 @@ static int cms_output_data(BIO *out, BIO *data, ASN1_VALUE *val, int flags, cmsbio = tmpbio; } - return 1; + return r; } diff --git a/crypto/cms/cms_lcl.h b/crypto/cms/cms_lcl.h index 7d60fac..ce65d6e 100644 --- a/crypto/cms/cms_lcl.h +++ b/crypto/cms/cms_lcl.h @@ -175,6 +175,8 @@ struct CMS_EncryptedContentInfo_st const EVP_CIPHER *cipher; unsigned char *key; size_t keylen; + /* Set to 1 if we are debugging decrypt and don't fake keys for MMA */ + int debug; }; struct CMS_RecipientInfo_st diff --git a/crypto/cms/cms_smime.c b/crypto/cms/cms_smime.c index f35883a..2be07c2 100644 --- a/crypto/cms/cms_smime.c +++ b/crypto/cms/cms_smime.c @@ -622,7 +622,10 @@ int CMS_decrypt_set1_pkey(CMS_ContentInfo *cms, EVP_PKEY *pk, X509 *cert) STACK_OF(CMS_RecipientInfo) *ris; CMS_RecipientInfo *ri; int i, r; + int debug = 0; ris = CMS_get0_RecipientInfos(cms); + if (ris) + debug = cms->d.envelopedData->encryptedContentInfo->debug; for (i = 0; i < sk_CMS_RecipientInfo_num(ris); i++) { ri = sk_CMS_RecipientInfo_value(ris, i); @@ -636,17 +639,38 @@ int CMS_decrypt_set1_pkey(CMS_ContentInfo *cms, EVP_PKEY *pk, X509 *cert) CMS_RecipientInfo_set0_pkey(ri, pk); r = CMS_RecipientInfo_decrypt(cms, ri); CMS_RecipientInfo_set0_pkey(ri, NULL); - if (r > 0) - return 1; if (cert) { + /* If not debugging clear any error and + * return success to avoid leaking of + * information useful to MMA + */ + if (!debug) + { + ERR_clear_error(); + return 1; + } + if (r > 0) + return 1; CMSerr(CMS_F_CMS_DECRYPT_SET1_PKEY, CMS_R_DECRYPT_ERROR); return 0; } - ERR_clear_error(); + /* If no cert and not debugging don't leave loop + * after first successful decrypt. Always attempt + * to decrypt all recipients to avoid leaking timing + * of a successful decrypt. + */ + else if (r > 0 && debug) + return 1; } } + /* If no cert and not debugging always return success */ + if (!cert && !debug) + { + ERR_clear_error(); + return 1; + } CMSerr(CMS_F_CMS_DECRYPT_SET1_PKEY, CMS_R_NO_MATCHING_RECIPIENT); return 0; @@ -705,9 +729,14 @@ int CMS_decrypt(CMS_ContentInfo *cms, EVP_PKEY *pk, X509 *cert, } if (!dcont && !check_content(cms)) return 0; + if (flags & CMS_DEBUG_DECRYPT) + cms->d.envelopedData->encryptedContentInfo->debug = 1; + else + cms->d.envelopedData->encryptedContentInfo->debug = 0; + if (!pk && !cert && !dcont && !out) + return 1; if (pk && !CMS_decrypt_set1_pkey(cms, pk, cert)) return 0; - cont = CMS_dataInit(cms, dcont); if (!cont) return 0; diff --git a/crypto/comp/c_rle.c b/crypto/comp/c_rle.c index efd366f..18bceae 100644 --- a/crypto/comp/c_rle.c +++ b/crypto/comp/c_rle.c @@ -46,7 +46,7 @@ static int rle_expand_block(COMP_CTX *ctx, unsigned char *out, { int i; - if (olen < (ilen-1)) + if (ilen == 0 || olen < (ilen-1)) { /* ZZZZZZZZZZZZZZZZZZZZZZ */ return(-1); @@ -59,4 +59,3 @@ static int rle_expand_block(COMP_CTX *ctx, unsigned char *out, } return(ilen-1); } - diff --git a/crypto/conf/conf_api.c b/crypto/conf/conf_api.c index 909d72b..17bae83 100644 --- a/crypto/conf/conf_api.c +++ b/crypto/conf/conf_api.c @@ -64,6 +64,7 @@ #endif #include +#include #include #include #include diff --git a/crypto/cryptlib.c b/crypto/cryptlib.c index 497d003..dd74ea8 100644 --- a/crypto/cryptlib.c +++ b/crypto/cryptlib.c @@ -396,7 +396,6 @@ BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, case DLL_THREAD_ATTACH: break; case DLL_THREAD_DETACH: - ERR_remove_state(0); break; case DLL_PROCESS_DETACH: break; diff --git a/crypto/crypto.h b/crypto/crypto.h index 0e4fb07..fc1374f 100644 --- a/crypto/crypto.h +++ b/crypto/crypto.h @@ -588,15 +588,15 @@ int OPENSSL_isservice(void); #endif /* def OPENSSL_FIPS */ +#define OPENSSL_HAVE_INIT 1 +void OPENSSL_init(void); + /* BEGIN ERROR CODES */ /* The following lines are auto generated by the script mkerr.pl. Any changes * made after this point may be overwritten when the script is next run. */ void ERR_load_CRYPTO_strings(void); -#define OPENSSL_HAVE_INIT 1 -void OPENSSL_init(void); - /* Error codes for the CRYPTO functions. */ /* Function codes. */ diff --git a/crypto/ec/ec2_smpl.c b/crypto/ec/ec2_smpl.c index 522d036..c06b3b6 100644 --- a/crypto/ec/ec2_smpl.c +++ b/crypto/ec/ec2_smpl.c @@ -821,7 +821,7 @@ int ec_GF2m_simple_is_on_curve(const EC_GROUP *group, const EC_POINT *point, BN_ field_sqr = group->meth->field_sqr; /* only support affine coordinates */ - if (!point->Z_is_one) goto err; + if (!point->Z_is_one) return -1; if (ctx == NULL) { @@ -871,6 +871,9 @@ int ec_GF2m_simple_cmp(const EC_GROUP *group, const EC_POINT *a, const EC_POINT { return EC_POINT_is_at_infinity(group, b) ? 0 : 1; } + + if (EC_POINT_is_at_infinity(group, b)) + return 1; if (a->Z_is_one && b->Z_is_one) { diff --git a/crypto/ec/ec_key.c b/crypto/ec/ec_key.c index 12fb0e6..522802c 100644 --- a/crypto/ec/ec_key.c +++ b/crypto/ec/ec_key.c @@ -304,7 +304,13 @@ int EC_KEY_check_key(const EC_KEY *eckey) ECerr(EC_F_EC_KEY_CHECK_KEY, ERR_R_PASSED_NULL_PARAMETER); return 0; } - + + if (EC_POINT_is_at_infinity(eckey->group, eckey->pub_key)) + { + ECerr(EC_F_EC_KEY_CHECK_KEY, EC_R_POINT_AT_INFINITY); + goto err; + } + if ((ctx = BN_CTX_new()) == NULL) goto err; if ((point = EC_POINT_new(eckey->group)) == NULL) diff --git a/crypto/ec/ecp_smpl.c b/crypto/ec/ecp_smpl.c index 4d26f8b..66a92e2 100644 --- a/crypto/ec/ecp_smpl.c +++ b/crypto/ec/ecp_smpl.c @@ -1406,6 +1406,9 @@ int ec_GFp_simple_cmp(const EC_GROUP *group, const EC_POINT *a, const EC_POINT * { return EC_POINT_is_at_infinity(group, b) ? 0 : 1; } + + if (EC_POINT_is_at_infinity(group, b)) + return 1; if (a->Z_is_one && b->Z_is_one) { diff --git a/crypto/ecdsa/ecdsatest.c b/crypto/ecdsa/ecdsatest.c index b07e312..1ad507d 100644 --- a/crypto/ecdsa/ecdsatest.c +++ b/crypto/ecdsa/ecdsatest.c @@ -168,10 +168,9 @@ int fbytes(unsigned char *buf, int num) return 0; } fbytes_counter ++; - ret = BN_bn2bin(tmp, buf); - if (ret == 0 || ret != num) + if (num != BN_num_bytes(tmp) || !BN_bn2bin(tmp, buf)) ret = 0; - else + else ret = 1; if (tmp) BN_free(tmp); @@ -287,9 +286,13 @@ int test_builtin(BIO *out) size_t crv_len = 0, n = 0; EC_KEY *eckey = NULL, *wrong_eckey = NULL; EC_GROUP *group; + ECDSA_SIG *ecdsa_sig = NULL; unsigned char digest[20], wrong_digest[20]; - unsigned char *signature = NULL; - unsigned int sig_len; + unsigned char *signature = NULL; + const unsigned char *sig_ptr; + unsigned char *sig_ptr2; + unsigned char *raw_buf = NULL; + unsigned int sig_len, degree, r_len, s_len, bn_len, buf_len; int nid, ret = 0; /* fill digest values with some random data */ @@ -339,7 +342,8 @@ int test_builtin(BIO *out) if (EC_KEY_set_group(eckey, group) == 0) goto builtin_err; EC_GROUP_free(group); - if (EC_GROUP_get_degree(EC_KEY_get0_group(eckey)) < 160) + degree = EC_GROUP_get_degree(EC_KEY_get0_group(eckey)); + if (degree < 160) /* drop the curve */ { EC_KEY_free(eckey); @@ -415,26 +419,89 @@ int test_builtin(BIO *out) } BIO_printf(out, "."); (void)BIO_flush(out); - /* modify a single byte of the signature */ - offset = signature[10] % sig_len; - dirt = signature[11]; - signature[offset] ^= dirt ? dirt : 1; + /* wrong length */ + if (ECDSA_verify(0, digest, 20, signature, sig_len - 1, + eckey) == 1) + { + BIO_printf(out, " failed\n"); + goto builtin_err; + } + BIO_printf(out, "."); + (void)BIO_flush(out); + + /* Modify a single byte of the signature: to ensure we don't + * garble the ASN1 structure, we read the raw signature and + * modify a byte in one of the bignums directly. */ + sig_ptr = signature; + if ((ecdsa_sig = d2i_ECDSA_SIG(NULL, &sig_ptr, sig_len)) == NULL) + { + BIO_printf(out, " failed\n"); + goto builtin_err; + } + + /* Store the two BIGNUMs in raw_buf. */ + r_len = BN_num_bytes(ecdsa_sig->r); + s_len = BN_num_bytes(ecdsa_sig->s); + bn_len = (degree + 7) / 8; + if ((r_len > bn_len) || (s_len > bn_len)) + { + BIO_printf(out, " failed\n"); + goto builtin_err; + } + buf_len = 2 * bn_len; + if ((raw_buf = OPENSSL_malloc(buf_len)) == NULL) + goto builtin_err; + /* Pad the bignums with leading zeroes. */ + memset(raw_buf, 0, buf_len); + BN_bn2bin(ecdsa_sig->r, raw_buf + bn_len - r_len); + BN_bn2bin(ecdsa_sig->s, raw_buf + buf_len - s_len); + + /* Modify a single byte in the buffer. */ + offset = raw_buf[10] % buf_len; + dirt = raw_buf[11] ? raw_buf[11] : 1; + raw_buf[offset] ^= dirt; + /* Now read the BIGNUMs back in from raw_buf. */ + if ((BN_bin2bn(raw_buf, bn_len, ecdsa_sig->r) == NULL) || + (BN_bin2bn(raw_buf + bn_len, bn_len, ecdsa_sig->s) == NULL)) + goto builtin_err; + + sig_ptr2 = signature; + sig_len = i2d_ECDSA_SIG(ecdsa_sig, &sig_ptr2); if (ECDSA_verify(0, digest, 20, signature, sig_len, eckey) == 1) { BIO_printf(out, " failed\n"); goto builtin_err; } + /* Sanity check: undo the modification and verify signature. */ + raw_buf[offset] ^= dirt; + if ((BN_bin2bn(raw_buf, bn_len, ecdsa_sig->r) == NULL) || + (BN_bin2bn(raw_buf + bn_len, bn_len, ecdsa_sig->s) == NULL)) + goto builtin_err; + + sig_ptr2 = signature; + sig_len = i2d_ECDSA_SIG(ecdsa_sig, &sig_ptr2); + if (ECDSA_verify(0, digest, 20, signature, sig_len, eckey) != 1) + { + BIO_printf(out, " failed\n"); + goto builtin_err; + } BIO_printf(out, "."); (void)BIO_flush(out); BIO_printf(out, " ok\n"); /* cleanup */ + /* clean bogus errors */ + ERR_clear_error(); OPENSSL_free(signature); signature = NULL; EC_KEY_free(eckey); eckey = NULL; EC_KEY_free(wrong_eckey); wrong_eckey = NULL; + ECDSA_SIG_free(ecdsa_sig); + ecdsa_sig = NULL; + OPENSSL_free(raw_buf); + raw_buf = NULL; } ret = 1; @@ -443,8 +510,12 @@ builtin_err: EC_KEY_free(eckey); if (wrong_eckey) EC_KEY_free(wrong_eckey); + if (ecdsa_sig) + ECDSA_SIG_free(ecdsa_sig); if (signature) OPENSSL_free(signature); + if (raw_buf) + OPENSSL_free(raw_buf); if (curves) OPENSSL_free(curves); diff --git a/crypto/ecdsa/ecs_ossl.c b/crypto/ecdsa/ecs_ossl.c index 551cf50..1bbf328 100644 --- a/crypto/ecdsa/ecs_ossl.c +++ b/crypto/ecdsa/ecs_ossl.c @@ -144,6 +144,14 @@ static int ecdsa_sign_setup(EC_KEY *eckey, BN_CTX *ctx_in, BIGNUM **kinvp, } while (BN_is_zero(k)); + /* We do not want timing information to leak the length of k, + * so we compute G*k using an equivalent scalar of fixed + * bit-length. */ + + if (!BN_add(k, k, order)) goto err; + if (BN_num_bits(k) <= BN_num_bits(order)) + if (!BN_add(k, k, order)) goto err; + /* compute r the x-coordinate of generator * k */ if (!EC_POINT_mul(group, tmp_point, k, NULL, NULL, ctx)) { diff --git a/crypto/evp/evp_test.c b/crypto/evp/evp_test.c index 436be20..a36ca7e 100644 --- a/crypto/evp/evp_test.c +++ b/crypto/evp/evp_test.c @@ -435,6 +435,7 @@ int main(int argc,char **argv) EXIT(3); } } + fclose(f); #ifndef OPENSSL_NO_ENGINE ENGINE_cleanup(); diff --git a/crypto/mem.c b/crypto/mem.c index 00ebaf0..05d7b9c 100644 --- a/crypto/mem.c +++ b/crypto/mem.c @@ -372,6 +372,10 @@ void *CRYPTO_realloc_clean(void *str, int old_len, int num, const char *file, if (num <= 0) return NULL; + /* We don't support shrinking the buffer. Note the memcpy that copies + * |old_len| bytes to the new buffer, below. */ + if (num < old_len) return NULL; + if (realloc_debug_func != NULL) realloc_debug_func(str, NULL, num, file, line, 0); ret=malloc_ex_func(num,file,line); diff --git a/crypto/ocsp/ocsp_lib.c b/crypto/ocsp/ocsp_lib.c index 2745081..441ccb7 100755 --- a/crypto/ocsp/ocsp_lib.c +++ b/crypto/ocsp/ocsp_lib.c @@ -169,14 +169,14 @@ int OCSP_parse_url(char *url, char **phost, char **pport, char **ppath, int *pss char *host, *port; - /* dup the buffer since we are going to mess with it */ - buf = BUF_strdup(url); - if (!buf) goto mem_err; - *phost = NULL; *pport = NULL; *ppath = NULL; + /* dup the buffer since we are going to mess with it */ + buf = BUF_strdup(url); + if (!buf) goto mem_err; + /* Check for initial colon */ p = strchr(buf, ':'); diff --git a/crypto/opensslv.h b/crypto/opensslv.h index 0da91c2..516940c 100644 --- a/crypto/opensslv.h +++ b/crypto/opensslv.h @@ -25,11 +25,11 @@ * (Prior to 0.9.5a beta1, a different scheme was used: MMNNFFRBB for * major minor fix final patch/beta) */ -#define OPENSSL_VERSION_NUMBER 0x0090811f +#define OPENSSL_VERSION_NUMBER 0x0090818fL #ifdef OPENSSL_FIPS -#define OPENSSL_VERSION_TEXT "OpenSSL 0.9.8q-fips 2 Dec 2010" +#define OPENSSL_VERSION_TEXT "OpenSSL 0.9.8x-fips 10 May 2012" #else -#define OPENSSL_VERSION_TEXT "OpenSSL 0.9.8q 2 Dec 2010" +#define OPENSSL_VERSION_TEXT "OpenSSL 0.9.8x 10 May 2012" #endif #define OPENSSL_VERSION_PTEXT " part of " OPENSSL_VERSION_TEXT diff --git a/crypto/perlasm/cbc.pl b/crypto/perlasm/cbc.pl index e43dc9a..6fc2510 100644 --- a/crypto/perlasm/cbc.pl +++ b/crypto/perlasm/cbc.pl @@ -158,7 +158,6 @@ sub cbc &jmp_ptr($count); &set_label("ej7"); - &xor("edx", "edx") if $ppro; # ppro friendly &movb(&HB("edx"), &BP(6,$in,"",0)); &shl("edx",8); &set_label("ej6"); @@ -170,7 +169,6 @@ sub cbc &jmp(&label("ejend")); &set_label("ej3"); &movb(&HB("ecx"), &BP(2,$in,"",0)); - &xor("ecx", "ecx") if $ppro; # ppro friendly &shl("ecx",8); &set_label("ej2"); &movb(&HB("ecx"), &BP(1,$in,"",0)); diff --git a/crypto/pkcs7/pk7_doit.c b/crypto/pkcs7/pk7_doit.c index c8f1eb1..8b3024e 100644 --- a/crypto/pkcs7/pk7_doit.c +++ b/crypto/pkcs7/pk7_doit.c @@ -420,6 +420,8 @@ BIO *PKCS7_dataDecode(PKCS7 *p7, EVP_PKEY *pkey, BIO *in_bio, X509 *pcert) int max; X509_OBJECT ret; #endif + unsigned char *tkey = NULL; + int tkeylen; int jj; if ((etmp=BIO_new(BIO_f_cipher())) == NULL) @@ -461,36 +463,42 @@ BIO *PKCS7_dataDecode(PKCS7 *p7, EVP_PKEY *pkey, BIO *in_bio, X509 *pcert) if (pcert == NULL) { + /* Temporary storage in case EVP_PKEY_decrypt + * overwrites output buffer on error. + */ + unsigned char *tmp2; + tmp2 = OPENSSL_malloc(jj); + if (!tmp2) + goto err; + jj = -1; + /* Always attempt to decrypt all cases to avoid + * leaking timing information about a successful + * decrypt. + */ for (i=0; ienc_key), M_ASN1_STRING_length(ri->enc_key), pkey); - if (jj > 0) - break; + if (tret > 0) + { + memcpy(tmp, tmp2, tret); + OPENSSL_cleanse(tmp2, tret); + jj = tret; + } ERR_clear_error(); - ri = NULL; - } - if (ri == NULL) - { - PKCS7err(PKCS7_F_PKCS7_DATADECODE, - PKCS7_R_NO_RECIPIENT_MATCHES_KEY); - goto err; } + OPENSSL_free(tmp2); } else { jj=EVP_PKEY_decrypt(tmp, M_ASN1_STRING_data(ri->enc_key), M_ASN1_STRING_length(ri->enc_key), pkey); - if (jj <= 0) - { - PKCS7err(PKCS7_F_PKCS7_DATADECODE, - ERR_R_EVP_LIB); - goto err; - } + ERR_clear_error(); } evp_ctx=NULL; @@ -499,24 +507,49 @@ BIO *PKCS7_dataDecode(PKCS7 *p7, EVP_PKEY *pkey, BIO *in_bio, X509 *pcert) goto err; if (EVP_CIPHER_asn1_to_param(evp_ctx,enc_alg->parameter) < 0) goto err; + /* Generate random key to counter MMA */ + tkeylen = EVP_CIPHER_CTX_key_length(evp_ctx); + tkey = OPENSSL_malloc(tkeylen); + if (!tkey) + goto err; + if (EVP_CIPHER_CTX_rand_key(evp_ctx, tkey) <= 0) + goto err; + /* If we have no key use random key */ + if (jj <= 0) + { + OPENSSL_free(tmp); + jj = tkeylen; + tmp = tkey; + tkey = NULL; + } - if (jj != EVP_CIPHER_CTX_key_length(evp_ctx)) { + if (jj != tkeylen) { /* Some S/MIME clients don't use the same key * and effective key length. The key length is * determined by the size of the decrypted RSA key. */ if(!EVP_CIPHER_CTX_set_key_length(evp_ctx, jj)) { - PKCS7err(PKCS7_F_PKCS7_DATADECODE, - PKCS7_R_DECRYPTED_KEY_IS_WRONG_LENGTH); - goto err; + /* As MMA defence use random key instead */ + OPENSSL_cleanse(tmp, jj); + OPENSSL_free(tmp); + jj = tkeylen; + tmp = tkey; + tkey = NULL; } } + ERR_clear_error(); if (EVP_CipherInit_ex(evp_ctx,NULL,NULL,tmp,NULL,0) <= 0) goto err; OPENSSL_cleanse(tmp,jj); + if (tkey) + { + OPENSSL_cleanse(tkey, tkeylen); + OPENSSL_free(tkey); + } + if (out == NULL) out=etmp; else diff --git a/crypto/pkcs7/pk7_smime.c b/crypto/pkcs7/pk7_smime.c index fd18ec3..6b458af 100644 --- a/crypto/pkcs7/pk7_smime.c +++ b/crypto/pkcs7/pk7_smime.c @@ -486,15 +486,34 @@ int PKCS7_decrypt(PKCS7 *p7, EVP_PKEY *pkey, X509 *cert, BIO *data, int flags) return 0; } ret = SMIME_text(bread, data); + if (ret > 0 && BIO_method_type(tmpmem) == BIO_TYPE_CIPHER) + { + if (!BIO_get_cipher_status(tmpmem)) + ret = 0; + } BIO_free_all(bread); return ret; } else { for(;;) { i = BIO_read(tmpmem, buf, sizeof(buf)); - if(i <= 0) break; - BIO_write(data, buf, i); + if(i <= 0) + { + ret = 1; + if (BIO_method_type(tmpmem) == BIO_TYPE_CIPHER) + { + if (!BIO_get_cipher_status(tmpmem)) + ret = 0; + } + + break; + } + if (BIO_write(data, buf, i) != i) + { + ret = 0; + break; + } } BIO_free_all(tmpmem); - return 1; + return ret; } } diff --git a/crypto/rc4/asm/rc4-x86_64.pl b/crypto/rc4/asm/rc4-x86_64.pl index 00c6fa2..53ce20e 100755 --- a/crypto/rc4/asm/rc4-x86_64.pl +++ b/crypto/rc4/asm/rc4-x86_64.pl @@ -167,7 +167,7 @@ $code.=<<___; movzb ($dat,$XX[0]),$TX[0]#d test \$-8,$len jz .Lcloop1 - cmp \$0,260($dat) + cmpl \$0,260($dat) jnz .Lcloop1 push %rbx jmp .Lcloop8 diff --git a/crypto/rc4/rc4_skey.c b/crypto/rc4/rc4_skey.c index 4478d1a..d1dc912 100644 --- a/crypto/rc4/rc4_skey.c +++ b/crypto/rc4/rc4_skey.c @@ -138,9 +138,9 @@ void RC4_set_key(RC4_KEY *key, int len, const unsigned char *data) */ #ifdef OPENSSL_FIPS unsigned long *ia32cap_ptr = OPENSSL_ia32cap_loc(); - if (ia32cap_ptr && (*ia32cap_ptr & (1<<28))) { + if (ia32cap_ptr && (*ia32cap_ptr & (1<<20))) { #else - if (OPENSSL_ia32cap_P & (1<<28)) { + if (OPENSSL_ia32cap_P & (1<<20)) { #endif unsigned char *cp=(unsigned char *)d; diff --git a/crypto/rsa/rsa_eay.c b/crypto/rsa/rsa_eay.c index 412d0ea..d477f08 100644 --- a/crypto/rsa/rsa_eay.c +++ b/crypto/rsa/rsa_eay.c @@ -312,51 +312,56 @@ static BN_BLINDING *rsa_get_blinding(RSA *rsa, int *local, BN_CTX *ctx) return ret; } -static int rsa_blinding_convert(BN_BLINDING *b, int local, BIGNUM *f, - BIGNUM *r, BN_CTX *ctx) -{ - if (local) +static int rsa_blinding_convert(BN_BLINDING *b, BIGNUM *f, BIGNUM *unblind, + BN_CTX *ctx) + { + if (unblind == NULL) + /* Local blinding: store the unblinding factor + * in BN_BLINDING. */ return BN_BLINDING_convert_ex(f, NULL, b, ctx); else { - int ret; - CRYPTO_r_lock(CRYPTO_LOCK_RSA_BLINDING); - ret = BN_BLINDING_convert_ex(f, r, b, ctx); - CRYPTO_r_unlock(CRYPTO_LOCK_RSA_BLINDING); - return ret; - } -} - -static int rsa_blinding_invert(BN_BLINDING *b, int local, BIGNUM *f, - BIGNUM *r, BN_CTX *ctx) -{ - if (local) - return BN_BLINDING_invert_ex(f, NULL, b, ctx); - else - { + /* Shared blinding: store the unblinding factor + * outside BN_BLINDING. */ int ret; CRYPTO_w_lock(CRYPTO_LOCK_RSA_BLINDING); - ret = BN_BLINDING_invert_ex(f, r, b, ctx); + ret = BN_BLINDING_convert_ex(f, unblind, b, ctx); CRYPTO_w_unlock(CRYPTO_LOCK_RSA_BLINDING); return ret; } -} + } + +static int rsa_blinding_invert(BN_BLINDING *b, BIGNUM *f, BIGNUM *unblind, + BN_CTX *ctx) + { + /* For local blinding, unblind is set to NULL, and BN_BLINDING_invert_ex + * will use the unblinding factor stored in BN_BLINDING. + * If BN_BLINDING is shared between threads, unblind must be non-null: + * BN_BLINDING_invert_ex will then use the local unblinding factor, + * and will only read the modulus from BN_BLINDING. + * In both cases it's safe to access the blinding without a lock. + */ + return BN_BLINDING_invert_ex(f, unblind, b, ctx); + } /* signing */ static int RSA_eay_private_encrypt(int flen, const unsigned char *from, unsigned char *to, RSA *rsa, int padding) { - BIGNUM *f, *ret, *br, *res; + BIGNUM *f, *ret, *res; int i,j,k,num=0,r= -1; unsigned char *buf=NULL; BN_CTX *ctx=NULL; int local_blinding = 0; + /* Used only if the blinding structure is shared. A non-NULL unblind + * instructs rsa_blinding_convert() and rsa_blinding_invert() to store + * the unblinding factor outside the blinding structure. */ + BIGNUM *unblind = NULL; BN_BLINDING *blinding = NULL; if ((ctx=BN_CTX_new()) == NULL) goto err; BN_CTX_start(ctx); f = BN_CTX_get(ctx); - br = BN_CTX_get(ctx); ret = BN_CTX_get(ctx); num = BN_num_bytes(rsa->n); buf = OPENSSL_malloc(num); @@ -404,8 +409,15 @@ static int RSA_eay_private_encrypt(int flen, const unsigned char *from, } if (blinding != NULL) - if (!rsa_blinding_convert(blinding, local_blinding, f, br, ctx)) + { + if (!local_blinding && ((unblind = BN_CTX_get(ctx)) == NULL)) + { + RSAerr(RSA_F_RSA_EAY_PRIVATE_ENCRYPT,ERR_R_MALLOC_FAILURE); + goto err; + } + if (!rsa_blinding_convert(blinding, f, unblind, ctx)) goto err; + } if ( (rsa->flags & RSA_FLAG_EXT_PKEY) || ((rsa->p != NULL) && @@ -439,7 +451,7 @@ static int RSA_eay_private_encrypt(int flen, const unsigned char *from, } if (blinding) - if (!rsa_blinding_invert(blinding, local_blinding, ret, br, ctx)) + if (!rsa_blinding_invert(blinding, ret, unblind, ctx)) goto err; if (padding == RSA_X931_PADDING) @@ -478,18 +490,21 @@ err: static int RSA_eay_private_decrypt(int flen, const unsigned char *from, unsigned char *to, RSA *rsa, int padding) { - BIGNUM *f, *ret, *br; + BIGNUM *f, *ret; int j,num=0,r= -1; unsigned char *p; unsigned char *buf=NULL; BN_CTX *ctx=NULL; int local_blinding = 0; + /* Used only if the blinding structure is shared. A non-NULL unblind + * instructs rsa_blinding_convert() and rsa_blinding_invert() to store + * the unblinding factor outside the blinding structure. */ + BIGNUM *unblind = NULL; BN_BLINDING *blinding = NULL; if((ctx = BN_CTX_new()) == NULL) goto err; BN_CTX_start(ctx); f = BN_CTX_get(ctx); - br = BN_CTX_get(ctx); ret = BN_CTX_get(ctx); num = BN_num_bytes(rsa->n); buf = OPENSSL_malloc(num); @@ -527,8 +542,15 @@ static int RSA_eay_private_decrypt(int flen, const unsigned char *from, } if (blinding != NULL) - if (!rsa_blinding_convert(blinding, local_blinding, f, br, ctx)) + { + if (!local_blinding && ((unblind = BN_CTX_get(ctx)) == NULL)) + { + RSAerr(RSA_F_RSA_EAY_PRIVATE_DECRYPT,ERR_R_MALLOC_FAILURE); goto err; + } + if (!rsa_blinding_convert(blinding, f, unblind, ctx)) + goto err; + } /* do the decrypt */ if ( (rsa->flags & RSA_FLAG_EXT_PKEY) || @@ -562,7 +584,7 @@ static int RSA_eay_private_decrypt(int flen, const unsigned char *from, } if (blinding) - if (!rsa_blinding_invert(blinding, local_blinding, ret, br, ctx)) + if (!rsa_blinding_invert(blinding, ret, unblind, ctx)) goto err; p=buf; diff --git a/crypto/x509/x509_vfy.c b/crypto/x509/x509_vfy.c index aeb6337..b927584 100644 --- a/crypto/x509/x509_vfy.c +++ b/crypto/x509/x509_vfy.c @@ -1097,7 +1097,7 @@ int X509_cmp_time(ASN1_TIME *ctm, time_t *cmp_time) atm.length=sizeof(buff2); atm.data=(unsigned char *)buff2; - if (X509_time_adj(&atm,-offset*60, cmp_time) == NULL) + if (X509_time_adj(&atm, offset*60, cmp_time) == NULL) return 0; if (ctm->type == V_ASN1_UTCTIME) diff --git a/crypto/x509v3/pcy_map.c b/crypto/x509v3/pcy_map.c index f28796e..acd2ede 100644 --- a/crypto/x509v3/pcy_map.c +++ b/crypto/x509v3/pcy_map.c @@ -70,8 +70,6 @@ static int ref_cmp(const X509_POLICY_REF * const *a, static void policy_map_free(X509_POLICY_REF *map) { - if (map->subjectDomainPolicy) - ASN1_OBJECT_free(map->subjectDomainPolicy); OPENSSL_free(map); } @@ -95,6 +93,7 @@ int policy_cache_set_mapping(X509 *x, POLICY_MAPPINGS *maps) { POLICY_MAPPING *map; X509_POLICY_REF *ref = NULL; + ASN1_OBJECT *subjectDomainPolicyRef; X509_POLICY_DATA *data; X509_POLICY_CACHE *cache = x->policy_cache; int i; @@ -153,13 +152,16 @@ int policy_cache_set_mapping(X509 *x, POLICY_MAPPINGS *maps) if (!sk_ASN1_OBJECT_push(data->expected_policy_set, map->subjectDomainPolicy)) goto bad_mapping; + /* map->subjectDomainPolicy will be freed when + * cache->data is freed. Set it to NULL to avoid double-free. */ + subjectDomainPolicyRef = map->subjectDomainPolicy; + map->subjectDomainPolicy = NULL; ref = OPENSSL_malloc(sizeof(X509_POLICY_REF)); if (!ref) goto bad_mapping; - ref->subjectDomainPolicy = map->subjectDomainPolicy; - map->subjectDomainPolicy = NULL; + ref->subjectDomainPolicy = subjectDomainPolicyRef; ref->data = data; if (!sk_X509_POLICY_REF_push(cache->maps, ref)) diff --git a/crypto/x509v3/pcy_tree.c b/crypto/x509v3/pcy_tree.c index 89f84bf..92ad0a2 100644 --- a/crypto/x509v3/pcy_tree.c +++ b/crypto/x509v3/pcy_tree.c @@ -612,6 +612,10 @@ int X509_policy_check(X509_POLICY_TREE **ptree, int *pexplicit_policy, case 2: return 1; + /* Some internal error */ + case -1: + return -1; + /* Some internal error */ case 0: return 0; @@ -691,4 +695,3 @@ int X509_policy_check(X509_POLICY_TREE **ptree, int *pexplicit_policy, return 0; } - diff --git a/crypto/x509v3/v3_addr.c b/crypto/x509v3/v3_addr.c index efdf7c3..c0e1d2d 100644 --- a/crypto/x509v3/v3_addr.c +++ b/crypto/x509v3/v3_addr.c @@ -142,12 +142,13 @@ unsigned int v3_addr_get_afi(const IPAddressFamily *f) * Expand the bitstring form of an address into a raw byte array. * At the moment this is coded for simplicity, not speed. */ -static void addr_expand(unsigned char *addr, +static int addr_expand(unsigned char *addr, const ASN1_BIT_STRING *bs, const int length, const unsigned char fill) { - OPENSSL_assert(bs->length >= 0 && bs->length <= length); + if (bs->length < 0 || bs->length > length) + return 0; if (bs->length > 0) { memcpy(addr, bs->data, bs->length); if ((bs->flags & 7) != 0) { @@ -159,6 +160,7 @@ static void addr_expand(unsigned char *addr, } } memset(addr + bs->length, fill, length - bs->length); + return 1; } /* @@ -177,13 +179,17 @@ static int i2r_address(BIO *out, unsigned char addr[ADDR_RAW_BUF_LEN]; int i, n; + if (bs->length < 0) + return 0; switch (afi) { case IANA_AFI_IPV4: - addr_expand(addr, bs, 4, fill); + if (!addr_expand(addr, bs, 4, fill)) + return 0; BIO_printf(out, "%d.%d.%d.%d", addr[0], addr[1], addr[2], addr[3]); break; case IANA_AFI_IPV6: - addr_expand(addr, bs, 16, fill); + if (!addr_expand(addr, bs, 16, fill)) + return 0; for (n = 16; n > 1 && addr[n-1] == 0x00 && addr[n-2] == 0x00; n -= 2) ; for (i = 0; i < n; i += 2) @@ -309,6 +315,12 @@ static int i2r_IPAddrBlocks(X509V3_EXT_METHOD *method, /* * Sort comparison function for a sequence of IPAddressOrRange * elements. + * + * There's no sane answer we can give if addr_expand() fails, and an + * assertion failure on externally supplied data is seriously uncool, + * so we just arbitrarily declare that if given invalid inputs this + * function returns -1. If this messes up your preferred sort order + * for garbage input, tough noogies. */ static int IPAddressOrRange_cmp(const IPAddressOrRange *a, const IPAddressOrRange *b, @@ -321,22 +333,26 @@ static int IPAddressOrRange_cmp(const IPAddressOrRange *a, switch (a->type) { case IPAddressOrRange_addressPrefix: - addr_expand(addr_a, a->u.addressPrefix, length, 0x00); + if (!addr_expand(addr_a, a->u.addressPrefix, length, 0x00)) + return -1; prefixlen_a = addr_prefixlen(a->u.addressPrefix); break; case IPAddressOrRange_addressRange: - addr_expand(addr_a, a->u.addressRange->min, length, 0x00); + if (!addr_expand(addr_a, a->u.addressRange->min, length, 0x00)) + return -1; prefixlen_a = length * 8; break; } switch (b->type) { case IPAddressOrRange_addressPrefix: - addr_expand(addr_b, b->u.addressPrefix, length, 0x00); + if (!addr_expand(addr_b, b->u.addressPrefix, length, 0x00)) + return -1; prefixlen_b = addr_prefixlen(b->u.addressPrefix); break; case IPAddressOrRange_addressRange: - addr_expand(addr_b, b->u.addressRange->min, length, 0x00); + if (!addr_expand(addr_b, b->u.addressRange->min, length, 0x00)) + return -1; prefixlen_b = length * 8; break; } @@ -378,6 +394,7 @@ static int range_should_be_prefix(const unsigned char *min, unsigned char mask; int i, j; + OPENSSL_assert(memcmp(min, max, length) <= 0); for (i = 0; i < length && min[i] == max[i]; i++) ; for (j = length - 1; j >= 0 && min[j] == 0x00 && max[j] == 0xFF; j--) @@ -651,22 +668,22 @@ int v3_addr_add_range(IPAddrBlocks *addr, /* * Extract min and max values from an IPAddressOrRange. */ -static void extract_min_max(IPAddressOrRange *aor, +static int extract_min_max(IPAddressOrRange *aor, unsigned char *min, unsigned char *max, int length) { - OPENSSL_assert(aor != NULL && min != NULL && max != NULL); + if (aor == NULL || min == NULL || max == NULL) + return 0; switch (aor->type) { case IPAddressOrRange_addressPrefix: - addr_expand(min, aor->u.addressPrefix, length, 0x00); - addr_expand(max, aor->u.addressPrefix, length, 0xFF); - return; + return (addr_expand(min, aor->u.addressPrefix, length, 0x00) && + addr_expand(max, aor->u.addressPrefix, length, 0xFF)); case IPAddressOrRange_addressRange: - addr_expand(min, aor->u.addressRange->min, length, 0x00); - addr_expand(max, aor->u.addressRange->max, length, 0xFF); - return; + return (addr_expand(min, aor->u.addressRange->min, length, 0x00) && + addr_expand(max, aor->u.addressRange->max, length, 0xFF)); } + return 0; } /* @@ -682,9 +699,10 @@ int v3_addr_get_range(IPAddressOrRange *aor, if (aor == NULL || min == NULL || max == NULL || afi_length == 0 || length < afi_length || (aor->type != IPAddressOrRange_addressPrefix && - aor->type != IPAddressOrRange_addressRange)) + aor->type != IPAddressOrRange_addressRange) || + !extract_min_max(aor, min, max, afi_length)) return 0; - extract_min_max(aor, min, max, afi_length); + return afi_length; } @@ -766,8 +784,9 @@ int v3_addr_is_canonical(IPAddrBlocks *addr) IPAddressOrRange *a = sk_IPAddressOrRange_value(aors, j); IPAddressOrRange *b = sk_IPAddressOrRange_value(aors, j + 1); - extract_min_max(a, a_min, a_max, length); - extract_min_max(b, b_min, b_max, length); + if (!extract_min_max(a, a_min, a_max, length) || + !extract_min_max(b, b_min, b_max, length)) + return 0; /* * Punt misordered list, overlapping start, or inverted range. @@ -795,14 +814,17 @@ int v3_addr_is_canonical(IPAddrBlocks *addr) } /* - * Check final range to see if it should be a prefix. + * Check range to see if it's inverted or should be a + * prefix. */ j = sk_IPAddressOrRange_num(aors) - 1; { IPAddressOrRange *a = sk_IPAddressOrRange_value(aors, j); - if (a->type == IPAddressOrRange_addressRange) { - extract_min_max(a, a_min, a_max, length); - if (range_should_be_prefix(a_min, a_max, length) >= 0) + if (a != NULL && a->type == IPAddressOrRange_addressRange) { + if (!extract_min_max(a, a_min, a_max, length)) + return 0; + if (memcmp(a_min, a_max, length) > 0 || + range_should_be_prefix(a_min, a_max, length) >= 0) return 0; } } @@ -836,8 +858,16 @@ static int IPAddressOrRanges_canonize(IPAddressOrRanges *aors, unsigned char a_min[ADDR_RAW_BUF_LEN], a_max[ADDR_RAW_BUF_LEN]; unsigned char b_min[ADDR_RAW_BUF_LEN], b_max[ADDR_RAW_BUF_LEN]; - extract_min_max(a, a_min, a_max, length); - extract_min_max(b, b_min, b_max, length); + if (!extract_min_max(a, a_min, a_max, length) || + !extract_min_max(b, b_min, b_max, length)) + return 0; + + /* + * Punt inverted ranges. + */ + if (memcmp(a_min, a_max, length) > 0 || + memcmp(b_min, b_max, length) > 0) + return 0; /* * Punt overlaps. @@ -864,6 +894,20 @@ static int IPAddressOrRanges_canonize(IPAddressOrRanges *aors, } } + /* + * Check for inverted final range. + */ + j = sk_IPAddressOrRange_num(aors) - 1; + { + IPAddressOrRange *a = sk_IPAddressOrRange_value(aors, j); + if (a != NULL && a->type == IPAddressOrRange_addressRange) { + unsigned char a_min[ADDR_RAW_BUF_LEN], a_max[ADDR_RAW_BUF_LEN]; + extract_min_max(a, a_min, a_max, length); + if (memcmp(a_min, a_max, length) > 0) + return 0; + } + } + return 1; } @@ -1012,6 +1056,11 @@ static void *v2i_IPAddrBlocks(struct v3_ext_method *method, X509V3_conf_err(val); goto err; } + if (memcmp(min, max, length_from_afi(afi)) > 0) { + X509V3err(X509V3_F_V2I_IPADDRBLOCKS, X509V3_R_EXTENSION_VALUE_ERROR); + X509V3_conf_err(val); + goto err; + } if (!v3_addr_add_range(addr, afi, safi, min, max)) { X509V3err(X509V3_F_V2I_IPADDRBLOCKS, ERR_R_MALLOC_FAILURE); goto err; @@ -1097,13 +1146,15 @@ static int addr_contains(IPAddressOrRanges *parent, p = 0; for (c = 0; c < sk_IPAddressOrRange_num(child); c++) { - extract_min_max(sk_IPAddressOrRange_value(child, c), - c_min, c_max, length); + if (!extract_min_max(sk_IPAddressOrRange_value(child, c), + c_min, c_max, length)) + return -1; for (;; p++) { if (p >= sk_IPAddressOrRange_num(parent)) return 0; - extract_min_max(sk_IPAddressOrRange_value(parent, p), - p_min, p_max, length); + if (!extract_min_max(sk_IPAddressOrRange_value(parent, p), + p_min, p_max, length)) + return 0; if (memcmp(p_max, c_max, length) < 0) continue; if (memcmp(p_min, c_min, length) > 0) diff --git a/crypto/x509v3/v3_asid.c b/crypto/x509v3/v3_asid.c index abd497e..11aad0b 100644 --- a/crypto/x509v3/v3_asid.c +++ b/crypto/x509v3/v3_asid.c @@ -61,7 +61,6 @@ #include #include -#include #include "cryptlib.h" #include #include @@ -172,11 +171,11 @@ static int ASIdOrRange_cmp(const ASIdOrRange * const *a_, { const ASIdOrRange *a = *a_, *b = *b_; - assert((a->type == ASIdOrRange_id && a->u.id != NULL) || + OPENSSL_assert((a->type == ASIdOrRange_id && a->u.id != NULL) || (a->type == ASIdOrRange_range && a->u.range != NULL && a->u.range->min != NULL && a->u.range->max != NULL)); - assert((b->type == ASIdOrRange_id && b->u.id != NULL) || + OPENSSL_assert((b->type == ASIdOrRange_id && b->u.id != NULL) || (b->type == ASIdOrRange_range && b->u.range != NULL && b->u.range->min != NULL && b->u.range->max != NULL)); @@ -215,7 +214,7 @@ int v3_asid_add_inherit(ASIdentifiers *asid, int which) if (*choice == NULL) { if ((*choice = ASIdentifierChoice_new()) == NULL) return 0; - assert((*choice)->u.inherit == NULL); + OPENSSL_assert((*choice)->u.inherit == NULL); if (((*choice)->u.inherit = ASN1_NULL_new()) == NULL) return 0; (*choice)->type = ASIdentifierChoice_inherit; @@ -250,7 +249,7 @@ int v3_asid_add_id_or_range(ASIdentifiers *asid, if (*choice == NULL) { if ((*choice = ASIdentifierChoice_new()) == NULL) return 0; - assert((*choice)->u.asIdsOrRanges == NULL); + OPENSSL_assert((*choice)->u.asIdsOrRanges == NULL); (*choice)->u.asIdsOrRanges = sk_ASIdOrRange_new(ASIdOrRange_cmp); if ((*choice)->u.asIdsOrRanges == NULL) return 0; @@ -286,7 +285,7 @@ static void extract_min_max(ASIdOrRange *aor, ASN1_INTEGER **min, ASN1_INTEGER **max) { - assert(aor != NULL && min != NULL && max != NULL); + OPENSSL_assert(aor != NULL && min != NULL && max != NULL); switch (aor->type) { case ASIdOrRange_id: *min = aor->u.id; @@ -359,6 +358,20 @@ static int ASIdentifierChoice_is_canonical(ASIdentifierChoice *choice) goto done; } + /* + * Check for inverted range. + */ + i = sk_ASIdOrRange_num(choice->u.asIdsOrRanges) - 1; + { + ASIdOrRange *a = sk_ASIdOrRange_value(choice->u.asIdsOrRanges, i); + ASN1_INTEGER *a_min, *a_max; + if (a != NULL && a->type == ASIdOrRange_range) { + extract_min_max(a, &a_min, &a_max); + if (ASN1_INTEGER_cmp(a_min, a_max) > 0) + goto done; + } + } + ret = 1; done: @@ -373,7 +386,7 @@ static int ASIdentifierChoice_is_canonical(ASIdentifierChoice *choice) int v3_asid_is_canonical(ASIdentifiers *asid) { return (asid == NULL || - (ASIdentifierChoice_is_canonical(asid->asnum) || + (ASIdentifierChoice_is_canonical(asid->asnum) && ASIdentifierChoice_is_canonical(asid->rdi))); } @@ -393,9 +406,18 @@ static int ASIdentifierChoice_canonize(ASIdentifierChoice *choice) return 1; /* - * We have a list. Sort it. + * If not a list, or if empty list, it's broken. + */ + if (choice->type != ASIdentifierChoice_asIdsOrRanges || + sk_ASIdOrRange_num(choice->u.asIdsOrRanges) == 0) { + X509V3err(X509V3_F_ASIDENTIFIERCHOICE_CANONIZE, + X509V3_R_EXTENSION_VALUE_ERROR); + return 0; + } + + /* + * We have a non-empty list. Sort it. */ - assert(choice->type == ASIdentifierChoice_asIdsOrRanges); sk_ASIdOrRange_sort(choice->u.asIdsOrRanges); /* @@ -413,7 +435,14 @@ static int ASIdentifierChoice_canonize(ASIdentifierChoice *choice) /* * Make sure we're properly sorted (paranoia). */ - assert(ASN1_INTEGER_cmp(a_min, b_min) <= 0); + OPENSSL_assert(ASN1_INTEGER_cmp(a_min, b_min) <= 0); + + /* + * Punt inverted ranges. + */ + if (ASN1_INTEGER_cmp(a_min, a_max) > 0 || + ASN1_INTEGER_cmp(b_min, b_max) > 0) + goto done; /* * Check for overlaps. @@ -466,13 +495,27 @@ static int ASIdentifierChoice_canonize(ASIdentifierChoice *choice) break; } ASIdOrRange_free(b); - (void)sk_ASIdOrRange_delete(choice->u.asIdsOrRanges, i + 1); + (void) sk_ASIdOrRange_delete(choice->u.asIdsOrRanges, i + 1); i--; continue; } } - assert(ASIdentifierChoice_is_canonical(choice)); /* Paranoia */ + /* + * Check for final inverted range. + */ + i = sk_ASIdOrRange_num(choice->u.asIdsOrRanges) - 1; + { + ASIdOrRange *a = sk_ASIdOrRange_value(choice->u.asIdsOrRanges, i); + ASN1_INTEGER *a_min, *a_max; + if (a != NULL && a->type == ASIdOrRange_range) { + extract_min_max(a, &a_min, &a_max); + if (ASN1_INTEGER_cmp(a_min, a_max) > 0) + goto done; + } + } + + OPENSSL_assert(ASIdentifierChoice_is_canonical(choice)); /* Paranoia */ ret = 1; @@ -499,6 +542,7 @@ static void *v2i_ASIdentifiers(struct v3_ext_method *method, struct v3_ext_ctx *ctx, STACK_OF(CONF_VALUE) *values) { + ASN1_INTEGER *min = NULL, *max = NULL; ASIdentifiers *asid = NULL; int i; @@ -509,7 +553,6 @@ static void *v2i_ASIdentifiers(struct v3_ext_method *method, for (i = 0; i < sk_CONF_VALUE_num(values); i++) { CONF_VALUE *val = sk_CONF_VALUE_value(values, i); - ASN1_INTEGER *min = NULL, *max = NULL; int i1, i2, i3, is_range, which; /* @@ -579,18 +622,19 @@ static void *v2i_ASIdentifiers(struct v3_ext_method *method, max = s2i_ASN1_INTEGER(NULL, s + i2); OPENSSL_free(s); if (min == NULL || max == NULL) { - ASN1_INTEGER_free(min); - ASN1_INTEGER_free(max); X509V3err(X509V3_F_V2I_ASIDENTIFIERS, ERR_R_MALLOC_FAILURE); goto err; } + if (ASN1_INTEGER_cmp(min, max) > 0) { + X509V3err(X509V3_F_V2I_ASIDENTIFIERS, X509V3_R_EXTENSION_VALUE_ERROR); + goto err; + } } if (!v3_asid_add_id_or_range(asid, which, min, max)) { - ASN1_INTEGER_free(min); - ASN1_INTEGER_free(max); X509V3err(X509V3_F_V2I_ASIDENTIFIERS, ERR_R_MALLOC_FAILURE); goto err; } + min = max = NULL; } /* @@ -602,6 +646,8 @@ static void *v2i_ASIdentifiers(struct v3_ext_method *method, err: ASIdentifiers_free(asid); + ASN1_INTEGER_free(min); + ASN1_INTEGER_free(max); return NULL; } @@ -709,9 +755,9 @@ static int v3_asid_validate_path_internal(X509_STORE_CTX *ctx, int i, ret = 1, inherit_as = 0, inherit_rdi = 0; X509 *x = NULL; - assert(chain != NULL && sk_X509_num(chain) > 0); - assert(ctx != NULL || ext != NULL); - assert(ctx == NULL || ctx->verify_cb != NULL); + OPENSSL_assert(chain != NULL && sk_X509_num(chain) > 0); + OPENSSL_assert(ctx != NULL || ext != NULL); + OPENSSL_assert(ctx == NULL || ctx->verify_cb != NULL); /* * Figure out where to start. If we don't have an extension to @@ -723,7 +769,7 @@ static int v3_asid_validate_path_internal(X509_STORE_CTX *ctx, } else { i = 0; x = sk_X509_value(chain, i); - assert(x != NULL); + OPENSSL_assert(x != NULL); if ((ext = x->rfc3779_asid) == NULL) goto done; } @@ -756,7 +802,7 @@ static int v3_asid_validate_path_internal(X509_STORE_CTX *ctx, */ for (i++; i < sk_X509_num(chain); i++) { x = sk_X509_value(chain, i); - assert(x != NULL); + OPENSSL_assert(x != NULL); if (x->rfc3779_asid == NULL) { if (child_as != NULL || child_rdi != NULL) validation_err(X509_V_ERR_UNNESTED_RESOURCE); -- cgit v1.1