diff options
author | mrezai <mhd.rezai@gmail.com> | 2016-04-15 19:03:35 +0430 |
---|---|---|
committer | mrezai <mhd.rezai@gmail.com> | 2016-04-15 19:03:35 +0430 |
commit | e97922f22038e9049ed4c2db5b3736dfaa0edde3 (patch) | |
tree | 37e036a343e7482a387b7acd0a88509af78a69eb /drivers/builtin_openssl2/ssl/s3_clnt.c | |
parent | 880f4abda44a42532abb6f15999a90bc85f6264a (diff) |
Update OpenSSL to version 1.0.2g
Diffstat (limited to 'drivers/builtin_openssl2/ssl/s3_clnt.c')
-rw-r--r-- | drivers/builtin_openssl2/ssl/s3_clnt.c | 471 |
1 files changed, 332 insertions, 139 deletions
diff --git a/drivers/builtin_openssl2/ssl/s3_clnt.c b/drivers/builtin_openssl2/ssl/s3_clnt.c index cfa5080e6b..04cc9f54a9 100644 --- a/drivers/builtin_openssl2/ssl/s3_clnt.c +++ b/drivers/builtin_openssl2/ssl/s3_clnt.c @@ -317,11 +317,11 @@ int ssl3_connect(SSL *s) s->state = SSL3_ST_CR_SESSION_TICKET_A; } #endif - } else + } else { s->state = SSL3_ST_CR_CERT_A; + } s->init_num = 0; break; - case SSL3_ST_CR_CERT_A: case SSL3_ST_CR_CERT_B: #ifndef OPENSSL_NO_TLSEXT @@ -675,6 +675,7 @@ int ssl3_client_hello(SSL *s) unsigned char *p, *d; int i; unsigned long l; + int al = 0; #ifndef OPENSSL_NO_COMP int j; SSL_COMP *comp; @@ -697,15 +698,64 @@ int ssl3_client_hello(SSL *s) if (!ssl_get_new_session(s, 0)) goto err; } + if (s->method->version == DTLS_ANY_VERSION) { + /* Determine which DTLS version to use */ + int options = s->options; + /* If DTLS 1.2 disabled correct the version number */ + if (options & SSL_OP_NO_DTLSv1_2) { + if (tls1_suiteb(s)) { + SSLerr(SSL_F_SSL3_CLIENT_HELLO, + SSL_R_ONLY_DTLS_1_2_ALLOWED_IN_SUITEB_MODE); + goto err; + } + /* + * Disabling all versions is silly: return an error. + */ + if (options & SSL_OP_NO_DTLSv1) { + SSLerr(SSL_F_SSL3_CLIENT_HELLO, SSL_R_WRONG_SSL_VERSION); + goto err; + } + /* + * Update method so we don't use any DTLS 1.2 features. + */ + s->method = DTLSv1_client_method(); + s->version = DTLS1_VERSION; + } else { + /* + * We only support one version: update method + */ + if (options & SSL_OP_NO_DTLSv1) + s->method = DTLSv1_2_client_method(); + s->version = DTLS1_2_VERSION; + } + s->client_version = s->version; + } /* else use the pre-loaded session */ p = s->s3->client_random; - if (ssl_fill_hello_random(s, 0, p, SSL3_RANDOM_SIZE) <= 0) + /* + * for DTLS if client_random is initialized, reuse it, we are + * required to use same upon reply to HelloVerify + */ + if (SSL_IS_DTLS(s)) { + size_t idx; + i = 1; + for (idx = 0; idx < sizeof(s->s3->client_random); idx++) { + if (p[idx]) { + i = 0; + break; + } + } + } else + i = 1; + + if (i && ssl_fill_hello_random(s, 0, p, + sizeof(s->s3->client_random)) <= 0) goto err; /* Do the message type and length last */ - d = p = &(buf[4]); + d = p = ssl_handshake_start(s); /*- * version indicates the negotiated version: for example from @@ -765,6 +815,17 @@ int ssl3_client_hello(SSL *s) p += i; } + /* cookie stuff for DTLS */ + if (SSL_IS_DTLS(s)) { + if (s->d1->cookie_len > sizeof(s->d1->cookie)) { + SSLerr(SSL_F_SSL3_CLIENT_HELLO, ERR_R_INTERNAL_ERROR); + goto err; + } + *(p++) = s->d1->cookie_len; + memcpy(p, s->d1->cookie, s->d1->cookie_len); + p += s->d1->cookie_len; + } + /* Ciphers supported */ i = ssl_cipher_list_to_bytes(s, SSL_get_ciphers(s), &(p[2]), 0); if (i == 0) { @@ -809,27 +870,21 @@ int ssl3_client_hello(SSL *s) goto err; } if ((p = - ssl_add_clienthello_tlsext(s, p, - buf + SSL3_RT_MAX_PLAIN_LENGTH)) == - NULL) { + ssl_add_clienthello_tlsext(s, p, buf + SSL3_RT_MAX_PLAIN_LENGTH, + &al)) == NULL) { + ssl3_send_alert(s, SSL3_AL_FATAL, al); SSLerr(SSL_F_SSL3_CLIENT_HELLO, ERR_R_INTERNAL_ERROR); goto err; } #endif - l = (p - d); - d = buf; - *(d++) = SSL3_MT_CLIENT_HELLO; - l2n3(l, d); - + l = p - d; + ssl_set_handshake_header(s, SSL3_MT_CLIENT_HELLO, l); s->state = SSL3_ST_CW_CLNT_HELLO_B; - /* number of bytes to write */ - s->init_num = p - buf; - s->init_off = 0; } /* SSL3_ST_CW_CLNT_HELLO_B */ - return (ssl3_do_write(s, SSL3_RT_HANDSHAKE)); + return ssl_do_write(s); err: s->state = SSL_ST_ERR; return (-1); @@ -839,13 +894,20 @@ int ssl3_get_server_hello(SSL *s) { STACK_OF(SSL_CIPHER) *sk; const SSL_CIPHER *c; + CERT *ct = s->cert; unsigned char *p, *d; - int i, al, ok; + int i, al = SSL_AD_INTERNAL_ERROR, ok; unsigned int j; long n; #ifndef OPENSSL_NO_COMP SSL_COMP *comp; #endif + /* + * Hello verify request and/or server hello version may not match so set + * first packet if we're negotiating version. + */ + if (SSL_IS_DTLS(s)) + s->first_packet = 1; n = s->method->ssl_get_message(s, SSL3_ST_CR_SRVR_HELLO_A, @@ -854,7 +916,8 @@ int ssl3_get_server_hello(SSL *s) if (!ok) return ((int)n); - if (SSL_version(s) == DTLS1_VERSION || SSL_version(s) == DTLS1_BAD_VER) { + if (SSL_IS_DTLS(s)) { + s->first_packet = 0; if (s->s3->tmp.message_type == DTLS1_MT_HELLO_VERIFY_REQUEST) { if (s->d1->send_cookie == 0) { s->s3->tmp.reuse_message = 1; @@ -875,6 +938,28 @@ int ssl3_get_server_hello(SSL *s) } d = p = (unsigned char *)s->init_msg; + if (s->method->version == DTLS_ANY_VERSION) { + /* Work out correct protocol version to use */ + int hversion = (p[0] << 8) | p[1]; + int options = s->options; + if (hversion == DTLS1_2_VERSION && !(options & SSL_OP_NO_DTLSv1_2)) + s->method = DTLSv1_2_client_method(); + else if (tls1_suiteb(s)) { + SSLerr(SSL_F_SSL3_GET_SERVER_HELLO, + SSL_R_ONLY_DTLS_1_2_ALLOWED_IN_SUITEB_MODE); + s->version = hversion; + al = SSL_AD_PROTOCOL_VERSION; + goto f_err; + } else if (hversion == DTLS1_VERSION && !(options & SSL_OP_NO_DTLSv1)) + s->method = DTLSv1_client_method(); + else { + SSLerr(SSL_F_SSL3_GET_SERVER_HELLO, SSL_R_WRONG_SSL_VERSION); + s->version = hversion; + al = SSL_AD_PROTOCOL_VERSION; + goto f_err; + } + s->session->ssl_version = s->version = s->method->version; + } if ((p[0] != (s->version >> 8)) || (p[1] != (s->version & 0xff))) { SSLerr(SSL_F_SSL3_GET_SERVER_HELLO, SSL_R_WRONG_SSL_VERSION); @@ -951,7 +1036,6 @@ int ssl3_get_server_hello(SSL *s) */ if (s->session->session_id_length > 0) { if (!ssl_get_new_session(s, 0)) { - al = SSL_AD_INTERNAL_ERROR; goto f_err; } } @@ -966,21 +1050,21 @@ int ssl3_get_server_hello(SSL *s) SSLerr(SSL_F_SSL3_GET_SERVER_HELLO, SSL_R_UNKNOWN_CIPHER_RETURNED); goto f_err; } - /* TLS v1.2 only ciphersuites require v1.2 or later */ - if ((c->algorithm_ssl & SSL_TLSV1_2) && - (TLS1_get_version(s) < TLS1_2_VERSION)) { - al = SSL_AD_ILLEGAL_PARAMETER; - SSLerr(SSL_F_SSL3_GET_SERVER_HELLO, SSL_R_WRONG_CIPHER_RETURNED); - goto f_err; - } -#ifndef OPENSSL_NO_SRP - if (((c->algorithm_mkey & SSL_kSRP) || (c->algorithm_auth & SSL_aSRP)) && - !(s->srp_ctx.srp_Mask & SSL_kSRP)) { + /* Set version disabled mask now we know version */ + if (!SSL_USE_TLS1_2_CIPHERS(s)) + ct->mask_ssl = SSL_TLSV1_2; + else + ct->mask_ssl = 0; + /* + * If it is a disabled cipher we didn't send it in client hello, so + * return an error. + */ + if (c->algorithm_ssl & ct->mask_ssl || + c->algorithm_mkey & ct->mask_k || c->algorithm_auth & ct->mask_a) { al = SSL_AD_ILLEGAL_PARAMETER; SSLerr(SSL_F_SSL3_GET_SERVER_HELLO, SSL_R_WRONG_CIPHER_RETURNED); goto f_err; } -#endif /* OPENSSL_NO_SRP */ p += ssl_put_cipher_by_char(s, NULL, NULL); sk = ssl_get_ciphers_by_id(s); @@ -1013,14 +1097,11 @@ int ssl3_get_server_hello(SSL *s) } s->s3->tmp.new_cipher = c; /* - * Don't digest cached records if TLS v1.2: we may need them for client + * Don't digest cached records if no sigalgs: we may need them for client * authentication. */ - if (TLS1_get_version(s) < TLS1_2_VERSION - && !ssl3_digest_cached_records(s)) { - al = SSL_AD_INTERNAL_ERROR; + if (!SSL_USE_SIGALGS(s) && !ssl3_digest_cached_records(s)) goto f_err; - } /* lets get the compression algorithm */ /* COMPRESSION */ #ifdef OPENSSL_NO_COMP @@ -1035,7 +1116,6 @@ int ssl3_get_server_hello(SSL *s) * using compression. */ if (s->session->compress_meth != 0) { - al = SSL_AD_INTERNAL_ERROR; SSLerr(SSL_F_SSL3_GET_SERVER_HELLO, SSL_R_INCONSISTENT_COMPRESSION); goto f_err; } @@ -1068,16 +1148,9 @@ int ssl3_get_server_hello(SSL *s) #ifndef OPENSSL_NO_TLSEXT /* TLS extensions */ - if (s->version >= SSL3_VERSION) { - if (!ssl_parse_serverhello_tlsext(s, &p, d, n, &al)) { - /* 'al' set by ssl_parse_serverhello_tlsext */ - SSLerr(SSL_F_SSL3_GET_SERVER_HELLO, SSL_R_PARSE_TLSEXT); - goto f_err; - } - if (ssl_check_serverhello_tlsext(s) <= 0) { - SSLerr(SSL_F_SSL3_GET_SERVER_HELLO, SSL_R_SERVERHELLO_TLSEXT); - goto err; - } + if (!ssl_parse_serverhello_tlsext(s, &p, d, n)) { + SSLerr(SSL_F_SSL3_GET_SERVER_HELLO, SSL_R_PARSE_TLSEXT); + goto err; } #endif @@ -1240,6 +1313,14 @@ int ssl3_get_server_certificate(SSL *s) } if (need_cert) { + int exp_idx = ssl_cipher_get_cert_index(s->s3->tmp.new_cipher); + if (exp_idx >= 0 && i != exp_idx) { + x = NULL; + al = SSL_AD_ILLEGAL_PARAMETER; + SSLerr(SSL_F_SSL3_GET_SERVER_CERTIFICATE, + SSL_R_WRONG_CERTIFICATE_TYPE); + goto f_err; + } sc->peer_cert_type = i; CRYPTO_add(&x->references, 1, CRYPTO_LOCK_X509); /* @@ -1267,7 +1348,6 @@ int ssl3_get_server_certificate(SSL *s) x = NULL; ret = 1; - if (0) { f_err: ssl3_send_alert(s, SSL3_AL_FATAL, al); @@ -1326,7 +1406,7 @@ int ssl3_get_key_exchange(SSL *s) * Can't skip server key exchange if this is an ephemeral * ciphersuite. */ - if (alg_k & (SSL_kEDH | SSL_kEECDH)) { + if (alg_k & (SSL_kDHE | SSL_kECDHE)) { SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, SSL_R_UNEXPECTED_MESSAGE); al = SSL_AD_UNEXPECTED_MESSAGE; goto f_err; @@ -1734,9 +1814,16 @@ int ssl3_get_key_exchange(SSL *s) SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, SSL_R_LENGTH_TOO_SHORT); goto f_err; } + /* + * Check curve is one of our preferences, if not server has sent an + * invalid curve. ECParameters is 3 bytes. + */ + if (!tls1_check_curve(s, p, 3)) { + SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, SSL_R_WRONG_CURVE); + goto f_err; + } - if ((*p != NAMED_CURVE_TYPE) || - ((curve_nid = tls1_ec_curve_id2nid(*(p + 2))) == 0)) { + if ((curve_nid = tls1_ec_curve_id2nid(*(p + 2))) == 0) { al = SSL_AD_INTERNAL_ERROR; SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, SSL_R_UNABLE_TO_FIND_ECDH_PARAMETERS); @@ -1824,29 +1911,16 @@ int ssl3_get_key_exchange(SSL *s) /* if it was signed, check the signature */ if (pkey != NULL) { - if (TLS1_get_version(s) >= TLS1_2_VERSION) { - int sigalg; + if (SSL_USE_SIGALGS(s)) { + int rv; if (2 > n) { SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, SSL_R_LENGTH_TOO_SHORT); goto f_err; } - - sigalg = tls12_get_sigid(pkey); - /* Should never happen */ - if (sigalg == -1) { - SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, ERR_R_INTERNAL_ERROR); + rv = tls12_check_peer_sigalg(&md, s, p, pkey); + if (rv == -1) goto err; - } - /* Check key type is consistent with signature */ - if (sigalg != (int)p[1]) { - SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, - SSL_R_WRONG_SIGNATURE_TYPE); - al = SSL_AD_DECODE_ERROR; - goto f_err; - } - md = tls12_get_hash(p[0]); - if (md == NULL) { - SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, SSL_R_UNKNOWN_DIGEST); + else if (rv == 0) { goto f_err; } #ifdef SSL_DEBUG @@ -1874,8 +1948,7 @@ int ssl3_get_key_exchange(SSL *s) goto f_err; } #ifndef OPENSSL_NO_RSA - if (pkey->type == EVP_PKEY_RSA - && TLS1_get_version(s) < TLS1_2_VERSION) { + if (pkey->type == EVP_PKEY_RSA && !SSL_USE_SIGALGS(s)) { int num; unsigned int size; @@ -1935,7 +2008,10 @@ int ssl3_get_key_exchange(SSL *s) } else { /* aNULL, aSRP or kPSK do not need public keys */ if (!(alg_a & (SSL_aNULL | SSL_aSRP)) && !(alg_k & SSL_kPSK)) { - SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, ERR_R_INTERNAL_ERROR); + /* Might be wrong key type, check it */ + if (ssl3_check_cert_and_algorithm(s)) + /* Otherwise this shouldn't happen */ + SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, ERR_R_INTERNAL_ERROR); goto err; } /* still data left over */ @@ -2028,12 +2104,21 @@ int ssl3_get_certificate_request(SSL *s) /* get the certificate types */ ctype_num = *(p++); - if (ctype_num > SSL3_CT_NUMBER) + if (s->cert->ctypes) { + OPENSSL_free(s->cert->ctypes); + s->cert->ctypes = NULL; + } + if (ctype_num > SSL3_CT_NUMBER) { + /* If we exceed static buffer copy all to cert structure */ + s->cert->ctypes = OPENSSL_malloc(ctype_num); + memcpy(s->cert->ctypes, p, ctype_num); + s->cert->ctype_num = (size_t)ctype_num; ctype_num = SSL3_CT_NUMBER; + } for (i = 0; i < ctype_num; i++) s->s3->tmp.ctype[i] = p[i]; - p += ctype_num; - if (TLS1_get_version(s) >= TLS1_2_VERSION) { + p += p[-1]; + if (SSL_USE_SIGALGS(s)) { n2s(p, llen); /* * Check we have enough room for signature algorithms and following @@ -2045,12 +2130,22 @@ int ssl3_get_certificate_request(SSL *s) SSL_R_DATA_LENGTH_TOO_LONG); goto err; } - if ((llen & 1) || !tls1_process_sigalgs(s, p, llen)) { + /* Clear certificate digests and validity flags */ + for (i = 0; i < SSL_PKEY_NUM; i++) { + s->cert->pkeys[i].digest = NULL; + s->cert->pkeys[i].valid_flags = 0; + } + if ((llen & 1) || !tls1_save_sigalgs(s, p, llen)) { ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR); SSLerr(SSL_F_SSL3_GET_CERTIFICATE_REQUEST, SSL_R_SIGNATURE_ALGORITHMS_ERROR); goto err; } + if (!tls1_process_sigalgs(s)) { + ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR); + SSLerr(SSL_F_SSL3_GET_CERTIFICATE_REQUEST, ERR_R_MALLOC_FAILURE); + goto err; + } p += llen; } @@ -2339,9 +2434,28 @@ int ssl3_get_server_done(SSL *s) return (ret); } +#ifndef OPENSSL_NO_DH +static DH *get_server_static_dh_key(SESS_CERT *scert) +{ + DH *dh_srvr = NULL; + EVP_PKEY *spkey = NULL; + int idx = scert->peer_cert_type; + + if (idx >= 0) + spkey = X509_get_pubkey(scert->peer_pkeys[idx].x509); + if (spkey) { + dh_srvr = EVP_PKEY_get1_DH(spkey); + EVP_PKEY_free(spkey); + } + if (dh_srvr == NULL) + SSLerr(SSL_F_GET_SERVER_STATIC_DH_KEY, ERR_R_INTERNAL_ERROR); + return dh_srvr; +} +#endif + int ssl3_send_client_key_exchange(SSL *s) { - unsigned char *p, *d; + unsigned char *p; int n; unsigned long alg_k; #ifndef OPENSSL_NO_RSA @@ -2361,8 +2475,7 @@ int ssl3_send_client_key_exchange(SSL *s) #endif if (s->state == SSL3_ST_CW_KEY_EXCH_A) { - d = (unsigned char *)s->init_buf->data; - p = &(d[4]); + p = ssl_handshake_start(s); alg_k = s->s3->tmp.new_cipher->algorithm_mkey; @@ -2574,33 +2687,45 @@ int ssl3_send_client_key_exchange(SSL *s) #ifndef OPENSSL_NO_DH else if (alg_k & (SSL_kEDH | SSL_kDHr | SSL_kDHd)) { DH *dh_srvr, *dh_clnt; + SESS_CERT *scert = s->session->sess_cert; - if (s->session->sess_cert == NULL) { + if (scert == NULL) { ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_UNEXPECTED_MESSAGE); SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE, SSL_R_UNEXPECTED_MESSAGE); goto err; } - if (s->session->sess_cert->peer_dh_tmp != NULL) - dh_srvr = s->session->sess_cert->peer_dh_tmp; - else { - /* we get them from the cert */ - ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_HANDSHAKE_FAILURE); - SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE, - SSL_R_UNABLE_TO_FIND_DH_PARAMETERS); - goto err; + if (scert->peer_dh_tmp != NULL) { + dh_srvr = scert->peer_dh_tmp; + } else { + dh_srvr = get_server_static_dh_key(scert); + if (dh_srvr == NULL) + goto err; } - /* generate a new random key */ - if ((dh_clnt = DHparams_dup(dh_srvr)) == NULL) { - SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE, ERR_R_DH_LIB); - goto err; - } - if (!DH_generate_key(dh_clnt)) { - SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE, ERR_R_DH_LIB); - DH_free(dh_clnt); - goto err; + if (s->s3->flags & TLS1_FLAGS_SKIP_CERT_VERIFY) { + /* Use client certificate key */ + EVP_PKEY *clkey = s->cert->key->privatekey; + dh_clnt = NULL; + if (clkey) + dh_clnt = EVP_PKEY_get1_DH(clkey); + if (dh_clnt == NULL) { + SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE, + ERR_R_INTERNAL_ERROR); + goto err; + } + } else { + /* generate a new random key */ + if ((dh_clnt = DHparams_dup(dh_srvr)) == NULL) { + SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE, ERR_R_DH_LIB); + goto err; + } + if (!DH_generate_key(dh_clnt)) { + SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE, ERR_R_DH_LIB); + DH_free(dh_clnt); + goto err; + } } /* @@ -2609,6 +2734,8 @@ int ssl3_send_client_key_exchange(SSL *s) */ n = DH_compute_key(p, dh_srvr->pub_key, dh_clnt); + if (scert->peer_dh_tmp == NULL) + DH_free(dh_srvr); if (n <= 0) { SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE, ERR_R_DH_LIB); @@ -2625,11 +2752,15 @@ int ssl3_send_client_key_exchange(SSL *s) /* clean up */ memset(p, 0, n); - /* send off the data */ - n = BN_num_bytes(dh_clnt->pub_key); - s2n(n, p); - BN_bn2bin(dh_clnt->pub_key, p); - n += 2; + if (s->s3->flags & TLS1_FLAGS_SKIP_CERT_VERIFY) + n = 0; + else { + /* send off the data */ + n = BN_num_bytes(dh_clnt->pub_key); + s2n(n, p); + BN_bn2bin(dh_clnt->pub_key, p); + n += 2; + } DH_free(dh_clnt); } @@ -3068,17 +3199,12 @@ int ssl3_send_client_key_exchange(SSL *s) goto err; } - *(d++) = SSL3_MT_CLIENT_KEY_EXCHANGE; - l2n3(n, d); - + ssl_set_handshake_header(s, SSL3_MT_CLIENT_KEY_EXCHANGE, n); s->state = SSL3_ST_CW_KEY_EXCH_B; - /* number of bytes to write */ - s->init_num = n + 4; - s->init_off = 0; } /* SSL3_ST_CW_KEY_EXCH_B */ - return (ssl3_do_write(s, SSL3_RT_HANDSHAKE)); + return ssl_do_write(s); err: #ifndef OPENSSL_NO_ECDH BN_CTX_free(bn_ctx); @@ -3094,7 +3220,7 @@ int ssl3_send_client_key_exchange(SSL *s) int ssl3_send_client_verify(SSL *s) { - unsigned char *p, *d; + unsigned char *p; unsigned char data[MD5_DIGEST_LENGTH + SHA_DIGEST_LENGTH]; EVP_PKEY *pkey; EVP_PKEY_CTX *pctx = NULL; @@ -3106,8 +3232,7 @@ int ssl3_send_client_verify(SSL *s) EVP_MD_CTX_init(&mctx); if (s->state == SSL3_ST_CW_CERT_VRFY_A) { - d = (unsigned char *)s->init_buf->data; - p = &(d[4]); + p = ssl_handshake_start(s); pkey = s->cert->key->privatekey; /* Create context from key and test if sha1 is allowed as digest */ pctx = EVP_PKEY_CTX_new(pkey, NULL); @@ -3116,7 +3241,7 @@ int ssl3_send_client_verify(SSL *s) goto err; } if (EVP_PKEY_CTX_set_signature_md(pctx, EVP_sha1()) > 0) { - if (TLS1_get_version(s) < TLS1_2_VERSION) + if (!SSL_USE_SIGALGS(s)) s->method->ssl3_enc->cert_verify_mac(s, NID_sha1, &(data @@ -3128,7 +3253,7 @@ int ssl3_send_client_verify(SSL *s) * For TLS v1.2 send signature algorithm and signature using agreed * digest and cached handshake records. */ - if (TLS1_get_version(s) >= TLS1_2_VERSION) { + if (SSL_USE_SIGALGS(s)) { long hdatalen = 0; void *hdata; const EVP_MD *md = s->cert->key->digest; @@ -3212,16 +3337,12 @@ int ssl3_send_client_verify(SSL *s) SSLerr(SSL_F_SSL3_SEND_CLIENT_VERIFY, ERR_R_INTERNAL_ERROR); goto err; } - *(d++) = SSL3_MT_CERTIFICATE_VERIFY; - l2n3(n, d); - + ssl_set_handshake_header(s, SSL3_MT_CERTIFICATE_VERIFY, n); s->state = SSL3_ST_CW_CERT_VRFY_B; - s->init_num = (int)n + 4; - s->init_off = 0; } EVP_MD_CTX_cleanup(&mctx); EVP_PKEY_CTX_free(pctx); - return (ssl3_do_write(s, SSL3_RT_HANDSHAKE)); + return ssl_do_write(s); err: EVP_MD_CTX_cleanup(&mctx); EVP_PKEY_CTX_free(pctx); @@ -3229,20 +3350,75 @@ int ssl3_send_client_verify(SSL *s) return (-1); } +/* + * Check a certificate can be used for client authentication. Currently check + * cert exists, if we have a suitable digest for TLS 1.2 if static DH client + * certificates can be used and optionally checks suitability for Suite B. + */ +static int ssl3_check_client_certificate(SSL *s) +{ + unsigned long alg_k; + if (!s->cert || !s->cert->key->x509 || !s->cert->key->privatekey) + return 0; + /* If no suitable signature algorithm can't use certificate */ + if (SSL_USE_SIGALGS(s) && !s->cert->key->digest) + return 0; + /* + * If strict mode check suitability of chain before using it. This also + * adjusts suite B digest if necessary. + */ + if (s->cert->cert_flags & SSL_CERT_FLAGS_CHECK_TLS_STRICT && + !tls1_check_chain(s, NULL, NULL, NULL, -2)) + return 0; + alg_k = s->s3->tmp.new_cipher->algorithm_mkey; + /* See if we can use client certificate for fixed DH */ + if (alg_k & (SSL_kDHr | SSL_kDHd)) { + SESS_CERT *scert = s->session->sess_cert; + int i = scert->peer_cert_type; + EVP_PKEY *clkey = NULL, *spkey = NULL; + clkey = s->cert->key->privatekey; + /* If client key not DH assume it can be used */ + if (EVP_PKEY_id(clkey) != EVP_PKEY_DH) + return 1; + if (i >= 0) + spkey = X509_get_pubkey(scert->peer_pkeys[i].x509); + if (spkey) { + /* Compare server and client parameters */ + i = EVP_PKEY_cmp_parameters(clkey, spkey); + EVP_PKEY_free(spkey); + if (i != 1) + return 0; + } + s->s3->flags |= TLS1_FLAGS_SKIP_CERT_VERIFY; + } + return 1; +} + int ssl3_send_client_certificate(SSL *s) { X509 *x509 = NULL; EVP_PKEY *pkey = NULL; int i; - unsigned long l; if (s->state == SSL3_ST_CW_CERT_A) { - if ((s->cert == NULL) || - (s->cert->key->x509 == NULL) || - (s->cert->key->privatekey == NULL)) - s->state = SSL3_ST_CW_CERT_B; - else + /* Let cert callback update client certificates if required */ + if (s->cert->cert_cb) { + i = s->cert->cert_cb(s, s->cert->cert_cb_arg); + if (i < 0) { + s->rwstate = SSL_X509_LOOKUP; + return -1; + } + if (i == 0) { + ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR); + s->state = SSL_ST_ERR; + return 0; + } + s->rwstate = SSL_NOTHING; + } + if (ssl3_check_client_certificate(s)) s->state = SSL3_ST_CW_CERT_C; + else + s->state = SSL3_ST_CW_CERT_B; } /* We need to get a client cert */ @@ -3271,6 +3447,8 @@ int ssl3_send_client_certificate(SSL *s) X509_free(x509); if (pkey != NULL) EVP_PKEY_free(pkey); + if (i && !ssl3_check_client_certificate(s)) + i = 0; if (i == 0) { if (s->version == SSL3_VERSION) { s->s3->tmp.cert_req = 0; @@ -3287,20 +3465,17 @@ int ssl3_send_client_certificate(SSL *s) if (s->state == SSL3_ST_CW_CERT_C) { s->state = SSL3_ST_CW_CERT_D; - l = ssl3_output_cert_chain(s, - (s->s3->tmp.cert_req == - 2) ? NULL : s->cert->key->x509); - if (!l) { + if (!ssl3_output_cert_chain(s, + (s->s3->tmp.cert_req == + 2) ? NULL : s->cert->key)) { SSLerr(SSL_F_SSL3_SEND_CLIENT_CERTIFICATE, ERR_R_INTERNAL_ERROR); ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR); s->state = SSL_ST_ERR; return 0; } - s->init_num = (int)l; - s->init_off = 0; } /* SSL3_ST_CW_CERT_D */ - return (ssl3_do_write(s, SSL3_RT_HANDSHAKE)); + return ssl_do_write(s); } #define has_bits(i,m) (((i)&(m)) == (m)) @@ -3324,7 +3499,7 @@ int ssl3_check_cert_and_algorithm(SSL *s) alg_a = s->s3->tmp.new_cipher->algorithm_auth; /* we don't have a certificate */ - if ((alg_a & (SSL_aDH | SSL_aNULL | SSL_aKRB5)) || (alg_k & SSL_kPSK)) + if ((alg_a & (SSL_aNULL | SSL_aKRB5)) || (alg_k & SSL_kPSK)) return (1); sc = s->session->sess_cert; @@ -3351,6 +3526,13 @@ int ssl3_check_cert_and_algorithm(SSL *s) } else { return 1; } + } else if (alg_a & SSL_aECDSA) { + SSLerr(SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM, + SSL_R_MISSING_ECDSA_SIGNING_CERT); + goto f_err; + } else if (alg_k & (SSL_kECDHr | SSL_kECDHe)) { + SSLerr(SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM, SSL_R_MISSING_ECDH_CERT); + goto f_err; } #endif pkey = X509_get_pubkey(sc->peer_pkeys[idx].x509); @@ -3401,22 +3583,33 @@ int ssl3_check_cert_and_algorithm(SSL *s) SSLerr(SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM, ERR_R_INTERNAL_ERROR); goto f_err; } - if ((alg_k & SSL_kDHr) && !has_bits(i, EVP_PK_DH | EVP_PKS_RSA)) { + if ((alg_k & SSL_kDHr) && !SSL_USE_SIGALGS(s) && + !has_bits(i, EVP_PK_DH | EVP_PKS_RSA)) { SSLerr(SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM, SSL_R_MISSING_DH_RSA_CERT); goto f_err; } # ifndef OPENSSL_NO_DSA - if ((alg_k & SSL_kDHd) && !has_bits(i, EVP_PK_DH | EVP_PKS_DSA)) { + if ((alg_k & SSL_kDHd) && !SSL_USE_SIGALGS(s) && + !has_bits(i, EVP_PK_DH | EVP_PKS_DSA)) { SSLerr(SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM, SSL_R_MISSING_DH_DSA_CERT); goto f_err; } # endif - /* Check DHE only: static DH not implemented. */ - if (alg_k & SSL_kEDH) { - int dh_size = BN_num_bits(dh->p); + if (alg_k & (SSL_kDHE | SSL_kDHr | SSL_kDHd)) { + int dh_size; + if (alg_k & SSL_kDHE) { + dh_size = BN_num_bits(dh->p); + } else { + DH *dh_srvr = get_server_static_dh_key(sc); + if (dh_srvr == NULL) + goto f_err; + dh_size = BN_num_bits(dh_srvr->p); + DH_free(dh_srvr); + } + if ((!SSL_C_IS_EXPORT(s->s3->tmp.new_cipher) && dh_size < 1024) || (SSL_C_IS_EXPORT(s->s3->tmp.new_cipher) && dh_size < 512)) { SSLerr(SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM, SSL_R_DH_KEY_TOO_SMALL); @@ -3444,7 +3637,7 @@ int ssl3_check_cert_and_algorithm(SSL *s) } else #endif #ifndef OPENSSL_NO_DH - if (alg_k & SSL_kEDH) { + if (alg_k & SSL_kDHE) { if (BN_num_bits(dh->p) > SSL_C_EXPORT_PKEYLENGTH(s->s3->tmp.new_cipher)) { /* We have a temporary DH key but it's too large. */ |