diff --git a/crypto/asn1/x_bignum.c b/crypto/asn1/x_bignum.c index 2ffa09301..7985235e2 100644 --- a/crypto/asn1/x_bignum.c +++ b/crypto/asn1/x_bignum.c @@ -126,7 +126,13 @@ static int bn_c2i(ASN1_VALUE **pval, const unsigned char *cont, int len, int utype, char *free_cont, const ASN1_ITEM *it) { BIGNUM *bn; - if(!*pval) bn_new(pval, it); + if(!*pval) + { + if (!bn_new(pval, it)) + { + return 0; + } + } bn = (BIGNUM *)*pval; if(!BN_bin2bn(cont, len, bn)) { bn_free(pval, it); diff --git a/crypto/err/err.c b/crypto/err/err.c index 6390b9a47..6349a74bd 100644 --- a/crypto/err/err.c +++ b/crypto/err/err.c @@ -175,8 +175,7 @@ static uint32_t get_error_values(int inc, int top, const char **file, int *line, uint32_t ret; state = err_get_state(); - - if (state->bottom == state->top) { + if (state == NULL || state->bottom == state->top) { return 0; } @@ -282,6 +281,10 @@ void ERR_clear_error(void) { ERR_STATE *const state = err_get_state(); unsigned i; + if (state == NULL) { + return; + } + for (i = 0; i < ERR_NUM_ERRORS; i++) { err_clear(&state->errors[i]); } @@ -481,7 +484,7 @@ static void err_set_error_data(char *data, int flags) { ERR_STATE *const state = err_get_state(); struct err_error_st *error; - if (state->top == state->bottom) { + if (state == NULL || state->top == state->bottom) { if (flags & ERR_FLAG_MALLOCED) { OPENSSL_free(data); } @@ -500,6 +503,10 @@ void ERR_put_error(int library, int func, int reason, const char *file, ERR_STATE *const state = err_get_state(); struct err_error_st *error; + if (state == NULL) { + return; + } + if (library == ERR_LIB_SYS && reason == 0) { #if defined(WIN32) reason = GetLastError(); @@ -600,7 +607,7 @@ void ERR_add_error_dataf(const char *format, ...) { int ERR_set_mark(void) { ERR_STATE *const state = err_get_state(); - if (state->bottom == state->top) { + if (state == NULL || state->bottom == state->top) { return 0; } state->errors[state->top].flags |= ERR_FLAG_MARK; @@ -611,6 +618,10 @@ int ERR_pop_to_mark(void) { ERR_STATE *const state = err_get_state(); struct err_error_st *error; + if (state == NULL) { + return 0; + } + while (state->bottom != state->top) { error = &state->errors[state->top]; diff --git a/crypto/err/err_impl.c b/crypto/err/err_impl.c index 755471496..7428fb737 100644 --- a/crypto/err/err_impl.c +++ b/crypto/err/err_impl.c @@ -231,6 +231,11 @@ static ERR_STATE *err_get_state(void) { CRYPTO_r_lock(CRYPTO_LOCK_ERR); } + if (state_hash == NULL) { + CRYPTO_r_unlock(CRYPTO_LOCK_ERR); + return NULL; + } + state = lh_ERR_STATE_retrieve(state_hash, &pattern); CRYPTO_r_unlock(CRYPTO_LOCK_ERR); if (state != NULL) { diff --git a/crypto/evp/evp_ctx.c b/crypto/evp/evp_ctx.c index d1ed67d6f..661603820 100644 --- a/crypto/evp/evp_ctx.c +++ b/crypto/evp/evp_ctx.c @@ -124,7 +124,10 @@ static EVP_PKEY_CTX *evp_pkey_ctx_new(EVP_PKEY *pkey, ENGINE *e, int id) { if (pmeth->init) { if (pmeth->init(ret) <= 0) { - EVP_PKEY_CTX_free(ret); + if (pkey) { + EVP_PKEY_free(ret->pkey); + } + OPENSSL_free(ret); return NULL; } } @@ -176,17 +179,25 @@ EVP_PKEY_CTX *EVP_PKEY_CTX_dup(EVP_PKEY_CTX *pctx) { if (pctx->pkey) { rctx->pkey = EVP_PKEY_dup(pctx->pkey); + if (rctx->pkey == NULL) { + goto err; + } } if (pctx->peerkey) { rctx->peerkey = EVP_PKEY_dup(pctx->peerkey); + if (rctx->peerkey == NULL) { + goto err; + } } if (pctx->pmeth->copy(rctx, pctx) > 0) { return rctx; } +err: EVP_PKEY_CTX_free(rctx); + OPENSSL_PUT_ERROR(EVP, EVP_PKEY_CTX_dup, ERR_LIB_EVP); return NULL; } @@ -485,6 +496,10 @@ int EVP_PKEY_keygen(EVP_PKEY_CTX *ctx, EVP_PKEY **ppkey) { if (!*ppkey) { *ppkey = EVP_PKEY_new(); + if (!*ppkey) { + OPENSSL_PUT_ERROR(EVP, EVP_PKEY_keygen, ERR_LIB_EVP); + return 0; + } } if (!ctx->pmeth->keygen(ctx, *ppkey)) { diff --git a/crypto/evp/evp_error.c b/crypto/evp/evp_error.c index d2d8abac1..b0d311ef9 100644 --- a/crypto/evp/evp_error.c +++ b/crypto/evp/evp_error.c @@ -20,6 +20,7 @@ const ERR_STRING_DATA EVP_error_string_data[] = { {ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_DigestSignAlgorithm, 0), "EVP_DigestSignAlgorithm"}, {ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_DigestVerifyInitFromAlgorithm, 0), "EVP_DigestVerifyInitFromAlgorithm"}, {ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_PKEY_CTX_ctrl, 0), "EVP_PKEY_CTX_ctrl"}, + {ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_PKEY_CTX_dup, 0), "EVP_PKEY_CTX_dup"}, {ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_PKEY_copy_parameters, 0), "EVP_PKEY_copy_parameters"}, {ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_PKEY_decrypt, 0), "EVP_PKEY_decrypt"}, {ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_PKEY_decrypt_init, 0), "EVP_PKEY_decrypt_init"}, diff --git a/crypto/evp/p_hmac.c b/crypto/evp/p_hmac.c index f068f2053..d78192059 100644 --- a/crypto/evp/p_hmac.c +++ b/crypto/evp/p_hmac.c @@ -109,6 +109,10 @@ static int pkey_hmac_copy(EVP_PKEY_CTX *dst, EVP_PKEY_CTX *src) { static void pkey_hmac_cleanup(EVP_PKEY_CTX *ctx) { HMAC_PKEY_CTX *hctx = ctx->data; + if (hctx == NULL) { + return; + } + HMAC_CTX_cleanup(&hctx->ctx); if (hctx->ktmp.data) { if (hctx->ktmp.length) { diff --git a/crypto/ex_data_impl.c b/crypto/ex_data_impl.c index 972e85a8e..db811d432 100644 --- a/crypto/ex_data_impl.c +++ b/crypto/ex_data_impl.c @@ -193,8 +193,10 @@ static LHASH_OF(EX_CLASS_ITEM) *get_classes(void) { static void cleanup(void) { LHASH_OF(EX_CLASS_ITEM) *classes = get_classes(); - lh_EX_CLASS_ITEM_doall(classes, class_free); - lh_EX_CLASS_ITEM_free(classes); + if (classes != NULL) { + lh_EX_CLASS_ITEM_doall(classes, class_free); + lh_EX_CLASS_ITEM_free(classes); + } global_classes = NULL; } @@ -204,6 +206,10 @@ static EX_CLASS_ITEM *get_class(int class_value) { EX_CLASS_ITEM template, *class_item; int ok = 0; + if (classes == NULL) { + return NULL; + } + CRYPTO_w_lock(CRYPTO_LOCK_EX_DATA); template.class_value = class_value; class_item = lh_EX_CLASS_ITEM_retrieve(classes, &template); diff --git a/crypto/x509/x509_vfy.c b/crypto/x509/x509_vfy.c index 8094c7869..030d3ce2c 100644 --- a/crypto/x509/x509_vfy.c +++ b/crypto/x509/x509_vfy.c @@ -2247,38 +2247,26 @@ int X509_STORE_CTX_init(X509_STORE_CTX *ctx, X509_STORE *store, X509 *x509, STACK_OF(X509) *chain) { int ret = 1; + int ex_data_allocated = 0; + + memset(ctx, 0, sizeof(X509_STORE_CTX)); ctx->ctx=store; - ctx->current_method=0; ctx->cert=x509; ctx->untrusted=chain; - ctx->crls = NULL; - ctx->last_untrusted=0; - ctx->other_ctx=NULL; - ctx->valid=0; - ctx->chain=NULL; - ctx->error=0; - ctx->explicit_policy=0; - ctx->error_depth=0; - ctx->current_cert=NULL; - ctx->current_issuer=NULL; - ctx->current_crl=NULL; - ctx->current_crl_score=0; - ctx->current_reasons=0; - ctx->tree = NULL; - ctx->parent = NULL; + + if(!CRYPTO_new_ex_data(CRYPTO_EX_INDEX_X509_STORE_CTX, ctx, + &ctx->ex_data)) + { + goto err; + } + ex_data_allocated = 1; ctx->param = X509_VERIFY_PARAM_new(); - if (!ctx->param) - { - OPENSSL_PUT_ERROR(X509, X509_STORE_CTX_init, ERR_R_MALLOC_FAILURE); - return 0; - } + goto err; /* Inherit callbacks and flags from X509_STORE if not set - * use defaults. - */ - + * use defaults. */ if (store) ret = X509_VERIFY_PARAM_inherit(ctx->param, store->param); @@ -2298,10 +2286,7 @@ int X509_STORE_CTX_init(X509_STORE_CTX *ctx, X509_STORE *store, X509 *x509, X509_VERIFY_PARAM_lookup("default")); if (ret == 0) - { - OPENSSL_PUT_ERROR(X509, X509_STORE_CTX_init, ERR_R_MALLOC_FAILURE); - return 0; - } + goto err; if (store && store->check_issued) ctx->check_issued = store->check_issued; @@ -2355,19 +2340,21 @@ int X509_STORE_CTX_init(X509_STORE_CTX *ctx, X509_STORE *store, X509 *x509, ctx->check_policy = check_policy; - - /* This memset() can't make any sense anyway, so it's removed. As - * X509_STORE_CTX_cleanup does a proper "free" on the ex_data, we put a - * corresponding "new" here and remove this bogus initialisation. */ - /* memset(&(ctx->ex_data),0,sizeof(CRYPTO_EX_DATA)); */ - if(!CRYPTO_new_ex_data(CRYPTO_EX_INDEX_X509_STORE_CTX, ctx, - &(ctx->ex_data))) - { - OPENSSL_free(ctx); - OPENSSL_PUT_ERROR(X509, X509_STORE_CTX_init, ERR_R_MALLOC_FAILURE); - return 0; - } return 1; + +err: + if (ex_data_allocated) + { + CRYPTO_free_ex_data(CRYPTO_EX_INDEX_X509_STORE_CTX, ctx, &ctx->ex_data); + } + if (ctx->param != NULL) + { + X509_VERIFY_PARAM_free(ctx->param); + } + + memset(ctx, 0, sizeof(X509_STORE_CTX)); + OPENSSL_PUT_ERROR(X509, X509_STORE_CTX_init, ERR_R_MALLOC_FAILURE); + return 0; } /* Set alternative lookup method: just a STACK of trusted certificates. diff --git a/crypto/x509/x_name.c b/crypto/x509/x_name.c index 56eeaf408..6e108f5fa 100644 --- a/crypto/x509/x_name.c +++ b/crypto/x509/x_name.c @@ -354,10 +354,15 @@ static int x509_name_canon(X509_NAME *a) if(!entries) goto err; if(!sk_STACK_OF_X509_NAME_ENTRY_push(intname, entries)) + { + sk_X509_NAME_ENTRY_free(entries); goto err; + } set = entry->set; } tmpentry = X509_NAME_ENTRY_new(); + if (tmpentry == NULL) + goto err; tmpentry->object = OBJ_dup(entry->object); if (!asn1_string_canon(tmpentry->value, entry->value)) goto err; diff --git a/include/openssl/evp.h b/include/openssl/evp.h index a760386e6..1e1dc83c9 100644 --- a/include/openssl/evp.h +++ b/include/openssl/evp.h @@ -829,6 +829,7 @@ struct evp_pkey_st { #define EVP_F_EVP_DigestVerifyInitFromAlgorithm 155 #define EVP_F_EVP_DigestSignAlgorithm 156 #define EVP_F_rsa_digest_verify_init_from_algorithm 157 +#define EVP_F_EVP_PKEY_CTX_dup 158 #define EVP_R_UNSUPPORTED_PUBLIC_KEY_TYPE 100 #define EVP_R_UNSUPPORTED_SIGNATURE_TYPE 101 #define EVP_R_INVALID_DIGEST_TYPE 102 diff --git a/ssl/d1_clnt.c b/ssl/d1_clnt.c index dcee9f82a..3af756b9f 100644 --- a/ssl/d1_clnt.c +++ b/ssl/d1_clnt.c @@ -242,7 +242,12 @@ int dtls1_connect(SSL *s) s->shutdown=0; /* every DTLS ClientHello resets Finished MAC */ - ssl3_init_finished_mac(s); + if (!ssl3_init_finished_mac(s)) + { + OPENSSL_PUT_ERROR(SSL, dtls1_connect, ERR_R_INTERNAL_ERROR); + ret = -1; + goto end; + } dtls1_start_timer(s); ret=ssl3_send_client_hello(s); diff --git a/ssl/d1_srvr.c b/ssl/d1_srvr.c index bf13620a0..0bb99b6c5 100644 --- a/ssl/d1_srvr.c +++ b/ssl/d1_srvr.c @@ -239,9 +239,15 @@ int dtls1_accept(SSL *s) * the output is sent in a way that TCP likes :-) * ...but not with SCTP :-) */ - if (!ssl_init_wbio_buffer(s,1)) { ret= -1; goto end; } + if (!ssl_init_wbio_buffer(s,1)) { ret= -1; goto end; } + + if (!ssl3_init_finished_mac(s)) + { + OPENSSL_PUT_ERROR(SSL, dtls1_accept, ERR_R_INTERNAL_ERROR); + ret = -1; + goto end; + } - ssl3_init_finished_mac(s); s->state=SSL3_ST_SR_CLNT_HELLO_A; s->ctx->stats.sess_accept++; } @@ -267,7 +273,12 @@ int dtls1_accept(SSL *s) s->state=SSL3_ST_SW_FLUSH; s->init_num=0; - ssl3_init_finished_mac(s); + if (!ssl3_init_finished_mac(s)) + { + OPENSSL_PUT_ERROR(SSL, dtls1_accept, ERR_R_INTERNAL_ERROR); + ret = -1; + goto end; + } break; case SSL3_ST_SW_HELLO_REQ_C: @@ -301,7 +312,12 @@ int dtls1_accept(SSL *s) s->s3->tmp.next_state=SSL3_ST_SR_CLNT_HELLO_A; /* HelloVerifyRequest resets Finished MAC */ - ssl3_init_finished_mac(s); + if (!ssl3_init_finished_mac(s)) + { + OPENSSL_PUT_ERROR(SSL, dtls1_accept, ERR_R_INTERNAL_ERROR); + ret = -1; + goto end; + } break; diff --git a/ssl/s23_clnt.c b/ssl/s23_clnt.c index efa3cd2ed..ebbd81001 100644 --- a/ssl/s23_clnt.c +++ b/ssl/s23_clnt.c @@ -188,7 +188,12 @@ int ssl23_connect(SSL *s) if (!ssl3_setup_buffers(s)) { ret= -1; goto end; } - ssl3_init_finished_mac(s); + if (!ssl3_init_finished_mac(s)) + { + OPENSSL_PUT_ERROR(SSL, ssl23_connect, ERR_R_INTERNAL_ERROR); + ret = -1; + goto end; + } s->state=SSL23_ST_CW_CLNT_HELLO_A; s->ctx->stats.sess_connect++; diff --git a/ssl/s23_srvr.c b/ssl/s23_srvr.c index ca8e5d6f1..b4290bbe5 100644 --- a/ssl/s23_srvr.c +++ b/ssl/s23_srvr.c @@ -191,7 +191,12 @@ int ssl23_accept(SSL *s) s->init_buf=buf; } - ssl3_init_finished_mac(s); + if (!ssl3_init_finished_mac(s)) + { + OPENSSL_PUT_ERROR(SSL, ssl23_accept, ERR_R_INTERNAL_ERROR); + ret = -1; + goto end; + } s->state=SSL23_ST_SR_CLNT_HELLO; s->ctx->stats.sess_accept++; diff --git a/ssl/s3_cbc.c b/ssl/s3_cbc.c index 44f408d56..510d48099 100644 --- a/ssl/s3_cbc.c +++ b/ssl/s3_cbc.c @@ -333,7 +333,7 @@ char ssl3_cbc_record_digest_supported(const EVP_MD_CTX *ctx) * ctx: the EVP_MD_CTX from which we take the hash function. * ssl3_cbc_record_digest_supported must return true for this EVP_MD_CTX. * md_out: the digest output. At most EVP_MAX_MD_SIZE bytes will be written. - * md_out_size: if non-NULL, the number of output bytes is written here. + * md_out_size: the number of output bytes is written here. * header: the 13-byte, TLS record header. * data: the record data itself, less any preceeding explicit IV. * data_plus_mac_size: the secret, reported length of the data and MAC @@ -346,7 +346,7 @@ char ssl3_cbc_record_digest_supported(const EVP_MD_CTX *ctx) * functions, above, we know that data_plus_mac_size is large enough to contain * a padding byte and MAC. (If the padding was invalid, it might contain the * padding too. ) */ -void ssl3_cbc_digest_record( +int ssl3_cbc_digest_record( const EVP_MD_CTX *ctx, unsigned char* md_out, size_t* md_out_size, @@ -409,9 +409,8 @@ void ssl3_cbc_digest_record( * called first to check that the hash function is * supported. */ assert(0); - if (md_out_size) - *md_out_size = -1; - return; + *md_out_size = 0; + return 0; } assert(md_length_size <= MAX_HASH_BIT_COUNT_BYTES); @@ -591,7 +590,12 @@ void ssl3_cbc_digest_record( } EVP_MD_CTX_init(&md_ctx); - EVP_DigestInit_ex(&md_ctx, ctx->digest, NULL /* engine */); + if (!EVP_DigestInit_ex(&md_ctx, ctx->digest, NULL /* engine */)) + { + EVP_MD_CTX_cleanup(&md_ctx); + return 0; + } + if (is_sslv3) { /* We repurpose |hmac_pad| to contain the SSLv3 pad2 block. */ @@ -611,7 +615,8 @@ void ssl3_cbc_digest_record( EVP_DigestUpdate(&md_ctx, mac_out, md_size); } EVP_DigestFinal(&md_ctx, md_out, &md_out_size_u); - if (md_out_size) - *md_out_size = md_out_size_u; + *md_out_size = md_out_size_u; EVP_MD_CTX_cleanup(&md_ctx); + + return 1; } diff --git a/ssl/s3_clnt.c b/ssl/s3_clnt.c index 47ae7675a..54352d963 100644 --- a/ssl/s3_clnt.c +++ b/ssl/s3_clnt.c @@ -276,7 +276,12 @@ int ssl3_connect(SSL *s) /* don't push the buffering BIO quite yet */ - ssl3_init_finished_mac(s); + if (!ssl3_init_finished_mac(s)) + { + OPENSSL_PUT_ERROR(SSL, ssl3_connect, ERR_R_INTERNAL_ERROR); + ret = -1; + goto end; + } s->state=SSL3_ST_CW_CLNT_HELLO_A; s->ctx->stats.sess_connect++; diff --git a/ssl/s3_enc.c b/ssl/s3_enc.c index fc94a9422..2474934a1 100644 --- a/ssl/s3_enc.c +++ b/ssl/s3_enc.c @@ -185,7 +185,11 @@ static int ssl3_generate_key_block(SSL *s, unsigned char *km, int num) for (j=0; jsession->master_key, s->session->master_key_length); @@ -193,7 +197,11 @@ static int ssl3_generate_key_block(SSL *s, unsigned char *km, int num) EVP_DigestUpdate(&s1,s->s3->client_random,SSL3_RANDOM_SIZE); EVP_DigestFinal_ex(&s1,smd,NULL); - EVP_DigestInit_ex(&m5,EVP_md5(), NULL); + if (!EVP_DigestInit_ex(&m5,EVP_md5(), NULL)) + { + OPENSSL_PUT_ERROR(SSL, ssl3_generate_key_block, ERR_LIB_EVP); + return 0; + } EVP_DigestUpdate(&m5,s->session->master_key, s->session->master_key_length); EVP_DigestUpdate(&m5,smd,SHA_DIGEST_LENGTH); @@ -470,12 +478,17 @@ int ssl3_enc(SSL *s, int send) return(1); } -void ssl3_init_finished_mac(SSL *s) +int ssl3_init_finished_mac(SSL *s) { if (s->s3->handshake_buffer) BIO_free(s->s3->handshake_buffer); if (s->s3->handshake_dgst) ssl3_free_digest_list(s); - s->s3->handshake_buffer=BIO_new(BIO_s_mem()); + s->s3->handshake_buffer = BIO_new(BIO_s_mem()); + if (s->s3->handshake_buffer == NULL) { + return 0; + } (void)BIO_set_close(s->s3->handshake_buffer,BIO_CLOSE); + + return 1; } void ssl3_free_digest_list(SSL *s) @@ -521,6 +534,12 @@ int ssl3_digest_cached_records(SSL *s, enum should_free_handshake_buffer_t shoul /* Allocate handshake_dgst array */ ssl3_free_digest_list(s); s->s3->handshake_dgst = OPENSSL_malloc(SSL_MAX_DIGEST * sizeof(EVP_MD_CTX *)); + if (s->s3->handshake_dgst == NULL) + { + OPENSSL_PUT_ERROR(SSL, ssl3_digest_cached_records, ERR_R_MALLOC_FAILURE); + return 0; + } + memset(s->s3->handshake_dgst,0,SSL_MAX_DIGEST *sizeof(EVP_MD_CTX *)); if (!BIO_mem_contents(s->s3->handshake_buffer, &hdata, &hdatalen)) { @@ -533,8 +552,18 @@ int ssl3_digest_cached_records(SSL *s, enum should_free_handshake_buffer_t shoul { if ((mask & ssl_get_algorithm2(s)) && md) { - s->s3->handshake_dgst[i]=EVP_MD_CTX_create(); - EVP_DigestInit_ex(s->s3->handshake_dgst[i],md,NULL); + s->s3->handshake_dgst[i] = EVP_MD_CTX_create(); + if (s->s3->handshake_dgst[i] == NULL) + { + OPENSSL_PUT_ERROR(SSL, ssl3_digest_cached_records, ERR_LIB_EVP); + return 0; + } + if (!EVP_DigestInit_ex(s->s3->handshake_dgst[i], md, NULL)) + { + EVP_MD_CTX_destroy(s->s3->handshake_dgst[i]); + OPENSSL_PUT_ERROR(SSL, ssl3_digest_cached_records, ERR_LIB_EVP); + return 0; + } EVP_DigestUpdate(s->s3->handshake_dgst[i],hdata,hdatalen); } else @@ -603,7 +632,12 @@ static int ssl3_handshake_mac(SSL *s, int md_nid, return 0; } EVP_MD_CTX_init(&ctx); - EVP_MD_CTX_copy_ex(&ctx,d); + if (!EVP_MD_CTX_copy_ex(&ctx,d)) + { + EVP_MD_CTX_cleanup(&ctx); + OPENSSL_PUT_ERROR(SSL, ssl3_generate_key_block, ERR_LIB_EVP); + return 0; + } n=EVP_MD_CTX_size(&ctx); if (n < 0) return 0; @@ -616,7 +650,12 @@ static int ssl3_handshake_mac(SSL *s, int md_nid, EVP_DigestUpdate(&ctx,ssl3_pad_1,npad); EVP_DigestFinal_ex(&ctx,md_buf,&i); - EVP_DigestInit_ex(&ctx,EVP_MD_CTX_md(&ctx), NULL); + if (!EVP_DigestInit_ex(&ctx,EVP_MD_CTX_md(&ctx), NULL)) + { + EVP_MD_CTX_cleanup(&ctx); + OPENSSL_PUT_ERROR(SSL, ssl3_generate_key_block, ERR_LIB_EVP); + return 0; + } EVP_DigestUpdate(&ctx,s->session->master_key, s->session->master_key_length); EVP_DigestUpdate(&ctx,ssl3_pad_2,npad); @@ -691,13 +730,16 @@ int n_ssl3_mac(SSL *ssl, unsigned char *md, int send) header[j++] = rec->length >> 8; header[j++] = rec->length & 0xff; - ssl3_cbc_digest_record( + if (!ssl3_cbc_digest_record( hash, md, &md_size, header, rec->input, rec->length + md_size, orig_len, mac_sec, md_size, - 1 /* is SSLv3 */); + 1 /* is SSLv3 */)) + { + return -1; + } } else { @@ -705,7 +747,11 @@ int n_ssl3_mac(SSL *ssl, unsigned char *md, int send) /* Chop the digest off the end :-) */ EVP_MD_CTX_init(&md_ctx); - EVP_MD_CTX_copy_ex( &md_ctx,hash); + if (!EVP_MD_CTX_copy_ex(&md_ctx,hash)) + { + EVP_MD_CTX_cleanup(&md_ctx); + return -1; + } EVP_DigestUpdate(&md_ctx,mac_sec,md_size); EVP_DigestUpdate(&md_ctx,ssl3_pad_1,npad); EVP_DigestUpdate(&md_ctx,seq,8); @@ -717,7 +763,11 @@ int n_ssl3_mac(SSL *ssl, unsigned char *md, int send) EVP_DigestUpdate(&md_ctx,rec->input,rec->length); EVP_DigestFinal_ex( &md_ctx,md,NULL); - EVP_MD_CTX_copy_ex( &md_ctx,hash); + if (!EVP_MD_CTX_copy_ex(&md_ctx,hash)) + { + EVP_MD_CTX_cleanup(&md_ctx); + return -1; + } EVP_DigestUpdate(&md_ctx,mac_sec,md_size); EVP_DigestUpdate(&md_ctx,ssl3_pad_2,npad); EVP_DigestUpdate(&md_ctx,md,md_size); @@ -761,7 +811,12 @@ int ssl3_generate_master_secret(SSL *s, unsigned char *out, unsigned char *p, EVP_MD_CTX_init(&ctx); for (i=0; i<3; i++) { - EVP_DigestInit_ex(&ctx, EVP_sha1(), NULL); + if (!EVP_DigestInit_ex(&ctx, EVP_sha1(), NULL)) + { + ret = 0; + break; + } + EVP_DigestUpdate(&ctx,salt[i],strlen((const char *)salt[i])); EVP_DigestUpdate(&ctx,p,len); EVP_DigestUpdate(&ctx,&(s->s3->client_random[0]), @@ -770,7 +825,12 @@ int ssl3_generate_master_secret(SSL *s, unsigned char *out, unsigned char *p, SSL3_RANDOM_SIZE); EVP_DigestFinal_ex(&ctx,buf,&n); - EVP_DigestInit_ex(&ctx, EVP_md5(), NULL); + if (!EVP_DigestInit_ex(&ctx, EVP_md5(), NULL)) + { + ret = 0; + break; + } + EVP_DigestUpdate(&ctx,p,len); EVP_DigestUpdate(&ctx,buf,n); EVP_DigestFinal_ex(&ctx,out,&n); diff --git a/ssl/s3_srvr.c b/ssl/s3_srvr.c index 24967836a..c7bc58bc1 100644 --- a/ssl/s3_srvr.c +++ b/ssl/s3_srvr.c @@ -294,7 +294,12 @@ int ssl3_accept(SSL *s) */ if (!ssl_init_wbio_buffer(s,1)) { ret= -1; goto end; } - ssl3_init_finished_mac(s); + if (!ssl3_init_finished_mac(s)) + { + OPENSSL_PUT_ERROR(SSL, ssl3_accept, ERR_R_INTERNAL_ERROR); + ret = -1; + goto end; + } s->state=SSL3_ST_SR_CLNT_HELLO_A; s->ctx->stats.sess_accept++; } @@ -329,7 +334,12 @@ int ssl3_accept(SSL *s) s->state=SSL3_ST_SW_FLUSH; s->init_num=0; - ssl3_init_finished_mac(s); + if (!ssl3_init_finished_mac(s)) + { + OPENSSL_PUT_ERROR(SSL, ssl3_accept, ERR_R_INTERNAL_ERROR); + ret = -1; + goto end; + } break; case SSL3_ST_SW_HELLO_REQ_C: @@ -2578,16 +2588,22 @@ int ssl3_send_new_session_ticket(SSL *s) &hctx, 1) < 0) { OPENSSL_free(session); + EVP_CIPHER_CTX_cleanup(&ctx); + HMAC_CTX_cleanup(&hctx); return -1; } } else { RAND_pseudo_bytes(iv, 16); - EVP_EncryptInit_ex(&ctx, EVP_aes_128_cbc(), NULL, - tctx->tlsext_tick_aes_key, iv); - HMAC_Init_ex(&hctx, tctx->tlsext_tick_hmac_key, 16, - tlsext_tick_md(), NULL); + if (!EVP_EncryptInit_ex(&ctx, EVP_aes_128_cbc(), NULL, tctx->tlsext_tick_aes_key, iv) || + !HMAC_Init_ex(&hctx, tctx->tlsext_tick_hmac_key, 16, tlsext_tick_md(), NULL)) + { + OPENSSL_free(session); + EVP_CIPHER_CTX_cleanup(&ctx); + HMAC_CTX_cleanup(&hctx); + return -1; + } memcpy(key_name, tctx->tlsext_tick_key_name, 16); } diff --git a/ssl/ssl_lib.c b/ssl/ssl_lib.c index 94383e594..ee6609395 100644 --- a/ssl/ssl_lib.c +++ b/ssl/ssl_lib.c @@ -3167,7 +3167,10 @@ EVP_MD_CTX *ssl_replace_hash(EVP_MD_CTX **hash,const EVP_MD *md) { ssl_clear_hash_ctx(hash); *hash = EVP_MD_CTX_create(); - if (md) EVP_DigestInit_ex(*hash,md,NULL); + if (md != NULL && *hash != NULL) + { + EVP_DigestInit_ex(*hash,md,NULL); + } return *hash; } void ssl_clear_hash_ctx(EVP_MD_CTX **hash) diff --git a/ssl/ssl_locl.h b/ssl/ssl_locl.h index 083e2f4e1..b1c189977 100644 --- a/ssl/ssl_locl.h +++ b/ssl/ssl_locl.h @@ -819,7 +819,7 @@ int ssl_fill_hello_random(SSL *s, int server, unsigned char *field, int len); const SSL_CIPHER *ssl3_get_cipher_by_value(uint16_t value); uint16_t ssl3_get_cipher_value(const SSL_CIPHER *c); -void ssl3_init_finished_mac(SSL *s); +int ssl3_init_finished_mac(SSL *s); int ssl3_send_server_certificate(SSL *s); int ssl3_send_new_session_ticket(SSL *s); int ssl3_send_cert_status(SSL *s); @@ -1120,7 +1120,7 @@ int tls1_cbc_remove_padding(const SSL* s, unsigned block_size, unsigned mac_size); char ssl3_cbc_record_digest_supported(const EVP_MD_CTX *ctx); -void ssl3_cbc_digest_record( +int ssl3_cbc_digest_record( const EVP_MD_CTX *ctx, unsigned char* md_out, size_t* md_out_size, diff --git a/ssl/t1_enc.c b/ssl/t1_enc.c index 6803e9bcc..05f2ecae2 100644 --- a/ssl/t1_enc.c +++ b/ssl/t1_enc.c @@ -447,6 +447,8 @@ static int tls1_change_cipher_state_cipher( cipher_ctx = s->enc_read_ctx; mac_ctx = ssl_replace_hash(&s->read_hash, NULL); + if (mac_ctx == NULL) + goto err; memcpy(s->s3->read_mac_secret, mac_secret, mac_secret_len); s->s3->read_mac_secret_size = mac_secret_len; @@ -476,7 +478,11 @@ static int tls1_change_cipher_state_cipher( s->write_hash = mac_ctx; } else + { mac_ctx = ssl_replace_hash(&s->write_hash, NULL); + if (mac_ctx == NULL) + goto err; + } memcpy(s->s3->write_mac_secret, mac_secret, mac_secret_len); s->s3->write_mac_secret_size = mac_secret_len; @@ -487,10 +493,15 @@ static int tls1_change_cipher_state_cipher( NULL, mac_secret, mac_secret_len); if (!mac_key) return 0; - EVP_DigestSignInit(mac_ctx, NULL, s->s3->tmp.new_hash, NULL, mac_key); + if (!EVP_DigestSignInit(mac_ctx, NULL, s->s3->tmp.new_hash, NULL, mac_key)) + { + EVP_PKEY_free(mac_key); + goto err; + } EVP_PKEY_free(mac_key); - EVP_CipherInit_ex(cipher_ctx, cipher, NULL /* engine */, key, iv, !is_read); + if (!EVP_CipherInit_ex(cipher_ctx, cipher, NULL /* engine */, key, iv, !is_read)) + goto err; return 1; @@ -1063,7 +1074,7 @@ int tls1_mac(SSL *ssl, unsigned char *md, int send) unsigned char *seq; EVP_MD_CTX *hash; size_t md_size, orig_len; - int i; + int i, ok; EVP_MD_CTX hmac, *mac_ctx; unsigned char header[13]; int t; @@ -1085,9 +1096,9 @@ int tls1_mac(SSL *ssl, unsigned char *md, int send) assert(t >= 0); md_size=t; - if (!EVP_MD_CTX_copy(&hmac,hash)) - return -1; mac_ctx = &hmac; + if (!EVP_MD_CTX_copy(mac_ctx, hash)) + return -1; if (SSL_IS_DTLS(ssl)) { @@ -1119,7 +1130,7 @@ int tls1_mac(SSL *ssl, unsigned char *md, int send) * timing-side channel information about how many blocks of * data we are hashing because that gives an attacker a * timing-oracle. */ - ssl3_cbc_digest_record( + ok = ssl3_cbc_digest_record( mac_ctx, md, &md_size, header, rec->input, @@ -1132,22 +1143,24 @@ int tls1_mac(SSL *ssl, unsigned char *md, int send) { EVP_DigestSignUpdate(mac_ctx,header,sizeof(header)); EVP_DigestSignUpdate(mac_ctx,rec->input,rec->length); - t=EVP_DigestSignFinal(mac_ctx,md,&md_size); - assert(t > 0); + ok = EVP_DigestSignFinal(mac_ctx,md,&md_size); } - - EVP_MD_CTX_cleanup(&hmac); + + EVP_MD_CTX_cleanup(mac_ctx); + + if (!ok) + return -1; if (!SSL_IS_DTLS(ssl)) { for (i=7; i>=0; i--) { ++seq[i]; - if (seq[i] != 0) break; + if (seq[i] != 0) break; } } - return(md_size); + return md_size; } int tls1_generate_master_secret(SSL *s, unsigned char *out, unsigned char *p, diff --git a/ssl/test/CMakeLists.txt b/ssl/test/CMakeLists.txt index 27d959634..f7f0efc7e 100644 --- a/ssl/test/CMakeLists.txt +++ b/ssl/test/CMakeLists.txt @@ -5,8 +5,9 @@ add_executable( async_bio.cc bssl_shim.cc + malloc.cc packeted_bio.cc test_config.cc ) -target_link_libraries(bssl_shim ssl crypto) +target_link_libraries(bssl_shim ssl crypto dl) diff --git a/ssl/test/bssl_shim.cc b/ssl/test/bssl_shim.cc index cdd62ff65..9f9fac37b 100644 --- a/ssl/test/bssl_shim.cc +++ b/ssl/test/bssl_shim.cc @@ -41,8 +41,8 @@ static int usage(const char *program) { static int g_ex_data_index = 0; -static void SetConfigPtr(SSL *ssl, const TestConfig *config) { - SSL_set_ex_data(ssl, g_ex_data_index, (void *)config); +static bool SetConfigPtr(SSL *ssl, const TestConfig *config) { + return SSL_set_ex_data(ssl, g_ex_data_index, (void *)config) == 1; } static const TestConfig *GetConfigPtr(SSL *ssl) { @@ -267,7 +267,8 @@ static SSL_CTX *setup_ctx(const TestConfig *config) { } dh = DH_get_2048_256(NULL); - if (!SSL_CTX_set_tmp_dh(ssl_ctx, dh)) { + if (dh == NULL || + !SSL_CTX_set_tmp_dh(ssl_ctx, dh)) { goto err; } @@ -335,7 +336,10 @@ static int do_exchange(SSL_SESSION **out_session, return 1; } - SetConfigPtr(ssl, config); + if (!SetConfigPtr(ssl, config)) { + BIO_print_errors_fp(stdout); + return 1; + } if (config->fallback_scsv) { if (!SSL_enable_fallback_scsv(ssl)) { diff --git a/ssl/test/malloc.cc b/ssl/test/malloc.cc new file mode 100644 index 000000000..3e3f8d73c --- /dev/null +++ b/ssl/test/malloc.cc @@ -0,0 +1,126 @@ +/* Copyright (c) 2014, Google Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + +#if defined(__linux__) + +#include +#include +#include +#include +#include + +#include + + +/* This file defines overrides for the standard allocation functions that allow + * a given allocation to be made to fail for testing. If the program is run + * with MALLOC_NUMBER_TO_FAIL set to a base-10 number then that allocation will + * return NULL. If MALLOC_ABORT_ON_FAIL is also defined then the allocation + * will abort() rather than return NULL. + * + * This code is not thread safe. */ + +static uint64_t current_malloc_count = 0; +static uint64_t malloc_number_to_fail = 0; +static char failure_enabled = 0, abort_on_fail = 0; +static int in_call = 0; + +extern "C" { +/* These are other names for the standard allocation functions. */ +extern void *__libc_malloc(size_t size); +extern void *__libc_calloc(size_t num_elems, size_t size); +extern void *__libc_realloc(void *ptr, size_t size); +} + +static void exit_handler(void) { + if (failure_enabled && current_malloc_count > malloc_number_to_fail) { + _exit(88); + } +} + +static void cpp_new_handler() { + // Return to try again. It won't fail a second time. + return; +} + +/* should_fail_allocation returns true if the current allocation should fail. */ +static int should_fail_allocation() { + static int init = 0; + char should_fail; + + if (in_call) { + return 0; + } + + in_call = 1; + + if (!init) { + const char *env = getenv("MALLOC_NUMBER_TO_FAIL"); + if (env != NULL && env[0] != 0) { + char *endptr; + malloc_number_to_fail = strtoull(env, &endptr, 10); + if (*endptr == 0) { + failure_enabled = 1; + atexit(exit_handler); + std::set_new_handler(cpp_new_handler); + } + } + abort_on_fail = (NULL != getenv("MALLOC_ABORT_ON_FAIL")); + init = 1; + } + + in_call = 0; + + if (!failure_enabled) { + return 0; + } + + should_fail = (current_malloc_count == malloc_number_to_fail); + current_malloc_count++; + + if (should_fail && abort_on_fail) { + abort(); + } + return should_fail; +} + +extern "C" { + +void *malloc(size_t size) { + if (should_fail_allocation()) { + return NULL; + } + + return __libc_malloc(size); +} + +void *calloc(size_t num_elems, size_t size) { + if (should_fail_allocation()) { + return NULL; + } + + return __libc_calloc(num_elems, size); +} + +void *realloc(void *ptr, size_t size) { + if (should_fail_allocation()) { + return NULL; + } + + return __libc_realloc(ptr, size); +} + +} // extern "C" + +#endif /* defined(linux) */ diff --git a/ssl/test/packeted_bio.cc b/ssl/test/packeted_bio.cc index 629d6c5b0..3894d85e3 100644 --- a/ssl/test/packeted_bio.cc +++ b/ssl/test/packeted_bio.cc @@ -67,7 +67,9 @@ static int packeted_read(BIO *bio, char *out, int outl) { uint32_t len = (len_bytes[0] << 24) | (len_bytes[1] << 16) | (len_bytes[2] << 8) | len_bytes[3]; char *buf = (char *)OPENSSL_malloc(len); - assert(buf != NULL); + if (buf == NULL) { + return -1; + } ret = BIO_read(bio->next_bio, buf, len); assert(ret == (int)len); diff --git a/ssl/test/runner/runner.go b/ssl/test/runner/runner.go index dca0479b7..cf1b1f985 100644 --- a/ssl/test/runner/runner.go +++ b/ssl/test/runner/runner.go @@ -16,14 +16,19 @@ import ( "os/exec" "path" "runtime" + "strconv" "strings" "sync" "syscall" ) -var useValgrind = flag.Bool("valgrind", false, "If true, run code under valgrind") -var useGDB = flag.Bool("gdb", false, "If true, run BoringSSL code under gdb") -var flagDebug *bool = flag.Bool("debug", false, "Hexdump the contents of the connection") +var ( + useValgrind = flag.Bool("valgrind", false, "If true, run code under valgrind") + useGDB = flag.Bool("gdb", false, "If true, run BoringSSL code under gdb") + flagDebug *bool = flag.Bool("debug", false, "Hexdump the contents of the connection") + mallocTest *int64 = flag.Int64("malloc-test", -1, "If non-negative, run each test with each malloc in turn failing from the given number onwards.") + mallocTestDebug *bool = flag.Bool("malloc-test-debug", false, "If true, ask bssl_shim to abort rather than fail a malloc. This can be used with a specific value for --malloc-test to identity the malloc failing that is causing problems.") +) const ( rsaCertificateFile = "cert.pem" @@ -703,7 +708,15 @@ func openSocketPair() (shimEnd *os.File, conn net.Conn) { return shimEnd, conn } -func runTest(test *testCase, buildDir string) error { +type moreMallocsError struct{} + +func (moreMallocsError) Error() string { + return "child process did not exhaust all allocation calls" +} + +var errMoreMallocs = moreMallocsError{} + +func runTest(test *testCase, buildDir string, mallocNumToFail int64) error { if !test.shouldFail && (len(test.expectedError) > 0 || len(test.expectedLocalError) > 0) { panic("Error expected without shouldFail in " + test.name) } @@ -758,6 +771,13 @@ func runTest(test *testCase, buildDir string) error { var stdoutBuf, stderrBuf bytes.Buffer shim.Stdout = &stdoutBuf shim.Stderr = &stderrBuf + if mallocNumToFail >= 0 { + shim.Env = []string{"MALLOC_NUMBER_TO_FAIL=" + strconv.FormatInt(mallocNumToFail, 10)} + if *mallocTestDebug { + shim.Env = append(shim.Env, "MALLOC_ABORT_ON_FAIL=1") + } + shim.Env = append(shim.Env, "_MALLOC_CHECK=1") + } if err := shim.Start(); err != nil { panic(err) @@ -805,6 +825,11 @@ func runTest(test *testCase, buildDir string) error { connResume.Close() childErr := shim.Wait() + if exitError, ok := childErr.(*exec.ExitError); ok { + if exitError.Sys().(syscall.WaitStatus).ExitStatus() == 88 { + return errMoreMallocs + } + } stdout := string(stdoutBuf.Bytes()) stderr := string(stderrBuf.Bytes()) @@ -2142,8 +2167,22 @@ func worker(statusChan chan statusMsg, c chan *testCase, buildDir string, wg *sy defer wg.Done() for test := range c { - statusChan <- statusMsg{test: test, started: true} - err := runTest(test, buildDir) + var err error + + if *mallocTest < 0 { + statusChan <- statusMsg{test: test, started: true} + err = runTest(test, buildDir, -1) + } else { + for mallocNumToFail := int64(*mallocTest); ; mallocNumToFail++ { + statusChan <- statusMsg{test: test, started: true} + if err = runTest(test, buildDir, mallocNumToFail); err != errMoreMallocs { + if err != nil { + fmt.Printf("\n\nmalloc test failed at %d: %s\n", mallocNumToFail, err) + } + break + } + } + } statusChan <- statusMsg{test: test, err: err} } }